From 09e7831f60b9135a859006721afe079d6636e827 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 24 Nov 2023 11:47:00 +0100 Subject: [PATCH 001/397] clean up 1.x code --------- Co-authored-by: Silvano Cerza --- .github/release.yml | 50 - .github/workflows/benchmarks.yml | 251 -- .github/workflows/docker_release.yml | 176 -- .github/workflows/e2e.yml | 88 - .github/workflows/examples_tests.yml | 82 - .github/workflows/imports.yml | 48 - .github/workflows/linting.yml | 83 - .github/workflows/linting_skipper.yml | 24 - .github/workflows/openapi_sync.yml | 56 - .github/workflows/pipeline_schema.yml | 38 - .github/workflows/preview_imports.yml | 55 - .github/workflows/pypi_release_preview.yml | 23 - .github/workflows/rest_api_tests.yml | 151 - .github/workflows/tests.yml | 876 ------ .github/workflows/tests_preview_skipper.yml | 21 - .github/workflows/tests_skipper.yml | 27 - .github/workflows/xpdf_release.yml | 39 - annotation_tool/README.md | 69 - annotation_tool/docker-compose.yml | 47 - conftest.py | 31 - docker-compose.yml | 34 - docs/pydoc/config/agent.yml | 28 - docs/pydoc/config/answer-generator.yml | 26 - docs/pydoc/config/base-converter.yml | 27 - .../config/base-doc-language-classifier.yml | 27 - .../pydoc/config/base-document-classifier.yml | 27 - docs/pydoc/config/base-document-store.yml | 27 - docs/pydoc/config/base-generator.yml | 27 - docs/pydoc/config/base-image-to-text.yml | 27 - docs/pydoc/config/base-preprocessor.yml | 27 - docs/pydoc/config/base-query-classifier.yml | 27 - docs/pydoc/config/base-ranker.yml | 27 - docs/pydoc/config/base-reader.yml | 27 - docs/pydoc/config/base-retriever.yml | 27 - docs/pydoc/config/base-summarizer.yml | 27 - docs/pydoc/config/base-translator.yml | 27 - docs/pydoc/config/crawler.yml | 26 - docs/pydoc/config/doc-language-classifier.yml | 26 - docs/pydoc/config/document-classifier.yml | 26 - docs/pydoc/config/document-store.yml | 40 - docs/pydoc/config/extractor.yml | 28 - docs/pydoc/config/file-classifier.yml | 26 - docs/pydoc/config/file-converters.yml | 39 - docs/pydoc/config/invocation-layers.yml | 41 - docs/pydoc/config/other.yml | 34 - docs/pydoc/config/pipelines.yml | 27 - docs/pydoc/config/preprocessor.yml | 26 - docs/pydoc/config/primitives.yml | 26 - docs/pydoc/config/prompt-node.yml | 34 - docs/pydoc/config/pseudo-label-generator.yml | 26 - docs/pydoc/config/query-classifier.yml | 26 - docs/pydoc/config/question-generator.yml | 26 - docs/pydoc/config/ranker.yml | 26 - docs/pydoc/config/reader.yml | 26 - docs/pydoc/config/retriever.yml | 26 - docs/pydoc/config/shaper.yml | 26 - docs/pydoc/config/summarizer.yml | 26 - .../pydoc/config/transformers-img-to-text.yml | 26 - docs/pydoc/config/translator.yml | 26 - docs/pydoc/config/utils.yml | 37 - docs/pydoc/config/whisper.yml | 26 - e2e/document_search/__init__.py | 0 e2e/document_search/test_standard_pipeline.py | 35 - e2e/document_stores/__init__.py | 0 e2e/document_stores/test_cosine_similarity.py | 152 - e2e/document_stores/test_similarity_score.py | 98 - e2e/document_stores/test_update_embeddings.py | 166 -- e2e/modeling/__init__.py | 0 e2e/modeling/test_adaptive_qa_inference.py | 76 - e2e/modeling/test_distillation.py | 103 - e2e/modeling/test_dpr.py | 960 ------ e2e/modeling/test_feature_extraction.py | 246 -- e2e/pipelines/__init__.py | 0 e2e/pipelines/test_extractive_qa.py | 29 - e2e/pipelines/test_pipeline_topologies.py | 190 -- e2e/pipelines/test_standard_pipelines.py | 399 --- examples/agent_multihop_qa.py | 116 - examples/arxiv_paper_summary.py | 34 - examples/basic_faq_pipeline.py | 76 - examples/basic_qa_pipeline.py | 79 - examples/conversational_agent.py | 66 - examples/getting_started.py | 34 - examples/hybrid_search_faq_pipeline.py | 85 - examples/link_content_blog_post_summary.py | 32 - examples/seq2seq_replacement.py | 28 - examples/talk_to_website.py | 77 - examples/test_basic_faq_pipeline.py | 19 - examples/test_basic_qa_pipeline.py | 23 - examples/test_getting_started.py | 26 - examples/web_lfqa.py | 47 - examples/web_lfqa_with_rankers.py | 67 - examples/web_qa.py | 35 - haystack-linter/LICENSE | 202 -- haystack-linter/README.md | 22 - haystack-linter/haystack_linter/__about__.py | 4 - haystack-linter/haystack_linter/__init__.py | 4 - haystack-linter/haystack_linter/linting.py | 85 - haystack-linter/pyproject.toml | 60 - haystack-linter/tests/__init__.py | 3 - haystack/__init__.py | 19 - haystack/agents/__init__.py | 3 - haystack/agents/agent_step.py | 147 - haystack/agents/base.py | 450 --- haystack/agents/conversational.py | 112 - haystack/agents/memory/__init__.py | 4 - haystack/agents/memory/base.py | 31 - haystack/agents/memory/conversation_memory.py | 60 - .../memory/conversation_summary_memory.py | 117 - haystack/agents/memory/no_memory.py | 32 - haystack/agents/types.py | 44 - haystack/agents/utils.py | 56 - haystack/cli/README.md | 53 - haystack/cli/__init__.py | 0 haystack/cli/entry_point.py | 17 - haystack/cli/prompt/__init__.py | 11 - haystack/cli/prompt/fetch.py | 33 - haystack/document_stores/__init__.py | 15 - haystack/document_stores/base.py | 898 ------ haystack/document_stores/deepsetcloud.py | 708 ----- .../document_stores/elasticsearch/__init__.py | 12 - .../document_stores/elasticsearch/base.py | 337 --- haystack/document_stores/elasticsearch/es7.py | 278 -- haystack/document_stores/elasticsearch/es8.py | 360 --- haystack/document_stores/es_converter.py | 260 -- haystack/document_stores/faiss.py | 737 ----- haystack/document_stores/filter_utils.py | 756 ----- haystack/document_stores/memory.py | 1050 ------- haystack/document_stores/opensearch.py | 1635 ----------- haystack/document_stores/pinecone.py | 1854 ------------ haystack/document_stores/search_engine.py | 1656 ----------- haystack/document_stores/sql.py | 802 ----- haystack/document_stores/utils.py | 285 -- haystack/document_stores/weaviate.py | 1714 ----------- haystack/environment.py | 132 - haystack/errors.py | 284 -- haystack/lazy_imports.py | 44 - haystack/mmh3.py | 347 --- haystack/modeling/__init__.py | 10 - haystack/modeling/data_handler/__init__.py | 0 haystack/modeling/data_handler/data_silo.py | 851 ------ haystack/modeling/data_handler/dataloader.py | 98 - haystack/modeling/data_handler/dataset.py | 103 - .../modeling/data_handler/input_features.py | 114 - haystack/modeling/data_handler/inputs.py | 25 - haystack/modeling/data_handler/processor.py | 2326 --------------- haystack/modeling/data_handler/samples.py | 195 -- haystack/modeling/evaluation/__init__.py | 1 - haystack/modeling/evaluation/eval.py | 221 -- haystack/modeling/evaluation/metrics.py | 486 --- haystack/modeling/evaluation/squad.py | 60 - haystack/modeling/infer.py | 520 ---- haystack/modeling/model/__init__.py | 0 haystack/modeling/model/adaptive_model.py | 830 ------ haystack/modeling/model/biadaptive_model.py | 530 ---- haystack/modeling/model/feature_extraction.py | 399 --- haystack/modeling/model/language_model.py | 974 ------ .../modeling/model/multimodal/__init__.py | 184 -- haystack/modeling/model/multimodal/base.py | 58 - .../model/multimodal/sentence_transformers.py | 92 - haystack/modeling/model/optimization.py | 308 -- haystack/modeling/model/prediction_head.py | 1129 ------- haystack/modeling/model/predictions.py | 335 --- haystack/modeling/model/triadaptive_model.py | 478 --- haystack/modeling/training/__init__.py | 1 - haystack/modeling/training/base.py | 952 ------ haystack/modeling/training/dpr.py | 1 - .../modeling/training/question_answering.py | 1 - haystack/modeling/utils.py | 349 --- haystack/modeling/visual.py | 103 - haystack/nodes/__init__.py | 64 - haystack/nodes/_json_schema.py | 471 --- haystack/nodes/answer_generator/__init__.py | 2 - haystack/nodes/answer_generator/base.py | 226 -- haystack/nodes/answer_generator/openai.py | 338 --- haystack/nodes/asyncio/sleeper.py | 74 - haystack/nodes/audio/__init__.py | 1 - haystack/nodes/audio/whisper_transcriber.py | 217 -- haystack/nodes/base.py | 362 --- haystack/nodes/connector/__init__.py | 1 - haystack/nodes/connector/crawler.py | 500 ---- .../nodes/doc_language_classifier/__init__.py | 2 - .../nodes/doc_language_classifier/base.py | 136 - .../doc_language_classifier/langdetect.py | 100 - .../doc_language_classifier/transformers.py | 182 -- .../nodes/document_classifier/__init__.py | 2 - haystack/nodes/document_classifier/base.py | 96 - .../nodes/document_classifier/transformers.py | 252 -- haystack/nodes/extractor/__init__.py | 1 - haystack/nodes/extractor/entity.py | 880 ------ haystack/nodes/file_classifier/__init__.py | 1 - haystack/nodes/file_classifier/file_type.py | 133 - haystack/nodes/file_converter/__init__.py | 24 - haystack/nodes/file_converter/azure.py | 345 --- haystack/nodes/file_converter/base.py | 241 -- haystack/nodes/file_converter/csv.py | 69 - haystack/nodes/file_converter/docx.py | 81 - haystack/nodes/file_converter/image.py | 170 -- haystack/nodes/file_converter/json.py | 96 - haystack/nodes/file_converter/markdown.py | 137 - haystack/nodes/file_converter/parsr.py | 334 --- haystack/nodes/file_converter/pdf.py | 307 -- haystack/nodes/file_converter/pdf_xpdf.py | 199 -- haystack/nodes/file_converter/pptx.py | 85 - haystack/nodes/file_converter/tika.py | 198 -- haystack/nodes/file_converter/txt.py | 90 - haystack/nodes/image_to_text/__init__.py | 2 - haystack/nodes/image_to_text/base.py | 59 - haystack/nodes/image_to_text/transformers.py | 187 -- haystack/nodes/label_generator/__init__.py | 1 - .../label_generator/pseudo_label_generator.py | 292 -- haystack/nodes/other/__init__.py | 7 - haystack/nodes/other/docs2answers.py | 80 - haystack/nodes/other/document_merger.py | 87 - haystack/nodes/other/join.py | 84 - haystack/nodes/other/join_answers.py | 91 - haystack/nodes/other/join_docs.py | 162 - haystack/nodes/other/route_documents.py | 154 - haystack/nodes/other/shaper.py | 849 ------ haystack/nodes/preprocessor/__init__.py | 2 - haystack/nodes/preprocessor/base.py | 108 - haystack/nodes/preprocessor/preprocessor.py | 944 ------ haystack/nodes/prompt/__init__.py | 4 - .../nodes/prompt/invocation_layer/__init__.py | 14 - .../prompt/invocation_layer/amazon_bedrock.py | 372 --- .../invocation_layer/anthropic_claude.py | 242 -- .../nodes/prompt/invocation_layer/aws_base.py | 79 - .../prompt/invocation_layer/azure_chatgpt.py | 47 - .../prompt/invocation_layer/azure_open_ai.py | 48 - .../nodes/prompt/invocation_layer/base.py | 62 - .../nodes/prompt/invocation_layer/chatgpt.py | 223 -- .../nodes/prompt/invocation_layer/cohere.py | 222 -- .../nodes/prompt/invocation_layer/handlers.py | 100 - .../prompt/invocation_layer/hugging_face.py | 395 --- .../hugging_face_inference.py | 296 -- .../nodes/prompt/invocation_layer/open_ai.py | 278 -- .../prompt/invocation_layer/sagemaker_base.py | 154 - .../invocation_layer/sagemaker_hf_infer.py | 267 -- .../invocation_layer/sagemaker_hf_text_gen.py | 222 -- .../prompt/invocation_layer/sagemaker_meta.py | 330 --- .../nodes/prompt/invocation_layer/utils.py | 20 - haystack/nodes/prompt/prompt_model.py | 167 -- haystack/nodes/prompt/prompt_node.py | 558 ---- haystack/nodes/prompt/prompt_template.py | 596 ---- haystack/nodes/prompt/shapers.py | 65 - haystack/nodes/query_classifier/__init__.py | 2 - haystack/nodes/query_classifier/base.py | 20 - .../nodes/query_classifier/transformers.py | 192 -- haystack/nodes/question_generator/__init__.py | 1 - .../question_generator/question_generator.py | 300 -- haystack/nodes/ranker/__init__.py | 6 - haystack/nodes/ranker/base.py | 171 -- haystack/nodes/ranker/cohere.py | 232 -- haystack/nodes/ranker/diversity.py | 153 - haystack/nodes/ranker/lost_in_the_middle.py | 133 - haystack/nodes/ranker/recentness_ranker.py | 189 -- .../nodes/ranker/sentence_transformers.py | 326 -- haystack/nodes/reader/__init__.py | 4 - haystack/nodes/reader/base.py | 256 -- haystack/nodes/reader/farm.py | 1475 ---------- haystack/nodes/reader/table.py | 947 ------ haystack/nodes/reader/transformers.py | 380 --- haystack/nodes/retriever/__init__.py | 12 - .../retriever/_base_embedding_encoder.py | 102 - .../nodes/retriever/_embedding_encoder.py | 444 --- haystack/nodes/retriever/_losses.py | 12 - haystack/nodes/retriever/_openai_encoder.py | 160 - haystack/nodes/retriever/base.py | 403 --- haystack/nodes/retriever/dense.py | 2331 --------------- haystack/nodes/retriever/link_content.py | 354 --- .../nodes/retriever/multimodal/__init__.py | 2 - .../nodes/retriever/multimodal/embedder.py | 215 -- .../nodes/retriever/multimodal/retriever.py | 222 -- haystack/nodes/retriever/sparse.py | 661 ----- haystack/nodes/retriever/web.py | 327 --- haystack/nodes/sampler/__init__.py | 2 - haystack/nodes/sampler/base.py | 91 - haystack/nodes/sampler/top_p_sampler.py | 166 -- haystack/nodes/search_engine/__init__.py | 2 - haystack/nodes/search_engine/base.py | 31 - haystack/nodes/search_engine/providers.py | 491 ---- haystack/nodes/search_engine/utils.py | 25 - haystack/nodes/search_engine/web.py | 108 - haystack/nodes/summarizer/__init__.py | 2 - haystack/nodes/summarizer/base.py | 52 - haystack/nodes/summarizer/transformers.py | 264 -- haystack/nodes/translator/__init__.py | 2 - haystack/nodes/translator/base.py | 104 - haystack/nodes/translator/transformers.py | 233 -- haystack/pipelines/__init__.py | 17 - haystack/pipelines/base.py | 2614 ----------------- haystack/pipelines/config.py | 519 ---- haystack/pipelines/ray.py | 486 --- haystack/pipelines/standard_pipelines.py | 780 ----- haystack/pipelines/utils.py | 360 --- haystack/schema.py | 1632 ---------- haystack/silenceable_tqdm.py | 40 - haystack/telemetry.py | 223 -- haystack/testing/__init__.py | 1 - haystack/testing/document_store.py | 567 ---- haystack/utils/__init__.py | 27 - haystack/utils/augment_squad.py | 312 -- haystack/utils/batching.py | 12 - haystack/utils/cleaning.py | 27 - haystack/utils/context_matching.py | 225 -- haystack/utils/deepsetcloud.py | 1767 ----------- haystack/utils/doc_store.py | 127 - haystack/utils/docker.py | 50 - haystack/utils/early_stopping.py | 99 - haystack/utils/experiment_tracking.py | 285 -- haystack/utils/export_utils.py | 223 -- haystack/utils/getting_started.py | 84 - haystack/utils/import_utils.py | 119 - haystack/utils/labels.py | 88 - haystack/utils/openai_utils.py | 264 -- haystack/utils/preprocessing.py | 209 -- haystack/utils/reflection.py | 15 - haystack/utils/requests_utils.py | 94 - haystack/utils/scipy_utils.py | 17 - haystack/utils/squad_data.py | 311 -- haystack/utils/squad_to_dpr.py | 356 --- haystack/utils/torch_utils.py | 54 - rest_api/LICENSE | 202 -- rest_api/README.md | 0 rest_api/pyproject.toml | 79 - rest_api/rest_api/__about__.py | 13 - rest_api/rest_api/__init__.py | 0 rest_api/rest_api/application.py | 25 - rest_api/rest_api/config.py | 16 - rest_api/rest_api/controller/__init__.py | 1 - rest_api/rest_api/controller/document.py | 56 - .../rest_api/controller/errors/__init__.py | 0 .../rest_api/controller/errors/http_error.py | 7 - rest_api/rest_api/controller/feedback.py | 199 -- rest_api/rest_api/controller/file_upload.py | 99 - rest_api/rest_api/controller/health.py | 129 - rest_api/rest_api/controller/search.py | 76 - rest_api/rest_api/controller/utils.py | 50 - rest_api/rest_api/pipeline/__init__.py | 76 - .../rest_api/pipeline/custom_component.py | 18 - .../pipeline_empty.haystack-pipeline.yml | 17 - .../pipeline/pipelines.haystack-pipeline.yml | 53 - .../pipelines_dpr.haystack-pipeline.yml | 53 - .../pipelines_faq.haystack-pipeline.yml | 40 - .../pipelines_web_lfqa.haystack-pipeline.yaml | 42 - rest_api/rest_api/schema.py | 60 - rest_api/rest_api/utils.py | 80 - rest_api/test/__init__.py | 0 rest_api/test/samples/pdf/sample_pdf_1.pdf | Bin 44524 -> 0 bytes rest_api/test/samples/pdf/sample_pdf_2.pdf | Bin 26093 -> 0 bytes rest_api/test/samples/test.bogus_pipeline.yml | 17 - .../test.docstore-no-params-pipeline.yml | 15 - .../test/samples/test.haystack-pipeline.yml | 37 - .../test.in-memory-haystack-pipeline.yml | 25 - rest_api/test/test_rest_api.py | 626 ---- test/agents/__init__.py | 0 test/agents/test_agent.py | 435 --- test/agents/test_agent_step.py | 109 - test/agents/test_conversational_agent.py | 105 - test/agents/test_memory.py | 45 - test/agents/test_summary_memory.py | 144 - test/agents/test_tools_manager.py | 218 -- test/benchmarks/README.md | 97 - .../benchmarks/configs/reader/debertabase.yml | 19 - .../configs/reader/debertalarge.yml | 19 - .../benchmarks/configs/reader/tinyroberta.yml | 19 - .../retriever/bm25-elasticsearch-100k.yml | 34 - .../retriever/bm25-opensearch-100k.yml | 34 - .../configs/retriever/bm25-weaviate-100k.yml | 36 - .../retriever/minilm-elasticsearch-100k.yml | 38 - .../retriever/minilm-opensearch-100k.yml | 38 - .../retriever/minilm-weaviate-100k.yml | 39 - .../mpnetbase-elasticsearch-100k.yml | 38 - .../retriever/mpnetbase-opensearch-100k.yml | 38 - .../retriever/mpnetbase-weaviate-100k.yml | 39 - .../bm25-debertabase-opensearch-100k.yml | 43 - .../bm25-debertalarge-opensearch-100k.yml | 43 - .../bm25-tinyroberta-opensearch-100k.yml | 43 - .../minilm-debertabase-opensearch-100k.yml | 46 - .../minilm-debertalarge-opensearch-100k.yml | 46 - .../minilm-tinyroberta-opensearch-100k.yml | 46 - .../mpnetbase-debertabase-opensearch-100k.yml | 46 - ...mpnetbase-debertalarge-opensearch-100k.yml | 46 - .../mpnetbase-tinyroberta-opensearch-100k.yml | 46 - test/benchmarks/datadog/metric_handler.py | 152 - test/benchmarks/datadog/requirements.txt | 1 - test/benchmarks/datadog/send_metrics.py | 165 -- test/benchmarks/distillation_config.json | 25 - test/benchmarks/model_distillation.py | 155 - test/benchmarks/nq_to_squad.py | 296 -- test/benchmarks/reader.py | 70 - test/benchmarks/retriever.py | 151 - test/benchmarks/retriever_reader.py | 107 - test/benchmarks/run.py | 82 - test/benchmarks/templates.py | 55 - test/benchmarks/utils.py | 187 -- test/cli/conftest.py | 7 - test/cli/test_prompt_fetch.py | 60 - test/document_stores/__init__.py | 0 test/document_stores/test_deepsetcloud.py | 422 --- test/document_stores/test_elasticsearch.py | 529 ---- test/document_stores/test_faiss.py | 330 --- test/document_stores/test_memory.py | 122 - test/document_stores/test_opensearch.py | 1301 -------- test/document_stores/test_pinecone.py | 735 ----- test/document_stores/test_search_engine.py | 266 -- test/document_stores/test_sql.py | 179 -- test/document_stores/test_sql_based.py | 274 -- test/document_stores/test_weaviate.py | 466 --- test/mocks/pinecone.py | 373 --- test/modeling/__init__.py | 0 test/modeling/conftest.py | 41 - .../tokenizer_config.json | 3 - test/modeling/test_dataloader.py | 47 - test/modeling/test_feature_extraction.py | 131 - test/modeling/test_model_loading.py | 43 - test/modeling/test_prediction_head.py | 30 - test/modeling/test_processor.py | 344 --- test/modeling/test_processor_save_load.py | 46 - test/modeling/test_question_answering.py | 308 -- test/nodes/__init__.py | 0 test/nodes/conftest.py | 188 -- test/nodes/test_connector.py | 260 -- test/nodes/test_diversity_ranker.py | 267 -- test/nodes/test_doc_language_classifier.py | 121 - test/nodes/test_document_classifier.py | 139 - test/nodes/test_document_merger.py | 108 - test/nodes/test_extractor.py | 235 -- test/nodes/test_file_converter.py | 631 ---- test/nodes/test_filetype_classifier.py | 168 -- test/nodes/test_generator.py | 208 -- test/nodes/test_image_to_text.py | 93 - test/nodes/test_join_answers.py | 31 - test/nodes/test_join_documents.py | 115 - test/nodes/test_label_generator.py | 135 - test/nodes/test_link_content_fetcher.py | 462 --- test/nodes/test_lost_in_the_middle.py | 154 - test/nodes/test_preprocessor.py | 705 ----- test/nodes/test_query_classifier.py | 103 - test/nodes/test_question_generator.py | 150 - test/nodes/test_ranker.py | 784 ----- test/nodes/test_reader.py | 516 ---- test/nodes/test_retriever.py | 1237 -------- test/nodes/test_route_documents.py | 98 - test/nodes/test_sampler.py | 105 - test/nodes/test_shaper.py | 1709 ----------- test/nodes/test_summarizer.py | 85 - test/nodes/test_table_reader.py | 263 -- test/nodes/test_translator.py | 115 - test/nodes/test_web_retriever.py | 267 -- test/nodes/test_web_search.py | 145 - test/nodes/test_whisper.py | 59 - test/others/__init__.py | 0 test/others/test_eval_data_from_json.py | 65 - test/others/test_schema.py | 1126 ------- test/others/test_squad_data.py | 140 - test/others/test_utils.py | 1712 ----------- test/pipelines/__init__.py | 0 test/pipelines/conftest.py | 14 - test/pipelines/test_eval.py | 2185 -------------- test/pipelines/test_eval_batch.py | 1035 ------- test/pipelines/test_pipeline.py | 2131 -------------- .../test_pipeline_debug_and_validation.py | 239 -- test/pipelines/test_pipeline_yaml.py | 1181 -------- test/pipelines/test_ray.py | 97 - test/pipelines/test_standard_pipelines.py | 93 - test/prompt/__init__.py | 0 test/prompt/conftest.py | 41 - test/prompt/invocation_layer/conftest.py | 14 - .../invocation_layer/test_amazon_bedrock.py | 1033 ------- .../invocation_layer/test_anthropic_claude.py | 277 -- test/prompt/invocation_layer/test_chatgpt.py | 76 - test/prompt/invocation_layer/test_cohere.py | 256 -- .../invocation_layer/test_hugging_face.py | 690 ----- .../test_hugging_face_inference.py | 375 --- .../test_invocation_layers.py | 19 - test/prompt/invocation_layer/test_openai.py | 138 - .../test_sagemaker_hf_infer.py | 431 --- .../test_sagemaker_hf_text_gen.py | 277 -- .../invocation_layer/test_sagemaker_meta.py | 470 --- test/prompt/test_handlers.py | 148 - test/prompt/test_prompt_model.py | 60 - test/prompt/test_prompt_node.py | 1204 -------- test/prompt/test_prompt_template.py | 494 ---- test/utils/__init__.py | 0 test/utils/test_deepset_cloud.py | 70 - test/utils/test_mmh3.py | 10 - test/utils/test_openai_utils.py | 148 - test/utils/test_requests.py | 72 - test/utils/test_tqdm.py | 85 - 489 files changed, 109682 deletions(-) delete mode 100644 .github/release.yml delete mode 100644 .github/workflows/benchmarks.yml delete mode 100644 .github/workflows/docker_release.yml delete mode 100644 .github/workflows/e2e.yml delete mode 100644 .github/workflows/examples_tests.yml delete mode 100644 .github/workflows/imports.yml delete mode 100644 .github/workflows/linting.yml delete mode 100644 .github/workflows/linting_skipper.yml delete mode 100644 .github/workflows/openapi_sync.yml delete mode 100644 .github/workflows/pipeline_schema.yml delete mode 100644 .github/workflows/preview_imports.yml delete mode 100644 .github/workflows/pypi_release_preview.yml delete mode 100644 .github/workflows/rest_api_tests.yml delete mode 100644 .github/workflows/tests.yml delete mode 100644 .github/workflows/tests_preview_skipper.yml delete mode 100644 .github/workflows/tests_skipper.yml delete mode 100644 .github/workflows/xpdf_release.yml delete mode 100644 annotation_tool/README.md delete mode 100644 annotation_tool/docker-compose.yml delete mode 100644 conftest.py delete mode 100644 docker-compose.yml delete mode 100644 docs/pydoc/config/agent.yml delete mode 100644 docs/pydoc/config/answer-generator.yml delete mode 100644 docs/pydoc/config/base-converter.yml delete mode 100644 docs/pydoc/config/base-doc-language-classifier.yml delete mode 100644 docs/pydoc/config/base-document-classifier.yml delete mode 100644 docs/pydoc/config/base-document-store.yml delete mode 100644 docs/pydoc/config/base-generator.yml delete mode 100644 docs/pydoc/config/base-image-to-text.yml delete mode 100644 docs/pydoc/config/base-preprocessor.yml delete mode 100644 docs/pydoc/config/base-query-classifier.yml delete mode 100644 docs/pydoc/config/base-ranker.yml delete mode 100644 docs/pydoc/config/base-reader.yml delete mode 100644 docs/pydoc/config/base-retriever.yml delete mode 100644 docs/pydoc/config/base-summarizer.yml delete mode 100644 docs/pydoc/config/base-translator.yml delete mode 100644 docs/pydoc/config/crawler.yml delete mode 100644 docs/pydoc/config/doc-language-classifier.yml delete mode 100644 docs/pydoc/config/document-classifier.yml delete mode 100644 docs/pydoc/config/document-store.yml delete mode 100644 docs/pydoc/config/extractor.yml delete mode 100644 docs/pydoc/config/file-classifier.yml delete mode 100644 docs/pydoc/config/file-converters.yml delete mode 100644 docs/pydoc/config/invocation-layers.yml delete mode 100644 docs/pydoc/config/other.yml delete mode 100644 docs/pydoc/config/pipelines.yml delete mode 100644 docs/pydoc/config/preprocessor.yml delete mode 100644 docs/pydoc/config/primitives.yml delete mode 100644 docs/pydoc/config/prompt-node.yml delete mode 100644 docs/pydoc/config/pseudo-label-generator.yml delete mode 100644 docs/pydoc/config/query-classifier.yml delete mode 100644 docs/pydoc/config/question-generator.yml delete mode 100644 docs/pydoc/config/ranker.yml delete mode 100644 docs/pydoc/config/reader.yml delete mode 100644 docs/pydoc/config/retriever.yml delete mode 100644 docs/pydoc/config/shaper.yml delete mode 100644 docs/pydoc/config/summarizer.yml delete mode 100644 docs/pydoc/config/transformers-img-to-text.yml delete mode 100644 docs/pydoc/config/translator.yml delete mode 100644 docs/pydoc/config/utils.yml delete mode 100644 docs/pydoc/config/whisper.yml delete mode 100644 e2e/document_search/__init__.py delete mode 100644 e2e/document_search/test_standard_pipeline.py delete mode 100644 e2e/document_stores/__init__.py delete mode 100644 e2e/document_stores/test_cosine_similarity.py delete mode 100644 e2e/document_stores/test_similarity_score.py delete mode 100644 e2e/document_stores/test_update_embeddings.py delete mode 100644 e2e/modeling/__init__.py delete mode 100644 e2e/modeling/test_adaptive_qa_inference.py delete mode 100644 e2e/modeling/test_distillation.py delete mode 100644 e2e/modeling/test_dpr.py delete mode 100644 e2e/modeling/test_feature_extraction.py delete mode 100644 e2e/pipelines/__init__.py delete mode 100644 e2e/pipelines/test_extractive_qa.py delete mode 100644 e2e/pipelines/test_pipeline_topologies.py delete mode 100644 e2e/pipelines/test_standard_pipelines.py delete mode 100644 examples/agent_multihop_qa.py delete mode 100644 examples/arxiv_paper_summary.py delete mode 100644 examples/basic_faq_pipeline.py delete mode 100644 examples/basic_qa_pipeline.py delete mode 100644 examples/conversational_agent.py delete mode 100644 examples/getting_started.py delete mode 100644 examples/hybrid_search_faq_pipeline.py delete mode 100644 examples/link_content_blog_post_summary.py delete mode 100644 examples/seq2seq_replacement.py delete mode 100644 examples/talk_to_website.py delete mode 100644 examples/test_basic_faq_pipeline.py delete mode 100644 examples/test_basic_qa_pipeline.py delete mode 100644 examples/test_getting_started.py delete mode 100644 examples/web_lfqa.py delete mode 100644 examples/web_lfqa_with_rankers.py delete mode 100644 examples/web_qa.py delete mode 100644 haystack-linter/LICENSE delete mode 100644 haystack-linter/README.md delete mode 100644 haystack-linter/haystack_linter/__about__.py delete mode 100644 haystack-linter/haystack_linter/__init__.py delete mode 100644 haystack-linter/haystack_linter/linting.py delete mode 100644 haystack-linter/pyproject.toml delete mode 100644 haystack-linter/tests/__init__.py delete mode 100644 haystack/__init__.py delete mode 100644 haystack/agents/__init__.py delete mode 100644 haystack/agents/agent_step.py delete mode 100644 haystack/agents/base.py delete mode 100644 haystack/agents/conversational.py delete mode 100644 haystack/agents/memory/__init__.py delete mode 100644 haystack/agents/memory/base.py delete mode 100644 haystack/agents/memory/conversation_memory.py delete mode 100644 haystack/agents/memory/conversation_summary_memory.py delete mode 100644 haystack/agents/memory/no_memory.py delete mode 100644 haystack/agents/types.py delete mode 100644 haystack/agents/utils.py delete mode 100644 haystack/cli/README.md delete mode 100644 haystack/cli/__init__.py delete mode 100644 haystack/cli/entry_point.py delete mode 100644 haystack/cli/prompt/__init__.py delete mode 100644 haystack/cli/prompt/fetch.py delete mode 100644 haystack/document_stores/__init__.py delete mode 100644 haystack/document_stores/base.py delete mode 100644 haystack/document_stores/deepsetcloud.py delete mode 100644 haystack/document_stores/elasticsearch/__init__.py delete mode 100644 haystack/document_stores/elasticsearch/base.py delete mode 100644 haystack/document_stores/elasticsearch/es7.py delete mode 100644 haystack/document_stores/elasticsearch/es8.py delete mode 100644 haystack/document_stores/es_converter.py delete mode 100644 haystack/document_stores/faiss.py delete mode 100644 haystack/document_stores/filter_utils.py delete mode 100644 haystack/document_stores/memory.py delete mode 100644 haystack/document_stores/opensearch.py delete mode 100644 haystack/document_stores/pinecone.py delete mode 100644 haystack/document_stores/search_engine.py delete mode 100644 haystack/document_stores/sql.py delete mode 100644 haystack/document_stores/utils.py delete mode 100644 haystack/document_stores/weaviate.py delete mode 100644 haystack/environment.py delete mode 100644 haystack/errors.py delete mode 100644 haystack/lazy_imports.py delete mode 100644 haystack/mmh3.py delete mode 100644 haystack/modeling/__init__.py delete mode 100644 haystack/modeling/data_handler/__init__.py delete mode 100644 haystack/modeling/data_handler/data_silo.py delete mode 100644 haystack/modeling/data_handler/dataloader.py delete mode 100644 haystack/modeling/data_handler/dataset.py delete mode 100644 haystack/modeling/data_handler/input_features.py delete mode 100644 haystack/modeling/data_handler/inputs.py delete mode 100644 haystack/modeling/data_handler/processor.py delete mode 100644 haystack/modeling/data_handler/samples.py delete mode 100644 haystack/modeling/evaluation/__init__.py delete mode 100644 haystack/modeling/evaluation/eval.py delete mode 100644 haystack/modeling/evaluation/metrics.py delete mode 100644 haystack/modeling/evaluation/squad.py delete mode 100644 haystack/modeling/infer.py delete mode 100644 haystack/modeling/model/__init__.py delete mode 100644 haystack/modeling/model/adaptive_model.py delete mode 100644 haystack/modeling/model/biadaptive_model.py delete mode 100644 haystack/modeling/model/feature_extraction.py delete mode 100644 haystack/modeling/model/language_model.py delete mode 100644 haystack/modeling/model/multimodal/__init__.py delete mode 100644 haystack/modeling/model/multimodal/base.py delete mode 100644 haystack/modeling/model/multimodal/sentence_transformers.py delete mode 100644 haystack/modeling/model/optimization.py delete mode 100644 haystack/modeling/model/prediction_head.py delete mode 100644 haystack/modeling/model/predictions.py delete mode 100644 haystack/modeling/model/triadaptive_model.py delete mode 100644 haystack/modeling/training/__init__.py delete mode 100644 haystack/modeling/training/base.py delete mode 100644 haystack/modeling/training/dpr.py delete mode 100644 haystack/modeling/training/question_answering.py delete mode 100644 haystack/modeling/utils.py delete mode 100644 haystack/modeling/visual.py delete mode 100644 haystack/nodes/__init__.py delete mode 100644 haystack/nodes/_json_schema.py delete mode 100644 haystack/nodes/answer_generator/__init__.py delete mode 100644 haystack/nodes/answer_generator/base.py delete mode 100644 haystack/nodes/answer_generator/openai.py delete mode 100644 haystack/nodes/asyncio/sleeper.py delete mode 100644 haystack/nodes/audio/__init__.py delete mode 100644 haystack/nodes/audio/whisper_transcriber.py delete mode 100644 haystack/nodes/base.py delete mode 100644 haystack/nodes/connector/__init__.py delete mode 100644 haystack/nodes/connector/crawler.py delete mode 100644 haystack/nodes/doc_language_classifier/__init__.py delete mode 100644 haystack/nodes/doc_language_classifier/base.py delete mode 100644 haystack/nodes/doc_language_classifier/langdetect.py delete mode 100644 haystack/nodes/doc_language_classifier/transformers.py delete mode 100644 haystack/nodes/document_classifier/__init__.py delete mode 100644 haystack/nodes/document_classifier/base.py delete mode 100644 haystack/nodes/document_classifier/transformers.py delete mode 100644 haystack/nodes/extractor/__init__.py delete mode 100644 haystack/nodes/extractor/entity.py delete mode 100644 haystack/nodes/file_classifier/__init__.py delete mode 100644 haystack/nodes/file_classifier/file_type.py delete mode 100644 haystack/nodes/file_converter/__init__.py delete mode 100644 haystack/nodes/file_converter/azure.py delete mode 100644 haystack/nodes/file_converter/base.py delete mode 100644 haystack/nodes/file_converter/csv.py delete mode 100644 haystack/nodes/file_converter/docx.py delete mode 100644 haystack/nodes/file_converter/image.py delete mode 100644 haystack/nodes/file_converter/json.py delete mode 100644 haystack/nodes/file_converter/markdown.py delete mode 100644 haystack/nodes/file_converter/parsr.py delete mode 100644 haystack/nodes/file_converter/pdf.py delete mode 100644 haystack/nodes/file_converter/pdf_xpdf.py delete mode 100644 haystack/nodes/file_converter/pptx.py delete mode 100644 haystack/nodes/file_converter/tika.py delete mode 100644 haystack/nodes/file_converter/txt.py delete mode 100644 haystack/nodes/image_to_text/__init__.py delete mode 100644 haystack/nodes/image_to_text/base.py delete mode 100644 haystack/nodes/image_to_text/transformers.py delete mode 100644 haystack/nodes/label_generator/__init__.py delete mode 100644 haystack/nodes/label_generator/pseudo_label_generator.py delete mode 100644 haystack/nodes/other/__init__.py delete mode 100644 haystack/nodes/other/docs2answers.py delete mode 100644 haystack/nodes/other/document_merger.py delete mode 100644 haystack/nodes/other/join.py delete mode 100644 haystack/nodes/other/join_answers.py delete mode 100644 haystack/nodes/other/join_docs.py delete mode 100644 haystack/nodes/other/route_documents.py delete mode 100644 haystack/nodes/other/shaper.py delete mode 100644 haystack/nodes/preprocessor/__init__.py delete mode 100644 haystack/nodes/preprocessor/base.py delete mode 100644 haystack/nodes/preprocessor/preprocessor.py delete mode 100644 haystack/nodes/prompt/__init__.py delete mode 100644 haystack/nodes/prompt/invocation_layer/__init__.py delete mode 100644 haystack/nodes/prompt/invocation_layer/amazon_bedrock.py delete mode 100644 haystack/nodes/prompt/invocation_layer/anthropic_claude.py delete mode 100644 haystack/nodes/prompt/invocation_layer/aws_base.py delete mode 100644 haystack/nodes/prompt/invocation_layer/azure_chatgpt.py delete mode 100644 haystack/nodes/prompt/invocation_layer/azure_open_ai.py delete mode 100644 haystack/nodes/prompt/invocation_layer/base.py delete mode 100644 haystack/nodes/prompt/invocation_layer/chatgpt.py delete mode 100644 haystack/nodes/prompt/invocation_layer/cohere.py delete mode 100644 haystack/nodes/prompt/invocation_layer/handlers.py delete mode 100644 haystack/nodes/prompt/invocation_layer/hugging_face.py delete mode 100644 haystack/nodes/prompt/invocation_layer/hugging_face_inference.py delete mode 100644 haystack/nodes/prompt/invocation_layer/open_ai.py delete mode 100644 haystack/nodes/prompt/invocation_layer/sagemaker_base.py delete mode 100644 haystack/nodes/prompt/invocation_layer/sagemaker_hf_infer.py delete mode 100644 haystack/nodes/prompt/invocation_layer/sagemaker_hf_text_gen.py delete mode 100644 haystack/nodes/prompt/invocation_layer/sagemaker_meta.py delete mode 100644 haystack/nodes/prompt/invocation_layer/utils.py delete mode 100644 haystack/nodes/prompt/prompt_model.py delete mode 100644 haystack/nodes/prompt/prompt_node.py delete mode 100644 haystack/nodes/prompt/prompt_template.py delete mode 100644 haystack/nodes/prompt/shapers.py delete mode 100644 haystack/nodes/query_classifier/__init__.py delete mode 100644 haystack/nodes/query_classifier/base.py delete mode 100644 haystack/nodes/query_classifier/transformers.py delete mode 100644 haystack/nodes/question_generator/__init__.py delete mode 100644 haystack/nodes/question_generator/question_generator.py delete mode 100644 haystack/nodes/ranker/__init__.py delete mode 100644 haystack/nodes/ranker/base.py delete mode 100644 haystack/nodes/ranker/cohere.py delete mode 100644 haystack/nodes/ranker/diversity.py delete mode 100644 haystack/nodes/ranker/lost_in_the_middle.py delete mode 100644 haystack/nodes/ranker/recentness_ranker.py delete mode 100644 haystack/nodes/ranker/sentence_transformers.py delete mode 100644 haystack/nodes/reader/__init__.py delete mode 100644 haystack/nodes/reader/base.py delete mode 100644 haystack/nodes/reader/farm.py delete mode 100644 haystack/nodes/reader/table.py delete mode 100644 haystack/nodes/reader/transformers.py delete mode 100644 haystack/nodes/retriever/__init__.py delete mode 100644 haystack/nodes/retriever/_base_embedding_encoder.py delete mode 100644 haystack/nodes/retriever/_embedding_encoder.py delete mode 100644 haystack/nodes/retriever/_losses.py delete mode 100644 haystack/nodes/retriever/_openai_encoder.py delete mode 100644 haystack/nodes/retriever/base.py delete mode 100644 haystack/nodes/retriever/dense.py delete mode 100644 haystack/nodes/retriever/link_content.py delete mode 100644 haystack/nodes/retriever/multimodal/__init__.py delete mode 100644 haystack/nodes/retriever/multimodal/embedder.py delete mode 100644 haystack/nodes/retriever/multimodal/retriever.py delete mode 100644 haystack/nodes/retriever/sparse.py delete mode 100644 haystack/nodes/retriever/web.py delete mode 100644 haystack/nodes/sampler/__init__.py delete mode 100644 haystack/nodes/sampler/base.py delete mode 100644 haystack/nodes/sampler/top_p_sampler.py delete mode 100644 haystack/nodes/search_engine/__init__.py delete mode 100644 haystack/nodes/search_engine/base.py delete mode 100644 haystack/nodes/search_engine/providers.py delete mode 100644 haystack/nodes/search_engine/utils.py delete mode 100644 haystack/nodes/search_engine/web.py delete mode 100644 haystack/nodes/summarizer/__init__.py delete mode 100644 haystack/nodes/summarizer/base.py delete mode 100644 haystack/nodes/summarizer/transformers.py delete mode 100644 haystack/nodes/translator/__init__.py delete mode 100644 haystack/nodes/translator/base.py delete mode 100644 haystack/nodes/translator/transformers.py delete mode 100644 haystack/pipelines/__init__.py delete mode 100644 haystack/pipelines/base.py delete mode 100644 haystack/pipelines/config.py delete mode 100644 haystack/pipelines/ray.py delete mode 100644 haystack/pipelines/standard_pipelines.py delete mode 100644 haystack/pipelines/utils.py delete mode 100644 haystack/schema.py delete mode 100644 haystack/silenceable_tqdm.py delete mode 100644 haystack/telemetry.py delete mode 100644 haystack/testing/__init__.py delete mode 100644 haystack/testing/document_store.py delete mode 100644 haystack/utils/__init__.py delete mode 100644 haystack/utils/augment_squad.py delete mode 100644 haystack/utils/batching.py delete mode 100644 haystack/utils/cleaning.py delete mode 100644 haystack/utils/context_matching.py delete mode 100644 haystack/utils/deepsetcloud.py delete mode 100644 haystack/utils/doc_store.py delete mode 100644 haystack/utils/docker.py delete mode 100644 haystack/utils/early_stopping.py delete mode 100644 haystack/utils/experiment_tracking.py delete mode 100644 haystack/utils/export_utils.py delete mode 100644 haystack/utils/getting_started.py delete mode 100644 haystack/utils/import_utils.py delete mode 100644 haystack/utils/labels.py delete mode 100644 haystack/utils/openai_utils.py delete mode 100644 haystack/utils/preprocessing.py delete mode 100644 haystack/utils/reflection.py delete mode 100644 haystack/utils/requests_utils.py delete mode 100644 haystack/utils/scipy_utils.py delete mode 100644 haystack/utils/squad_data.py delete mode 100644 haystack/utils/squad_to_dpr.py delete mode 100644 haystack/utils/torch_utils.py delete mode 100644 rest_api/LICENSE delete mode 100644 rest_api/README.md delete mode 100644 rest_api/pyproject.toml delete mode 100644 rest_api/rest_api/__about__.py delete mode 100644 rest_api/rest_api/__init__.py delete mode 100644 rest_api/rest_api/application.py delete mode 100644 rest_api/rest_api/config.py delete mode 100644 rest_api/rest_api/controller/__init__.py delete mode 100644 rest_api/rest_api/controller/document.py delete mode 100644 rest_api/rest_api/controller/errors/__init__.py delete mode 100644 rest_api/rest_api/controller/errors/http_error.py delete mode 100644 rest_api/rest_api/controller/feedback.py delete mode 100644 rest_api/rest_api/controller/file_upload.py delete mode 100644 rest_api/rest_api/controller/health.py delete mode 100644 rest_api/rest_api/controller/search.py delete mode 100644 rest_api/rest_api/controller/utils.py delete mode 100644 rest_api/rest_api/pipeline/__init__.py delete mode 100644 rest_api/rest_api/pipeline/custom_component.py delete mode 100644 rest_api/rest_api/pipeline/pipeline_empty.haystack-pipeline.yml delete mode 100644 rest_api/rest_api/pipeline/pipelines.haystack-pipeline.yml delete mode 100644 rest_api/rest_api/pipeline/pipelines_dpr.haystack-pipeline.yml delete mode 100644 rest_api/rest_api/pipeline/pipelines_faq.haystack-pipeline.yml delete mode 100644 rest_api/rest_api/pipeline/pipelines_web_lfqa.haystack-pipeline.yaml delete mode 100644 rest_api/rest_api/schema.py delete mode 100644 rest_api/rest_api/utils.py delete mode 100644 rest_api/test/__init__.py delete mode 100644 rest_api/test/samples/pdf/sample_pdf_1.pdf delete mode 100644 rest_api/test/samples/pdf/sample_pdf_2.pdf delete mode 100644 rest_api/test/samples/test.bogus_pipeline.yml delete mode 100644 rest_api/test/samples/test.docstore-no-params-pipeline.yml delete mode 100644 rest_api/test/samples/test.haystack-pipeline.yml delete mode 100644 rest_api/test/samples/test.in-memory-haystack-pipeline.yml delete mode 100644 rest_api/test/test_rest_api.py delete mode 100644 test/agents/__init__.py delete mode 100644 test/agents/test_agent.py delete mode 100644 test/agents/test_agent_step.py delete mode 100644 test/agents/test_conversational_agent.py delete mode 100644 test/agents/test_memory.py delete mode 100644 test/agents/test_summary_memory.py delete mode 100644 test/agents/test_tools_manager.py delete mode 100644 test/benchmarks/README.md delete mode 100644 test/benchmarks/configs/reader/debertabase.yml delete mode 100644 test/benchmarks/configs/reader/debertalarge.yml delete mode 100644 test/benchmarks/configs/reader/tinyroberta.yml delete mode 100644 test/benchmarks/configs/retriever/bm25-elasticsearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever/bm25-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever/bm25-weaviate-100k.yml delete mode 100644 test/benchmarks/configs/retriever/minilm-elasticsearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever/minilm-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever/minilm-weaviate-100k.yml delete mode 100644 test/benchmarks/configs/retriever/mpnetbase-elasticsearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever/mpnetbase-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever/mpnetbase-weaviate-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/bm25-debertabase-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/bm25-debertalarge-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/bm25-tinyroberta-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/minilm-debertabase-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/minilm-debertalarge-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/minilm-tinyroberta-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/mpnetbase-debertabase-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/mpnetbase-debertalarge-opensearch-100k.yml delete mode 100644 test/benchmarks/configs/retriever_reader/mpnetbase-tinyroberta-opensearch-100k.yml delete mode 100644 test/benchmarks/datadog/metric_handler.py delete mode 100644 test/benchmarks/datadog/requirements.txt delete mode 100644 test/benchmarks/datadog/send_metrics.py delete mode 100644 test/benchmarks/distillation_config.json delete mode 100644 test/benchmarks/model_distillation.py delete mode 100644 test/benchmarks/nq_to_squad.py delete mode 100644 test/benchmarks/reader.py delete mode 100644 test/benchmarks/retriever.py delete mode 100644 test/benchmarks/retriever_reader.py delete mode 100644 test/benchmarks/run.py delete mode 100644 test/benchmarks/templates.py delete mode 100644 test/benchmarks/utils.py delete mode 100644 test/cli/conftest.py delete mode 100644 test/cli/test_prompt_fetch.py delete mode 100644 test/document_stores/__init__.py delete mode 100644 test/document_stores/test_deepsetcloud.py delete mode 100644 test/document_stores/test_elasticsearch.py delete mode 100644 test/document_stores/test_faiss.py delete mode 100644 test/document_stores/test_memory.py delete mode 100644 test/document_stores/test_opensearch.py delete mode 100644 test/document_stores/test_pinecone.py delete mode 100644 test/document_stores/test_search_engine.py delete mode 100644 test/document_stores/test_sql.py delete mode 100644 test/document_stores/test_sql_based.py delete mode 100644 test/document_stores/test_weaviate.py delete mode 100644 test/mocks/pinecone.py delete mode 100644 test/modeling/__init__.py delete mode 100644 test/modeling/conftest.py delete mode 100644 test/modeling/samples/test_get_tokenizer_from_path/tokenizer_config.json delete mode 100644 test/modeling/test_dataloader.py delete mode 100644 test/modeling/test_feature_extraction.py delete mode 100644 test/modeling/test_model_loading.py delete mode 100644 test/modeling/test_prediction_head.py delete mode 100644 test/modeling/test_processor.py delete mode 100644 test/modeling/test_processor_save_load.py delete mode 100644 test/modeling/test_question_answering.py delete mode 100644 test/nodes/__init__.py delete mode 100644 test/nodes/conftest.py delete mode 100644 test/nodes/test_connector.py delete mode 100644 test/nodes/test_diversity_ranker.py delete mode 100644 test/nodes/test_doc_language_classifier.py delete mode 100644 test/nodes/test_document_classifier.py delete mode 100644 test/nodes/test_document_merger.py delete mode 100644 test/nodes/test_extractor.py delete mode 100644 test/nodes/test_file_converter.py delete mode 100644 test/nodes/test_filetype_classifier.py delete mode 100644 test/nodes/test_generator.py delete mode 100644 test/nodes/test_image_to_text.py delete mode 100644 test/nodes/test_join_answers.py delete mode 100644 test/nodes/test_join_documents.py delete mode 100644 test/nodes/test_label_generator.py delete mode 100644 test/nodes/test_link_content_fetcher.py delete mode 100644 test/nodes/test_lost_in_the_middle.py delete mode 100644 test/nodes/test_preprocessor.py delete mode 100644 test/nodes/test_query_classifier.py delete mode 100644 test/nodes/test_question_generator.py delete mode 100644 test/nodes/test_ranker.py delete mode 100644 test/nodes/test_reader.py delete mode 100644 test/nodes/test_retriever.py delete mode 100644 test/nodes/test_route_documents.py delete mode 100644 test/nodes/test_sampler.py delete mode 100644 test/nodes/test_shaper.py delete mode 100644 test/nodes/test_summarizer.py delete mode 100644 test/nodes/test_table_reader.py delete mode 100644 test/nodes/test_translator.py delete mode 100644 test/nodes/test_web_retriever.py delete mode 100644 test/nodes/test_web_search.py delete mode 100644 test/nodes/test_whisper.py delete mode 100644 test/others/__init__.py delete mode 100644 test/others/test_eval_data_from_json.py delete mode 100644 test/others/test_schema.py delete mode 100644 test/others/test_squad_data.py delete mode 100644 test/others/test_utils.py delete mode 100644 test/pipelines/__init__.py delete mode 100644 test/pipelines/conftest.py delete mode 100644 test/pipelines/test_eval.py delete mode 100644 test/pipelines/test_eval_batch.py delete mode 100644 test/pipelines/test_pipeline.py delete mode 100644 test/pipelines/test_pipeline_debug_and_validation.py delete mode 100644 test/pipelines/test_pipeline_yaml.py delete mode 100644 test/pipelines/test_ray.py delete mode 100644 test/pipelines/test_standard_pipelines.py delete mode 100644 test/prompt/__init__.py delete mode 100644 test/prompt/conftest.py delete mode 100644 test/prompt/invocation_layer/conftest.py delete mode 100644 test/prompt/invocation_layer/test_amazon_bedrock.py delete mode 100644 test/prompt/invocation_layer/test_anthropic_claude.py delete mode 100644 test/prompt/invocation_layer/test_chatgpt.py delete mode 100644 test/prompt/invocation_layer/test_cohere.py delete mode 100644 test/prompt/invocation_layer/test_hugging_face.py delete mode 100644 test/prompt/invocation_layer/test_hugging_face_inference.py delete mode 100644 test/prompt/invocation_layer/test_invocation_layers.py delete mode 100644 test/prompt/invocation_layer/test_openai.py delete mode 100644 test/prompt/invocation_layer/test_sagemaker_hf_infer.py delete mode 100644 test/prompt/invocation_layer/test_sagemaker_hf_text_gen.py delete mode 100644 test/prompt/invocation_layer/test_sagemaker_meta.py delete mode 100644 test/prompt/test_handlers.py delete mode 100644 test/prompt/test_prompt_model.py delete mode 100644 test/prompt/test_prompt_node.py delete mode 100644 test/prompt/test_prompt_template.py delete mode 100644 test/utils/__init__.py delete mode 100644 test/utils/test_deepset_cloud.py delete mode 100644 test/utils/test_mmh3.py delete mode 100644 test/utils/test_openai_utils.py delete mode 100644 test/utils/test_requests.py delete mode 100644 test/utils/test_tqdm.py diff --git a/.github/release.yml b/.github/release.yml deleted file mode 100644 index 14070bf398..0000000000 --- a/.github/release.yml +++ /dev/null @@ -1,50 +0,0 @@ -changelog: - exclude: - labels: - - ignore-for-release-notes - - Proposal - categories: - - title: Breaking Changes - labels: - - breaking change - - title: Pipeline - labels: - - topic:pipeline - - topic:DPR - - topic:reader - - topic:retriever - - topic:tableQA - - topic:file_converter - - topic:preprocessing - - topic:crawler - - topic:images - - topic:audio - - topic:eval - - topic:other_nodes - - title: Models - labels: - - topic:models - - title: DocumentStores - labels: - - topic:document_store - - topic:elasticsearch - - topic:faiss - - topic:weaviate - - topic:pinecone - - topic:sql - - topic:knowledge_graph - - title: REST API - labels: - - topic:api - - title: UI / Demo - labels: - - topic:ui - - title: Documentation - labels: - - type:documentation - - title: Tutorials - labels: - - topic:tutorials - - title: Other Changes - labels: - - "*" diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml deleted file mode 100644 index 4c310118d3..0000000000 --- a/.github/workflows/benchmarks.yml +++ /dev/null @@ -1,251 +0,0 @@ -name: Benchmarks - -on: - workflow_dispatch: - schedule: - # At 00:01 on Sunday - - cron: "1 0 * * 0" - -permissions: - id-token: write - contents: read - -env: - AWS_REGION: eu-central-1 - -jobs: - deploy-runner: - runs-on: ubuntu-latest - outputs: - cml_runner_id: ${{ steps.deploy.outputs.cml_runner_id }} - steps: - - uses: actions/checkout@v4 - - - uses: iterative/setup-cml@v2 - - - name: AWS authentication - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a - with: - aws-region: ${{ env.AWS_REGION }} - role-to-assume: ${{ secrets.AWS_CI_ROLE_ARN }} - - - name: Launch EC2 instance and deploy runner - id: deploy - env: - repo_token: ${{ secrets.HAYSTACK_BOT_TOKEN }} - run: | - OUTPUT=$(cml runner launch \ - --cloud aws \ - --cloud-region ${{ env.AWS_REGION }} \ - --cloud-type=p3.2xlarge \ - --cloud-hdd-size=64 \ - --labels=cml 2>&1 | tee /dev/fd/2) - # Extract 'id' from the log and set it as an environment variable - ID_VALUE=$(echo "$OUTPUT" | jq -r '.message? | fromjson? | select(.id != null) | .id // empty') - echo "cml_runner_id=$ID_VALUE" >> "$GITHUB_OUTPUT" - - run-reader-benchmarks: - needs: deploy-runner - runs-on: [self-hosted, cml] - container: - image: docker://iterativeai/cml:0-dvc2-base1-gpu - options: --gpus all - timeout-minutes: 2880 - - steps: - - uses: actions/checkout@v4 - - - name: Install Haystack + Datadog requirements - run: | - pip install .[metrics,benchmarks,inference] - pip install -r test/benchmarks/datadog/requirements.txt - - - name: Run benchmarks - working-directory: test/benchmarks - run: | - mkdir +p out - for f in ./configs/reader/*.yml; do - name="${f%.*}" - echo "=== Running benchmarks for $name ==="; - config_name="$(basename "$name")" - python run.py --output "out/$config_name.json" "$f"; - echo "=== Benchmarks done for $name (or failed) ==="; - done - - - name: Send Benchmark results to Datadog - working-directory: test/benchmarks - run: | - python datadog/send_metrics.py out/ ${{ secrets.CORE_DATADOG_API_KEY }} https://api.datadoghq.eu - - - name: Archive benchmark results - uses: actions/upload-artifact@v3 - with: - name: benchmark-results-reader - path: test/benchmarks/out/ - - run-elasticsearch-benchmarks: - needs: - - deploy-runner - - run-reader-benchmarks - runs-on: [self-hosted, cml] - container: - image: docker://iterativeai/cml:0-dvc2-base1-gpu - options: --gpus all - services: - elasticsearch: - image: elasticsearch:7.17.6 - env: - discovery.type: "single-node" - ports: - - 9201:9200 - timeout-minutes: 2880 - - steps: - - uses: actions/checkout@v4 - - - name: Install Haystack + Datadog requirements - run: | - pip install .[metrics,elasticsearch,benchmarks,inference] - pip install -r test/benchmarks/datadog/requirements.txt - - - name: Run benchmarks - working-directory: test/benchmarks - run: | - mkdir +p out - for f in ./configs/**/*-elasticsearch-*.yml; do - name="${f%.*}" - echo "=== Running benchmarks for $name ==="; - config_name="$(basename "$name")" - python run.py --output "out/$config_name.json" "$f"; - echo "=== Benchmarks done for $name (or failed) ==="; - done - - - name: Send Benchmark results to Datadog - working-directory: test/benchmarks - run: | - python datadog/send_metrics.py out/ ${{ secrets.CORE_DATADOG_API_KEY }} https://api.datadoghq.eu - - - name: Archive benchmark results - uses: actions/upload-artifact@v3 - with: - name: benchmark-results-elasticsearch - path: test/benchmarks/out/ - - run-weaviate-benchmarks: - needs: - - deploy-runner - - run-elasticsearch-benchmarks - runs-on: [self-hosted, cml] - container: - image: docker://iterativeai/cml:0-dvc2-base1-gpu - options: --gpus all - services: - weaviate: - image: semitechnologies/weaviate:1.17.2 - env: - AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "true" - PERSISTENCE_DATA_PATH: "/var/lib/weaviate" - ports: - - 8080:8080 - timeout-minutes: 2880 - - steps: - - uses: actions/checkout@v4 - - - name: Install Haystack + Datadog requirements - run: | - pip install .[metrics,weaviate,benchmarks,inference] - pip install -r test/benchmarks/datadog/requirements.txt - - - name: Run benchmarks - working-directory: test/benchmarks - run: | - mkdir +p out - for f in ./configs/**/*-weaviate-*.yml; do - name="${f%.*}" - echo "=== Running benchmarks for $name ==="; - config_name="$(basename "$name")" - python run.py --output "out/$config_name.json" "$f"; - echo "=== Benchmarks done for $name (or failed) ==="; - done - - - name: Send Benchmark results to Datadog - working-directory: test/benchmarks - run: | - python datadog/send_metrics.py out/ ${{ secrets.CORE_DATADOG_API_KEY }} https://api.datadoghq.eu - - - name: Archive benchmark results - uses: actions/upload-artifact@v3 - with: - name: benchmark-results-weaviate - path: test/benchmarks/out/ - - run-opensearch-benchmarks: - needs: - - deploy-runner - - run-weaviate-benchmarks - runs-on: [self-hosted, cml] - container: - image: docker://iterativeai/cml:0-dvc2-base1-gpu - options: --gpus all - services: - opensearch: - image: opensearchproject/opensearch:1.3.5 - env: - discovery.type: "single-node" - OPENSEARCH_JAVA_OPTS: "-Xms4096m -Xmx4096m" - ports: - - 9200:9200 - timeout-minutes: 2880 - - steps: - - uses: actions/checkout@v4 - - - name: Install Haystack + Datadog requirements - run: | - pip install .[metrics,opensearch,benchmarks,inference] - pip install -r test/benchmarks/datadog/requirements.txt - - - name: Run benchmarks - working-directory: test/benchmarks - run: | - mkdir +p out - for f in ./configs/**/*-opensearch-*.yml; do - name="${f%.*}" - echo "=== Running benchmarks for $name ==="; - config_name="$(basename "$name")" - python run.py --output "out/$config_name.json" "$f"; - echo "=== Benchmarks done for $name (or failed) ==="; - done - - - name: Send Benchmark results to Datadog - working-directory: test/benchmarks - run: | - python datadog/send_metrics.py out/ ${{ secrets.CORE_DATADOG_API_KEY }} https://api.datadoghq.eu - - - name: Archive benchmark results - uses: actions/upload-artifact@v3 - with: - name: benchmark-results-opensearch - path: test/benchmarks/out/ - - terminate-runner: - if: always() - needs: - - deploy-runner - - run-opensearch-benchmarks - runs-on: ubuntu-latest - steps: - - name: AWS authentication - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a - with: - aws-region: ${{ env.AWS_REGION }} - role-to-assume: ${{ secrets.AWS_CI_ROLE_ARN }} - - - name: Terminate EC2 instance - env: - CML_RUNNER_ID: ${{needs.deploy-runner.outputs.cml_runner_id}} - run: | - # Get the instance ID using its Name tag and terminate the instance - INSTANCE_ID=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=${{ env.CML_RUNNER_ID }}" --query "Reservations[*].Instances[*].[InstanceId]" --output text) - aws ec2 terminate-instances --instance-ids "$INSTANCE_ID" diff --git a/.github/workflows/docker_release.yml b/.github/workflows/docker_release.yml deleted file mode 100644 index b9f2e8f60c..0000000000 --- a/.github/workflows/docker_release.yml +++ /dev/null @@ -1,176 +0,0 @@ -name: Docker image release - -on: - workflow_dispatch: - push: - branches: - - main - tags: - - "v[0-9].[0-9]+.[0-9]+*" - -env: - DOCKER_REPO_NAME: deepset/haystack - -jobs: - build-and-push: - name: Build ${{ matrix.target }} images - runs-on: ubuntu-latest-4-cores - strategy: - matrix: - target: - - "cpu" - - "cpu-remote-inference" - - "gpu" - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: $DOCKER_REPO_NAME - - - name: Build base images - uses: docker/bake-action@v4 - env: - IMAGE_TAG_SUFFIX: ${{ steps.meta.outputs.version }} - HAYSTACK_VERSION: ${{ steps.meta.outputs.version }} - with: - workdir: docker - targets: base-${{ matrix.target }} - push: true - - - name: Test base image - run: | - EXPECTED_VERSION=$(cat VERSION.txt) - if [[ $EXPECTED_VERSION == *"-"* ]]; then - EXPECTED_VERSION=$(cut -d '-' -f 1 < VERSION.txt)$(cut -d '-' -f 2 < VERSION.txt) - fi - TAG="base-${{ matrix.target }}-${{ steps.meta.outputs.version }}" - - PLATFORM="linux/amd64" - VERSION=$(docker run --platform "$PLATFORM" --rm "deepset/haystack:$TAG" python -c"import haystack; print(haystack.__version__)") - [[ "$VERSION" = "$EXPECTED_VERSION" ]] || echo "::error 'Haystack version in deepset/haystack:$TAG image for $PLATFORM is different from expected'" - - PLATFORM="linux/arm64" - VERSION=$(docker run --platform "$PLATFORM" --rm "deepset/haystack:$TAG" python -c"import haystack; print(haystack.__version__)") - [[ "$VERSION" = "$EXPECTED_VERSION" ]] || echo "::error 'Haystack version in deepset/haystack:$TAG image for $PLATFORM is different from expected'" - - # Remove image after test to avoid filling the GitHub runner and prevent its failure - docker rmi "deepset/haystack:$TAG" - - - name: Test non-inference image - if: contains(matrix.target, 'inference') != true - run: | - TAG="base-${{ matrix.target }}-${{ steps.meta.outputs.version }}" - - # docker commands below always output a non-empty string, otherwise the step will exit abnormally - PLATFORM="linux/amd64" - TORCH_INSTALLED=$(docker run --platform "$PLATFORM" --rm "deepset/haystack:$TAG" pip list | grep torch || echo 'not found') - [[ "$TORCH_INSTALLED" != "not found" ]] || echo "::error::Pytorch is not installed in deepset/haystack:$TAG image for $PLATFORM" - - PLATFORM="linux/arm64" - TORCH_INSTALLED=$(docker run --platform "$PLATFORM" --rm "deepset/haystack:$TAG" pip list | grep torch || echo 'not found') - [[ "$TORCH_INSTALLED" != "not found" ]] || echo "::error::Pytorch is not installed in deepset/haystack:$TAG image for $PLATFORM" - - - name: Test inference image - if: contains(matrix.target, 'inference') - run: | - TAG="base-${{ matrix.target }}-${{ steps.meta.outputs.version }}" - - # docker commands below always output a non-empty string, otherwise the step will exit abnormally - PLATFORM="linux/amd64" - TORCH_INSTALLED=$(docker run --platform "$PLATFORM" --rm "deepset/haystack:$TAG" sh -c "pip list | grep torch || echo 'not found'") - [[ "$TORCH_INSTALLED" == "not found" ]] || echo "::error::Pytorch is installed in deepset/haystack:$TAG image for $PLATFORM" - - PLATFORM="linux/arm64" - TORCH_INSTALLED=$(docker run --platform "$PLATFORM" --rm "deepset/haystack:$TAG" sh -c "pip list | grep torch || echo 'not found'") - [[ "$TORCH_INSTALLED" == "not found" ]] || echo "::error::Pytorch is installed in deepset/haystack:$TAG image for $PLATFORM" - - - name: Build api images - uses: docker/bake-action@v4 - env: - IMAGE_TAG_SUFFIX: ${{ steps.meta.outputs.version }} - BASE_IMAGE_TAG_SUFFIX: ${{ steps.meta.outputs.version }} - with: - workdir: docker - targets: ${{ matrix.target }} - push: true - - - name: Test inference API invocation - if: contains(matrix.target, 'inference') - env: - SERPERDEV_API_KEY: ${{ secrets.SERPERDEV_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - run: | - TAG="${{ matrix.target }}-${{ steps.meta.outputs.version }}" - - PLATFORMS=("linux/amd64" "linux/arm64") - for PLATFORM in "${PLATFORMS[@]}"; do - docker run --name test-container -d \ - --platform "$PLATFORM" \ - -e PIPELINE_YAML_PATH=/opt/venv/lib/python3.10/site-packages/rest_api/pipeline/pipelines_web_lfqa.haystack-pipeline.yaml \ - -e "RETRIEVER_PARAMS_API_KEY=$SERPERDEV_API_KEY" \ - -e "PROMPTNODE_PARAMS_API_KEY=$OPENAI_API_KEY" \ - -p 8080:8000 "deepset/haystack:$TAG" - - I=0 - until docker logs test-container 2>&1 | grep "Uvicorn running"; do - echo "Waiting" - sleep 2 - ((I++)) && ((I==100)) && echo "::error 'Timeout waiting for Uvicorn to start using deepset/haystack:$TAG image for $PLATFORM'" - done - - RESULT=$(curl -s -X POST -H "Content-Type: application/json" -d "{\"query\": \"Where in Europe, should I live?\"}" http://localhost:8080/query) - [[ -n "$RESULT" ]] || echo "::error 'No response from inference API using deepset/haystack:$TAG image for $PLATFORM'" - - docker rm -f test-container - done - - - name: Get latest version of Haystack - id: latest-version - if: startsWith(github.ref, 'refs/tags/') - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - VERSION=$(gh api repos/${{ github.repository }}/releases/latest --jq ".tag_name") - echo "release=$VERSION" >> "$GITHUB_OUTPUT" - - - name: Compare current version with latest - uses: madhead/semver-utils@latest - id: version - if: startsWith(github.ref, 'refs/tags/') - with: - # Version being built - version: ${{ github.ref_name }} - # Compare to latest - compare-to: ${{ steps.latest-version.outputs.release }} - - # This step should only run when we release a new minor, so - # that we can tag the most recent image without the version number. - # For example, if the previous step builds `deepset/haystack:cpu-1.8.0`, - # this builds `deepset/haystack:cpu` - - name: Build api images no version in tag - uses: docker/bake-action@v4 - if: steps.version.outputs.comparison-result == '>' - env: - IMAGE_TAG_SUFFIX: ${{ steps.meta.outputs.version }} - BASE_IMAGE_TAG_SUFFIX: ${{ steps.meta.outputs.version }} - with: - workdir: docker - targets: ${{ matrix.target }}-latest - push: true diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml deleted file mode 100644 index af42e93542..0000000000 --- a/.github/workflows/e2e.yml +++ /dev/null @@ -1,88 +0,0 @@ -# If you change this name also do it in ci_metrics.yml -name: end-to-end - -on: - workflow_dispatch: # Activate this workflow manually - schedule: - - cron: "0 0 * * *" - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - paths: - - "e2e/**/*.py" - - "!e2e/preview/**/*.py" # See e2e_preview.yml - - ".github/workflows/e2e.yml" - -env: - PYTHON_VERSION: "3.8" - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} - SERPERDEV_API_KEY: ${{ secrets.SERPERDEV_API_KEY }} - -jobs: - e2e: - timeout-minutes: 60 - strategy: - fail-fast: false # Avoid cancelling the others if one of these fails - matrix: - folder: - - "document_search" - - "pipelines" - - "preview" - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt install ffmpeg # for local Whisper tests - - - name: Run Elasticsearch - run: | - docker run -d -p 9200:9200 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms128m -Xmx256m" elasticsearch:7.9.2 - - - name: Run Opensearch - run: | - docker run -d -p 9201:9200 -p 9600:9600 -e "discovery.type=single-node" opensearchproject/opensearch:1.3.5 - - - name: Run Weaviate - run: docker run -d -p 8080:8080 --name haystack_test_weaviate --env AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED='true' --env PERSISTENCE_DATA_PATH='/var/lib/weaviate' --env ENABLE_EXPERIMENTAL_BM25='true' --env DISK_USE_READONLY_PERCENTAGE='95' semitechnologies/weaviate:1.17.2 - - - name: Install Haystack - run: pip install -e .[inference,elasticsearch7,faiss,weaviate,opensearch,dev,pdf,preview] langdetect - - # FIXME caching prevents PRs from running the e2e tests properly - - # - name: Cache HF models - # id: cache-hf-models - # uses: actions/cache@v3 - # with: - # path: ./e2e - # key: ${{ runner.os }}-${{ hashFiles('**/models_to_cache.txt') }} - # env: - # SEGMENT_DOWNLOAD_TIMEOUT_MINS: 15 - - # - name: Download models - # if: steps.cache-hf-models.outputs.cache-hit != 'true' - # shell: python - # run: | - # from transformers import AutoModel - # with open("./e2e/models_to_cache.txt") as file: - # AutoModel.from_pretrained(file.readline().rstrip()) - - - name: Run tests - env: - TOKENIZERS_PARALLELISM: 'false' # Avoid logspam by tokenizers - # we add "and not document_store" to exclude the tests that were ported to the new strategy - run: | - pytest e2e/${{ matrix.folder }} diff --git a/.github/workflows/examples_tests.yml b/.github/workflows/examples_tests.yml deleted file mode 100644 index c0a7f10887..0000000000 --- a/.github/workflows/examples_tests.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: Examples tests - -on: - workflow_dispatch: # Activate this workflow manually - push: - branches: - - main - pull_request: - paths: - - "examples/**" - - "!examples/preview/**" - types: - - opened - - reopened - - synchronize - - ready_for_review - -env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - HUGGINGFACE_API_KEY: ${{ secrets.HUGGINGFACE_API_KEY }} - PYTHON_VERSION: "3.8" - -jobs: - tests: - name: Examples - runs-on: ubuntu-latest - services: - elasticsearch: - image: elasticsearch:7.17.6 - env: - discovery.type: "single-node" - ES_JAVA_OPTS: "-Xms128m -Xmx256m" - ports: - - 9200:9200 - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: | - pip install --upgrade pip - pip install .[inference,dev,elasticsearch,preprocessing,file-conversion] - - - name: Run - run: pytest examples/ --ignore examples/preview/ - - - name: Calculate alert data - id: calculator - if: (success() || failure()) && github.ref_name == 'main' - shell: bash - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/imports.yml b/.github/workflows/imports.yml deleted file mode 100644 index 9c2c44401e..0000000000 --- a/.github/workflows/imports.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Dependency checker - -on: - push: - branches: - - main - # release branches have the form v1.9.x - - 'v[0-9].*[0-9].x' - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - paths: - - "**.py" - - "pyproject.toml" - - "!.github/**/*.py" - - "!rest_api/**/*.py" - - "!test/*" - -env: - PYTHON_VERSION: "3.8" - -jobs: - - base-install: - strategy: - fail-fast: false - matrix: - os: - - macos-latest - - ubuntu-latest - - windows-latest - runs-on: ${{ matrix.os }} - steps: - - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack with no extras - run: pip install . - - - name: Import Haystack - run: python -c 'import haystack' diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml deleted file mode 100644 index 2a8a6d96e7..0000000000 --- a/.github/workflows/linting.yml +++ /dev/null @@ -1,83 +0,0 @@ -# If you change this name also do it in linting-skipper.yml and ci_metrics.yml -name: Linting - -on: - pull_request: - paths: - - "**.py" - - "**/pyproject.toml" - - "!haystack/preview/**/*.py" - - "!test/preview/**/*.py" - - "!e2e/preview/**/*.py" - -env: - PYTHON_VERSION: "3.8" - -jobs: - mypy: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - # With the default value of 1, there are corner cases where tj-actions/changed-files - # fails with a `no merge base` error - fetch-depth: 0 - - - name: Get changed files - id: files - uses: tj-actions/changed-files@v40 - with: - files: | - **/*.py - files_ignore: | - test/** - rest_api/test/** - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: | - pip install ".[all,dev]" - - - name: Mypy - if: steps.files.outputs.any_changed == 'true' - run: | - mkdir .mypy_cache/ - mypy --install-types --non-interactive ${{ steps.files.outputs.all_changed_files }} --exclude=rest_api/build/ --exclude=rest_api/test/ - - pylint: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - # With the default value of 1, there are corner cases where tj-actions/changed-files - # fails with a `no merge base` error - fetch-depth: 0 - - - name: Get changed files - id: files - uses: tj-actions/changed-files@v40 - with: - files: | - **/*.py - files_ignore: | - test/** - rest_api/test/** - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: | - pip install ".[all,dev]" - pip install ./haystack-linter - - - name: Pylint - if: steps.files.outputs.any_changed == 'true' - run: | - pylint -ry -j 0 ${{ steps.files.outputs.all_changed_files }} diff --git a/.github/workflows/linting_skipper.yml b/.github/workflows/linting_skipper.yml deleted file mode 100644 index 0176579329..0000000000 --- a/.github/workflows/linting_skipper.yml +++ /dev/null @@ -1,24 +0,0 @@ -# If you change this name also do it in linting.yml and ci_metrics.yml -name: Linting - -on: - pull_request: - paths-ignore: - - "**.py" - - "**/pyproject.toml" - - "!haystack/preview/**/*.py" - - "!test/preview/**/*.py" - - "!e2e/preview/**/*.py" - -jobs: - mypy: - runs-on: ubuntu-latest - steps: - - name: Skip mypy - run: echo "Skipped mypy" - - pylint: - runs-on: ubuntu-latest - steps: - - name: Skip pylint - run: echo "Skipped pylint" diff --git a/.github/workflows/openapi_sync.yml b/.github/workflows/openapi_sync.yml deleted file mode 100644 index 44f248e972..0000000000 --- a/.github/workflows/openapi_sync.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Sync OpenAPI Schema with Readme - -on: - push: - branches: - - main - # release branches have the form v1.9.x - - "v[0-9].*[0-9].x" - -env: - PYTHON_VERSION: "3.8" - -jobs: - run: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install dependencies - run: sudo apt update && sudo apt-get install libsndfile1 ffmpeg - - - name: Install Haystack - run: | - pip install --upgrade pip - pip install -U -e .[all,dev] - pip install -e ./rest_api - - - name: Update OpenAPI specs - run: python .github/utils/generate_openapi_specs.py - - - name: Get OpenAPI specs id - id: openapi-specs - env: - README_API_KEY: ${{ secrets.README_API_KEY }} - run: | - VERSION="$(cut -d "." -f 1,2 < VERSION.txt)" - if [[ "$(cat VERSION.txt)" == *"rc0" ]]; then - VERSION="$VERSION-unstable" - fi - SPECS_ID=$(curl https://dash.readme.com/api/v1/api-specification \ - -u "$README_API_KEY:" \ - --header "x-readme-version: $VERSION" \ - | jq -r ".[0].id") - echo "id=$SPECS_ID" >> "$GITHUB_OUTPUT" - - - name: Sync OpenAPI specs - uses: readmeio/rdme@8.3.1 - env: - README_API_KEY: ${{ secrets.README_API_KEY }} - README_API_DEFINITION_ID: ${{ steps.openapi-specs.outputs.id }} - with: - rdme: openapi openapi.json --key="$README_API_KEY" --id="$README_API_DEFINITION_ID" diff --git a/.github/workflows/pipeline_schema.yml b/.github/workflows/pipeline_schema.yml deleted file mode 100644 index b2b03e4f2c..0000000000 --- a/.github/workflows/pipeline_schema.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: YAML Schema -run-name: Update schema for ref ${{ github.event.workflow_run.head_branch || inputs.ref || 'main' }} - -on: - workflow_dispatch: # Activate this workflow manually - inputs: - ref: - description: Tag or branch name of Haystack version - required: true - type: string - default: main - - workflow_run: - workflows: - - Docker image release - types: - - completed - -env: - HAYSTACK_REF: ${{ github.event.workflow_run.head_branch || inputs.ref || 'main' }} - -jobs: - - run: - name: Update schema for ref ${{ github.event.workflow_run.head_branch || inputs.ref || 'main' }} - if: ${{ !github.event.workflow_run || github.event.workflow_run.conclusion == 'success' }} - runs-on: ubuntu-latest - steps: - # Start a workflow in https://github.com/deepset-ai/haystack-json-schema - # https://docs.github.com/en/rest/repos/repos#create-a-repository-dispatch-event - - name: 'Dispatch to schemas repository with ref "${{ env.HAYSTACK_REF }}"' - run: | - curl \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.HAYSTACK_BOT_TOKEN }}" \ - https://api.github.com/repos/deepset-ai/haystack-json-schema/dispatches \ - -d '{"event_type":"generate-pipeline-schemas","client_payload":{"ref":"${{ env.HAYSTACK_REF }}"}}' diff --git a/.github/workflows/preview_imports.yml b/.github/workflows/preview_imports.yml deleted file mode 100644 index ba2d70f76d..0000000000 --- a/.github/workflows/preview_imports.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Verify preview imports only preview - -on: - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - paths: - - "haystack/preview/**.py" - -jobs: - verify-imports: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - # With the default value of 1, there are corner cases where tj-actions/changed-files - # fails with a `no merge base` error - fetch-depth: 0 - - - name: Get changed files - id: files - uses: tj-actions/changed-files@v40 - with: - files: | - haystack/preview/**.py - - - name: Check imports - shell: python - run: | - import re - regex = r"^(from haystack|import haystack)(?!\.preview| import preview)(.*)" - - changed_files = "${{ steps.files.outputs.all_changed_files }}".split() - matches = {} - for path in changed_files: - with open(path, "r") as f: - file_matches = [] - for line in f.readlines(): - file_matches.extend(re.finditer(regex, line.strip())) - if file_matches: - matches[path] = file_matches - - for path, match in matches.items(): - print(f"Bad imports in file '{path}'") - for m in match: - print(m.group()) - print() - - if matches: - print("::error:: Imports in haystack.preview can only import from haystack.preview") - import sys; sys.exit(1) diff --git a/.github/workflows/pypi_release_preview.yml b/.github/workflows/pypi_release_preview.yml deleted file mode 100644 index 91e9b0f7e4..0000000000 --- a/.github/workflows/pypi_release_preview.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Trigger preview release - -on: - push: - branches: - - main - paths: - - "haystack/preview/**.py" - -jobs: - release-on-pypi: - runs-on: ubuntu-latest - - steps: - - name: Trigger preview release - env: - HAYSTACK_BOT_REPO_DISPATCH_PA_TOKEN: ${{ secrets.HAYSTACK_BOT_REPO_DISPATCH_PA_TOKEN }} - run: | - curl -L \ - -X POST \ - -H "Authorization: Bearer $HAYSTACK_BOT_REPO_DISPATCH_PA_TOKEN" \ - https://api.github.com/repos/deepset-ai/haystack-preview-package/dispatches \ - -d '{"event_type":"preview_release"}' diff --git a/.github/workflows/rest_api_tests.yml b/.github/workflows/rest_api_tests.yml deleted file mode 100644 index e3fc5a5971..0000000000 --- a/.github/workflows/rest_api_tests.yml +++ /dev/null @@ -1,151 +0,0 @@ -# If you change this name also do it in ci_metrics.yml -name: REST API Tests - -on: - push: - branches: - - main - # release branches have the form v1.9.x - - "v[0-9].*[0-9].x" - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - paths: - - "rest_api/**.py" - - "rest_api/pyproject.toml" - -env: - PYTHON_VERSION: "3.8" - -jobs: - black: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Black - run: | - pip install --upgrade pip - pip install .[formatting] - - - name: Check status - run: | - if ! black . --check; then - git status - echo "###################################################################################################" - echo "# " - echo "# CHECK FAILED! Black found issues with your code formatting." - echo "# " - echo "# Either:" - echo "# 1. Run Black locally before committing:" - echo "# " - echo "# pip install .[formatting]" - echo "# black ." - echo "# " - echo "# 2. Install the pre-commit hook:" - echo "# " - echo "# pre-commit install --hook-type pre-push" - echo "# " - echo "# 3. See https://github.com/deepset-ai/haystack/blob/main/CONTRIBUTING.md for help." - echo "# " - echo "# If you have further problems, please open an issue: https://github.com/deepset-ai/haystack/issues" - echo "# " - echo "##################################################################################################" - exit 1 - fi - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - rest_api: - needs: black - - strategy: - matrix: - os: [windows-latest, ubuntu-latest] - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install REST API - run: | - pip install -U "./rest_api[dev]" - pip install ".[inference,dev]" - pip install . - - - name: Run tests - env: - PYTEST_PARAMS: --maxfail=5 --durations=10 --suppress-no-test-exit-code - run: | - pytest ${{ env.PYTEST_PARAMS }} rest_api/ - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index 307f3d2916..0000000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,876 +0,0 @@ -# If you change this name also do it in tests_skipper.yml and ci_metrics.yml -name: Tests - -on: - workflow_dispatch: # Activate this workflow manually - push: - branches: - - main - # release branches have the form v1.9.x - - "v[0-9].*[0-9].x" - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - paths: - - "**.py" - - "pyproject.toml" - - "!haystack/preview/**/*.py" # See tests_preview.yml - - "!test/preview/**/*.py" # See tests_preview.yml - - "!e2e/preview/**/*.py" # See e2e_preview.yml - - "!.github/**/*.py" - - "!rest_api/**/*.py" - - "!docs/**/*.py" - -env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }} - PYTHON_VERSION: "3.8" - -jobs: - black: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Black - run: | - pip install --upgrade pip - pip install .[formatting] - - - name: Check status - run: | - if ! black . --check; then - git status - echo "###################################################################################################" - echo "# " - echo "# CHECK FAILED! Black found issues with your code formatting." - echo "# " - echo "# Either:" - echo "# 1. Run Black locally before committing:" - echo "# " - echo "# pip install .[formatting]" - echo "# black ." - echo "# " - echo "# 2. Install the pre-commit hook:" - echo "# " - echo "# pre-commit install --hook-type pre-push" - echo "# " - echo "# 3. See https://github.com/deepset-ai/haystack/blob/main/CONTRIBUTING.md for help." - echo "# " - echo "# If you have further problems, please open an issue: https://github.com/deepset-ai/haystack/issues" - echo "# " - echo "##################################################################################################" - exit 1 - fi - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - unit-tests: - name: Unit / ${{ matrix.topic }} / ${{ matrix.os }} / ${{ matrix.dependencies }} - needs: black - strategy: - fail-fast: false - matrix: - os: - - ubuntu-latest - - windows-latest - topic: - - document_stores - - nodes - - agents - - cli - - prompt - - pipelines - - utils - - others - - modeling - dependencies: - - all,dev - include: - - topic: document_stores - os: ubuntu-latest - dependencies: elasticsearch8,faiss,weaviate,pinecone,opensearch,inference,crawler,preprocessing,file-conversion,pdf,ocr,metrics,dev - - topic: document_stores - os: windows-latest - dependencies: elasticsearch8,faiss,weaviate,pinecone,opensearch,inference,crawler,preprocessing,file-conversion,pdf,ocr,metrics,dev - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[${{ matrix.dependencies }}] - - - name: Run - run: pytest --cov-report xml:coverage.xml --cov="haystack" -m "unit" test/${{ matrix.topic }} - - - name: Coveralls Parallel - # We upload only coverage for ubuntu as handling both os - # complicates the workflow too much for little to no gain - if: matrix.os == 'ubuntu-latest' - uses: coverallsapp/github-action@v2 - with: - path-to-lcov: coverage.xml - flag-name: ${{ matrix.topic }} - parallel: true - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - upload-coverage: - needs: unit-tests - runs-on: ubuntu-latest - steps: - - name: Coveralls Finished - uses: coverallsapp/github-action@v2 - with: - parallel-finished: true - - integration-tests-elasticsearch7: - name: Integration / Elasticsearch7 / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - runs-on: ${{ matrix.os }} - services: - elasticsearch: - image: elasticsearch:7.17.6 - env: - discovery.type: "single-node" - ES_JAVA_OPTS: "-Xms128m -Xmx256m" - ports: - - 9200:9200 - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[elasticsearch,dev,preprocessing,inference] - - - name: Run tests - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_elasticsearch.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-elasticsearch8: - name: Integration / Elasticsearch8 / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - runs-on: ${{ matrix.os }} - services: - elasticsearch: - image: elasticsearch:8.10.2 - env: - discovery.type: "single-node" - xpack.security.enabled: "false" - ES_JAVA_OPTS: "-Xms128m -Xmx256m" - ports: - - 9200:9200 - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[elasticsearch8,dev,preprocessing,inference] - - - name: Make elasticsearch comfortable with a disk almost full - run: | - curl -X PUT "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d' - { - "persistent": { - "cluster.routing.allocation.disk.watermark.low": "90%", - "cluster.routing.allocation.disk.watermark.low.max_headroom": "100GB", - "cluster.routing.allocation.disk.watermark.high": "95%", - "cluster.routing.allocation.disk.watermark.high.max_headroom": "20GB", - "cluster.routing.allocation.disk.watermark.flood_stage": "97%", - "cluster.routing.allocation.disk.watermark.flood_stage.max_headroom": "5GB", - "cluster.routing.allocation.disk.watermark.flood_stage.frozen": "97%", - "cluster.routing.allocation.disk.watermark.flood_stage.frozen.max_headroom": "5GB" - } - } - ' - curl -X PUT "localhost:9200/*/_settings?expand_wildcards=all&pretty" -H 'Content-Type: application/json' -d' - { - "index.blocks.read_only_allow_delete": null - } - ' - - - name: Run tests - run: | - pytest -x -m"document_store and integration" test/document_stores/test_elasticsearch.py - - - name: logs - if: failure() - run: | - docker logs "${{ job.services.elasticsearch.id }}" - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-sql: - name: Integration / SQL / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,sql,preprocessing] - - - name: Run tests - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_sql.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-opensearch: - name: Integration / Opensearch / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - runs-on: ${{ matrix.os }} - services: - opensearch: - image: opensearchproject/opensearch:1.3.5 - env: - discovery.type: "single-node" - ES_JAVA_OPTS: "-Xms128m -Xmx256m" - ports: - - 9200:9200 - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,opensearch,preprocessing] - - - name: Run tests - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_opensearch.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-dc: - name: Integration / dC / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,preprocessing] - - - name: Run tests - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_deepsetcloud.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-faiss: - name: Integration / faiss / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[faiss,dev,preprocessing] - - - name: Run tests - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_faiss.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-weaviate: - name: Integration / Weaviate / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - runs-on: ${{ matrix.os }} - services: - weaviate: - image: semitechnologies/weaviate:1.17.2 - env: - AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "true" - PERSISTENCE_DATA_PATH: "/var/lib/weaviate" - ENABLE_EXPERIMENTAL_BM25: "true" - DISK_USE_READONLY_PERCENTAGE: 95 - ports: - - 8080:8080 - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,weaviate,preprocessing] - - - name: Run tests - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_weaviate.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-pinecone: - name: Integration / pinecone / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,pinecone,preprocessing] - - - name: Run tests - env: - PINECONE_API_KEY: ${{ secrets.PINECONE_API_KEY }} - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_pinecone.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-memory: - name: Integration / memory / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,preprocessing,inference] - - - name: Run tests - run: | - pytest --maxfail=5 -m "document_store and integration" test/document_stores/test_memory.py - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-promptnode: - name: Integration / PromptNode / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,preprocessing,inference] - - - name: Run tests - run: | - pytest --maxfail=5 -m "integration" test/prompt - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - integration-tests-agents: - name: Integration / Agents / ${{ matrix.os }} - needs: - - unit-tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install Haystack - run: pip install .[dev,preprocessing,inference] - - - name: Run tests - run: | - pytest --maxfail=5 -m "integration" test/agents - - - name: Calculate alert data - id: calculator - shell: bash - if: (success() || failure()) && github.ref_name == 'main' - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "alert_type=success" >> "$GITHUB_OUTPUT"; - else - echo "alert_type=error" >> "$GITHUB_OUTPUT"; - fi - - - name: Send event to Datadog - if: (success() || failure()) && github.ref_name == 'main' - uses: masci/datadog@v1 - with: - api-key: ${{ secrets.CORE_DATADOG_API_KEY }} - api-url: https://api.datadoghq.eu - events: | - - title: "${{ github.workflow }} workflow" - text: "Job ${{ github.job }} in branch ${{ github.ref_name }}" - alert_type: "${{ steps.calculator.outputs.alert_type }}" - source_type_name: "Github" - host: ${{ github.repository_owner }} - tags: - - "project:${{ github.repository }}" - - "job:${{ github.job }}" - - "run_id:${{ github.run_id }}" - - "workflow:${{ github.workflow }}" - - "branch:${{ github.ref_name }}" - - "url:https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - - catch-all: - name: Catch-all check - runs-on: ubuntu-latest - # This job will be executed only after all the other tests - # are successful. - # This way we'll be able to mark only this test as required - # and skip it accordingly. - needs: - - integration-tests-elasticsearch7 - - integration-tests-elasticsearch8 - - integration-tests-sql - - integration-tests-opensearch - - integration-tests-dc - - integration-tests-faiss - - integration-tests-weaviate - - integration-tests-pinecone - - integration-tests-memory - - integration-tests-promptnode - - integration-tests-agents - - steps: - - name: Finisher - run: echo "Finish him!" diff --git a/.github/workflows/tests_preview_skipper.yml b/.github/workflows/tests_preview_skipper.yml deleted file mode 100644 index 2f64eaae99..0000000000 --- a/.github/workflows/tests_preview_skipper.yml +++ /dev/null @@ -1,21 +0,0 @@ -# If you change this name also do it in tests_preview.yml -name: Tests (Preview) - -on: - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - paths-ignore: - - "haystack/preview/**/*.py" - - "test/preview/**/*.py" - -jobs: - catch-all: - name: Catch-all check - runs-on: ubuntu-latest - steps: - - name: Skip preview tests - run: echo "Skipped!" diff --git a/.github/workflows/tests_skipper.yml b/.github/workflows/tests_skipper.yml deleted file mode 100644 index 5ac396aebd..0000000000 --- a/.github/workflows/tests_skipper.yml +++ /dev/null @@ -1,27 +0,0 @@ -# If you change this name also do it in tests.yml and ci_metrics.yml -name: Tests - -on: - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - paths-ignore: - - "**.py" - - "pyproject.toml" - - "!haystack/preview/**/*.py" # See tests_preview.yml - - "!test/preview/**/*.py" # See tests_preview.yml - - "!e2e/preview/**/*.py" # See e2e_preview.yml - - "!.github/**/*.py" - - "!rest_api/**/*.py" - - "!docs/**/*.py" - -jobs: - catch-all: - name: Catch-all check - runs-on: ubuntu-latest - steps: - - name: Skip tests - run: echo "Skipped!" diff --git a/.github/workflows/xpdf_release.yml b/.github/workflows/xpdf_release.yml deleted file mode 100644 index 1d0a1304c2..0000000000 --- a/.github/workflows/xpdf_release.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Xpdf Docker image release - -on: - push: - branches: - - main - paths: - - docker/docker-bake-xpdf.hcl - - docker/Dockerfile.xpdf - -jobs: - publish-xpdf-image: - runs-on: ubuntu-latest - env: - DOCKER_REPO_NAME: deepset/xpdf - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Build and publish Xpdf image - uses: docker/bake-action@v4 - with: - files: "docker-bake-xpdf.hcl" - workdir: docker - targets: xpdf - push: true diff --git a/annotation_tool/README.md b/annotation_tool/README.md deleted file mode 100644 index 97fa31570e..0000000000 --- a/annotation_tool/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Annotation Tool - -- Create labels with different techniques: Come up with questions (+ answers) while reading passages (SQuAD style) or have a set of predefined questions and look for answers in the document (~ Natural Questions). -- Structure your work via organizations, projects, users -- Upload your documents or import a predefined list of questions -- Export your labels in SQuAD Format - -![image](../docs/img/annotation_tool.png) - -# Local version (Docker) - -1. Configure credentials & database in the [`docker-compose.yml`](https://github.com/deepset-ai/haystack/blob/main/annotation_tool/docker-compose.yml): - -The credentials should match in database image and application configuration. - - DEFAULT_ADMIN_EMAIL: "example@example.com" - DEFAULT_ADMIN_PASSWORD: "DEMO-PASSWORD" - - DB_HOSTNAME: "db" - DB_NAME: "databasename" - DB_USERNAME: "somesafeuser" - DB_PASSWORD: "somesafepassword" - - POSTGRES_USER: "somesafeuser" - POSTGRES_PASSWORD: "somesafepassword" - POSTGRES_DB: "databasename" - - COOKIE_KEYS: "somesafecookiekeys" - JWT_SECRET: "somesafesecret" - - -2. Run docker-compose by executing `docker-compose up`. - - -3. The UI should be available at `localhost:7001`. - -# Usage -The manual (of a slightly earlier version) can be found [here](https://drive.google.com/file/d/1Wv3OIC0Z7ibHIzOm9Xw_r0gjTFmpl-33/view). While it doesn't include all latest features, the basic workflow and tips for label quality are still the same. - -# Annotation FAQ - -1. What is a good question? -- A good question is a fact-seeking question that can be answered with an entity (person, organisation, location, etc.) or explanation. A bad question is ambiguous, incomprehensible, dependent on clear false presuppositions, opinion seeking, or not clearly a request for factual information. -- The question should ask about information present in the text passage given. It should not be answerable only with additional knowledge or your interpretation. -- Do not copy paste answer text into the question. Good questions do not contain the exact same words as the answer or the context around the answer. The question should be a reformulation with synonyms and in different order as the context of the answer. -- Questions should be very precise natural questions you would ask when you want information from another person. -2. How many questions should you ask per text passage? -- Maximally ask 20 questions per passage -- Some text passages are not suited for 20 questions. Do not make up very constructed and complicated questions just to fill up the 20 - move on to the next text. -- Try to ask questions covering the whole passage and focus on questions covering important information. Do not only ask questions about a single sentence in that passage. -3. What is a good answer span? -- Always mark whole words. Do not start or end the answer within a word. -- For short answers: The answer should be as short and as close to a spoken human answer as possible. Do not include punctuation. -- For long answers: Please mark whole sentences with punctuation. The sentences can also pick up parts of the question, or mark even whole text passages. Mark passages only if they are not too large (e.g. not more than 8-10 sentences). -4. How do I differentiate long vs short answers? -- If there is a short answer possible you should always select short answer over long answer. -- Short precise answers like numbers or a few words are short answers. -- Long answers include lists of possibilities or multiple sentences are needed to answer the question correctly. -5. How to handle multiple possible answers to a single question? -- As of now there is no functionality to mark multiple answers per single question. -- Workaround: You can add a question with the same text but different answer selection by using the button below the question list (Button reads “custom question”) -6. What to do with grammatically wrong or incorrectly spelled questions? -- Include them. When users use the tool and ask questions they will likely contain grammar and spelling errors, too. -- Exception: The question needs to be understandable without reading and interpretation of the corresponding text passage. If you do not understand the question, please mark the question as “I don’t understand the question”. -7. What to do with text passages that are not properly converted or contain (in part) information that cannot be labelled (e.g. just lists or garbage text)? -- Please do not annotate this text -- You can write down what is missing, or the cause why you cannot label the text + the text number and title. -8. Which browser to use? -- Please use the Chrome browser. The tool is not tested for other browsers. diff --git a/annotation_tool/docker-compose.yml b/annotation_tool/docker-compose.yml deleted file mode 100644 index c5522cf081..0000000000 --- a/annotation_tool/docker-compose.yml +++ /dev/null @@ -1,47 +0,0 @@ -version: "3" -services: - backend: - image: deepset/haystack-annotation:latest - environment: - NODE_ENV: "production" - DB_HOSTNAME: "db" - DB_NAME: "databasename" - DB_USERNAME: "somesafeuser" - DB_PASSWORD: "somesafepassword" - # IMPORTANT: please configure credentials with secure strings. - # DEFAULT_ADMIN_EMAIL: "example@example.com" - # DEFAULT_ADMIN_PASSWORD: "DEMO_PASSWORD" - # COOKIE_KEYS: "somesafecookiekeys" - # JWT_SECRET: "somesafesecret" - # DOMAIN_WHITELIST: "*" - ports: - - "7001:7001" - links: - - "db:database" - depends_on: - - db - networks: - - app-network - restart: unless-stopped - - db: - image: "postgres:12" - environment: - POSTGRES_USER: "somesafeuser" - POSTGRES_PASSWORD: "somesafepassword" - POSTGRES_DB: "databasename" - ports: - - "5432:5432" - volumes: - - ./postgres-data:/var/lib/postgresql/data - networks: - - app-network - healthcheck: - test: "pg_isready --username=somesafeuser --dbname=databasename && psql --username=somesafeuser --list" - timeout: 3s - retries: 5 - restart: unless-stopped - -networks: - app-network: - driver: bridge diff --git a/conftest.py b/conftest.py deleted file mode 100644 index 7d27f2659d..0000000000 --- a/conftest.py +++ /dev/null @@ -1,31 +0,0 @@ -def pytest_addoption(parser): - parser.addoption( - "--document_store_type", action="store", default="elasticsearch, faiss, sql, memory, weaviate, pinecone" - ) - parser.addoption( - "--mock-dc", action="store_true", default=True, help="Mock HTTP requests to dC while running tests" - ) - parser.addoption( - "--mock-pinecone", action="store_true", default=True, help="Mock HTTP requests to Pinecone while running tests" - ) - - -def pytest_generate_tests(metafunc): - # Ugly hack to avoid polluting preview tests this with unwanted fixtures - if "test/preview" in metafunc.module.__file__ or "test\\preview" in metafunc.module.__file__: - return - # Get selected docstores from CLI arg - document_store_type = metafunc.config.option.document_store_type - selected_doc_stores = [item.strip() for item in document_store_type.split(",")] - - # parametrize document_store fixture if it's in the test function argument list - # but does not have an explicit parametrize annotation e.g - # @pytest.mark.parametrize("document_store", ["memory"], indirect=False) - found_mark_parametrize_document_store = False - for marker in metafunc.definition.iter_markers("parametrize"): - if "document_store" in marker.args[0]: - found_mark_parametrize_document_store = True - break - # for all others that don't have explicit parametrization, we add the ones from the CLI arg - if "document_store" in metafunc.fixturenames and not found_mark_parametrize_document_store: - metafunc.parametrize("document_store", selected_doc_stores, indirect=True) diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 209a7f3176..0000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,34 +0,0 @@ -services: - - haystack-api: - image: "deepset/haystack:cpu" - volumes: - - ./rest_api/rest_api/pipeline:/opt/pipelines - ports: - - 8000:8000 - restart: on-failure - environment: - - DOCUMENTSTORE_PARAMS_HOST=elasticsearch - - PIPELINE_YAML_PATH=/opt/pipelines/pipelines.haystack-pipeline.yml - - TOKENIZERS_PARALLELISM=false - # Uncomment the following line to customise how much time (in seconds) a worker can spend serving a request - # before it times out. This should include the time required to cache the models and setup the pipelines. - - # - GUNICORN_CMD_ARGS="--timeout=3000" - depends_on: - elasticsearch: - condition: service_healthy - - elasticsearch: - image: "docker.elastic.co/elasticsearch/elasticsearch:7.17.6" - ports: - - 9200:9200 - restart: on-failure - environment: - - discovery.type=single-node - - "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" - healthcheck: - test: curl --fail http://localhost:9200/_cat/health || exit 1 - interval: 10s - timeout: 1s - retries: 10 diff --git a/docs/pydoc/config/agent.yml b/docs/pydoc/config/agent.yml deleted file mode 100644 index 20dcf2be7a..0000000000 --- a/docs/pydoc/config/agent.yml +++ /dev/null @@ -1,28 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/agents] - modules: ['base', 'conversational', 'utils', 'agent_step', 'memory/conversation_memory', 'memory/conversation_summary_memory'] - ignore_when_discovered: ['__init__'] -processors: - - type: filter - expression: "name not in ['print_text']" - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Uses a large language model to answer complex queries that require multiple steps to find the correct answer. - category_slug: haystack-classes - title: Agent API - slug: agent-api - order: 0 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: agent_api.md diff --git a/docs/pydoc/config/answer-generator.yml b/docs/pydoc/config/answer-generator.yml deleted file mode 100644 index 285c2d0678..0000000000 --- a/docs/pydoc/config/answer-generator.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/answer_generator] - modules: ["openai"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Reads a set of documents and generates an answer to a question, word by word - category_slug: haystack-classes - title: Answer Generator API - slug: answer-generator-api - order: 5 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: answer_generator_api.md diff --git a/docs/pydoc/config/base-converter.yml b/docs/pydoc/config/base-converter.yml deleted file mode 100644 index cd2dc04077..0000000000 --- a/docs/pydoc/config/base-converter.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/file_converter] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for implementing file converters. - category_slug: haystack-classes - title: Base Converters API - slug: base-converters-api - order: 72 - parent_doc_slug: file-converters-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_converters_api.md diff --git a/docs/pydoc/config/base-doc-language-classifier.yml b/docs/pydoc/config/base-doc-language-classifier.yml deleted file mode 100644 index 8db7b399bf..0000000000 --- a/docs/pydoc/config/base-doc-language-classifier.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/doc_language_classifier] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Document Language Classifiers. - category_slug: haystack-classes - title: Base Document Language Classifier API - slug: base-doc-language-classifier-api - order: 27 - parent_doc_slug: doc-language-classifier-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_doc_language_classifier_api.md diff --git a/docs/pydoc/config/base-document-classifier.yml b/docs/pydoc/config/base-document-classifier.yml deleted file mode 100644 index 5c3726ccf5..0000000000 --- a/docs/pydoc/config/base-document-classifier.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/document_classifier] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for the Document Classifier. - category_slug: haystack-classes - title: Base Document Classifier API - slug: base-document-classifier-api - order: 22 - parent_doc_slug: document-classifier-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_document_classifier_api.md diff --git a/docs/pydoc/config/base-document-store.yml b/docs/pydoc/config/base-document-store.yml deleted file mode 100644 index 32c045fcc3..0000000000 --- a/docs/pydoc/config/base-document-store.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/document_stores] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract classes for the Document Stores and Keyword Document Stores. - category_slug: haystack-classes - title: Base Document Store API - slug: base-document-store-api - order: 32 - parent_doc_slug: document-store-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_document_store_api.md diff --git a/docs/pydoc/config/base-generator.yml b/docs/pydoc/config/base-generator.yml deleted file mode 100644 index 41d8fd8907..0000000000 --- a/docs/pydoc/config/base-generator.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/answer_generator] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Generators. - category_slug: haystack-classes - title: BaseGenerator API - slug: basegenerator-api - order: 7 - parent_doc_slug: answer-generator-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: basegenerator_api.md diff --git a/docs/pydoc/config/base-image-to-text.yml b/docs/pydoc/config/base-image-to-text.yml deleted file mode 100644 index ef707d340b..0000000000 --- a/docs/pydoc/config/base-image-to-text.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/image_to_text] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for ImageToText. - category_slug: haystack-classes - title: BaseImageToText API - slug: base-image-to-text-api - order: 187 - parent_doc_slug: transformers-image-to-text-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base-image-to-text.md diff --git a/docs/pydoc/config/base-preprocessor.yml b/docs/pydoc/config/base-preprocessor.yml deleted file mode 100644 index e443b32e92..0000000000 --- a/docs/pydoc/config/base-preprocessor.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/preprocessor] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for the PreProcessor. - category_slug: haystack-classes - title: Base PreProcessor API - slug: base-preprocessor-api - order: 102 - parent_doc_slug: preprocessor-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_preprocessor_api.md diff --git a/docs/pydoc/config/base-query-classifier.yml b/docs/pydoc/config/base-query-classifier.yml deleted file mode 100644 index b6c359562e..0000000000 --- a/docs/pydoc/config/base-query-classifier.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/query_classifier] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Query Classifiers. - category_slug: haystack-classes - title: Base Query Classifier API - slug: base-query-classifier-api - order: 132 - parent_doc_slug: query-classifier-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: query_classifier_api.md diff --git a/docs/pydoc/config/base-ranker.yml b/docs/pydoc/config/base-ranker.yml deleted file mode 100644 index 7b69105c2b..0000000000 --- a/docs/pydoc/config/base-ranker.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/ranker] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Rankers. - category_slug: haystack-classes - title: Base Ranker API - slug: base-ranker-api - order: 152 - parent_doc_slug: ranker-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_ranker_api.md diff --git a/docs/pydoc/config/base-reader.yml b/docs/pydoc/config/base-reader.yml deleted file mode 100644 index c544c0cb91..0000000000 --- a/docs/pydoc/config/base-reader.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/reader] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Readers. - category_slug: haystack-classes - title: Base Reader API - slug: base-reader-api - order: 162 - parent_doc_slug: reader-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_reader_api.md diff --git a/docs/pydoc/config/base-retriever.yml b/docs/pydoc/config/base-retriever.yml deleted file mode 100644 index e1a2ed132a..0000000000 --- a/docs/pydoc/config/base-retriever.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/retriever] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Retrievers. - category_slug: haystack-classes - title: Base Retriever API - slug: base-retriever-api - order: 172 - parent_doc_slug: retriever-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_retriever_api.md diff --git a/docs/pydoc/config/base-summarizer.yml b/docs/pydoc/config/base-summarizer.yml deleted file mode 100644 index cb6e62e0ba..0000000000 --- a/docs/pydoc/config/base-summarizer.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/summarizer] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Summarizers. - category_slug: haystack-classes - title: Base Summarizer API - slug: base-summarizer-api - order: 182 - parent_doc_slug: summarizer-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_summarizer_api.md diff --git a/docs/pydoc/config/base-translator.yml b/docs/pydoc/config/base-translator.yml deleted file mode 100644 index a2ff1cfbd4..0000000000 --- a/docs/pydoc/config/base-translator.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/translator] - modules: ["base"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Abstract class for Translators. - category_slug: haystack-classes - title: Base Translator API - slug: base-translator-api - order: 192 - parent_doc_slug: translator-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: base_translator_api.md diff --git a/docs/pydoc/config/crawler.yml b/docs/pydoc/config/crawler.yml deleted file mode 100644 index 657e2f9890..0000000000 --- a/docs/pydoc/config/crawler.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/connector] - modules: ["crawler"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: The Crawler scrapes the text from a website, creates a Haystack Document object out of it, and saves it to a JSON file. - category_slug: haystack-classes - title: Crawler API - slug: crawler-api - order: 10 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: crawler_api.md diff --git a/docs/pydoc/config/doc-language-classifier.yml b/docs/pydoc/config/doc-language-classifier.yml deleted file mode 100644 index e5b6eab7a6..0000000000 --- a/docs/pydoc/config/doc-language-classifier.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/doc_language_classifier] - modules: ["langdetect", "transformers"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Detects the language of the Documents - category_slug: haystack-classes - title: Document Language Classifier API - slug: doc-language-classifier-api - order: 25 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: doc_language_classifier_api.md diff --git a/docs/pydoc/config/document-classifier.yml b/docs/pydoc/config/document-classifier.yml deleted file mode 100644 index 0c0a46a550..0000000000 --- a/docs/pydoc/config/document-classifier.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/document_classifier] - modules: ["transformers"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Used to create predictions that are attached to documents as metadata. - category_slug: haystack-classes - title: Document Classifier API - slug: document-classifier-api - order: 20 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: document_classifier_api.md diff --git a/docs/pydoc/config/document-store.yml b/docs/pydoc/config/document-store.yml deleted file mode 100644 index 4e39d54d3d..0000000000 --- a/docs/pydoc/config/document-store.yml +++ /dev/null @@ -1,40 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/document_stores, ../../../haystack/document_stores/elasticsearch] - modules: - [ - "es7", - "es8", - "opensearch", - "memory", - "sql", - "faiss", - "weaviate", - "deepsetcloud", - "pinecone", - "search_engine", - "elasticsearch.base", - "utils", - ] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Stores your texts and meta data and provides them to the Retriever at query time. - category_slug: haystack-classes - title: Document Store API - slug: document-store-api - order: 30 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: document_store_api.md diff --git a/docs/pydoc/config/extractor.yml b/docs/pydoc/config/extractor.yml deleted file mode 100644 index 13249dd8cc..0000000000 --- a/docs/pydoc/config/extractor.yml +++ /dev/null @@ -1,28 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/extractor] - modules: ["entity"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: filter - expression: "name not in ['_EntityPostProcessor']" - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Extracts predefined entities out of a piece of text. - category_slug: haystack-classes - title: Entity Extractor API - slug: entity-extractor-api - order: 50 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: entity_extractor_api.md diff --git a/docs/pydoc/config/file-classifier.yml b/docs/pydoc/config/file-classifier.yml deleted file mode 100644 index d916b9c224..0000000000 --- a/docs/pydoc/config/file-classifier.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/file_classifier] - modules: ["file_type"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Distinguishes between text, PDF, Markdown, Docx and HTML files and routes them to the appropriate File Converter in an indexing pipeline. - category_slug: haystack-classes - title: File Classifier API - slug: file-classifier-api - order: 60 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: file_classifier_api.md diff --git a/docs/pydoc/config/file-converters.yml b/docs/pydoc/config/file-converters.yml deleted file mode 100644 index 0ca3866831..0000000000 --- a/docs/pydoc/config/file-converters.yml +++ /dev/null @@ -1,39 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/file_converter] - modules: - [ - "azure", - "csv", - "docx", - "image", - "json", - "markdown", - "parsr", - "pdf", - "pptx", - "tika", - "txt" - ] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Extracts text from files in different formats and cast it into the unified Document format. - category_slug: haystack-classes - title: File Converters API - slug: file-converters-api - order: 70 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: file_converters_api.md diff --git a/docs/pydoc/config/invocation-layers.yml b/docs/pydoc/config/invocation-layers.yml deleted file mode 100644 index eddc0511d7..0000000000 --- a/docs/pydoc/config/invocation-layers.yml +++ /dev/null @@ -1,41 +0,0 @@ -loaders: - - type: python - search_path: [../../../haystack/nodes/prompt/invocation_layer] - modules: - [ - "anthropic_claude", - "azure_chatgpt", - "azure_open_ai", - "chatgpt", - "cohere", - "hugging_face", - "hugging_face_inference", - "open_ai", - "sagemaker_base", - "sagemaker_hf_infer", - "sagemaker_hf_text_gen", - "sagemaker_meta", - ] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Enables use of Large Language Models from different providers with PromptNode. - category_slug: haystack-classes - title: Invocation Layers API - slug: invocation-layers-api - order: 117 - parent_doc_slug: prompt-node-api - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: invocation_layers_api.md diff --git a/docs/pydoc/config/other.yml b/docs/pydoc/config/other.yml deleted file mode 100644 index a9f2f04d69..0000000000 --- a/docs/pydoc/config/other.yml +++ /dev/null @@ -1,34 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/other] - modules: - [ - "docs2answers", - "join_docs", - "join_answers", - "route_documents", - "document_merger", - "shaper", - ] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: The utility classes of Haystack. - category_slug: haystack-classes - title: Other API - slug: other-api - order: 80 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: other_api.md diff --git a/docs/pydoc/config/pipelines.yml b/docs/pydoc/config/pipelines.yml deleted file mode 100644 index 609d32913c..0000000000 --- a/docs/pydoc/config/pipelines.yml +++ /dev/null @@ -1,27 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/pipelines] - modules: ["base", "ray", "standard_pipelines"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: "name not in ['_HaystackBeirRetrieverAdapter', '_RayDeploymentWrapper']" - - type: filter - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Arranges nodes in a predefined flow. - category_slug: haystack-classes - title: Pipelines API - slug: pipelines-api - order: 90 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: pipelines_api.md diff --git a/docs/pydoc/config/preprocessor.yml b/docs/pydoc/config/preprocessor.yml deleted file mode 100644 index a1f006c8d9..0000000000 --- a/docs/pydoc/config/preprocessor.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/preprocessor] - modules: ["preprocessor"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Normalize white spaces, gets rid of headers and footers, cleans empty lines in your Documents, or splits them into smaller pieces. - category_slug: haystack-classes - title: PreProcessor API - slug: preprocessor-api - order: 100 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: preprocessor_api.md diff --git a/docs/pydoc/config/primitives.yml b/docs/pydoc/config/primitives.yml deleted file mode 100644 index c689eec608..0000000000 --- a/docs/pydoc/config/primitives.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack] - modules: ["schema"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: These are the core classes that carry data through the system. - category_slug: haystack-classes - title: Primitives API - slug: primitives-api - order: 110 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: primitives_api.md diff --git a/docs/pydoc/config/prompt-node.yml b/docs/pydoc/config/prompt-node.yml deleted file mode 100644 index e2b5e37041..0000000000 --- a/docs/pydoc/config/prompt-node.yml +++ /dev/null @@ -1,34 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/prompt] - modules: - [ - "prompt_node", - "prompt_model", - "prompt_template", - "shapers", - ] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: filter - expression: "name not in ['PromptTemplateValidationError', 'PromptModelInvocationLayer', 'StopWordsCriteria', 'HFLocalInvocationLayer', 'OpenAIInvocationLayer', '_ValidationVisitor', '_FstringParamsTransformer']" - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Uses Large Language Models directly in your pipelines. - category_slug: haystack-classes - title: PromptNode API - slug: prompt-node-api - order: 115 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: prompt_node_api.md diff --git a/docs/pydoc/config/pseudo-label-generator.yml b/docs/pydoc/config/pseudo-label-generator.yml deleted file mode 100644 index 28f645deeb..0000000000 --- a/docs/pydoc/config/pseudo-label-generator.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/label_generator] - modules: ["pseudo_label_generator"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Creates training data for dense retrievers without human annotation. - category_slug: haystack-classes - title: Pseudo Label Generator API - slug: pseudo-label-generator-api - order: 120 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: pseudo_label_generator_api.md diff --git a/docs/pydoc/config/query-classifier.yml b/docs/pydoc/config/query-classifier.yml deleted file mode 100644 index d8c863163b..0000000000 --- a/docs/pydoc/config/query-classifier.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/query_classifier] - modules: ["transformers"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Distinguishes between keyword, question and statements queries. - category_slug: haystack-classes - title: Query Classifier API - slug: query-classifier-api - order: 130 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: query_classifier_api.md diff --git a/docs/pydoc/config/question-generator.yml b/docs/pydoc/config/question-generator.yml deleted file mode 100644 index 4a3f9a64fd..0000000000 --- a/docs/pydoc/config/question-generator.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/question_generator] - modules: ["question_generator"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Takes a Document as input and generates questions which it believes the Document can answer. - category_slug: haystack-classes - title: Question Generator API - slug: question-generator-api - order: 140 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: question_generator_api.md diff --git a/docs/pydoc/config/ranker.yml b/docs/pydoc/config/ranker.yml deleted file mode 100644 index f456f076e8..0000000000 --- a/docs/pydoc/config/ranker.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/ranker] - modules: ["sentence_transformers", "recentness_ranker", "cohere", "diversity", "lost_in_the_middle"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Reorders a set of Documents based on their relevance to the Query. - category_slug: haystack-classes - title: Ranker API - slug: ranker-api - order: 150 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: ranker_api.md diff --git a/docs/pydoc/config/reader.yml b/docs/pydoc/config/reader.yml deleted file mode 100644 index c1959f8c65..0000000000 --- a/docs/pydoc/config/reader.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/reader] - modules: ["farm", "transformers", "table"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Takes a question and a set of Documents as input and returns an Answer by selecting a text span within the Documents. - category_slug: haystack-classes - title: Reader API - slug: reader-api - order: 160 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: reader_api.md diff --git a/docs/pydoc/config/retriever.yml b/docs/pydoc/config/retriever.yml deleted file mode 100644 index 6b7da4c997..0000000000 --- a/docs/pydoc/config/retriever.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/retriever] - modules: ["sparse", "dense", "multimodal/retriever", "web", "link_content"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Sweeps through a document store and returns a set of candidate documents that are relevant to the query. - category_slug: haystack-classes - title: Retriever API - slug: retriever-api - order: 170 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: retriever_api.md diff --git a/docs/pydoc/config/shaper.yml b/docs/pydoc/config/shaper.yml deleted file mode 100644 index b2d5c8b801..0000000000 --- a/docs/pydoc/config/shaper.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/other] - modules: ['shaper'] - ignore_when_discovered: ['__init__'] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: A helper node with a variety of functions. - category_slug: haystack-classes - title: Shaper API - slug: shaper-api - order: 175 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: shaper_api.md diff --git a/docs/pydoc/config/summarizer.yml b/docs/pydoc/config/summarizer.yml deleted file mode 100644 index 329153ef48..0000000000 --- a/docs/pydoc/config/summarizer.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/summarizer] - modules: ["transformers"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: The Summarizer gives a short overview of a long Document. - category_slug: haystack-classes - title: Summarizer API - slug: summarizer-api - order: 180 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: summarizer_api.md diff --git a/docs/pydoc/config/transformers-img-to-text.yml b/docs/pydoc/config/transformers-img-to-text.yml deleted file mode 100644 index 96160b1acc..0000000000 --- a/docs/pydoc/config/transformers-img-to-text.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/image_to_text] - modules: ["transformers"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Generates captions for images. - category_slug: haystack-classes - title: TransformersImageToText API - slug: transformers-image-to-text-api - order: 185 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: transformers-image-to-text.md diff --git a/docs/pydoc/config/translator.yml b/docs/pydoc/config/translator.yml deleted file mode 100644 index 8d33ec7db1..0000000000 --- a/docs/pydoc/config/translator.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/translator] - modules: ["transformers"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Does what it says on the tin - it translates text from one language into another. - category_slug: haystack-classes - title: Translator API - slug: translator-api - order: 190 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: translator_api.md diff --git a/docs/pydoc/config/utils.yml b/docs/pydoc/config/utils.yml deleted file mode 100644 index ddd044fd94..0000000000 --- a/docs/pydoc/config/utils.yml +++ /dev/null @@ -1,37 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/utils] - modules: - [ - "doc_store", - "export_utils", - "preprocessing", - "squad_data", - "early_stopping", - "cleaning", - "context_matching", - "deepsetcloud", - "docker", - ] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Utility functions for Haystack. - category_slug: haystack-classes - title: Utils API - slug: utils-api - order: 200 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: utils_api.md diff --git a/docs/pydoc/config/whisper.yml b/docs/pydoc/config/whisper.yml deleted file mode 100644 index 5b8b4324de..0000000000 --- a/docs/pydoc/config/whisper.yml +++ /dev/null @@ -1,26 +0,0 @@ -loaders: - - type: loaders.CustomPythonLoader - search_path: [../../../haystack/nodes/audio] - modules: ["whisper_transcriber"] - ignore_when_discovered: ["__init__"] -processors: - - type: filter - expression: - documented_only: true - do_not_filter_modules: false - skip_empty_modules: true - - type: smart - - type: crossref -renderer: - type: renderers.ReadmeRenderer - excerpt: Transcribes audio files. - category_slug: haystack-classes - title: Whisper API - slug: whisper-api - order: 210 - markdown: - descriptive_class_title: false - descriptive_module_title: true - add_method_class_prefix: true - add_member_class_prefix: false - filename: whisper_api.md diff --git a/e2e/document_search/__init__.py b/e2e/document_search/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/e2e/document_search/test_standard_pipeline.py b/e2e/document_search/test_standard_pipeline.py deleted file mode 100644 index 5401e70f2e..0000000000 --- a/e2e/document_search/test_standard_pipeline.py +++ /dev/null @@ -1,35 +0,0 @@ -import pytest - -from haystack.nodes import EmbeddingRetriever -from haystack.pipelines import DocumentSearchPipeline - -from ..conftest import document_store - - -@pytest.mark.parametrize("document_store_name", ["memory", "faiss", "weaviate", "elasticsearch"]) -def test_document_search_standard_pipeline(document_store_name, docs, tmp_path): - """ - Testing the DocumentSearchPipeline with most common parameters according to our template: - https://github.com/deepset-ai/templates/blob/main/pipelines/DenseDocSearch.yaml - The common multi-qa-mpnet-base-dot-v1 model is replaced with the very similar paraphrase-MiniLM-L3-v2, - which reduces runtime and model size by ~6x - """ - with document_store(document_store_name, docs, tmp_path, embedding_dim=384) as ds: - retriever = EmbeddingRetriever( - document_store=ds, embedding_model="sentence-transformers/paraphrase-MiniLM-L3-v2" - ) - ds.update_embeddings(retriever) - pipeline = DocumentSearchPipeline(retriever) - prediction = pipeline.run("Paul lives in New York") - scores = [document.score for document in prediction["documents"]] - assert [document.content for document in prediction["documents"]] == [ - "My name is Paul and I live in New York", - "My name is Matteo and I live in Rome", - "My name is Christelle and I live in Paris", - "My name is Carla and I live in Berlin", - "My name is Camila and I live in Madrid", - ] - assert scores == pytest.approx( - [0.9149981737136841, 0.6895168423652649, 0.641706794500351, 0.6206043660640717, 0.5837393924593925], - abs=1e-3, - ) diff --git a/e2e/document_stores/__init__.py b/e2e/document_stores/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/e2e/document_stores/test_cosine_similarity.py b/e2e/document_stores/test_cosine_similarity.py deleted file mode 100644 index 98b1406cf3..0000000000 --- a/e2e/document_stores/test_cosine_similarity.py +++ /dev/null @@ -1,152 +0,0 @@ -from copy import deepcopy -import math - -import pytest -import numpy as np - -from haystack.schema import Document - -from ..conftest import document_store - - -DOCUMENTS = [ - { - "meta": {"name": "name_1", "year": "2020", "month": "01"}, - "content": "text_1", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_2", "year": "2020", "month": "02"}, - "content": "text_2", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_3", "year": "2020", "month": "03"}, - "content": "text_3", - "embedding": np.random.rand(768).astype(np.float64), - }, - { - "meta": {"name": "name_4", "year": "2021", "month": "01"}, - "content": "text_4", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_5", "year": "2021", "month": "02"}, - "content": "text_5", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_6", "year": "2021", "month": "03"}, - "content": "text_6", - "embedding": np.random.rand(768).astype(np.float64), - }, -] - - -@pytest.mark.parametrize("name", ["faiss", "weaviate", "opensearch_faiss", "elasticsearch", "memory"]) -def test_cosine_similarity(name, tmp_path): - documents = [Document.from_dict(d) for d in DOCUMENTS] - with document_store(name, documents, tmp_path) as ds: - # below we will write documents to the store and then query it to see if vectors were normalized or not - query = np.random.rand(768).astype(np.float32) - query_results = ds.query_by_embedding( - query_emb=query, top_k=len(documents), return_embedding=True, scale_score=False - ) - - # check if search with cosine similarity returns the correct number of results - assert len(query_results) == len(documents) - - original_embeddings = {doc["content"]: doc["embedding"] for doc in DOCUMENTS} - - for doc in query_results: - result_emb = doc.embedding - original_emb = original_embeddings[doc.content] - - expected_emb = original_emb - # embeddings of document stores which only support dot product out of the box must be normalized - if name in ["faiss", "weaviate", "opensearch_faiss"]: - expected_emb = original_emb / np.linalg.norm(original_emb) - - # check if the stored embedding was normalized or not - np.testing.assert_allclose( - expected_emb, result_emb, rtol=0.2, atol=5e-07 - ) # high tolerance was necessary for Milvus 2 - - # check if the score is plausible for cosine similarity - cosine_score = np.dot(result_emb, query) / (np.linalg.norm(result_emb) * np.linalg.norm(query)) - assert cosine_score == pytest.approx(doc.score, 0.01) - - -@pytest.mark.parametrize("name", ["faiss", "weaviate", "opensearch_faiss", "elasticsearch", "memory"]) -def test_update_embeddings_cosine_similarity(name, tmp_path): - # clear embeddings and convert to Document - documents = deepcopy(DOCUMENTS) - for doc in documents: - doc.pop("embedding") - documents = [Document.from_dict(d) for d in documents] - - with document_store(name, documents, tmp_path) as ds: - # we wrote documents to the store and then query it to see if vectors were normalized - original_embeddings = {} - - # now check if vectors are normalized when updating embeddings - class MockRetriever: - def embed_documents(self, docs): - embeddings = [] - for doc in docs: - embedding = np.random.rand(768).astype(np.float32) - original_embeddings[doc.content] = embedding - embeddings.append(embedding) - return np.stack(embeddings) - - retriever = MockRetriever() - ds.update_embeddings(retriever=retriever) - - query = np.random.rand(768).astype(np.float32) - query_results = ds.query_by_embedding( - query_emb=query, top_k=len(DOCUMENTS), return_embedding=True, scale_score=False - ) - - # check if search with cosine similarity returns the correct number of results - assert len(query_results) == len(DOCUMENTS) - - for doc in query_results: - result_emb = doc.embedding - original_emb = original_embeddings[doc.content] - - expected_emb = original_emb - # embeddings of document stores which only support dot product out of the box must be normalized - if name in ["faiss", "weaviate", "opensearch_faiss"]: - expected_emb = original_emb / np.linalg.norm(original_emb) - - # check if the stored embedding was normalized or not - np.testing.assert_allclose( - expected_emb, result_emb, rtol=0.2, atol=5e-07 - ) # high tolerance was necessary for Milvus 2 - - # check if the score is plausible for cosine similarity - cosine_score = np.dot(result_emb, query) / (np.linalg.norm(result_emb) * np.linalg.norm(query)) - assert cosine_score == pytest.approx(doc.score, 0.01) - - -@pytest.mark.parametrize("name", ["faiss", "weaviate", "memory", "elasticsearch", "opensearch_faiss"]) -def test_cosine_sanity_check(name, tmp_path): - VEC_1 = np.array([0.1, 0.2, 0.3], dtype="float32") - VEC_2 = np.array([0.4, 0.5, 0.6], dtype="float32") - - # This is the cosine similarity of VEC_1 and VEC_2 calculated using sklearn.metrics.pairwise.cosine_similarity - # The score is normalized to yield a value between 0 and 1. - KNOWN_COSINE = 0.9746317 - KNOWN_SCALED_COSINE = (KNOWN_COSINE + 1) / 2 - - docs = [Document.from_dict({"name": "vec_1", "text": "vec_1", "content": "vec_1", "embedding": VEC_1})] - with document_store(name, docs, tmp_path, embedding_dim=3) as ds: - query_results = ds.query_by_embedding(query_emb=VEC_2, top_k=1, return_embedding=True, scale_score=True) - - # check if faiss returns the same cosine similarity. Manual testing with faiss yielded 0.9746318 - assert math.isclose(query_results[0].score, KNOWN_SCALED_COSINE, abs_tol=0.0002) - - query_results = ds.query_by_embedding(query_emb=VEC_2, top_k=1, return_embedding=True, scale_score=False) - - # check if faiss returns the same cosine similarity. Manual testing with faiss yielded 0.9746318 - assert math.isclose(query_results[0].score, KNOWN_COSINE, abs_tol=0.0002) diff --git a/e2e/document_stores/test_similarity_score.py b/e2e/document_stores/test_similarity_score.py deleted file mode 100644 index ef3c23cd13..0000000000 --- a/e2e/document_stores/test_similarity_score.py +++ /dev/null @@ -1,98 +0,0 @@ -import pytest - -from haystack.nodes import EmbeddingRetriever -from haystack.pipelines import DocumentSearchPipeline - -from ..conftest import document_store - - -@pytest.mark.parametrize("name", ["memory", "faiss", "weaviate", "elasticsearch"]) -def test_similarity_score_sentence_transformers(name, docs, tmp_path): - with document_store(name, docs, tmp_path, embedding_dim=384) as ds: - retriever = EmbeddingRetriever( - document_store=ds, embedding_model="sentence-transformers/paraphrase-MiniLM-L3-v2" - ) - ds.update_embeddings(retriever) - pipeline = DocumentSearchPipeline(retriever) - prediction = pipeline.run("Paul lives in New York") - scores = [document.score for document in prediction["documents"]] - assert [document.content for document in prediction["documents"]] == [ - "My name is Paul and I live in New York", - "My name is Matteo and I live in Rome", - "My name is Christelle and I live in Paris", - "My name is Carla and I live in Berlin", - "My name is Camila and I live in Madrid", - ] - assert scores == pytest.approx( - [0.9149981737136841, 0.6895168423652649, 0.641706794500351, 0.6206043660640717, 0.5837393924593925], - abs=1e-3, - ) - - -@pytest.mark.parametrize("name", ["memory", "faiss", "weaviate", "elasticsearch"]) -def test_similarity_score(name, docs, tmp_path): - with document_store(name, docs, tmp_path, embedding_dim=384) as ds: - retriever = EmbeddingRetriever( - document_store=ds, embedding_model="sentence-transformers/paraphrase-MiniLM-L3-v2", model_format="farm" - ) - ds.update_embeddings(retriever) - pipeline = DocumentSearchPipeline(retriever) - prediction = pipeline.run("Paul lives in New York") - scores = [document.score for document in prediction["documents"]] - assert scores == pytest.approx( - [0.9102507941407827, 0.6937791467877008, 0.6491682889305038, 0.6321622491318529, 0.5909129441370939], - abs=1e-3, - ) - - -@pytest.mark.parametrize("name", ["memory", "faiss", "weaviate", "elasticsearch"]) -def test_similarity_score_without_scaling(name, docs, tmp_path): - with document_store(name, docs, tmp_path, embedding_dim=384) as ds: - retriever = EmbeddingRetriever( - document_store=ds, - embedding_model="sentence-transformers/paraphrase-MiniLM-L3-v2", - scale_score=False, - model_format="farm", - ) - ds.update_embeddings(retriever) - pipeline = DocumentSearchPipeline(retriever) - prediction = pipeline.run("Paul lives in New York") - scores = [document.score for document in prediction["documents"]] - assert scores == pytest.approx( - [0.8205015882815654, 0.3875582935754016, 0.29833657786100765, 0.26432449826370585, 0.18182588827418789], - abs=1e-3, - ) - - -@pytest.mark.parametrize("name", ["memory", "faiss", "weaviate", "elasticsearch"]) -def test_similarity_score_dot_product(name, docs, tmp_path): - with document_store(name, docs, tmp_path, similarity="dot_product", embedding_dim=384) as ds: - retriever = EmbeddingRetriever( - document_store=ds, embedding_model="sentence-transformers/paraphrase-MiniLM-L3-v2", model_format="farm" - ) - ds.update_embeddings(retriever) - pipeline = DocumentSearchPipeline(retriever) - prediction = pipeline.run("Paul lives in New York") - scores = [document.score for document in prediction["documents"]] - assert scores == pytest.approx( - [0.5526494403409358, 0.5247784342375555, 0.5189836829440964, 0.5179697273254912, 0.5112024928228626], - abs=1e-3, - ) - - -@pytest.mark.parametrize("name", ["memory", "faiss", "weaviate", "elasticsearch"]) -def test_similarity_score_dot_product_without_scaling(name, docs, tmp_path): - with document_store(name, docs, tmp_path, embedding_dim=384, similarity="dot_product") as ds: - retriever = EmbeddingRetriever( - document_store=ds, - embedding_model="sentence-transformers/paraphrase-MiniLM-L3-v2", - scale_score=False, - model_format="farm", - ) - ds.update_embeddings(retriever) - pipeline = DocumentSearchPipeline(retriever) - prediction = pipeline.run("Paul lives in New York") - scores = [document.score for document in prediction["documents"]] - assert scores == pytest.approx( - [21.13810000000001, 9.919499999999971, 7.597099999999955, 7.191000000000031, 4.481750000000034], abs=1e-3 - ) diff --git a/e2e/document_stores/test_update_embeddings.py b/e2e/document_stores/test_update_embeddings.py deleted file mode 100644 index 0666bd432a..0000000000 --- a/e2e/document_stores/test_update_embeddings.py +++ /dev/null @@ -1,166 +0,0 @@ -import pytest -import numpy as np -import pandas as pd - -from haystack.nodes import EmbeddingRetriever, TableTextRetriever - -from ..conftest import document_store - - -@pytest.mark.parametrize("name", ["elasticsearch", "faiss", "memory"]) -def test_update_embeddings(name, tmp_path): - documents = [] - for i in range(6): - documents.append({"content": f"text_{i}", "id": str(i), "meta_field": f"value_{i}"}) - documents.append({"content": "text_0", "id": "6", "meta_field": "value_0"}) - - with document_store(name, documents, tmp_path) as ds: - retriever = EmbeddingRetriever(document_store=ds, embedding_model="deepset/sentence_bert", use_gpu=False) - - ds.update_embeddings(retriever, batch_size=3) - documents = ds.get_all_documents(return_embedding=True) - assert len(documents) == 7 - for doc in documents: - assert type(doc.embedding) is np.ndarray - - documents = ds.get_all_documents(filters={"meta_field": ["value_0"]}, return_embedding=True) - assert len(documents) == 2 - for doc in documents: - assert doc.meta["meta_field"] == "value_0" - np.testing.assert_array_almost_equal(documents[0].embedding, documents[1].embedding, decimal=4) - - documents = ds.get_all_documents(filters={"meta_field": ["value_0", "value_5"]}, return_embedding=True) - documents_with_value_0 = [doc for doc in documents if doc.meta["meta_field"] == "value_0"] - documents_with_value_5 = [doc for doc in documents if doc.meta["meta_field"] == "value_5"] - np.testing.assert_raises( - AssertionError, - np.testing.assert_array_equal, - documents_with_value_0[0].embedding, - documents_with_value_5[0].embedding, - ) - - doc = { - "content": "text_7", - "id": "7", - "meta_field": "value_7", - "embedding": retriever.embed_queries(queries=["a random string"])[0], - } - ds.write_documents([doc]) - - documents = [] - for i in range(8, 11): - documents.append({"content": f"text_{i}", "id": str(i), "meta_field": f"value_{i}"}) - ds.write_documents(documents) - - doc_before_update = ds.get_all_documents(filters={"meta_field": ["value_7"]})[0] - embedding_before_update = doc_before_update.embedding - - ds.update_embeddings(retriever, batch_size=3, update_existing_embeddings=False) - doc_after_update = ds.get_all_documents(filters={"meta_field": ["value_7"]})[0] - embedding_after_update = doc_after_update.embedding - np.testing.assert_array_equal(embedding_before_update, embedding_after_update) - - # test updating with filters - if name == "faiss": - with pytest.raises(Exception): - ds.update_embeddings(retriever, update_existing_embeddings=True, filters={"meta_field": ["value"]}) - else: - ds.update_embeddings(retriever, batch_size=3, filters={"meta_field": ["value_0", "value_1"]}) - doc_after_update = ds.get_all_documents(filters={"meta_field": ["value_7"]})[0] - embedding_after_update = doc_after_update.embedding - np.testing.assert_array_equal(embedding_before_update, embedding_after_update) - - # test update all embeddings - ds.update_embeddings(retriever, batch_size=3, update_existing_embeddings=True) - assert ds.get_embedding_count() == 11 - doc_after_update = ds.get_all_documents(filters={"meta_field": ["value_7"]})[0] - embedding_after_update = doc_after_update.embedding - np.testing.assert_raises( - AssertionError, np.testing.assert_array_equal, embedding_before_update, embedding_after_update - ) - - # test update embeddings for newly added docs - documents = [] - for i in range(12, 15): - documents.append({"content": f"text_{i}", "id": str(i), "meta_field": f"value_{i}"}) - ds.write_documents(documents) - - ds.update_embeddings(retriever, batch_size=3, update_existing_embeddings=False) - assert ds.get_embedding_count() == 14 - - -def test_update_embeddings_table_text_retriever(tmp_path): - documents = [] - for i in range(3): - documents.append( - {"content": f"text_{i}", "id": f"pssg_{i}", "meta_field": f"value_text_{i}", "content_type": "text"} - ) - documents.append( - { - "content": pd.DataFrame(columns=[f"col_{i}", f"col_{i+1}"], data=[[f"cell_{i}", f"cell_{i+1}"]]), - "id": f"table_{i}", - "meta_field": f"value_table_{i}", - "content_type": "table", - } - ) - documents.append({"content": "text_0", "id": "pssg_4", "meta_field": "value_text_0", "content_type": "text"}) - documents.append( - { - "content": pd.DataFrame(columns=["col_0", "col_1"], data=[["cell_0", "cell_1"]]), - "id": "table_4", - "meta_field": "value_table_0", - "content_type": "table", - } - ) - - with document_store("elasticsearch", documents, tmp_path, embedding_dim=512) as ds: - retriever = TableTextRetriever( - document_store=document_store, - query_embedding_model="deepset/bert-small-mm_retrieval-question_encoder", - passage_embedding_model="deepset/bert-small-mm_retrieval-passage_encoder", - table_embedding_model="deepset/bert-small-mm_retrieval-table_encoder", - use_gpu=False, - ) - ds.update_embeddings(retriever, batch_size=3) - documents = ds.get_all_documents(return_embedding=True) - assert len(documents) == 8 - for doc in documents: - assert type(doc.embedding) is np.ndarray - - # Check if Documents with same content (text) get same embedding - documents = ds.get_all_documents(filters={"meta_field": ["value_text_0"]}, return_embedding=True) - assert len(documents) == 2 - for doc in documents: - assert doc.meta["meta_field"] == "value_text_0" - np.testing.assert_array_almost_equal(documents[0].embedding, documents[1].embedding, decimal=4) - - # Check if Documents with same content (table) get same embedding - documents = ds.get_all_documents(filters={"meta_field": ["value_table_0"]}, return_embedding=True) - assert len(documents) == 2 - for doc in documents: - assert doc.meta["meta_field"] == "value_table_0" - np.testing.assert_array_almost_equal(documents[0].embedding, documents[1].embedding, decimal=4) - - # Check if Documents with different content (text) get different embedding - documents = ds.get_all_documents( - filters={"meta_field": ["value_text_1", "value_text_2"]}, return_embedding=True - ) - np.testing.assert_raises( - AssertionError, np.testing.assert_array_equal, documents[0].embedding, documents[1].embedding - ) - - # Check if Documents with different content (table) get different embeddings - documents = ds.get_all_documents( - filters={"meta_field": ["value_table_1", "value_table_2"]}, return_embedding=True - ) - np.testing.assert_raises( - AssertionError, np.testing.assert_array_equal, documents[0].embedding, documents[1].embedding - ) - - # Check if Documents with different content (table + text) get different embeddings - documents = ds.get_all_documents( - filters={"meta_field": ["value_text_1", "value_table_1"]}, return_embedding=True - ) - np.testing.assert_raises( - AssertionError, np.testing.assert_array_equal, documents[0].embedding, documents[1].embedding - ) diff --git a/e2e/modeling/__init__.py b/e2e/modeling/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/e2e/modeling/test_adaptive_qa_inference.py b/e2e/modeling/test_adaptive_qa_inference.py deleted file mode 100644 index 6738a3dfbe..0000000000 --- a/e2e/modeling/test_adaptive_qa_inference.py +++ /dev/null @@ -1,76 +0,0 @@ -import pytest - -from haystack.modeling.infer import Inferencer - - -@pytest.mark.parametrize("multiprocessing_chunksize", [None, 2]) -def test_qa_format_and_results(multiprocessing_chunksize): - qa_inputs_dicts = [ - { - "questions": ["In what country is Normandy"], - "text": "The Normans are an ethnic group that arose in Normandy, a northern region " - "of France, from contact between Viking settlers and indigenous Franks and Gallo-Romans", - }, - { - "questions": ["Who counted the game among the best ever made?"], - "text": "Twilight Princess was released to universal critical acclaim and commercial success. It received " - "perfect scores from major publications such as 1UP.com, Computer and Video Games, Electronic " - "Gaming Monthly, Game Informer, GamesRadar, and GameSpy. On the review aggregators GameRankings " - "and Metacritic, Twilight Princess has average scores of 95% and 95 for the Wii version and scores " - "of 95% and 96 for the GameCube version. GameTrailers in their review called it one of the " - "greatest games ever created.", - }, - ] - ground_truths = ["France", "GameTrailers"] - - adaptive_model_qa = Inferencer.load( - "deepset/bert-medium-squad2-distilled", task_type="question_answering", batch_size=16, gpu=False - ) - results = adaptive_model_qa.inference_from_dicts( - dicts=qa_inputs_dicts, multiprocessing_chunksize=multiprocessing_chunksize - ) - - # sample results - # [ - # { - # "task": "qa", - # "predictions": [ - # { - # "question": "In what country is Normandy", - # "question_id": "None", - # "ground_truth": None, - # "answers": [ - # { - # "score": 1.1272038221359253, - # "probability": -1, - # "answer": "France", - # "offset_answer_start": 54, - # "offset_answer_end": 60, - # "context": "The Normans gave their name to Normandy, a region in France.", - # "offset_context_start": 0, - # "offset_context_end": 60, - # "document_id": None, - # } - # ] - # } - # ], - # } - # ] - predictions = list(results)[0]["predictions"] - - for prediction, ground_truth, qa_input_dict in zip(predictions, ground_truths, qa_inputs_dicts): - assert prediction["question"] == qa_input_dict["questions"][0] - answer = prediction["answers"][0] - assert answer["answer"] in answer["context"] - assert answer["answer"] == ground_truth - assert { - "answer", - "score", - "probability", - "offset_answer_start", - "offset_answer_end", - "context", - "offset_context_start", - "offset_context_end", - "document_id", - } == answer.keys() diff --git a/e2e/modeling/test_distillation.py b/e2e/modeling/test_distillation.py deleted file mode 100644 index 5e7a0119fb..0000000000 --- a/e2e/modeling/test_distillation.py +++ /dev/null @@ -1,103 +0,0 @@ -import torch - -from haystack.nodes import FARMReader -from haystack.modeling.data_handler.processor import UnlabeledTextProcessor - - -def create_checkpoint(model): - weights = [] - for name, weight in model.inferencer.model.named_parameters(): - if "weight" in name and weight.requires_grad: - weights.append(torch.clone(weight)) - return weights - - -def assert_weight_change(weights, new_weights): - print([torch.equal(old_weight, new_weight) for old_weight, new_weight in zip(weights, new_weights)]) - assert not any(torch.equal(old_weight, new_weight) for old_weight, new_weight in zip(weights, new_weights)) - - -def test_prediction_layer_distillation(samples_path): - student = FARMReader(model_name_or_path="prajjwal1/bert-mini", num_processes=0) - teacher = FARMReader(model_name_or_path="prajjwal1/bert-small", num_processes=0) - - # create a checkpoint of weights before distillation - student_weights = create_checkpoint(student) - - assert len(student_weights) == 38 - - student_weights.pop(-2) # pooler is not updated due to different attention head - - student.distil_prediction_layer_from(teacher, data_dir=samples_path / "squad", train_filename="tiny.json") - - # create new checkpoint - new_student_weights = create_checkpoint(student) - - assert len(new_student_weights) == 38 - - new_student_weights.pop(-2) # pooler is not updated due to different attention head - - # check if weights have changed - assert_weight_change(student_weights, new_student_weights) - - -def test_intermediate_layer_distillation(samples_path): - student = FARMReader(model_name_or_path="huawei-noah/TinyBERT_General_4L_312D") - teacher = FARMReader(model_name_or_path="bert-base-uncased") - - # create a checkpoint of weights before distillation - student_weights = create_checkpoint(student) - - assert len(student_weights) == 38 - - student_weights.pop(-1) # last layer is not affected by tinybert loss - student_weights.pop(-1) # pooler is not updated due to different attention head - - student.distil_intermediate_layers_from( - teacher_model=teacher, data_dir=samples_path / "squad", train_filename="tiny.json" - ) - - # create new checkpoint - new_student_weights = create_checkpoint(student) - - assert len(new_student_weights) == 38 - - new_student_weights.pop(-1) # last layer is not affected by tinybert loss - new_student_weights.pop(-1) # pooler is not updated due to different attention head - - # check if weights have changed - assert_weight_change(student_weights, new_student_weights) - - -def test_intermediate_layer_distillation_from_scratch(samples_path): - student = FARMReader(model_name_or_path="huawei-noah/TinyBERT_General_4L_312D") - teacher = FARMReader(model_name_or_path="bert-base-uncased") - - # create a checkpoint of weights before distillation - student_weights = create_checkpoint(student) - - assert len(student_weights) == 38 - - student_weights.pop(-1) # last layer is not affected by tinybert loss - student_weights.pop(-1) # pooler is not updated due to different attention head - - processor = UnlabeledTextProcessor( - tokenizer=teacher.inferencer.processor.tokenizer, - max_seq_len=128, - train_filename="doc_2.txt", - data_dir=samples_path / "docs", - ) - student.distil_intermediate_layers_from( - teacher_model=teacher, data_dir=samples_path / "squad", train_filename="tiny.json", processor=processor - ) - - # create new checkpoint - new_student_weights = create_checkpoint(student) - - assert len(new_student_weights) == 38 - - new_student_weights.pop(-1) # last layer is not affected by tinybert loss - new_student_weights.pop(-1) # pooler is not updated due to different attention head - - # check if weights have changed - assert_weight_change(student_weights, new_student_weights) diff --git a/e2e/modeling/test_dpr.py b/e2e/modeling/test_dpr.py deleted file mode 100644 index 281d33a197..0000000000 --- a/e2e/modeling/test_dpr.py +++ /dev/null @@ -1,960 +0,0 @@ -from typing import Dict, Any -from pathlib import Path -import os - -import numpy as np -import pytest -import torch -from torch.utils.data import SequentialSampler -from tqdm import tqdm -from transformers import AutoTokenizer - -from haystack.modeling.data_handler.dataloader import NamedDataLoader -from haystack.modeling.data_handler.processor import TextSimilarityProcessor -from haystack.modeling.model.biadaptive_model import BiAdaptiveModel -from haystack.modeling.model.language_model import get_language_model, DPREncoder -from haystack.modeling.model.prediction_head import TextSimilarityHead - -from haystack.modeling.utils import initialize_device_settings - - -def test_dpr_modules(): - # 1.Create question and passage tokenizers - query_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path="facebook/dpr-question_encoder-single-nq-base", do_lower_case=True, use_fast=True - ) - passage_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path="facebook/dpr-ctx_encoder-single-nq-base", do_lower_case=True, use_fast=True - ) - - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_query=256, - max_seq_len_passage=256, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - data_dir="data/retriever", - train_filename="nq-train.json", - dev_filename="nq-dev.json", - test_filename="nq-dev.json", - embed_title=True, - num_hard_negatives=1, - ) - - question_language_model = DPREncoder( - pretrained_model_name_or_path="bert-base-uncased", - model_type="DPRQuestionEncoder", - model_kwargs={"hidden_dropout_prob": 0, "attention_probs_dropout_prob": 0}, - ) - passage_language_model = DPREncoder( - pretrained_model_name_or_path="bert-base-uncased", - model_type="DPRContextEncoder", - model_kwargs={"hidden_dropout_prob": 0, "attention_probs_dropout_prob": 0}, - ) - - prediction_head = TextSimilarityHead(similarity_function="dot_product") - - devices, _ = initialize_device_settings(use_cuda=True) - model = BiAdaptiveModel( - language_model1=question_language_model, - language_model2=passage_language_model, - prediction_heads=[prediction_head], - embeds_dropout_prob=0.0, - lm1_output_types=["per_sequence"], - lm2_output_types=["per_sequence"], - device=devices[0], - ) - - model.connect_heads_with_processor(processor.tasks) - - assert type(model) == BiAdaptiveModel - assert type(processor) == TextSimilarityProcessor - assert type(question_language_model) == DPREncoder - assert type(passage_language_model) == DPREncoder - - # check embedding layer weights - assert list(model.named_parameters())[0][1][0, 0].item() - -0.010200000368058681 < 0.0001 - - d = { - "query": "big little lies season 2 how many episodes", - "passages": [ - { - "title": "Big Little Lies (TV series)", - "text": "series garnered several accolades. It received 16 Emmy Award nominations and won eight, including Outstanding Limited Series and acting awards for Kidman, Skarsgård, and Dern. The trio also won Golden Globe Awards in addition to a Golden Globe Award for Best Miniseries or Television Film win for the series. Kidman and Skarsgård also received Screen Actors Guild Awards for their performances. Despite originally being billed as a miniseries, HBO renewed the series for a second season. Production on the second season began in March 2018 and is set to premiere in 2019. All seven episodes are being written by Kelley", - "label": "positive", - "external_id": "18768923", - }, - { - "title": "Little People, Big World", - "text": 'final minutes of the season two-A finale, "Farm Overload". A crowd had gathered around Jacob, who was lying on the ground near the trebuchet. The first two episodes of season two-B focus on the accident, and how the local media reacted to it. The first season of "Little People, Big World" generated solid ratings for TLC (especially in the important 18–49 demographic), leading to the show\'s renewal for a second season. Critical reviews of the series have been generally positive, citing the show\'s positive portrayal of little people. Conversely, other reviews have claimed that the show has a voyeuristic bend', - "label": "hard_negative", - "external_id": "7459116", - }, - { - "title": "Cormac McCarthy", - "text": 'chores of the house, Lee was asked by Cormac to also get a day job so he could focus on his novel writing. Dismayed with the situation, she moved to Wyoming, where she filed for divorce and landed her first job teaching. Cormac McCarthy is fluent in Spanish and lived in Ibiza, Spain, in the 1960s and later settled in El Paso, Texas, where he lived for nearly 20 years. In an interview with Richard B. Woodward from "The New York Times", "McCarthy doesn\'t drink anymore – he quit 16 years ago in El Paso, with one of his young', - "label": "negative", - "passage_id": "2145653", - }, - ], - } - - dataset, tensor_names, _ = processor.dataset_from_dicts( # pylint: disable=unbalanced-tuple-unpacking - dicts=[d], return_baskets=False - ) - features = {key: val.unsqueeze(0).to(devices[0]) for key, val in zip(tensor_names, dataset[0])} - - # test features - assert torch.all( - torch.eq( - features["query_input_ids"][0][:10].cpu(), - torch.tensor([101, 2502, 2210, 3658, 2161, 1016, 2129, 2116, 4178, 102]), - ) - ) - assert torch.all( - torch.eq( - features["passage_input_ids"][0][0][:10].cpu(), - torch.tensor([101, 2502, 2210, 3658, 1006, 2694, 2186, 1007, 102, 2186]), - ) - ) - assert len(features["query_segment_ids"][0].nonzero()) == 0 - assert len(features["passage_segment_ids"][0].nonzero()) == 0 - assert torch.all(torch.eq(features["query_attention_mask"].nonzero()[:, 1].cpu(), torch.tensor(list(range(10))))) - assert torch.all( - torch.eq(features["passage_attention_mask"][0][0].nonzero().cpu().squeeze(), torch.tensor(list(range(127)))) - ) - assert torch.all( - torch.eq(features["passage_attention_mask"][0][1].nonzero().cpu().squeeze(), torch.tensor(list(range(143)))) - ) - - features_query = {key.replace("query_", ""): value for key, value in features.items() if key.startswith("query_")} - features_passage = { - key.replace("passage_", ""): value for key, value in features.items() if key.startswith("passage_") - } - max_seq_len = features_passage.get("input_ids").shape[-1] - features_passage = {key: value.view(-1, max_seq_len) for key, value in features_passage.items()} - - # test model encodings - query_vector = model.language_model1(**features_query)[0] - passage_vector = model.language_model2(**features_passage)[0] - - assert torch.all( - torch.le( - query_vector[0, :10].cpu() - - torch.tensor([-0.2135, -0.4748, 0.0501, -0.0430, -0.1747, -0.0441, 0.5638, 0.1405, 0.2285, 0.0893]), - torch.ones((1, 10)) * 0.0001, - ) - ) - assert torch.all( - torch.le( - passage_vector[0, :10].cpu() - - torch.tensor([0.0557, -0.6836, -0.3645, -0.5566, 0.2034, -0.3656, 0.2969, -0.0555, 0.3405, -0.8691]), - torch.ones((1, 10)) * 0.0001, - ) - ) - assert torch.all( - torch.le( - passage_vector[1, :10].cpu() - - torch.tensor([-0.2006, -1.5002, -0.1897, -0.3421, -0.0405, -0.0471, -0.0306, 0.1156, 0.3350, -0.3412]), - torch.ones((1, 10)) * 0.0001, - ) - ) - - # test logits and loss - embeddings = model( - query_input_ids=features.get("query_input_ids", None), - query_segment_ids=features.get("query_segment_ids", None), - query_attention_mask=features.get("query_attention_mask", None), - passage_input_ids=features.get("passage_input_ids", None), - passage_segment_ids=features.get("passage_segment_ids", None), - passage_attention_mask=features.get("passage_attention_mask", None), - ) - query_emb, passage_emb = embeddings[0] - assert torch.all(torch.eq(query_emb.cpu(), query_vector.cpu())) - assert torch.all(torch.eq(passage_emb.cpu(), passage_vector.cpu())) - - loss = model.logits_to_loss_per_head(embeddings, **features) - similarity_scores = model.prediction_heads[0]._embeddings_to_scores(query_emb, passage_emb).cpu() - assert torch.all( - torch.le(similarity_scores - torch.tensor([[-1.8311e-03, -6.3016e00]]), torch.ones((1, 2)) * 0.0001) - ) - assert (loss[0].item() - 0.0018) <= 0.0001 - - -query_input_ids = [ - torch.tensor([101, 2073, 2003, 3317, 2006, 1996, 2940, 2241, 2006, 102]), - torch.tensor([101, 2043, 2106, 1996, 2548, 2155, 11092, 1996, 2171, 10064]), - torch.tensor([101, 2054, 2003, 1037, 4937, 102, 0, 0, 0, 0]), -] -query_attention_mask = [ - torch.tensor(range(10)).unsqueeze(-1), - torch.tensor(range(11)).unsqueeze(-1), - torch.tensor(range(6)).unsqueeze(-1), -] -passage_ids = { - "titled": [ - torch.tensor( - [ - [101, 3317, 2006, 1996, 2940, 102, 3317, 2006, 1996, 2940], - [101, 3317, 2940, 1010, 2047, 2148, 3575, 102, 8765, 2061], - [101, 3317, 2940, 1010, 27492, 102, 3419, 18874, 3385, 1010], - ] - ), - torch.tensor( - [ - [101, 2160, 1997, 10064, 102, 2160, 1997, 10064, 1996, 2160], - [101, 26902, 1010, 11017, 1997, 10387, 102, 2384, 1010, 1998], - [101, 102, 102, 0, 0, 0, 0, 0, 0, 0], - ] - ), - torch.tensor( - [ - [101, 2516, 2007, 1000, 2569, 3494, 1000, 102, 2023, 2003], - [101, 102, 102, 0, 0, 0, 0, 0, 0, 0], - [101, 102, 102, 0, 0, 0, 0, 0, 0, 0], - ] - ), - ], - "untitled": [ - torch.tensor( - [ - [101, 3317, 2006, 1996, 2940, 1000, 3317, 2006, 1996, 2940], - [101, 8765, 2061, 2004, 2000, 5438, 1037, 8084, 10527, 5701], - [101, 3419, 18874, 3385, 1010, 3818, 1000, 1000, 2152, 2006], - ] - ), - torch.tensor( - [ - [101, 2160, 1997, 10064, 1996, 2160, 1997, 10064, 2003, 1996], - [101, 2384, 1010, 1998, 2001, 2000, 2202, 2173, 1999, 1037], - [101, 102, 102, 0, 0, 0, 0, 0, 0, 0], - ] - ), - torch.tensor( - [ - [101, 2023, 2003, 1037, 1026, 7308, 1028, 6251, 1012, 8870], - [101, 102, 102, 0, 0, 0, 0, 0, 0, 0], - [101, 102, 102, 0, 0, 0, 0, 0, 0, 0], - ] - ), - ], -} - -passage_attention = { - "titled": [ - [ - torch.tensor(range(140)).unsqueeze(-1), - torch.tensor(range(130)).unsqueeze(-1), - torch.tensor(range(127)).unsqueeze(-1), - ], - [ - torch.tensor(range(132)).unsqueeze(-1), - torch.tensor(range(121)).unsqueeze(-1), - torch.tensor(range(3)).unsqueeze(-1), - ], - [ - torch.tensor(range(22)).unsqueeze(-1), - torch.tensor(range(3)).unsqueeze(-1), - torch.tensor(range(3)).unsqueeze(-1), - ], - ], - "untitled": [ - [ - torch.tensor(range(135)).unsqueeze(-1), - torch.tensor(range(123)).unsqueeze(-1), - torch.tensor(range(122)).unsqueeze(-1), - ], - [ - torch.tensor(range(128)).unsqueeze(-1), - torch.tensor(range(115)).unsqueeze(-1), - torch.tensor(range(3)).unsqueeze(-1), - ], - [ - torch.tensor(range(15)).unsqueeze(-1), - torch.tensor(range(3)).unsqueeze(-1), - torch.tensor(range(3)).unsqueeze(-1), - ], - ], -} -labels1 = [[1, 0], [1, 0], [1, 0]] -labels2 = [[1, 0, 0], [1, 0, 0], [1, 0, 0]] - - -@pytest.mark.parametrize( - "embed_title, passage_ids, passage_attns", - [ - (True, passage_ids["titled"], passage_attention["titled"]), - (False, passage_ids["untitled"], passage_attention["untitled"]), - ], -) -@pytest.mark.parametrize("use_fast", [True, False]) -@pytest.mark.parametrize("num_hard_negatives, labels", [(1, labels1), (2, labels2)]) -def test_dpr_processor(embed_title, passage_ids, passage_attns, use_fast, num_hard_negatives, labels): - dict = [ - { - "query": "where is castle on the hill based on", - "answers": ["Framlingham Castle"], - "passages": [ - { - "text": 'Castle on the Hill "Castle on the Hill" is a song by English singer-songwriter Ed Sheeran. It was released as a digital download on 6 January 2017 as one of the double lead singles from his third studio album "÷" (2017), along with "Shape of You". "Castle on the Hill" was written and produced by Ed Sheeran and Benny Blanco. The song refers to Framlingham Castle in Sheeran\'s home town. Released on the same day as "Shape of You", "Castle on the Hill" reached number two in a number of countries, including the UK, Australia and Germany, while "Shape of', - "title": "Castle on the Hill", - "label": "positive", - "external_id": "19930582", - }, - { - "text": 'crops so as to feed a struggling infant colony. Governor King began Government Farm 3 there on 8 July 1801, referring to it as "Castle Hill" on 1 March 1802. The majority of the convicts who worked the prison farm were Irish Catholics, many having been transported for seditious activity in 1798. The most notorious incident being the Battle of Vinegar Hill where around 39 were slaughtered. They were branded "politicals" and exiled for life, never to return. The first free settler in Castle Hill, a Frenchman Baron Verincourt de Clambe, in unusual circumstances received a grant of 200 acres', - "title": "Castle Hill, New South Wales", - "label": "hard_negative", - "external_id": "1977568", - }, - { - "text": 'Tom Gleeson, proposed ""high on the peak of Castle Hill, overlooking the harbour"" would be a suitable location for the monument. Having arrived in Townsville, the monument was then placed in storage for a number of years. It was not until October 1947 that the Council discussed where to place the monument. A number of locations were considered: Castle Hill, the Botanic Gardens, in front of the Queens Hotel, the Anzac Memorial Park and the Railway Oval, but Castle Hill was ultimately the council\'s choice. In February 1948, the Queensland Government gave its approval to the council to place the', - "title": "Castle Hill, Townsville", - "label": "hard_negative", - "external_id": "3643705", - }, - # Empty title - { - "title": "", - "text": "Director Radio Iași); Dragoș-Liviu Vîlceanu; Mihnea-Adrian Vîlceanu; Nathalie-Teona", - "label": "positive", - "external_id": "b21eaeff-e08b-4548-b5e0-a280f6f4efef", - }, - ], - }, - { - "query": "when did the royal family adopt the name windsor", - "answers": ["in 1917"], - "passages": [ - { - "text": 'House of Windsor The House of Windsor is the reigning royal house of the United Kingdom and the other Commonwealth realms. The dynasty is of German paternal descent and was originally a branch of the House of Saxe-Coburg and Gotha, itself derived from the House of Wettin, which succeeded the House of Hanover to the British monarchy following the death of Queen Victoria, wife of Albert, Prince Consort. The name was changed from "Saxe-Coburg and Gotha" to the English "Windsor" (from "Windsor Castle") in 1917 because of anti-German sentiment in the British Empire during World War I. There have been', - "title": "House of Windsor", - "label": "positive", - "external_id": "1478954", - }, - { - "text": "2005, and was to take place in a civil ceremony at Windsor Castle, with a subsequent religious service of blessing at St George's Chapel. However, to conduct a civil marriage at Windsor Castle would oblige the venue to obtain a licence for civil marriages, which it did not have. A condition of such a licence is that the licensed venue must be available for a period of one year to anyone wishing to be married there, and as the royal family did not wish to make Windsor Castle available to the public for civil marriages, even just for one year,", - "title": "Camilla, Duchess of Cornwall", - "label": "hard_negative", - "external_id": "1399730", - }, - ], - }, - { - "query": "what is a cat?", - "answers": ["animal", "feline"], - "passages": [ - { - "text": "This is a sentence. Cats are good pets.", - "title": 'title with "special characters" ', - "label": "positive", - "external_id": "0", - }, - { - "text": "2nd text => More text about cats is good", - "title": "2nd title \n", - "label": "positive", - "external_id": "1", - }, - ], - }, - ] - - query_tok = "facebook/dpr-question_encoder-single-nq-base" - query_tokenizer = AutoTokenizer.from_pretrained(query_tok, use_fast=use_fast) - passage_tok = "facebook/dpr-ctx_encoder-single-nq-base" - passage_tokenizer = AutoTokenizer.from_pretrained(passage_tok, use_fast=use_fast) - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_query=256, - max_seq_len_passage=256, - data_dir="data/retriever", - train_filename="nq-train.json", - test_filename="nq-dev.json", - embed_title=embed_title, - num_hard_negatives=num_hard_negatives, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - shuffle_negatives=False, - ) - - for i, d in enumerate(dict): - __, ___, _, baskets = processor.dataset_from_dicts(dicts=[d], return_baskets=True) - feat = baskets[0].samples[0].features - assert torch.all(torch.eq(torch.tensor(feat[0]["query_input_ids"][:10]), query_input_ids[i])) - assert len(torch.tensor(feat[0]["query_segment_ids"]).nonzero()) == 0 - assert torch.all(torch.eq(torch.tensor(feat[0]["query_attention_mask"]).nonzero(), query_attention_mask[i])) - - positive_indices = np.where(np.array(feat[0]["label_ids"]) == 1)[0].item() - assert torch.all( - torch.eq( - torch.tensor(feat[0]["passage_input_ids"])[positive_indices, :10], passage_ids[i][positive_indices] - ) - ) - for j in range(num_hard_negatives + 1): - assert torch.all( - torch.eq(torch.tensor(feat[0]["passage_attention_mask"][j]).nonzero(), passage_attns[i][j]) - ) - assert torch.all( - torch.eq(torch.tensor(feat[0]["label_ids"]), torch.tensor(labels[i])[: num_hard_negatives + 1]) - ) - assert len(torch.tensor(feat[0]["passage_segment_ids"]).nonzero()) == 0 - - -def test_dpr_problematic(): - erroneous_dicts = [ - { - "query": [1], - "answers": ["Framlingham Castle"], - "passages": [ - { - "text": 'Castle on the Hill "Castle on the Hill" is a song by English singer-songwriter Ed Sheeran. It was released as a digital download on 6 January 2017 as one of the double lead singles from his third studio album "÷" (2017), along with "Shape of You". "Castle on the Hill" was written and produced by Ed Sheeran and Benny Blanco. The song refers to Framlingham Castle in Sheeran\'s home town. Released on the same day as "Shape of You", "Castle on the Hill" reached number two in a number of countries, including the UK, Australia and Germany, while "Shape of', - "title": "Castle on the Hill", - "label": "positive", - "external_id": "19930582", - }, - { - "text": 'crops so as to feed a struggling infant colony. Governor King began Government Farm 3 there on 8 July 1801, referring to it as "Castle Hill" on 1 March 1802. The majority of the convicts who worked the prison farm were Irish Catholics, many having been transported for seditious activity in 1798. The most notorious incident being the Battle of Vinegar Hill where around 39 were slaughtered. They were branded "politicals" and exiled for life, never to return. The first free settler in Castle Hill, a Frenchman Baron Verincourt de Clambe, in unusual circumstances received a grant of 200 acres', - "title": "Castle Hill, New South Wales", - "label": "hard_negative", - "external_id": "1977568", - }, - { - "text": 'Tom Gleeson, proposed ""high on the peak of Castle Hill, overlooking the harbour"" would be a suitable location for the monument. Having arrived in Townsville, the monument was then placed in storage for a number of years. It was not until October 1947 that the Council discussed where to place the monument. A number of locations were considered: Castle Hill, the Botanic Gardens, in front of the Queens Hotel, the Anzac Memorial Park and the Railway Oval, but Castle Hill was ultimately the council\'s choice. In February 1948, the Queensland Government gave its approval to the council to place the', - "title": "Castle Hill, Townsville", - "label": "hard_negative", - "external_id": "3643705", - }, - ], - }, - { - "query": "when did the royal family adopt the name windsor", - "answers": ["in 1917"], - "passages": [ - { - "text2": 'House of Windsor The House of Windsor is the reigning royal house of the United Kingdom and the other Commonwealth realms. The dynasty is of German paternal descent and was originally a branch of the House of Saxe-Coburg and Gotha, itself derived from the House of Wettin, which succeeded the House of Hanover to the British monarchy following the death of Queen Victoria, wife of Albert, Prince Consort. The name was changed from "Saxe-Coburg and Gotha" to the English "Windsor" (from "Windsor Castle") in 1917 because of anti-German sentiment in the British Empire during World War I. There have been', - "title": "House of Windsor", - "label": "positive", - "external_id": "1478954", - }, - { - "text2": "2005, and was to take place in a civil ceremony at Windsor Castle, with a subsequent religious service of blessing at St George's Chapel. However, to conduct a civil marriage at Windsor Castle would oblige the venue to obtain a licence for civil marriages, which it did not have. A condition of such a licence is that the licensed venue must be available for a period of one year to anyone wishing to be married there, and as the royal family did not wish to make Windsor Castle available to the public for civil marriages, even just for one year,", - "title": "Camilla, Duchess of Cornwall", - "label": "hard_negative", - "external_id": "1399730", - }, - ], - }, - { - "query": "what is a cat?", - "answers": ["animal", "feline"], - "passages": [ - { - "text": "This is a sentence. Cats are good pets.", - "title": 'title with "special characters" ', - "label": "positive", - "external_id": "0", - }, - { - "text": "2nd text => More text about cats is good", - "title": "2nd title \n", - "label": "positive", - "external_id": "1", - }, - ], - }, - ] - - query_tok = "facebook/dpr-question_encoder-single-nq-base" - query_tokenizer = AutoTokenizer.from_pretrained(query_tok) - passage_tok = "facebook/dpr-ctx_encoder-single-nq-base" - passage_tokenizer = AutoTokenizer.from_pretrained(passage_tok) - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_query=256, - max_seq_len_passage=256, - data_dir="data/retriever", - train_filename="nq-train.json", - test_filename="nq-dev.json", - embed_title=True, - num_hard_negatives=1, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - shuffle_negatives=False, - ) - - _, __, problematic_ids, ___ = processor.dataset_from_dicts(dicts=erroneous_dicts, return_baskets=True) - assert problematic_ids == {0, 1} - - -def test_dpr_query_only(): - erroneous_dicts = [ - {"query": "where is castle on the hill based on", "answers": ["Framlingham Castle"]}, - {"query": "where is castle on the hill 2 based on", "answers": ["Framlingham Castle 2"]}, - ] - - query_tok = "facebook/dpr-question_encoder-single-nq-base" - query_tokenizer = AutoTokenizer.from_pretrained(query_tok) - passage_tok = "facebook/dpr-ctx_encoder-single-nq-base" - passage_tokenizer = AutoTokenizer.from_pretrained(passage_tok) - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_query=256, - max_seq_len_passage=256, - data_dir="data/retriever", - train_filename="nq-train.json", - test_filename="nq-dev.json", - embed_title=True, - num_hard_negatives=1, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - shuffle_negatives=False, - ) - - _, tensor_names, problematic_ids, __ = processor.dataset_from_dicts(dicts=erroneous_dicts, return_baskets=True) - assert len(problematic_ids) == 0 - assert tensor_names == ["query_input_ids", "query_segment_ids", "query_attention_mask"] - - -def test_dpr_context_only(): - erroneous_dicts = [ - { - "passages": [ - { - "text": "House of Windsor 2 The House of Windsor is the reigning royal house of the United", - "title": "House of Windsor", - "label": "positive", - "external_id": "1478954", - }, - { - "text": "2005, and was to take place in a civil ceremony at Windsor Castle, with a subsequent religious", - "title": "Camilla, Duchess of Cornwall", - "label": "hard_negative", - "external_id": "1399730", - }, - ] - }, - { - "passages": [ - { - "text": "House of Windsor The House of Windsor is the reigning royal house of the", - "title": "House of Windsor", - "label": "positive", - "external_id": "1478954", - }, - { - "text": "2005, and was to take place in a civil ceremony at Windsor Castle, with a subsequent", - "title": "Camilla, Duchess of Cornwall", - "label": "hard_negative", - "external_id": "1399730", - }, - ] - }, - ] - - query_tok = "facebook/dpr-question_encoder-single-nq-base" - query_tokenizer = AutoTokenizer.from_pretrained(query_tok) - passage_tok = "facebook/dpr-ctx_encoder-single-nq-base" - passage_tokenizer = AutoTokenizer.from_pretrained(passage_tok) - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_query=256, - max_seq_len_passage=256, - data_dir="data/retriever", - train_filename="nq-train.json", - test_filename="nq-dev.json", - embed_title=True, - num_hard_negatives=1, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - shuffle_negatives=False, - ) - - _, tensor_names, problematic_ids, __ = processor.dataset_from_dicts(dicts=erroneous_dicts, return_baskets=True) - assert len(problematic_ids) == 0 - assert tensor_names == ["passage_input_ids", "passage_segment_ids", "passage_attention_mask", "label_ids"] - - -def test_dpr_processor_save_load(tmp_path): - d = { - "query": "big little lies season 2 how many episodes ?", - "passages": [ - { - "title": "Big Little Lies (TV series)", - "text": "series garnered several accolades. It received 16 Emmy Award nominations and won eight, including Outstanding Limited Series and acting awards for Kidman, Skarsgård, and Dern. The trio also won Golden Globe Awards in addition to a Golden Globe Award for Best Miniseries or Television Film win for the series. Kidman and Skarsgård also received Screen Actors Guild Awards for their performances. Despite originally being billed as a miniseries, HBO renewed the series for a second season. Production on the second season began in March 2018 and is set to premiere in 2019. All seven episodes are being written by Kelley", - "label": "positive", - "external_id": "18768923", - }, - { - "title": "Little People, Big World", - "text": 'final minutes of the season two-A finale, "Farm Overload". A crowd had gathered around Jacob, who was lying on the ground near the trebuchet. The first two episodes of season two-B focus on the accident, and how the local media reacted to it. The first season of "Little People, Big World" generated solid ratings for TLC (especially in the important 18–49 demographic), leading to the show\'s renewal for a second season. Critical reviews of the series have been generally positive, citing the show\'s positive portrayal of little people. Conversely, other reviews have claimed that the show has a voyeuristic bend', - "label": "hard_negative", - "external_id": "7459116", - }, - { - "title": "Cormac McCarthy", - "text": 'chores of the house, Lee was asked by Cormac to also get a day job so he could focus on his novel writing. Dismayed with the situation, she moved to Wyoming, where she filed for divorce and landed her first job teaching. Cormac McCarthy is fluent in Spanish and lived in Ibiza, Spain, in the 1960s and later settled in El Paso, Texas, where he lived for nearly 20 years. In an interview with Richard B. Woodward from "The New York Times", "McCarthy doesn\'t drink anymore – he quit 16 years ago in El Paso, with one of his young', - "label": "negative", - "passage_id": "2145653", - }, - ], - } - - query_tok = "facebook/dpr-question_encoder-single-nq-base" - query_tokenizer = AutoTokenizer.from_pretrained(query_tok) - passage_tok = "facebook/dpr-ctx_encoder-single-nq-base" - passage_tokenizer = AutoTokenizer.from_pretrained(passage_tok) - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_query=256, - max_seq_len_passage=256, - data_dir="data/retriever", - train_filename="nq-train.json", - test_filename="nq-dev.json", - embed_title=True, - num_hard_negatives=1, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - shuffle_negatives=False, - ) - save_dir = f"{tmp_path}/testsave/dpr_processor" - processor.save(save_dir=save_dir) - dataset, __, _ = processor.dataset_from_dicts( # pylint: disable=unbalanced-tuple-unpacking - dicts=[d], return_baskets=False - ) - loadedprocessor = TextSimilarityProcessor.load_from_dir(load_dir=save_dir) - dataset2, __, _ = loadedprocessor.dataset_from_dicts(dicts=[d], return_baskets=False) - assert np.array_equal(dataset.tensors[0], dataset2.tensors[0]) - - -@pytest.mark.parametrize( - "query_and_passage_model", - [ - { - "query": "etalab-ia/dpr-question_encoder-fr_qa-camembert", - "passage": "etalab-ia/dpr-ctx_encoder-fr_qa-camembert", - }, - { - "query": "deepset/gbert-base-germandpr-question_encoder", - "passage": "deepset/gbert-base-germandpr-ctx_encoder", - }, - {"query": "facebook/dpr-question_encoder-single-nq-base", "passage": "facebook/dpr-ctx_encoder-single-nq-base"}, - ], -) -def test_dpr_processor_save_load_non_bert_tokenizer(tmp_path: Path, query_and_passage_model: Dict[str, str]): - """ - This test compares 1) a model that was loaded from model hub with - 2) a model from model hub that was saved to disk and then loaded from disk and - 3) a model in FARM style that was saved to disk and then loaded from disk - """ - - d = { - "query": "Comment s'appelle le portail open data du gouvernement?", - "passages": [ - { - "title": "Etalab", - "text": "Etalab est une administration publique française qui fait notamment office " - "de Chief Data Officer de l'État et coordonne la conception et la mise en œuvre " - "de sa stratégie dans le domaine de la donnée (ouverture et partage des données " - "publiques ou open data, exploitation des données et intelligence artificielle...). " - "Ainsi, Etalab développe et maintient le portail des données ouvertes du gouvernement " - "français data.gouv.fr. Etalab promeut également une plus grande ouverture " - "l'administration sur la société (gouvernement ouvert) : transparence de l'action " - "publique, innovation ouverte, participation citoyenne... elle promeut l’innovation, " - "l’expérimentation, les méthodes de travail ouvertes, agiles et itératives, ainsi que " - "les synergies avec la société civile pour décloisonner l’administration et favoriser " - "l’adoption des meilleures pratiques professionnelles dans le domaine du numérique. " - "À ce titre elle étudie notamment l’opportunité de recourir à des technologies en voie " - "de maturation issues du monde de la recherche. Cette entité chargée de l'innovation " - "au sein de l'administration doit contribuer à l'amélioration du service public grâce " - "au numérique. Elle est rattachée à la Direction interministérielle du numérique, dont " - "les missions et l’organisation ont été fixées par le décret du 30 octobre 2019.  Dirigé " - "par Laure Lucchesi depuis 2016, elle rassemble une équipe pluridisciplinaire d'une " - "trentaine de personnes.", - "label": "positive", - "external_id": "1", - } - ], - } - - # load model from model hub - query_embedding_model = query_and_passage_model["query"] - passage_embedding_model = query_and_passage_model["passage"] - query_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=query_embedding_model - ) # tokenizer class is inferred automatically - query_encoder = get_language_model(pretrained_model_name_or_path=query_embedding_model) - passage_tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=passage_embedding_model) - passage_encoder = get_language_model(pretrained_model_name_or_path=passage_embedding_model) - - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_passage=256, - max_seq_len_query=256, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - embed_title=True, - num_hard_negatives=0, - num_positives=1, - ) - prediction_head = TextSimilarityHead(similarity_function="dot_product") - - if torch.cuda.is_available(): - device = torch.device("cuda") - elif ( - hasattr(torch.backends, "mps") - and torch.backends.mps.is_available() - and os.getenv("HAYSTACK_MPS_ENABLED", "true") != "false" - ): - device = torch.device("mps") - else: - device = torch.device("cpu") - model = BiAdaptiveModel( - language_model1=query_encoder, - language_model2=passage_encoder, - prediction_heads=[prediction_head], - embeds_dropout_prob=0.1, - lm1_output_types=["per_sequence"], - lm2_output_types=["per_sequence"], - device=device, - ) - model.connect_heads_with_processor(processor.tasks, require_labels=False) - - # save model that was loaded from model hub to disk - save_dir = f"{tmp_path}/testsave/dpr_model" - query_encoder_dir = "query_encoder" - passage_encoder_dir = "passage_encoder" - model.save(Path(save_dir), lm1_name=query_encoder_dir, lm2_name=passage_encoder_dir) - query_tokenizer.save_pretrained(save_dir + f"/{query_encoder_dir}") - passage_tokenizer.save_pretrained(save_dir + f"/{passage_encoder_dir}") - - # load model from disk - loaded_query_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=Path(save_dir) / query_encoder_dir, use_fast=True - ) # tokenizer class is inferred automatically - loaded_query_encoder = get_language_model(pretrained_model_name_or_path=Path(save_dir) / query_encoder_dir) - loaded_passage_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=Path(save_dir) / passage_encoder_dir, use_fast=True - ) - loaded_passage_encoder = get_language_model(pretrained_model_name_or_path=Path(save_dir) / passage_encoder_dir) - - loaded_processor = TextSimilarityProcessor( - query_tokenizer=loaded_query_tokenizer, - passage_tokenizer=loaded_passage_tokenizer, - max_seq_len_passage=256, - max_seq_len_query=256, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - embed_title=True, - num_hard_negatives=0, - num_positives=1, - ) - loaded_prediction_head = TextSimilarityHead(similarity_function="dot_product") - - if torch.cuda.is_available(): - device = torch.device("cuda") - elif ( - hasattr(torch.backends, "mps") - and torch.backends.mps.is_available() - and os.getenv("HAYSTACK_MPS_ENABLED", "true") != "false" - ): - device = torch.device("mps") - else: - device = torch.device("cpu") - loaded_model = BiAdaptiveModel( - language_model1=loaded_query_encoder, - language_model2=loaded_passage_encoder, - prediction_heads=[loaded_prediction_head], - embeds_dropout_prob=0.1, - lm1_output_types=["per_sequence"], - lm2_output_types=["per_sequence"], - device=device, - ) - loaded_model.connect_heads_with_processor(loaded_processor.tasks, require_labels=False) - - # compare model loaded from model hub with model loaded from disk - dataset, tensor_names, _ = processor.dataset_from_dicts( # pylint: disable=unbalanced-tuple-unpacking - dicts=[d], return_baskets=False - ) - dataset2, tensor_names2, _ = loaded_processor.dataset_from_dicts( # pylint: disable=unbalanced-tuple-unpacking - dicts=[d], return_baskets=False - ) - assert np.array_equal(dataset.tensors[0], dataset2.tensors[0]) - - # generate embeddings with model loaded from model hub - dataset, tensor_names, _, __ = processor.dataset_from_dicts( - dicts=[d], indices=list(range(len([d]))), return_baskets=True - ) - - data_loader = NamedDataLoader( - dataset=dataset, sampler=SequentialSampler(dataset), batch_size=16, tensor_names=tensor_names - ) - all_embeddings: Dict[str, Any] = {"query": [], "passages": []} - model.eval() - - for batch in tqdm(data_loader, desc="Creating Embeddings", unit=" Batches", disable=True): - batch = {key: batch[key].to(device) for key in batch} - - # get logits - with torch.inference_mode(): - query_embeddings, passage_embeddings = model.forward( - query_input_ids=batch.get("query_input_ids", None), - query_segment_ids=batch.get("query_segment_ids", None), - query_attention_mask=batch.get("query_attention_mask", None), - passage_input_ids=batch.get("passage_input_ids", None), - passage_segment_ids=batch.get("passage_segment_ids", None), - passage_attention_mask=batch.get("passage_attention_mask", None), - )[0] - if query_embeddings is not None: - all_embeddings["query"].append(query_embeddings.cpu().numpy()) - if passage_embeddings is not None: - all_embeddings["passages"].append(passage_embeddings.cpu().numpy()) - - if all_embeddings["passages"]: - all_embeddings["passages"] = np.concatenate(all_embeddings["passages"]) - if all_embeddings["query"]: - all_embeddings["query"] = np.concatenate(all_embeddings["query"]) - - # generate embeddings with model loaded from disk - dataset2, tensor_names2, _, __ = loaded_processor.dataset_from_dicts( - dicts=[d], indices=list(range(len([d]))), return_baskets=True - ) - - data_loader = NamedDataLoader( - dataset=dataset2, sampler=SequentialSampler(dataset2), batch_size=16, tensor_names=tensor_names2 - ) - all_embeddings2: Dict[str, Any] = {"query": [], "passages": []} - loaded_model.eval() - - for batch in tqdm(data_loader, desc="Creating Embeddings", unit=" Batches", disable=True): - batch = {key: batch[key].to(device) for key in batch} - - # get logits - with torch.inference_mode(): - query_embeddings, passage_embeddings = loaded_model.forward( - query_input_ids=batch.get("query_input_ids", None), - query_segment_ids=batch.get("query_segment_ids", None), - query_attention_mask=batch.get("query_attention_mask", None), - passage_input_ids=batch.get("passage_input_ids", None), - passage_segment_ids=batch.get("passage_segment_ids", None), - passage_attention_mask=batch.get("passage_attention_mask", None), - )[0] - if query_embeddings is not None: - all_embeddings2["query"].append(query_embeddings.cpu().numpy()) - if passage_embeddings is not None: - all_embeddings2["passages"].append(passage_embeddings.cpu().numpy()) - - if all_embeddings2["passages"]: - all_embeddings2["passages"] = np.concatenate(all_embeddings2["passages"]) - if all_embeddings2["query"]: - all_embeddings2["query"] = np.concatenate(all_embeddings2["query"]) - - # compare embeddings of model loaded from model hub and model loaded from disk - assert np.array_equal(all_embeddings["query"][0], all_embeddings2["query"][0]) - - # save the model that was loaded from disk to disk - save_dir = f"{tmp_path}/testsave/dpr_model" - query_encoder_dir = "query_encoder" - passage_encoder_dir = "passage_encoder" - loaded_model.save(Path(save_dir), lm1_name=query_encoder_dir, lm2_name=passage_encoder_dir) - loaded_query_tokenizer.save_pretrained(save_dir + f"/{query_encoder_dir}") - loaded_passage_tokenizer.save_pretrained(save_dir + f"/{passage_encoder_dir}") - - # load model from disk - query_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=Path(save_dir) / query_encoder_dir - ) # tokenizer class is inferred automatically - query_encoder = get_language_model(pretrained_model_name_or_path=Path(save_dir) / query_encoder_dir) - passage_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=Path(save_dir) / passage_encoder_dir - ) - passage_encoder = get_language_model(pretrained_model_name_or_path=Path(save_dir) / passage_encoder_dir) - - processor = TextSimilarityProcessor( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - max_seq_len_passage=256, - max_seq_len_query=256, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - embed_title=True, - num_hard_negatives=0, - num_positives=1, - ) - prediction_head = TextSimilarityHead(similarity_function="dot_product") - - if torch.cuda.is_available(): - device = torch.device("cuda") - elif ( - hasattr(torch.backends, "mps") - and torch.backends.mps.is_available() - and os.getenv("HAYSTACK_MPS_ENABLED", "true") != "false" - ): - device = torch.device("mps") - else: - device = torch.device("cpu") - model = BiAdaptiveModel( - language_model1=query_encoder, - language_model2=passage_encoder, - prediction_heads=[prediction_head], - embeds_dropout_prob=0.1, - lm1_output_types=["per_sequence"], - lm2_output_types=["per_sequence"], - device=device, - ) - model.connect_heads_with_processor(processor.tasks, require_labels=False) - - # compare a model loaded from disk that originated from the model hub and was then saved disk with - # a model loaded from disk that also originated from a FARM style model that was saved to disk - dataset3, tensor_names3, _ = processor.dataset_from_dicts( # pylint: disable=unbalanced-tuple-unpacking - dicts=[d], return_baskets=False - ) - dataset2, tensor_names2, _ = loaded_processor.dataset_from_dicts( # pylint: disable=unbalanced-tuple-unpacking - dicts=[d], return_baskets=False - ) - assert np.array_equal(dataset3.tensors[0], dataset2.tensors[0]) - - # generate embeddings with model loaded from disk that originated from a FARM style model that was saved to disk earlier - dataset3, tensor_names3, _, __ = loaded_processor.dataset_from_dicts( - dicts=[d], indices=list(range(len([d]))), return_baskets=True - ) - - data_loader = NamedDataLoader( - dataset=dataset3, sampler=SequentialSampler(dataset3), batch_size=16, tensor_names=tensor_names3 - ) - all_embeddings3: Dict[str, Any] = {"query": [], "passages": []} - loaded_model.eval() - - for batch in tqdm(data_loader, desc="Creating Embeddings", unit=" Batches", disable=True): - batch = {key: batch[key].to(device) for key in batch} - - # get logits - with torch.inference_mode(): - query_embeddings, passage_embeddings = loaded_model.forward( - query_input_ids=batch.get("query_input_ids", None), - query_segment_ids=batch.get("query_segment_ids", None), - query_attention_mask=batch.get("query_attention_mask", None), - passage_input_ids=batch.get("passage_input_ids", None), - passage_segment_ids=batch.get("passage_segment_ids", None), - passage_attention_mask=batch.get("passage_attention_mask", None), - )[0] - if query_embeddings is not None: - all_embeddings3["query"].append(query_embeddings.cpu().numpy()) - if passage_embeddings is not None: - all_embeddings3["passages"].append(passage_embeddings.cpu().numpy()) - - if all_embeddings3["passages"]: - all_embeddings3["passages"] = np.concatenate(all_embeddings3["passages"]) - if all_embeddings3["query"]: - all_embeddings3["query"] = np.concatenate(all_embeddings3["query"]) - - # compare embeddings of model loaded from model hub and model loaded from disk that originated from a FARM style - # model that was saved to disk earlier - assert np.array_equal(all_embeddings["query"][0], all_embeddings3["query"][0]) diff --git a/e2e/modeling/test_feature_extraction.py b/e2e/modeling/test_feature_extraction.py deleted file mode 100644 index 3989be955f..0000000000 --- a/e2e/modeling/test_feature_extraction.py +++ /dev/null @@ -1,246 +0,0 @@ -import re - -import pytest -import numpy as np -from tokenizers.pre_tokenizers import WhitespaceSplit - -from haystack.modeling.model.feature_extraction import FeatureExtractor - - -BERT = "bert-base-cased" -ROBERTA = "roberta-base" -XLNET = "xlnet-base-cased" - -TOKENIZERS_TO_TEST = [BERT, ROBERTA, XLNET] -TOKENIZERS_TO_TEST_WITH_TOKEN_MARKER = [(BERT, "##"), (ROBERTA, "Ġ"), (XLNET, "▁")] - -REGULAR_SENTENCE = "This is a sentence" -GERMAN_SENTENCE = "Der entscheidende Pass" -OTHER_ALPHABETS = "力加勝北区ᴵᴺᵀᵃছজটডণত" -GIBBERISH_SENTENCE = "Thiso text is included tolod makelio sure Unicodeel is handled properly:" -SENTENCE_WITH_ELLIPSIS = "This is a sentence..." -SENTENCE_WITH_LINEBREAK_1 = "and another one\n\n\nwithout space" -SENTENCE_WITH_LINEBREAK_2 = """This is a sentence. - With linebreak""" -SENTENCE_WITH_LINEBREAKS = """Sentence - with - multiple - newlines - """ -SENTENCE_WITH_EXCESS_WHITESPACE = "This is a sentence with multiple spaces" -SENTENCE_WITH_TABS = "This is a sentence with multiple tabs" -SENTENCE_WITH_CUSTOM_TOKEN = "Let's see all on this text and. !23# neverseenwordspossible" - - -def convert_offset_from_word_reference_to_text_reference(offsets, words, word_spans): - """ - Token offsets are originally relative to the beginning of the word - We make them relative to the beginning of the sentence. - - Not a fixture, just a utility. - """ - token_offsets = [] - for (start, end), word_index in zip(offsets, words): - word_start = word_spans[word_index][0] - token_offsets.append((start + word_start, end + word_start)) - return token_offsets - - -@pytest.mark.parametrize("model_name", TOKENIZERS_TO_TEST) -def test_save_load(tmp_path, model_name: str): - tokenizer = FeatureExtractor(pretrained_model_name_or_path=model_name, do_lower_case=False) - text = "Some Text with neverseentokens plus !215?#. and a combined-token_with/chars" - - tokenizer.feature_extractor.add_tokens(new_tokens=["neverseentokens"]) - original_encoding = tokenizer.feature_extractor(text) - - save_dir = tmp_path / "saved_tokenizer" - tokenizer.feature_extractor.save_pretrained(save_dir) - - tokenizer_loaded = FeatureExtractor(pretrained_model_name_or_path=save_dir) - new_encoding = tokenizer_loaded.feature_extractor(text) - - assert original_encoding == new_encoding - - -@pytest.mark.parametrize( - "edge_case", - [ - REGULAR_SENTENCE, - OTHER_ALPHABETS, - GIBBERISH_SENTENCE, - SENTENCE_WITH_ELLIPSIS, - SENTENCE_WITH_LINEBREAK_1, - SENTENCE_WITH_LINEBREAK_2, - SENTENCE_WITH_LINEBREAKS, - SENTENCE_WITH_EXCESS_WHITESPACE, - SENTENCE_WITH_TABS, - ], -) -@pytest.mark.parametrize("model_name", TOKENIZERS_TO_TEST) -def test_tokenization_on_edge_cases_full_sequence_tokenization(model_name: str, edge_case: str): - """ - Verify that tokenization on full sequence is the same as the one on "whitespace tokenized words" - """ - tokenizer = FeatureExtractor(pretrained_model_name_or_path=model_name, do_lower_case=False, add_prefix_space=True) - - pre_tokenizer = WhitespaceSplit() - words_and_spans = pre_tokenizer.pre_tokenize_str(edge_case) - words = [x[0] for x in words_and_spans] - - encoded = tokenizer.feature_extractor(words, is_split_into_words=True, add_special_tokens=False).encodings[0] - expected_tokenization = tokenizer.feature_extractor.tokenize( - " ".join(edge_case.split()) - ) # remove multiple whitespaces - - assert encoded.tokens == expected_tokenization - - -@pytest.mark.parametrize("edge_case", [SENTENCE_WITH_CUSTOM_TOKEN, GERMAN_SENTENCE]) -@pytest.mark.parametrize("model_name", [t for t in TOKENIZERS_TO_TEST if t != ROBERTA]) -def test_tokenization_on_edge_cases_full_sequence_tokenization_roberta_exceptions(model_name: str, edge_case: str): - """ - Verify that tokenization on full sequence is the same as the one on "whitespace tokenized words". - These test cases work for all tokenizers under test except for RoBERTa. - """ - tokenizer = FeatureExtractor(pretrained_model_name_or_path=model_name, do_lower_case=False, add_prefix_space=True) - - pre_tokenizer = WhitespaceSplit() - words_and_spans = pre_tokenizer.pre_tokenize_str(edge_case) - words = [x[0] for x in words_and_spans] - - encoded = tokenizer.feature_extractor(words, is_split_into_words=True, add_special_tokens=False).encodings[0] - expected_tokenization = tokenizer.feature_extractor.tokenize( - " ".join(edge_case.split()) - ) # remove multiple whitespaces - - assert encoded.tokens == expected_tokenization - - -@pytest.mark.parametrize( - "edge_case", - [ - REGULAR_SENTENCE, - # OTHER_ALPHABETS, # contains [UNK] that are impossible to match back to original text space - GIBBERISH_SENTENCE, - SENTENCE_WITH_ELLIPSIS, - SENTENCE_WITH_LINEBREAK_1, - SENTENCE_WITH_LINEBREAK_2, - SENTENCE_WITH_LINEBREAKS, - SENTENCE_WITH_EXCESS_WHITESPACE, - SENTENCE_WITH_TABS, - ], -) -@pytest.mark.parametrize("model_name,marker", TOKENIZERS_TO_TEST_WITH_TOKEN_MARKER) -def test_tokenization_on_edge_cases_full_sequence_verify_spans(model_name: str, marker: str, edge_case: str): - tokenizer = FeatureExtractor(pretrained_model_name_or_path=model_name, do_lower_case=False, add_prefix_space=True) - - pre_tokenizer = WhitespaceSplit() - words_and_spans = pre_tokenizer.pre_tokenize_str(edge_case) - words = [x[0] for x in words_and_spans] - word_spans = [x[1] for x in words_and_spans] - - encoded = tokenizer.feature_extractor(words, is_split_into_words=True, add_special_tokens=False).encodings[0] - - # subword-tokens have special chars depending on model type. To align with original text we get rid of them - tokens = [token.replace(marker, "") for token in encoded.tokens] - token_offsets = convert_offset_from_word_reference_to_text_reference(encoded.offsets, encoded.words, word_spans) - - for token, (start, end) in zip(tokens, token_offsets): - assert token == edge_case[start:end] - - -@pytest.mark.parametrize( - "edge_case", - [ - REGULAR_SENTENCE, - GERMAN_SENTENCE, - SENTENCE_WITH_EXCESS_WHITESPACE, - OTHER_ALPHABETS, - GIBBERISH_SENTENCE, - SENTENCE_WITH_ELLIPSIS, - SENTENCE_WITH_CUSTOM_TOKEN, - SENTENCE_WITH_LINEBREAK_1, - SENTENCE_WITH_LINEBREAK_2, - SENTENCE_WITH_LINEBREAKS, - SENTENCE_WITH_TABS, - ], -) -def test_detokenization_for_bert(edge_case): - tokenizer = FeatureExtractor(pretrained_model_name_or_path=BERT, do_lower_case=False) - - encoded = tokenizer(edge_case, add_special_tokens=False).encodings[0] - - detokenized = " ".join(encoded.tokens) - detokenized = re.sub(r"(^|\s+)(##)", "", detokenized) - - detokenized_ids = tokenizer(detokenized, add_special_tokens=False)["input_ids"] - detokenized_tokens = [tokenizer.decode([tok_id]).strip() for tok_id in detokenized_ids] - - assert encoded.tokens == detokenized_tokens - - -def test_encode_plus_for_bert(): - tokenizer = FeatureExtractor(pretrained_model_name_or_path=BERT, do_lower_case=False) - text = "Some Text with neverseentokens plus !215?#. and a combined-token_with/chars" - - encoded_batch = tokenizer(text) - encoded = encoded_batch.encodings[0] - - words = np.array(encoded.words) - words[0] = -1 - words[-1] = -1 - - print(words.tolist()) - - tokens = encoded.tokens - offsets = [x[0] for x in encoded.offsets] - start_of_word = [False] + list(np.ediff1d(words) > 0) - - assert list(zip(tokens, offsets, start_of_word)) == [ - ("[CLS]", 0, False), - ("Some", 0, True), - ("Text", 5, True), - ("with", 10, True), - ("never", 15, True), - ("##see", 20, False), - ("##nto", 23, False), - ("##ken", 26, False), - ("##s", 29, False), - ("plus", 31, True), - ("!", 36, True), - ("215", 37, True), - ("?", 40, True), - ("#", 41, True), - (".", 42, True), - ("and", 44, True), - ("a", 48, True), - ("combined", 50, True), - ("-", 58, True), - ("token", 59, True), - ("_", 64, True), - ("with", 65, True), - ("/", 69, True), - ("ch", 70, True), - ("##ars", 72, False), - ("[SEP]", 0, False), - ] - - -def test_tokenize_custom_vocab_bert(): - tokenizer = FeatureExtractor(pretrained_model_name_or_path=BERT, do_lower_case=False) - - tokenizer.feature_extractor.add_tokens(new_tokens=["neverseentokens"]) - text = "Some Text with neverseentokens plus !215?#. and a combined-token_with/chars" - - tokenized = tokenizer.feature_extractor.tokenize(text) - assert ( - tokenized == "Some Text with neverseentokens plus ! 215 ? # . and a combined - token _ with / ch ##ars".split() - ) - encoded = tokenizer.feature_extractor(text, add_special_tokens=False).encodings[0] - offsets = [x[0] for x in encoded.offsets] - start_of_word_single = [True] + list(np.ediff1d(encoded.words) > 0) - - assert encoded.tokens == tokenized - assert offsets == [0, 5, 10, 15, 31, 36, 37, 40, 41, 42, 44, 48, 50, 58, 59, 64, 65, 69, 70, 72] - assert start_of_word_single == [True] * 19 + [False] diff --git a/e2e/pipelines/__init__.py b/e2e/pipelines/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/e2e/pipelines/test_extractive_qa.py b/e2e/pipelines/test_extractive_qa.py deleted file mode 100644 index 24c43e9cda..0000000000 --- a/e2e/pipelines/test_extractive_qa.py +++ /dev/null @@ -1,29 +0,0 @@ -from haystack.nodes import TransformersTranslator, FARMReader, TfidfRetriever -from haystack.pipelines import ExtractiveQAPipeline, TranslationWrapperPipeline -from haystack.document_stores import InMemoryDocumentStore - - -def test_extractive_qa_answers_with_translator(docs): - en_to_de_translator = TransformersTranslator(model_name_or_path="Helsinki-NLP/opus-mt-en-de") - de_to_en_translator = TransformersTranslator(model_name_or_path="Helsinki-NLP/opus-mt-de-en") - - ds = InMemoryDocumentStore(use_bm25=False) - retriever = TfidfRetriever(document_store=ds) - reader = FARMReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", use_gpu=False, top_k_per_sample=5, num_processes=0 - ) - ds.write_documents(docs) - - base_pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever) - pipeline = TranslationWrapperPipeline( - input_translator=de_to_en_translator, output_translator=en_to_de_translator, pipeline=base_pipeline - ) - - prediction = pipeline.run(query="Wer lebt in Berlin?", params={"Reader": {"top_k": 3}}) - assert prediction is not None - assert prediction["query"] == "Wer lebt in Berlin?" - assert "Carla" in prediction["answers"][0].answer - assert prediction["answers"][0].score <= 1 - assert prediction["answers"][0].score >= 0 - assert prediction["answers"][0].meta["meta_field"] == "test1" - assert prediction["answers"][0].context == "My name is Carla and I live in Berlin" diff --git a/e2e/pipelines/test_pipeline_topologies.py b/e2e/pipelines/test_pipeline_topologies.py deleted file mode 100644 index 752191d34a..0000000000 --- a/e2e/pipelines/test_pipeline_topologies.py +++ /dev/null @@ -1,190 +0,0 @@ -import math -import pytest - -from haystack.pipelines import Pipeline, RootNode -from haystack.document_stores import InMemoryDocumentStore -from haystack.nodes import DensePassageRetriever, BM25Retriever, TransformersQueryClassifier, JoinDocuments, FARMReader - - -@pytest.mark.parametrize("classifier", [TransformersQueryClassifier()]) -def test_query_keyword_statement_classifier(classifier): - class KeywordOutput(RootNode): - outgoing_edges = 2 - - def run(self, **kwargs): - kwargs["output"] = "keyword" - return kwargs, "output_1" - - class QuestionOutput(RootNode): - outgoing_edges = 2 - - def run(self, **kwargs): - kwargs["output"] = "question" - return kwargs, "output_2" - - pipeline = Pipeline() - pipeline.add_node(name="classifier", component=classifier, inputs=["Query"]) - pipeline.add_node(name="KeywordNode", component=KeywordOutput(), inputs=["classifier.output_2"]) - pipeline.add_node(name="QuestionNode", component=QuestionOutput(), inputs=["classifier.output_1"]) - output = pipeline.run(query="morse code") - assert output["output"] == "keyword" - - output = pipeline.run(query="How old is John?") - assert output["output"] == "question" - - -def test_join_merge_no_weights(docs): - document_store = InMemoryDocumentStore(embedding_dim=768, similarity="dot_product", use_bm25=True) - document_store.write_documents(documents=docs) - bm25 = BM25Retriever(document_store=document_store) - dpr = DensePassageRetriever( - document_store=document_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base", - use_gpu=False, - ) - document_store.update_embeddings(dpr) - - query = "Where does Carla live?" - - join_node = JoinDocuments(join_mode="merge") - p = Pipeline() - p.add_node(component=bm25, name="R1", inputs=["Query"]) - p.add_node(component=dpr, name="R2", inputs=["Query"]) - p.add_node(component=join_node, name="Join", inputs=["R1", "R2"]) - results = p.run(query=query) - assert len(results["documents"]) == 5 - - -def test_join_merge_with_weights(docs): - document_store = InMemoryDocumentStore(embedding_dim=768, similarity="dot_product", use_bm25=True) - document_store.write_documents(documents=docs) - bm25 = BM25Retriever(document_store=document_store) - dpr = DensePassageRetriever( - document_store=document_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base", - use_gpu=False, - ) - document_store.update_embeddings(dpr) - - query = "Where does Carla live?" - - join_node = JoinDocuments(join_mode="merge", weights=[1000, 1], top_k_join=2) - p = Pipeline() - p.add_node(component=bm25, name="R1", inputs=["Query"]) - p.add_node(component=dpr, name="R2", inputs=["Query"]) - p.add_node(component=join_node, name="Join", inputs=["R1", "R2"]) - results = p.run(query=query) - assert math.isclose(results["documents"][0].score, 0.5336782589721345, rel_tol=0.0001) - assert len(results["documents"]) == 2 - - -def test_join_concatenate(docs): - document_store = InMemoryDocumentStore(embedding_dim=768, similarity="dot_product", use_bm25=True) - document_store.write_documents(documents=docs) - bm25 = BM25Retriever(document_store=document_store) - dpr = DensePassageRetriever( - document_store=document_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base", - use_gpu=False, - ) - document_store.update_embeddings(dpr) - - query = "Where does Carla live?" - - join_node = JoinDocuments(join_mode="concatenate") - p = Pipeline() - p.add_node(component=bm25, name="R1", inputs=["Query"]) - p.add_node(component=dpr, name="R2", inputs=["Query"]) - p.add_node(component=join_node, name="Join", inputs=["R1", "R2"]) - results = p.run(query=query) - assert len(results["documents"]) == 5 - - -def test_join_concatenate_with_topk(docs): - document_store = InMemoryDocumentStore(embedding_dim=768, similarity="dot_product", use_bm25=True) - document_store.write_documents(documents=docs) - bm25 = BM25Retriever(document_store=document_store) - dpr = DensePassageRetriever( - document_store=document_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base", - use_gpu=False, - ) - document_store.update_embeddings(dpr) - - query = "Where does Carla live?" - - join_node = JoinDocuments(join_mode="concatenate") - p = Pipeline() - p.add_node(component=bm25, name="R1", inputs=["Query"]) - p.add_node(component=dpr, name="R2", inputs=["Query"]) - p.add_node(component=join_node, name="Join", inputs=["R1", "R2"]) - one_result = p.run(query=query, params={"Join": {"top_k_join": 1}}) - two_results = p.run(query=query, params={"Join": {"top_k_join": 2}}) - assert len(one_result["documents"]) == 1 - assert len(two_results["documents"]) == 2 - - -def test_join_with_reader(docs): - document_store = InMemoryDocumentStore(embedding_dim=768, similarity="dot_product", use_bm25=True) - document_store.write_documents(documents=docs) - bm25 = BM25Retriever(document_store=document_store) - dpr = DensePassageRetriever( - document_store=document_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base", - use_gpu=False, - ) - document_store.update_embeddings(dpr) - reader = FARMReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", use_gpu=False, top_k_per_sample=5, num_processes=0 - ) - - query = "Where does Carla live?" - - join_node = JoinDocuments() - p = Pipeline() - p.add_node(component=bm25, name="R1", inputs=["Query"]) - p.add_node(component=dpr, name="R2", inputs=["Query"]) - p.add_node(component=join_node, name="Join", inputs=["R1", "R2"]) - p.add_node(component=reader, name="Reader", inputs=["Join"]) - results = p.run(query=query) - # check whether correct answer is within top 2 predictions - assert results["answers"][0].answer == "Berlin" or results["answers"][1].answer == "Berlin" - - -def test_join_with_rrf(docs): - document_store = InMemoryDocumentStore(embedding_dim=768, similarity="dot_product", use_bm25=True) - document_store.write_documents(documents=docs) - bm25 = BM25Retriever(document_store=document_store) - dpr = DensePassageRetriever( - document_store=document_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base", - use_gpu=False, - ) - document_store.update_embeddings(dpr) - - query = "Where does Carla live?" - - join_node = JoinDocuments(join_mode="reciprocal_rank_fusion") - p = Pipeline() - p.add_node(component=bm25, name="R1", inputs=["Query"]) - p.add_node(component=dpr, name="R2", inputs=["Query"]) - p.add_node(component=join_node, name="Join", inputs=["R1", "R2"]) - results = p.run(query=query) - - # list of precalculated expected results - expected_scores = [ - 0.03278688524590164, - 0.03200204813108039, - 0.03200204813108039, - 0.031009615384615385, - 0.031009615384615385, - ] - assert all( - doc.score == pytest.approx(expected_scores[idx], abs=1e-3) for idx, doc in enumerate(results["documents"]) - ) diff --git a/e2e/pipelines/test_standard_pipelines.py b/e2e/pipelines/test_standard_pipelines.py deleted file mode 100644 index f25ddcd13b..0000000000 --- a/e2e/pipelines/test_standard_pipelines.py +++ /dev/null @@ -1,399 +0,0 @@ -import os -import asyncio - -import pytest - -from haystack.document_stores import InMemoryDocumentStore, ElasticsearchDocumentStore -from haystack.nodes.retriever.web import WebRetriever -from haystack.pipelines import ( - Pipeline, - FAQPipeline, - DocumentSearchPipeline, - MostSimilarDocumentsPipeline, - WebQAPipeline, - SearchSummarizationPipeline, -) -from haystack.nodes import EmbeddingRetriever, PromptNode, BM25Retriever, TransformersSummarizer -from haystack.nodes.asyncio.sleeper import Sleeper # noqa # pylint: disable=unused-import -from haystack.schema import Document - - -def test_faq_pipeline(): - documents = [ - {"content": f"How to test module-{i}?", "meta": {"source": f"wiki{i}", "answer": f"Using tests for module-{i}"}} - for i in range(1, 6) - ] - document_store = InMemoryDocumentStore() - retriever = EmbeddingRetriever(document_store=document_store, embedding_model="deepset/sentence_bert") - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - pipeline = FAQPipeline(retriever=retriever) - - output = pipeline.run(query="How to test this?", params={"Retriever": {"top_k": 3}}) - assert len(output["answers"]) == 3 - assert output["query"].startswith("How to") - assert output["answers"][0].answer.startswith("Using tests") - - output = pipeline.run( - query="How to test this?", params={"Retriever": {"filters": {"source": ["wiki2"]}, "top_k": 5}} - ) - assert len(output["answers"]) == 1 - - -def test_document_search_pipeline(): - documents = [ - {"content": "Sample text for document-1", "meta": {"source": "wiki1"}}, - {"content": "Sample text for document-2", "meta": {"source": "wiki2"}}, - {"content": "Sample text for document-3", "meta": {"source": "wiki3"}}, - {"content": "Sample text for document-4", "meta": {"source": "wiki4"}}, - {"content": "Sample text for document-5", "meta": {"source": "wiki5"}}, - ] - document_store = InMemoryDocumentStore() - retriever = EmbeddingRetriever(document_store=document_store, embedding_model="deepset/sentence_bert") - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - pipeline = DocumentSearchPipeline(retriever=retriever) - output = pipeline.run(query="How to test this?", params={"top_k": 4}) - assert len(output.get("documents", [])) == 4 - - output = pipeline.run(query="How to test this?", params={"filters": {"source": ["wiki2"]}, "top_k": 5}) - assert len(output["documents"]) == 1 - - -def test_most_similar_documents_pipeline(): - documents = [ - {"id": "a", "content": "Sample text for document-1", "meta": {"source": "wiki1"}}, - {"id": "b", "content": "Sample text for document-2", "meta": {"source": "wiki2"}}, - {"content": "Sample text for document-3", "meta": {"source": "wiki3"}}, - {"content": "Sample text for document-4", "meta": {"source": "wiki4"}}, - {"content": "Sample text for document-5", "meta": {"source": "wiki5"}}, - ] - document_store = InMemoryDocumentStore() - retriever = EmbeddingRetriever(document_store=document_store, embedding_model="deepset/sentence_bert") - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - docs_id: list = ["a", "b"] - pipeline = MostSimilarDocumentsPipeline(document_store=document_store) - list_of_documents = pipeline.run(document_ids=docs_id) - - assert len(list_of_documents[0]) > 1 - assert isinstance(list_of_documents, list) - assert len(list_of_documents) == len(docs_id) - - for another_list in list_of_documents: - assert isinstance(another_list, list) - for document in another_list: - assert isinstance(document, Document) - assert isinstance(document.id, str) - assert isinstance(document.content, str) - - -async def test_most_similar_documents_pipeline_with_filters(): - documents = [ - {"id": "a", "content": "Sample text for document-1", "meta": {"source": "wiki1"}}, - {"id": "b", "content": "Sample text for document-2", "meta": {"source": "wiki2"}}, - {"content": "Sample text for document-3", "meta": {"source": "wiki3"}}, - {"content": "Sample text for document-4", "meta": {"source": "wiki4"}}, - {"content": "Sample text for document-5", "meta": {"source": "wiki5"}}, - ] - document_store = InMemoryDocumentStore() - retriever = EmbeddingRetriever(document_store=document_store, embedding_model="deepset/sentence_bert") - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - docs_id: list = ["a", "b"] - filters = {"source": ["wiki3", "wiki4", "wiki5"]} - pipeline = MostSimilarDocumentsPipeline(document_store=document_store) - list_of_documents = pipeline.run(document_ids=docs_id, filters=filters) - - assert len(list_of_documents[0]) > 1 - assert isinstance(list_of_documents, list) - assert len(list_of_documents) == len(docs_id) - - for another_list in list_of_documents: - assert isinstance(another_list, list) - for document in another_list: - assert isinstance(document, Document) - assert isinstance(document.id, str) - assert isinstance(document.content, str) - assert document.meta["source"] in ["wiki3", "wiki4", "wiki5"] - - -@pytest.mark.asyncio -async def test_query_and_indexing_pipeline(samples_path): - # test correct load of indexing pipeline from yaml - pipeline = Pipeline.load_from_yaml( - samples_path / "pipelines" / "test.haystack-pipeline.yml", pipeline_name="indexing_pipeline" - ) - await pipeline._arun(file_paths=samples_path / "pipelines" / "sample_pdf_1.pdf") - # test correct load of query pipeline from yaml - pipeline = Pipeline.load_from_yaml( - samples_path / "pipelines" / "test.haystack-pipeline.yml", pipeline_name="query_pipeline" - ) - prediction = await pipeline._arun( - query="Who made the PDF specification?", params={"Retriever": {"top_k": 2}, "Reader": {"top_k": 1}} - ) - assert prediction["query"] == "Who made the PDF specification?" - assert prediction["answers"][0].answer == "Adobe Systems" - assert "_debug" not in prediction.keys() - - -@pytest.mark.asyncio -async def test_async_concurrent_complex_pipeline(samples_path): - documents = [ - {"content": "How to test module-1?", "meta": {"source": "wiki1", "answer": "Using tests for module-1"}}, - {"content": "How to test module-2?", "meta": {"source": "wiki2", "answer": "Using tests for module-2"}}, - {"content": "How to test module-3?", "meta": {"source": "wiki3", "answer": "Using tests for module-3"}}, - {"content": "How to test module-4?", "meta": {"source": "wiki4", "answer": "Using tests for module-4"}}, - {"content": "How to test module-5?", "meta": {"source": "wiki5", "answer": "Using tests for module-5"}}, - ] - document_store = ElasticsearchDocumentStore() - document_store.write_documents(documents) - - # test correct load of indexing pipeline from yaml - pipeline = Pipeline.load_from_yaml(samples_path / "pipelines" / "async_test_pipeline.yml", pipeline_name="query") - queries = [ - "How to test module-1?", - "How to test module-2?", - "How to test module-3?", - "How to test module-4?", - "How to test module-5?", - ] - futures = [] - for query in queries: - future = pipeline._arun(query=query) - futures.append(future) - - await asyncio.gather(*futures) - - -@pytest.mark.asyncio -async def test_async_sequential_complex_pipeline(samples_path): - documents = [ - {"content": "How to test module-1?", "meta": {"source": "wiki1", "answer": "Using tests for module-1"}}, - {"content": "How to test module-2?", "meta": {"source": "wiki2", "answer": "Using tests for module-2"}}, - {"content": "How to test module-3?", "meta": {"source": "wiki3", "answer": "Using tests for module-3"}}, - {"content": "How to test module-4?", "meta": {"source": "wiki4", "answer": "Using tests for module-4"}}, - {"content": "How to test module-5?", "meta": {"source": "wiki5", "answer": "Using tests for module-5"}}, - ] - document_store = ElasticsearchDocumentStore() - document_store.write_documents(documents) - - # test correct load of indexing pipeline from yaml - pipeline = Pipeline.load_from_yaml(samples_path / "pipelines" / "async_test_pipeline.yml", pipeline_name="query") - queries = [ - "How to test module-1?", - "How to test module-2?", - "How to test module-3?", - "How to test module-4?", - "How to test module-5?", - ] - for query in queries: - await pipeline._arun(query=query) - - -@pytest.mark.skipif( - not os.environ.get("OPENAI_API_KEY", None), - reason="Please export an env var called OPENAI_API_KEY containing the OpenAI API key to run this test.", -) -@pytest.mark.skipif( - not os.environ.get("SERPERDEV_API_KEY", None), - reason="Please export an env var called SERPERDEV_API_KEY containing the SerperDev key to run this test.", -) -def test_webqa_pipeline(): - search_key = os.environ.get("SERPERDEV_API_KEY") - openai_key = os.environ.get("OPENAI_API_KEY") - pn = PromptNode( - "text-davinci-003", - api_key=openai_key, - max_length=256, - default_prompt_template="question-answering-with-document-scores", - ) - web_retriever = WebRetriever(api_key=search_key, top_search_results=2) - pipeline = WebQAPipeline(retriever=web_retriever, prompt_node=pn) - result = pipeline.run(query="Who is the father of Arya Stark?") - assert isinstance(result, dict) - assert len(result["results"]) == 1 - answer = result["results"][0] - assert "stark" in answer.lower() or "ned" in answer.lower() - - -def test_faq_pipeline_batch(): - documents = [ - {"content": "How to test module-1?", "meta": {"source": "wiki1", "answer": "Using tests for module-1"}}, - {"content": "How to test module-2?", "meta": {"source": "wiki2", "answer": "Using tests for module-2"}}, - {"content": "How to test module-3?", "meta": {"source": "wiki3", "answer": "Using tests for module-3"}}, - {"content": "How to test module-4?", "meta": {"source": "wiki4", "answer": "Using tests for module-4"}}, - {"content": "How to test module-5?", "meta": {"source": "wiki5", "answer": "Using tests for module-5"}}, - ] - document_store = InMemoryDocumentStore(embedding_dim=384) - retriever = EmbeddingRetriever( - document_store=document_store, embedding_model="sentence-transformers/all-MiniLM-L6-v2" - ) - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - pipeline = FAQPipeline(retriever=retriever) - - output = pipeline.run_batch(queries=["How to test this?", "How to test this?"], params={"Retriever": {"top_k": 3}}) - assert len(output["answers"]) == 2 # 2 queries - assert len(output["answers"][0]) == 3 # 3 answers per query - assert output["queries"][0].startswith("How to") - assert output["answers"][0][0].answer.startswith("Using tests") - - -def test_document_search_pipeline_batch(): - documents = [ - {"content": "Sample text for document-1", "meta": {"source": "wiki1"}}, - {"content": "Sample text for document-2", "meta": {"source": "wiki2"}}, - {"content": "Sample text for document-3", "meta": {"source": "wiki3"}}, - {"content": "Sample text for document-4", "meta": {"source": "wiki4"}}, - {"content": "Sample text for document-5", "meta": {"source": "wiki5"}}, - ] - document_store = InMemoryDocumentStore(embedding_dim=384) - retriever = EmbeddingRetriever( - document_store=document_store, embedding_model="sentence-transformers/all-MiniLM-L6-v2" - ) - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - pipeline = DocumentSearchPipeline(retriever=retriever) - output = pipeline.run_batch(queries=["How to test this?", "How to test this?"], params={"top_k": 4}) - assert len(output["documents"]) == 2 # 2 queries - assert len(output["documents"][0]) == 4 # 4 docs per query - - -def test_most_similar_documents_pipeline_batch(): - documents = [ - {"id": "a", "content": "Sample text for document-1", "meta": {"source": "wiki1"}}, - {"id": "b", "content": "Sample text for document-2", "meta": {"source": "wiki2"}}, - {"content": "Sample text for document-3", "meta": {"source": "wiki3"}}, - {"content": "Sample text for document-4", "meta": {"source": "wiki4"}}, - {"content": "Sample text for document-5", "meta": {"source": "wiki5"}}, - ] - document_store = InMemoryDocumentStore(embedding_dim=384) - retriever = EmbeddingRetriever( - document_store=document_store, embedding_model="sentence-transformers/all-MiniLM-L6-v2" - ) - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - docs_id: list = ["a", "b"] - pipeline = MostSimilarDocumentsPipeline(document_store=document_store) - list_of_documents = pipeline.run_batch(document_ids=docs_id) - - assert len(list_of_documents[0]) > 1 - assert isinstance(list_of_documents, list) - assert len(list_of_documents) == len(docs_id) - - for another_list in list_of_documents: - assert isinstance(another_list, list) - for document in another_list: - assert isinstance(document, Document) - assert isinstance(document.id, str) - assert isinstance(document.content, str) - - -def test_most_similar_documents_pipeline_with_filters_batch(): - documents = [ - {"id": "a", "content": "Sample text for document-1", "meta": {"source": "wiki1"}}, - {"id": "b", "content": "Sample text for document-2", "meta": {"source": "wiki2"}}, - {"content": "Sample text for document-3", "meta": {"source": "wiki3"}}, - {"content": "Sample text for document-4", "meta": {"source": "wiki4"}}, - {"content": "Sample text for document-5", "meta": {"source": "wiki5"}}, - ] - document_store = InMemoryDocumentStore(embedding_dim=384) - retriever = EmbeddingRetriever( - document_store=document_store, embedding_model="sentence-transformers/all-MiniLM-L6-v2" - ) - document_store = InMemoryDocumentStore(embedding_dim=384) - document_store.write_documents(documents) - document_store.update_embeddings(retriever) - - docs_id: list = ["a", "b"] - filters = {"source": ["wiki3", "wiki4", "wiki5"]} - pipeline = MostSimilarDocumentsPipeline(document_store=document_store) - list_of_documents = pipeline.run_batch(document_ids=docs_id, filters=filters) - - assert len(list_of_documents[0]) > 1 - assert isinstance(list_of_documents, list) - assert len(list_of_documents) == len(docs_id) - - for another_list in list_of_documents: - assert isinstance(another_list, list) - for document in another_list: - assert isinstance(document, Document) - assert isinstance(document.id, str) - assert isinstance(document.content, str) - assert document.meta["source"] in ["wiki3", "wiki4", "wiki5"] - - -def test_summarization_pipeline(): - docs = [ - Document( - content=""" - PG&E stated it scheduled the blackouts in response to forecasts for high winds amid dry conditions. - The aim is to reduce the risk of wildfires. Nearly 800 thousand customers were scheduled to be affected - by the shutoffs which were expected to last through at least midday tomorrow. - """ - ), - Document( - content=""" - The Eiffel Tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, and the tallest - structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. During its construction, - the Eiffel Tower surpassed the Washington Monument to become the tallest man-made structure in the world, a - title it held for 41 years until the Chrysler Building in New York City was finished in 1930. It was the first - structure to reach a height of 300 metres. Due to the addition of a broadcasting aerial at the top of the tower - in 1957, it is now taller than the Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, the Eiffel - Tower is the second tallest free-standing structure in France after the Millau Viaduct. - """ - ), - ] - summarizer = TransformersSummarizer(model_name_or_path="sshleifer/distilbart-xsum-12-6", use_gpu=False) - - ds = InMemoryDocumentStore(use_bm25=True) - retriever = BM25Retriever(document_store=ds) - ds.write_documents(docs) - - query = "Eiffel Tower" - pipeline = SearchSummarizationPipeline(retriever=retriever, summarizer=summarizer, return_in_answer_format=True) - output = pipeline.run(query=query, params={"Retriever": {"top_k": 1}}) - answers = output["answers"] - assert len(answers) == 1 - assert answers[0]["answer"].strip() == "The Eiffel Tower is one of the world's tallest structures." - - -def test_summarization_pipeline_one_summary(): - split_docs = [ - Document( - content=""" - The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, and the tallest structure in Paris. - Its base is square, measuring 125 metres (410 ft) on each side. During its construction, the Eiffel Tower surpassed the - Washington Monument to become the tallest man-made structure in the world, a title it held for 41 years until the Chrysler - Building in New York City was finished in 1930. - """ - ), - Document( - content=""" - It was the first structure to reach a height of 300 metres. Due to the addition of a broadcasting aerial at the - top of the tower in 1957, it is now taller than the Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, - the Eiffel Tower is the second tallest free-standing structure in France after the Millau Viaduct. - """ - ), - ] - ds = InMemoryDocumentStore(use_bm25=True) - retriever = BM25Retriever(document_store=ds) - ds.write_documents(split_docs) - summarizer = TransformersSummarizer(model_name_or_path="sshleifer/distilbart-xsum-12-6", use_gpu=False) - - query = "Eiffel Tower" - pipeline = SearchSummarizationPipeline( - retriever=retriever, summarizer=summarizer, generate_single_summary=True, return_in_answer_format=True - ) - output = pipeline.run(query=query, params={"Retriever": {"top_k": 2}}) - answers = output["answers"] - assert len(answers) == 1 - assert answers[0]["answer"].strip() == "The Eiffel Tower was built in 1924 in Paris, France." diff --git a/examples/agent_multihop_qa.py b/examples/agent_multihop_qa.py deleted file mode 100644 index fba2517774..0000000000 --- a/examples/agent_multihop_qa.py +++ /dev/null @@ -1,116 +0,0 @@ -import os - -from haystack.agents import Agent, Tool -from haystack.agents.base import ToolsManager -from haystack.agents.types import AgentToolLogger -from haystack.nodes import PromptNode, PromptTemplate -from haystack.nodes.retriever.web import WebRetriever -from haystack.pipelines import WebQAPipeline - -search_key = os.environ.get("SERPERDEV_API_KEY") -if not search_key: - raise ValueError("Please set the SERPERDEV_API_KEY environment variable") - -openai_key = os.environ.get("OPENAI_API_KEY") -if not openai_key: - raise ValueError("Please set the OPENAI_API_KEY environment variable") - - -pn = PromptNode( - "gpt-3.5-turbo", - api_key=openai_key, - max_length=256, - default_prompt_template="question-answering-with-document-scores", -) -web_retriever = WebRetriever(api_key=search_key) -pipeline = WebQAPipeline(retriever=web_retriever, prompt_node=pn) - -few_shot_prompt = """ -You are a helpful and knowledgeable agent. To achieve your goal of answering complex questions correctly, you have access to the following tools: - -Search: useful for when you need to Google questions. You should ask targeted questions, for example, Who is Anthony Dirrell's brother? - -To answer questions, you'll need to go through multiple steps involving step-by-step thinking and selecting appropriate tools and their inputs; tools will respond with observations. When you are ready for a final answer, respond with the `Final Answer:` -Examples: -## -Question: Anthony Dirrell is the brother of which super middleweight title holder? -Thought: Let's think step by step. To answer this question, we first need to know who Anthony Dirrell is. -Tool: Search -Tool Input: Who is Anthony Dirrell? -Observation: Boxer -Thought: We've learned Anthony Dirrell is a Boxer. Now, we need to find out who his brother is. -Tool: Search -Tool Input: Who is Anthony Dirrell brother? -Observation: Andre Dirrell -Thought: We've learned Andre Dirrell is Anthony Dirrell's brother. Now, we need to find out what title Andre Dirrell holds. -Tool: Search -Tool Input: What is the Andre Dirrell title? -Observation: super middleweight -Thought: We've learned Andre Dirrell title is super middleweight. Now, we can answer the question. -Final Answer: Andre Dirrell -## -Question: What year was the party of the winner of the 1971 San Francisco mayoral election founded? -Thought: Let's think step by step. To answer this question, we first need to know who won the 1971 San Francisco mayoral election. -Tool: Search -Tool Input: Who won the 1971 San Francisco mayoral election? -Observation: Joseph Alioto -Thought: We've learned Joseph Alioto won the 1971 San Francisco mayoral election. Now, we need to find out what party he belongs to. -Tool: Search -Tool Input: What party does Joseph Alioto belong to? -Observation: Democratic Party -Thought: We've learned Democratic Party is the party of Joseph Alioto. Now, we need to find out when the Democratic Party was founded. -Tool: Search -Tool Input: When was the Democratic Party founded? -Observation: 1828 -Thought: We've learned the Democratic Party was founded in 1828. Now, we can answer the question. -Final Answer: 1828 -## -Question: Right Back At It Again contains lyrics co-written by the singer born in what city? -Thought: Let's think step by step. To answer this question, we first need to know what song the question is referring to. -Tool: Search -Tool Input: What is the song Right Back At It Again? -Observation: "Right Back at It Again" is the song by A Day to Remember -Thought: We've learned Right Back At It Again is a song by A Day to Remember. Now, we need to find out who co-wrote the song. -Tool: Search -Tool Input: Who co-wrote the song Right Back At It Again? -Observation: Jeremy McKinnon -Thought: We've learned Jeremy McKinnon co-wrote the song Right Back At It Again. Now, we need to find out what city he was born in. -Tool: Search -Tool Input: Where was Jeremy McKinnon born? -Observation: Gainsville, Florida -Thought: We've learned Gainsville, Florida is the city Jeremy McKinnon was born in. Now, we can answer the question. -Final Answer: Gainsville, Florida -## -Question: {query} -Thought: -{transcript} -""" -few_shot_agent_template = PromptTemplate(few_shot_prompt) -prompt_node = PromptNode( - "gpt-3.5-turbo", api_key=os.environ.get("OPENAI_API_KEY"), max_length=512, stop_words=["Observation:"] -) - -web_qa_tool = Tool( - name="Search", - pipeline_or_node=pipeline, - description="useful for when you need to Google questions.", - output_variable="results", -) - -agent = Agent( - prompt_node=prompt_node, prompt_template=few_shot_agent_template, tools_manager=ToolsManager([web_qa_tool]) -) -atl = AgentToolLogger(agent_events=agent.callback_manager, tool_events=agent.tm.callback_manager) - -hotpot_questions = [ - "What year was the father of the Princes in the Tower born?", - "Name the movie in which the daughter of Noel Harrison plays Violet Trefusis.", - "Where was the actress who played the niece in the Priest film born?", - "Which author is English: John Braine or Studs Terkel?", -] -verbose = False -for question in hotpot_questions: - result = agent.run(query=question) - print(f"\n{result}") - if verbose: - print(f"\n{atl.logs}") diff --git a/examples/arxiv_paper_summary.py b/examples/arxiv_paper_summary.py deleted file mode 100644 index ca92d2f1c1..0000000000 --- a/examples/arxiv_paper_summary.py +++ /dev/null @@ -1,34 +0,0 @@ -import os -from haystack.nodes import PromptNode, LinkContentFetcher, PromptTemplate -from haystack import Pipeline - -anthropic_key = os.environ.get("ANTHROPIC_API_KEY") -if not anthropic_key: - raise ValueError("Please set the ANTHROPIC_API_KEY environment variable") - -alt_user_agents = [ - "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15" -] - -retriever = LinkContentFetcher(user_agents=alt_user_agents) -pt = PromptTemplate( - "Given the content below, create a summary consisting of three sections: Objectives, " - "Implementation and Learnings/Conclusions.\n" - "Each section should have at least three bullet points. \n" - "In the content below disregard References section.\n\n: {documents}" -) - -prompt_node = PromptNode( - "claude-instant-1", api_key=anthropic_key, max_length=512, default_prompt_template=pt, model_kwargs={"stream": True} -) - -pipeline = Pipeline() -pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) -pipeline.add_node(component=prompt_node, name="PromptNode", inputs=["Retriever"]) - -research_papers = ["https://arxiv.org/pdf/2307.03172.pdf", "https://arxiv.org/pdf/1706.03762.pdf"] - -for research_paper in research_papers: - print(f"Research paper summary: {research_paper}") - pipeline.run(research_paper) - print("\n\n\n") diff --git a/examples/basic_faq_pipeline.py b/examples/basic_faq_pipeline.py deleted file mode 100644 index e198ca5367..0000000000 --- a/examples/basic_faq_pipeline.py +++ /dev/null @@ -1,76 +0,0 @@ -# Disable pylint errors for logging basicConfig -# pylint: disable=no-logging-basicconfig -import logging - -import pandas as pd - -from haystack.document_stores import ElasticsearchDocumentStore -from haystack.nodes import EmbeddingRetriever -from haystack.nodes.other.docs2answers import Docs2Answers -from haystack.pipelines import Pipeline -from haystack.utils import fetch_archive_from_http, launch_es, print_answers - -logging.basicConfig(format="%(levelname)s - %(name)s - %(message)s", level=logging.WARNING) -logging.getLogger("haystack").setLevel(logging.INFO) - - -def basic_faq_pipeline(): - document_store = ElasticsearchDocumentStore( - host="localhost", - username="", - password="", - index="example-document", - embedding_field="question_emb", - embedding_dim=384, - excluded_meta_data=["question_emb"], - similarity="cosine", - ) - - retriever = EmbeddingRetriever( - document_store=document_store, - embedding_model="sentence-transformers/all-MiniLM-L6-v2", - use_gpu=True, - scale_score=False, - ) - - doc_to_answers = Docs2Answers() - - doc_dir = "data/basic_faq_pipeline" - s3_url = "https://core-engineering.s3.eu-central-1.amazonaws.com/public/scripts/small_faq_covid.csv1.zip" - fetch_archive_from_http(url=s3_url, output_dir=doc_dir) - - df = pd.read_csv(f"{doc_dir}/small_faq_covid.csv") - - # Minimal cleaning - df.fillna(value="", inplace=True) - df["question"] = df["question"].apply(lambda x: x.strip()) - print(df.head()) - - # Get embeddings for our questions from the FAQs - questions = list(df["question"].values) - df["question_emb"] = retriever.embed_queries(queries=questions).tolist() - df = df.rename(columns={"question": "content"}) - - # Convert Dataframe to list of dicts and index them in our DocumentStore - docs_to_index = df.to_dict(orient="records") - document_store.write_documents(docs_to_index) - document_store.update_embeddings(retriever) - - # Initialize a Pipeline (this time without a reader) and ask questions - pipeline = Pipeline() - pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - pipeline.add_node(component=doc_to_answers, name="Docs2Answers", inputs=["Retriever"]) - - # Ask a question - prediction = pipeline.run(query="How is the virus spreading?", params={"Retriever": {"top_k": 10}}) - - print_answers(prediction, details="medium") - - # Remove the index once we're done to save space - document_store.delete_index(index="example-document") - return prediction - - -if __name__ == "__main__": - launch_es() - basic_faq_pipeline() diff --git a/examples/basic_qa_pipeline.py b/examples/basic_qa_pipeline.py deleted file mode 100644 index 97988627ee..0000000000 --- a/examples/basic_qa_pipeline.py +++ /dev/null @@ -1,79 +0,0 @@ -# Disable pylint errors for logging basicConfig -# pylint: disable=no-logging-basicconfig -import logging -from pathlib import Path - -from haystack.document_stores import ElasticsearchDocumentStore -from haystack.nodes import BM25Retriever, FARMReader -from haystack.nodes.file_classifier import FileTypeClassifier -from haystack.nodes.file_converter import TextConverter -from haystack.nodes.preprocessor import PreProcessor -from haystack.pipelines import Pipeline -from haystack.utils import fetch_archive_from_http, launch_es, print_answers - -logging.basicConfig(format="%(levelname)s - %(name)s - %(message)s", level=logging.WARNING) -logging.getLogger("haystack").setLevel(logging.INFO) - - -def basic_qa_pipeline(): - # Initialize a DocumentStore - document_store = ElasticsearchDocumentStore(host="localhost", username="", password="", index="example-document") - - # fetch, pre-process and write documents - doc_dir = "data/basic_qa_pipeline" - s3_url = "https://core-engineering.s3.eu-central-1.amazonaws.com/public/scripts/wiki_gameofthrones_txt1.zip" - fetch_archive_from_http(url=s3_url, output_dir=doc_dir) - - file_paths = [p for p in Path(doc_dir).glob("**/*")] - files_metadata = [{"name": path.name} for path in file_paths] - - # Indexing Pipeline - indexing_pipeline = Pipeline() - - # Makes sure the file is a TXT file (FileTypeClassifier node) - classifier = FileTypeClassifier() - indexing_pipeline.add_node(classifier, name="Classifier", inputs=["File"]) - - # Converts a file into text and performs basic cleaning (TextConverter node) - text_converter = TextConverter(remove_numeric_tables=True) - indexing_pipeline.add_node(text_converter, name="Text_converter", inputs=["Classifier.output_1"]) - - # - Pre-processes the text by performing splits and adding metadata to the text (Preprocessor node) - preprocessor = PreProcessor( - clean_whitespace=True, - clean_empty_lines=True, - split_length=100, - split_overlap=50, - split_respect_sentence_boundary=True, - ) - indexing_pipeline.add_node(preprocessor, name="Preprocessor", inputs=["Text_converter"]) - - # - Writes the resulting documents into the document store - indexing_pipeline.add_node(document_store, name="Document_Store", inputs=["Preprocessor"]) - - # Then we run it with the documents and their metadata as input - indexing_pipeline.run(file_paths=file_paths, meta=files_metadata) - - # Initialize Retriever & Reader - retriever = BM25Retriever(document_store=document_store) - reader = FARMReader(model_name_or_path="deepset/roberta-base-squad2", use_gpu=True) - - # Query Pipeline - pipeline = Pipeline() - pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - pipeline.add_node(component=reader, name="Reader", inputs=["Retriever"]) - - prediction = pipeline.run( - query="Who is the father of Arya Stark?", params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 5}} - ) - - print_answers(prediction, details="minimum") - - # Remove the index once we're done to save space - document_store.delete_index(index="example-document") - return prediction - - -if __name__ == "__main__": - launch_es() - basic_qa_pipeline() diff --git a/examples/conversational_agent.py b/examples/conversational_agent.py deleted file mode 100644 index 78a084944e..0000000000 --- a/examples/conversational_agent.py +++ /dev/null @@ -1,66 +0,0 @@ -import os - -from haystack.agents.base import Tool -from haystack.agents.conversational import ConversationalAgent -from haystack.agents.memory import ConversationSummaryMemory -from haystack.nodes import PromptNode, WebRetriever, PromptTemplate -from haystack.pipelines import WebQAPipeline -from haystack.agents.types import Color - -search_api_key = os.environ.get("SEARCH_API_KEY") -if not search_api_key: - raise ValueError("Please set the SEARCH_API_KEY environment variable") -openai_api_key = os.environ.get("OPENAI_API_KEY") -if not openai_api_key: - raise ValueError("Please set the OPENAI_API_KEY environment variable") - -web_prompt = """ -Synthesize a comprehensive answer from the following most relevant paragraphs and the given question. -Provide a clear and concise answer, no longer than 10-20 words. -\n\n Paragraphs: {documents} \n\n Question: {query} \n\n Answer: -""" - -web_prompt_node = PromptNode( - "gpt-3.5-turbo", default_prompt_template=PromptTemplate(prompt=web_prompt), api_key=openai_api_key -) - -web_retriever = WebRetriever(api_key=search_api_key, top_search_results=3, mode="snippets") -pipeline = WebQAPipeline(retriever=web_retriever, prompt_node=web_prompt_node) -web_qa_tool = Tool( - name="Search", - pipeline_or_node=pipeline, - description="useful for when you need to Google questions if you cannot find answers in the the previous conversation", - output_variable="results", - logging_color=Color.MAGENTA, -) - -conversational_agent_prompt_node = PromptNode( - "gpt-3.5-turbo", - api_key=openai_api_key, - max_length=256, - stop_words=["Observation:"], - model_kwargs={"temperature": 0.5, "top_p": 0.9}, -) -memory = ConversationSummaryMemory(conversational_agent_prompt_node, summary_frequency=2) - -conversational_agent = ConversationalAgent( - prompt_node=conversational_agent_prompt_node, tools=[web_qa_tool], memory=memory -) - -test = False -if test: - questions = [ - "Why was Jamie Foxx recently hospitalized?", - "Where was he hospitalized?", - "What movie was he filming at the time?", - "Who is Jamie's female co-star in the movie he was filing at that time?", - "Tell me more about her, who is her partner?", - ] - for question in questions: - conversational_agent.run(question) -else: - while True: - user_input = input("\nHuman (type 'exit' or 'quit' to quit): ") - if user_input.lower() == "exit" or user_input.lower() == "quit": - break - response = conversational_agent.run(user_input) diff --git a/examples/getting_started.py b/examples/getting_started.py deleted file mode 100644 index af0d5012fa..0000000000 --- a/examples/getting_started.py +++ /dev/null @@ -1,34 +0,0 @@ -from haystack.document_stores import InMemoryDocumentStore -from haystack.utils import build_pipeline, add_example_data, print_answers - - -def getting_started(provider, API_KEY): - """ - This getting_started example shows you how to use LLMs with your data with a technique called Retrieval Augmented Generation - RAG. - - :param provider: We are model agnostic :) Here, you can choose from: "anthropic", "cohere", "huggingface", and "openai". - :param API_KEY: The API key matching the provider. - - """ - - # We support many different databases. Here we load a simple and lightweight in-memory database. - document_store = InMemoryDocumentStore(use_bm25=True) - - # Pipelines are the main abstraction in Haystack, they connect components like LLMs and databases. - pipeline = build_pipeline(provider, API_KEY, document_store) - - # Download and add Game of Thrones TXT articles to Haystack's database. - # You can also provide a folder with your local documents. - # You might need to install additional dependencies - look inside the function for more information. - add_example_data(document_store, "data/GoT_getting_started") - - # Ask a question on the data you just added. - result = pipeline.run(query="Who is the father of Arya Stark?") - - # For details such as which documents were used to generate the answer, look into the object. - print_answers(result, details="medium") - return result - - -if __name__ == "__main__": - getting_started(provider="openai", API_KEY="ADD KEY HERE") diff --git a/examples/hybrid_search_faq_pipeline.py b/examples/hybrid_search_faq_pipeline.py deleted file mode 100644 index d4fcba6cf0..0000000000 --- a/examples/hybrid_search_faq_pipeline.py +++ /dev/null @@ -1,85 +0,0 @@ -# import logging - -import pandas as pd - -from haystack.document_stores import ElasticsearchDocumentStore -from haystack.nodes import EmbeddingRetriever, BM25Retriever, JoinDocuments, SentenceTransformersRanker -from haystack.nodes.other.docs2answers import Docs2Answers -from haystack.utils import launch_es, print_answers, fetch_archive_from_http -from haystack.pipelines import Pipeline - -# logging.basicConfig(format="%(levelname)s - %(name)s - %(message)s", level=logging.WARNING) -# logging.getLogger("haystack").setLevel(logging.INFO) - - -def hybrid_search_faq_pipeline(): - document_store = ElasticsearchDocumentStore( - host="localhost", - username="", - password="", - index="document", - embedding_field="question_emb", - embedding_dim=384, - excluded_meta_data=["question_emb"], - similarity="cosine", - ) - - sparse_retriever = BM25Retriever(document_store=document_store) - dense_retriever = EmbeddingRetriever( - document_store=document_store, - embedding_model="sentence-transformers/all-MiniLM-L6-v2", - use_gpu=True, - scale_score=False, - ) - join_documents = JoinDocuments(join_mode="reciprocal_rank_fusion") - rerank = SentenceTransformersRanker(model_name_or_path="cross-encoder/ms-marco-MiniLM-L-6-v2") - - doc_to_answers = Docs2Answers() - - doc_dir = "data/basic_faq_pipeline" - s3_url = "https://core-engineering.s3.eu-central-1.amazonaws.com/public/scripts/small_faq_covid.csv1.zip" - fetch_archive_from_http(url=s3_url, output_dir=doc_dir) - - df = pd.read_csv(f"{doc_dir}/small_faq_covid.csv") - - # Minimal cleaning - df.fillna(value="", inplace=True) - df["question"] = df["question"].apply(lambda x: x.strip()) - print(df.head()) - - # Get embeddings for our questions from the FAQs - questions = list(df["question"].values) - df["question_emb"] = dense_retriever.embed_queries(queries=questions).tolist() - df = df.rename(columns={"question": "content"}) - - # Convert Dataframe to list of dicts and index them in our DocumentStore - docs_to_index = df.to_dict(orient="records") - document_store.write_documents(docs_to_index) - document_store.update_embeddings(retriever=dense_retriever) - - # Initialize a Pipeline (this time without a reader) and ask questions - pipeline = Pipeline() - pipeline.add_node(component=sparse_retriever, name="SparseRetriever", inputs=["Query"]) - pipeline.add_node(component=dense_retriever, name="DenseRetriever", inputs=["Query"]) - pipeline.add_node(component=join_documents, name="JoinDocuments", inputs=["SparseRetriever", "DenseRetriever"]) - pipeline.add_node(component=rerank, name="ReRanker", inputs=["JoinDocuments"]) - pipeline.add_node(component=doc_to_answers, name="Docs2Answers", inputs=["ReRanker"]) - - # Ask a question - prediction = pipeline.run( - query="How is the virus spreading?", - params={ - "SparseRetriever": {"top_k": 10}, - "DenseRetriever": {"top_k": 10}, - "JoinDocuments": {"top_k_join": 15}, - "ReRanker": {"top_k": 5}, - }, - ) - - print_answers(prediction, details="medium") - return prediction - - -if __name__ == "__main__": - launch_es() - hybrid_search_faq_pipeline() diff --git a/examples/link_content_blog_post_summary.py b/examples/link_content_blog_post_summary.py deleted file mode 100644 index 46d5280a72..0000000000 --- a/examples/link_content_blog_post_summary.py +++ /dev/null @@ -1,32 +0,0 @@ -import os -from haystack.nodes import PromptNode, LinkContentFetcher, PromptTemplate -from haystack import Pipeline - -anthropic_key = os.environ.get("ANTHROPIC_API_KEY") -if not anthropic_key: - raise ValueError("Please set the ANTHROPIC_API_KEY environment variable") - -retriever = LinkContentFetcher() -pt = PromptTemplate( - "Given the paragraphs of the blog post, " - "provide the main learnings and the final conclusion using short bullet points format." - "\n\nParagraphs: {documents}" -) - -prompt_node = PromptNode( - "claude-instant-1", api_key=anthropic_key, max_length=512, default_prompt_template=pt, model_kwargs={"stream": True} -) - -pipeline = Pipeline() -pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) -pipeline.add_node(component=prompt_node, name="PromptNode", inputs=["Retriever"]) - -blog_posts = [ - "https://pythonspeed.com/articles/base-image-python-docker-images/", - "https://lilianweng.github.io/posts/2023-06-23-agent/", -] - -for blog_post in blog_posts: - print(f"Blog post summary: {blog_post}") - pipeline.run(blog_post) - print("\n\n\n") diff --git a/examples/seq2seq_replacement.py b/examples/seq2seq_replacement.py deleted file mode 100644 index 4241dae873..0000000000 --- a/examples/seq2seq_replacement.py +++ /dev/null @@ -1,28 +0,0 @@ -from haystack import Document -from haystack.nodes import PromptNode, PromptTemplate - -p = PromptNode("vblagoje/bart_lfqa") - -# Start by defining a question/query -query = "Why does water heated to room temperature feel colder than the air around it?" - -# Given the question above, suppose the documents below were found in some document store -documents = [ - "when the skin is completely wet. The body continuously loses water by...", - "at greater pressures. There is an ambiguity, however, as to the meaning of the terms 'heating' and 'cooling'...", - "are not in a relation of thermal equilibrium, heat will flow from the hotter to the colder, by whatever pathway...", - "air condition and moving along a line of constant enthalpy toward a state of higher humidity. A simple example ...", - "Thermal contact conductance. In physics, thermal contact conductance is the study of heat conduction between solid ...", -] - - -# Manually concatenate the question and support documents into BART input -# conditioned_doc = "

" + "

".join([d for d in documents]) -# query_and_docs = "question: {} context: {}".format(query, conditioned_doc) - -# Or use the PromptTemplate as shown here -pt = PromptTemplate("lfqa", "question: {query} context: {join(documents, delimiter='

')}") # type: ignore [arg-type] - -res = p.prompt(prompt_template=pt, query=query, documents=[Document(d) for d in documents]) - -print(res) diff --git a/examples/talk_to_website.py b/examples/talk_to_website.py deleted file mode 100644 index 83de457c5c..0000000000 --- a/examples/talk_to_website.py +++ /dev/null @@ -1,77 +0,0 @@ -import logging -import os -from typing import Dict, Any - -from haystack import Pipeline -from haystack.document_stores import InMemoryDocumentStore -from haystack.nodes import PromptNode, PromptTemplate, TopPSampler -from haystack.nodes.ranker import LostInTheMiddleRanker -from haystack.nodes.retriever.web import WebRetriever - -search_key = os.environ.get("SERPERDEV_API_KEY") -if not search_key: - raise ValueError("Please set the SERPERDEV_API_KEY environment variable") - -models_config: Dict[str, Any] = { - "openai": {"api_key": os.environ.get("OPENAI_API_KEY"), "model_name": "gpt-3.5-turbo"}, - "anthropic": {"api_key": os.environ.get("ANTHROPIC_API_KEY"), "model_name": "claude-instant-1"}, - "hf": {"api_key": os.environ.get("HF_API_KEY"), "model_name": "tiiuae/falcon-7b-instruct"}, -} -prompt_text = """ -Synthesize a comprehensive answer from the provided paragraphs and the given question.\n -Focus on the question and avoid unnecessary information in your answer.\n -\n\n Paragraphs: {join(documents)} \n\n Question: {query} \n\n Answer: -""" - -stream = True -model: Dict[str, str] = models_config["openai"] -prompt_node = PromptNode( - model["model_name"], - default_prompt_template=PromptTemplate(prompt_text), - api_key=model["api_key"], - max_length=768, - model_kwargs={"stream": stream}, -) - -web_retriever = WebRetriever( - api_key=search_key, - allowed_domains=["haystack.deepset.ai"], - top_search_results=10, - mode="preprocessed_documents", - top_k=50, - cache_document_store=InMemoryDocumentStore(), -) - -pipeline = Pipeline() -pipeline.add_node(component=web_retriever, name="Retriever", inputs=["Query"]) -pipeline.add_node(component=TopPSampler(top_p=0.90), name="Sampler", inputs=["Retriever"]) -pipeline.add_node(component=LostInTheMiddleRanker(1024), name="LostInTheMiddleRanker", inputs=["Sampler"]) -pipeline.add_node(component=prompt_node, name="PromptNode", inputs=["LostInTheMiddleRanker"]) - -logging.disable(logging.CRITICAL) - -test = False -questions = [ - "What are the main benefits of using pipelines in Haystack?", - "Are there any ready-made pipelines available and why should I use them?", -] - -print(f"Running pipeline with {model['model_name']}\n") - -if test: - for question in questions: - if stream: - print("Answer:") - response = pipeline.run(query=question) - if not stream: - print(f"Answer: {response['results'][0]}") -else: - while True: - user_input = input("\nAsk question (type 'exit' or 'quit' to quit): ") - if user_input.lower() == "exit" or user_input.lower() == "quit": - break - if stream: - print("Answer:") - response = pipeline.run(query=user_input) - if not stream: - print(f"Answer: {response['results'][0]}") diff --git a/examples/test_basic_faq_pipeline.py b/examples/test_basic_faq_pipeline.py deleted file mode 100644 index b637ad7223..0000000000 --- a/examples/test_basic_faq_pipeline.py +++ /dev/null @@ -1,19 +0,0 @@ -from examples.basic_faq_pipeline import basic_faq_pipeline - -from haystack.schema import Answer - - -def test_basic_faq_pipeline(): - prediction = basic_faq_pipeline() - - assert prediction is not None - assert prediction["query"] == "How is the virus spreading?" - - assert len(prediction["answers"]) == 10 # top-k of Retriever - assert type(prediction["answers"][0]) == Answer - assert ( - prediction["answers"][0].answer - == """This virus was first detected in Wuhan City, Hubei Province, China. The first infections were linked to a live animal market, but the virus is now spreading from person-to-person. It’s important to note that person-to-person spread can happen on a continuum. Some viruses are highly contagious (like measles), while other viruses are less so.\n\nThe virus that causes COVID-19 seems to be spreading easily and sustainably in the community (“community spread”) in some affected geographic areas. Community spread means people have been infected with the virus in an area, including some who are not sure how or where they became infected.\n\nLearn what is known about the spread of newly emerged coronaviruses.""" - ) - assert prediction["answers"][0].score <= 1 - assert prediction["answers"][0].score >= 0 diff --git a/examples/test_basic_qa_pipeline.py b/examples/test_basic_qa_pipeline.py deleted file mode 100644 index d538979822..0000000000 --- a/examples/test_basic_qa_pipeline.py +++ /dev/null @@ -1,23 +0,0 @@ -from examples.basic_qa_pipeline import basic_qa_pipeline - -from haystack.schema import Answer, Document - - -def test_basic_qa_pipeline(): - prediction = basic_qa_pipeline() - - assert prediction is not None - assert prediction["query"] == "Who is the father of Arya Stark?" - - assert len(prediction["answers"]) == 5 # top-k of Reader - assert type(prediction["answers"][0]) == Answer - assert prediction["answers"][0].answer == "Ned" - assert prediction["answers"][0].score <= 1 - assert prediction["answers"][0].score >= 0 - assert prediction["answers"][0].meta["name"] == "43_Arya_Stark.txt" - - assert len(prediction["documents"]) == 10 # top-k of Retriever - assert type(prediction["documents"][0]) == Document - assert prediction["documents"][0].score <= 1 - assert prediction["documents"][0].score >= 0 - assert prediction["documents"][0].meta["name"] == "450_Baelor.txt" diff --git a/examples/test_getting_started.py b/examples/test_getting_started.py deleted file mode 100644 index ee4b99aa98..0000000000 --- a/examples/test_getting_started.py +++ /dev/null @@ -1,26 +0,0 @@ -import os - -import pytest - -from examples.getting_started import getting_started -from haystack.schema import Answer, Document - - -@pytest.mark.parametrize("provider", ["cohere", "huggingface", "openai"]) -def test_getting_started(provider): - if provider == "anthropic": - api_key = os.environ.get("ANTHROPIC_API_KEY", "") - elif provider == "cohere": - api_key = os.environ.get("COHERE_API_KEY", "") - elif provider == "huggingface": - api_key = os.environ.get("HUGGINGFACE_API_KEY", "") - elif provider == "openai": - api_key = os.environ.get("OPENAI_API_KEY", "") - - if api_key: - result = getting_started(provider=provider, API_KEY=api_key) - - # Testing only for functionality. Since model predictions from APIs might change, we cannot test those directly. - assert isinstance(result, dict) - assert type(result["answers"][0]) == Answer - assert type(result["documents"][0]) == Document diff --git a/examples/web_lfqa.py b/examples/web_lfqa.py deleted file mode 100644 index ff5dbe15e0..0000000000 --- a/examples/web_lfqa.py +++ /dev/null @@ -1,47 +0,0 @@ -import logging -import os - -from haystack.nodes import PromptNode, PromptTemplate, TopPSampler -from haystack.nodes.retriever.web import WebRetriever -from haystack.pipelines import WebQAPipeline - -search_key = os.environ.get("SERPERDEV_API_KEY") -if not search_key: - raise ValueError("Please set the SERPERDEV_API_KEY environment variable") - -openai_key = os.environ.get("OPENAI_API_KEY") -if not search_key: - raise ValueError("Please set the OPENAI_API_KEY environment variable") - -prompt_text = """ -Synthesize a comprehensive answer from the following most relevant paragraphs and the given question. -Provide a clear and concise response that summarizes the key points and information presented in the paragraphs. -Your answer should be in your own words and be no longer than 50 words. -\n\n Paragraphs: {documents} \n\n Question: {query} \n\n Answer: -""" - -prompt_node = PromptNode( - "text-davinci-003", default_prompt_template=PromptTemplate(prompt_text), api_key=openai_key, max_length=256 -) - -web_retriever = WebRetriever(api_key=search_key, top_search_results=5, mode="preprocessed_documents", top_k=30) -pipeline = WebQAPipeline(retriever=web_retriever, prompt_node=prompt_node, sampler=TopPSampler(top_p=0.8)) - -# Long-Form QA requiring multiple context paragraphs for the synthesis of an elaborate generative answer -questions = [ - "What are the advantages of EmbeddingRetriever in Haystack?", - "What are the advantages of PromptNode in Haystack?", - "What PromptModelInvocationLayer implementations are available in Haystack?", -] - -# Avoid all failed html parsing logs -logger = logging.getLogger("haystack.nodes.retriever.link_content") -logger.setLevel(logging.CRITICAL) -logger = logging.getLogger("boilerpy3") -logger.setLevel(logging.CRITICAL) - - -for q in questions: - print(f"Question: {q}") - response = pipeline.run(query=q) - print(f"Answer: {response['results'][0]}") diff --git a/examples/web_lfqa_with_rankers.py b/examples/web_lfqa_with_rankers.py deleted file mode 100644 index b175042b49..0000000000 --- a/examples/web_lfqa_with_rankers.py +++ /dev/null @@ -1,67 +0,0 @@ -import logging -import os -from typing import Dict, Any - -from haystack import Pipeline -from haystack.nodes import PromptNode, PromptTemplate, TopPSampler -from haystack.nodes.ranker import DiversityRanker, LostInTheMiddleRanker -from haystack.nodes.retriever import WebRetriever - -search_key = os.environ.get("SERPERDEV_API_KEY") -if not search_key: - raise ValueError("Please set the SERPERDEV_API_KEY environment variable") - -models_config: Dict[str, Any] = { - "openai": {"api_key": os.environ.get("OPENAI_API_KEY"), "model_name": "gpt-3.5-turbo"}, - "anthropic": {"api_key": os.environ.get("ANTHROPIC_API_KEY"), "model_name": "claude-instant-1"}, - "hf": {"api_key": os.environ.get("HF_API_KEY"), "model_name": "tiiuae/falcon-7b-instruct"}, -} -prompt_text = """ -Synthesize a comprehensive answer from the provided paragraphs and the given question.\n -Answer in full sentences and paragraphs, don't use bullet points or lists.\n -If the answer includes multiple chronological events, order them chronologically.\n -\n\n Paragraphs: {join(documents)} \n\n Question: {query} \n\n Answer: -""" - -stream = True -model: Dict[str, str] = models_config["openai"] -prompt_node = PromptNode( - model["model_name"], - default_prompt_template=PromptTemplate(prompt_text), - api_key=model["api_key"], - max_length=768, - model_kwargs={"stream": stream}, -) - -web_retriever = WebRetriever(api_key=search_key, top_search_results=5, mode="preprocessed_documents", top_k=50) - -sampler = TopPSampler(top_p=0.97) -diversity_ranker = DiversityRanker() -litm_ranker = LostInTheMiddleRanker(word_count_threshold=1024) - -pipeline = Pipeline() -pipeline.add_node(component=web_retriever, name="Retriever", inputs=["Query"]) -pipeline.add_node(component=sampler, name="Sampler", inputs=["Retriever"]) -pipeline.add_node(component=diversity_ranker, name="DiversityRanker", inputs=["Sampler"]) -pipeline.add_node(component=litm_ranker, name="LostInTheMiddleRanker", inputs=["DiversityRanker"]) -pipeline.add_node(component=prompt_node, name="PromptNode", inputs=["LostInTheMiddleRanker"]) - -logging.disable(logging.CRITICAL) - - -questions = [ - "What are the primary causes and effects of climate change on global and local scales?", - "What were the key events and influences that led to Renaissance; how did these developments shape modern Western culture?", - "How have advances in technology in the 21st century affected job markets and economies around the world?", - "How has the European Union influenced the political, economic, and social dynamics of Europe?", -] - -print(f"\nRunning pipeline with {model['model_name']}\n") - -for q in questions: - print(f"\nQuestion: {q}") - if stream: - print("Answer:") - response = pipeline.run(query=q) - if not stream: - print(f"Answer: {response['results'][0]}") diff --git a/examples/web_qa.py b/examples/web_qa.py deleted file mode 100644 index 352d2d226d..0000000000 --- a/examples/web_qa.py +++ /dev/null @@ -1,35 +0,0 @@ -import os -from haystack.nodes import PromptNode -from haystack.nodes.retriever.web import WebRetriever -from haystack.pipelines import WebQAPipeline - -search_key = os.environ.get("SERPERDEV_API_KEY") -if not search_key: - raise ValueError("Please set the SERPERDEV_API_KEY environment variable") - -openai_key = os.environ.get("OPENAI_API_KEY") -if not search_key: - raise ValueError("Please set the OPENAI_API_KEY environment variable") - -prompt_node = PromptNode( - "text-davinci-003", - api_key=openai_key, - max_length=256, - default_prompt_template="question-answering-with-document-scores", -) -web_retriever = WebRetriever(api_key=search_key) -pipeline = WebQAPipeline(retriever=web_retriever, prompt_node=prompt_node) - -questions = [ - "Who won the 1971 San Francisco mayoral election?", - "Where was Jeremy McKinnon born?", - "What river is near Dundalk, Ireland?", - "Who is Kyle Moran?", - "What party does Joseph Alioto belong to?", - "When was the Democratic Party founded?", - "Who is Olivia Wilde's boyfriend?", -] - -for question in questions: - response = pipeline.run(question) - print(f"{question} - {response['answers'][0].answer}") diff --git a/haystack-linter/LICENSE b/haystack-linter/LICENSE deleted file mode 100644 index 6fb66d8d5f..0000000000 --- a/haystack-linter/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 deepset GmbH - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/haystack-linter/README.md b/haystack-linter/README.md deleted file mode 100644 index 5a8b958b5b..0000000000 --- a/haystack-linter/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# haystack_linter - -[![PyPI - Version](https://img.shields.io/pypi/v/haystack-linter.svg)](https://pypi.org/project/haystack-linter) -[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/haystack-linter.svg)](https://pypi.org/project/haystack-linter) - ------ - -**Table of Contents** - -- [haystack\_linter](#haystack_linter) - - [Installation](#installation) - - [License](#license) - -## Installation - -```console -pip install haystack-linter -``` - -## License - -`haystack-linter` is distributed under the terms of the [Apache License 2.0](https://spdx.org/licenses/Apache-2.0.html) license. diff --git a/haystack-linter/haystack_linter/__about__.py b/haystack-linter/haystack_linter/__about__.py deleted file mode 100644 index 858696fbf3..0000000000 --- a/haystack-linter/haystack_linter/__about__.py +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: 2023-present deepset -# -# SPDX-License-Identifier: Apache-2.0 -__version__ = "0.0.1" diff --git a/haystack-linter/haystack_linter/__init__.py b/haystack-linter/haystack_linter/__init__.py deleted file mode 100644 index 9c6a149fdf..0000000000 --- a/haystack-linter/haystack_linter/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: 2023-present deepset -# -# SPDX-License-Identifier: Apache-2.0 -from .linting import register diff --git a/haystack-linter/haystack_linter/linting.py b/haystack-linter/haystack_linter/linting.py deleted file mode 100644 index 52286324ba..0000000000 --- a/haystack-linter/haystack_linter/linting.py +++ /dev/null @@ -1,85 +0,0 @@ -# SPDX-FileCopyrightText: 2023-present deepset -# -# SPDX-License-Identifier: Apache-2.0 -# -# https://pylint.pycqa.org/en/latest/development_guide/how_tos/custom_checkers.html - -from typing import TYPE_CHECKING, Optional, List, Any - -from astroid import nodes - -from pylint.checkers import BaseChecker - -if TYPE_CHECKING: - from pylint.lint import PyLinter - - -class DirectLoggingChecker(BaseChecker): - name = "no-direct-logging" - msgs = { - "W9001": ( - "Use a logger object instead of a direct logging function like 'logging.%s()'", - "no-direct-logging", - "Do not use direct calls to logging functions like logging.info(), " - "rather create a logger object with getLogger and use it instead. " - "See https://github.com/deepset-ai/haystack/issues/4202.", - ) - } - - def __init__(self, linter: Optional["PyLinter"] = None) -> None: - super().__init__(linter) - self._function_stack: List[Any] = [] - - def visit_functiondef(self, node: nodes.FunctionDef) -> None: - self._function_stack.append([]) - - def leave_functiondef(self, node: nodes.FunctionDef) -> None: - self._function_stack.pop() - - def visit_call(self, node: nodes.Call) -> None: - if ( - isinstance(node.func, nodes.Attribute) - and isinstance(node.func.expr, nodes.Name) - and node.func.expr.name == "logging" - and node.func.attrname in ["debug", "info", "warning", "error", "critical", "exception"] - ): - self.add_message("no-direct-logging", args=node.func.attrname, node=node) - - -class NoLoggingConfigurationChecker(BaseChecker): - name = "no-logging-basicconfig" - msgs = { - "W9002": ( - "Do not use 'logging.basicConfig' in Haystack code: Haystack should not configure any loggers.", - "no-logging-basicconfig", - "Do not configure the logger explicitly, because this would be problematic for users. " - "Always configure the loggers only in scripts that use Haystack, like tutorials, rather than Haystack itself.", - ) - } - - def __init__(self, linter: Optional["PyLinter"] = None) -> None: - super().__init__(linter) - self._function_stack: List[Any] = [] - - def visit_functiondef(self, node: nodes.FunctionDef) -> None: - self._function_stack.append([]) - - def leave_functiondef(self, node: nodes.FunctionDef) -> None: - self._function_stack.pop() - - def visit_call(self, node: nodes.Call) -> None: - if ( - isinstance(node.func, nodes.Attribute) - and isinstance(node.func.expr, nodes.Name) - and node.func.expr.name == "logging" - and node.func.attrname in ["basicConfig"] - ): - self.add_message("no-logging-basicconfig", node=node) - - -def register(linter: "PyLinter") -> None: - """This required method auto registers the checker during initialization. - :param linter: The linter to register the checker to. - """ - linter.register_checker(DirectLoggingChecker(linter)) - linter.register_checker(NoLoggingConfigurationChecker(linter)) diff --git a/haystack-linter/pyproject.toml b/haystack-linter/pyproject.toml deleted file mode 100644 index 22ab4c02c1..0000000000 --- a/haystack-linter/pyproject.toml +++ /dev/null @@ -1,60 +0,0 @@ -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[project] -name = "haystack-linter" -description = '' -readme = "README.md" -requires-python = ">=3.8" -license = "Apache-2.0" -keywords = [] -authors = [ - { name = "deepset.ai", email = "info@deepset.ai" }, -] -classifiers = [ - "Development Status :: 4 - Beta", - "Programming Language :: Python", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", -] -dependencies = [] -dynamic = ["version"] - -[project.urls] -Documentation = "https://github.com/unknown/haystack-linter#readme" -Issues = "https://github.com/unknown/haystack-linter/issues" -Source = "https://github.com/unknown/haystack-linter" - -[tool.hatch.version] -path = "haystack_linter/__about__.py" - -[tool.hatch.envs.default] -dependencies = [ - "pytest", - "pytest-cov", -] -[tool.hatch.envs.default.scripts] -cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=haystack_linter --cov=tests {args}" -no-cov = "cov --no-cov {args}" - -[[tool.hatch.envs.test.matrix]] -python = ["38", "39", "310", "311"] - -[tool.coverage.run] -branch = true -parallel = true -omit = [ - "haystack_linter/__about__.py", -] - -[tool.coverage.report] -exclude_lines = [ - "no cov", - "if __name__ == .__main__.:", - "if TYPE_CHECKING:", -] diff --git a/haystack-linter/tests/__init__.py b/haystack-linter/tests/__init__.py deleted file mode 100644 index af1543e3a1..0000000000 --- a/haystack-linter/tests/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-FileCopyrightText: 2023-present deepset -# -# SPDX-License-Identifier: Apache-2.0 diff --git a/haystack/__init__.py b/haystack/__init__.py deleted file mode 100644 index 6e4376972f..0000000000 --- a/haystack/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# pylint: disable=wrong-import-position -# Logging is not configured here on purpose, see https://github.com/deepset-ai/haystack/issues/2485 - -from importlib import metadata - -__version__: str = str(metadata.version("farm-haystack")) - - -import haystack.silenceable_tqdm # Needs to be imported first to wrap TQDM for all following modules -from haystack.schema import Document, Answer, Label, MultiLabel, Span, EvaluationResult, TableCell -from haystack.nodes.base import BaseComponent -from haystack.pipelines.base import Pipeline -from haystack.environment import set_pytorch_secure_model_loading -from haystack.mmh3 import hash128 - - -# Enables torch's secure model loading through setting an env var. -# Does not use torch. -set_pytorch_secure_model_loading() diff --git a/haystack/agents/__init__.py b/haystack/agents/__init__.py deleted file mode 100644 index 927733b832..0000000000 --- a/haystack/agents/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from haystack.agents.agent_step import AgentStep -from haystack.agents.base import Agent -from haystack.agents.base import Tool diff --git a/haystack/agents/agent_step.py b/haystack/agents/agent_step.py deleted file mode 100644 index ec5660ea64..0000000000 --- a/haystack/agents/agent_step.py +++ /dev/null @@ -1,147 +0,0 @@ -from __future__ import annotations - -import logging -import re -from typing import Optional, Dict, Any - -from haystack import Answer -from haystack.errors import AgentError - -logger = logging.getLogger(__name__) - - -class AgentStep: - """ - The AgentStep class represents a single step in the execution of an agent. - """ - - def __init__( - self, - current_step: int = 1, - max_steps: int = 10, - final_answer_pattern: Optional[str] = None, - prompt_node_response: str = "", - transcript: str = "", - ): - """ - :param current_step: The current step in the execution of the agent. - :param max_steps: The maximum number of steps the agent can execute. - :param final_answer_pattern: The regex pattern to extract the final answer from the PromptNode response. If no - pattern is provided, entire prompt node response is considered the final answer. - :param prompt_node_response: The PromptNode response received. - text it generated during execution up to this step. The transcript is used to generate the next prompt. - """ - self.current_step = current_step - self.max_steps = max_steps - self.final_answer_pattern = final_answer_pattern or r"^([\s\S]+)$" - self.prompt_node_response = prompt_node_response - self.transcript = transcript - - def create_next_step(self, prompt_node_response: Any, current_step: Optional[int] = None) -> AgentStep: - """ - Creates the next agent step based on the current step and the PromptNode response. - :param prompt_node_response: The PromptNode response received. - :param current_step: The current step in the execution of the agent. - """ - if not isinstance(prompt_node_response, list) or not prompt_node_response: - raise AgentError( - f"Agent output must be a non-empty list of str, but {prompt_node_response} received. " - f"Transcript:\n{self.transcript}" - ) - cls = type(self) - return cls( - current_step=current_step if current_step else self.current_step + 1, - max_steps=self.max_steps, - final_answer_pattern=self.final_answer_pattern, - prompt_node_response=prompt_node_response[0], - transcript=self.transcript, - ) - - def final_answer(self, query: str) -> Dict[str, Any]: - """ - Formats an answer as a dict containing `query` and `answers` similar to the output of a Pipeline. - The full transcript based on the Agent's initial prompt template and the text it generated during execution. - - :param query: The search query - """ - answer: Dict[str, Any] = { - "query": query, - "answers": [Answer(answer="", type="generative")], - "transcript": self.transcript, - } - if self.current_step > self.max_steps: - logger.warning( - "Maximum number of iterations (%s) reached for query (%s). Increase max_steps " - "or no answer can be provided for this query.", - self.max_steps, - query, - ) - else: - final_answer = self.parse_final_answer() - if not final_answer: - logger.warning( - "Final answer parser (%s) could not parse PromptNode response (%s).", - self.final_answer_pattern, - self.prompt_node_response, - ) - else: - answer = { - "query": query, - "answers": [Answer(answer=final_answer, type="generative")], - "transcript": self.transcript, - } - return answer - - def is_last(self) -> bool: - """ - Check if this is the last step of the Agent. - :return: True if this is the last step of the Agent, False otherwise. - """ - return bool(self.parse_final_answer()) or self.current_step > self.max_steps - - def completed(self, observation: Optional[str]) -> None: - """ - Update the transcript with the observation - :param observation: received observation from the Agent environment. - """ - self.transcript += ( - f"{self.prompt_node_response}\nObservation: {observation}\nThought:" - if observation - else self.prompt_node_response - ) - - def __repr__(self) -> str: - """ - Return a string representation of the AgentStep object. - - :return: A string that represents the AgentStep object. - """ - return ( - f"AgentStep(current_step={self.current_step}, max_steps={self.max_steps}, " - f"prompt_node_response={self.prompt_node_response}, final_answer_pattern={self.final_answer_pattern}, " - f"transcript={self.transcript})" - ) - - def parse_final_answer(self) -> Optional[str]: - """ - Parse the final answer from the response of the prompt node. - - This function searches the prompt node's response for a match with the - pre-defined final answer pattern. If a match is found, it's returned as the - final answer after removing leading/trailing quotes and whitespaces. - If no match is found, it returns None. - - :return: The final answer as a string if a match is found, otherwise None. - """ - # Search for a match with the final answer pattern in the prompt node response - final_answer_match = re.search(self.final_answer_pattern, self.prompt_node_response) - - if final_answer_match: - # If a match is found, get the first group (i.e., the content inside the parentheses of the regex pattern) - final_answer = final_answer_match.group(1) - - # Remove leading/trailing quotes and whitespaces, then return the final answer - return final_answer.strip('" ') # type: ignore - else: - # If no match is found, return None - return None diff --git a/haystack/agents/base.py b/haystack/agents/base.py deleted file mode 100644 index da6d1d61ba..0000000000 --- a/haystack/agents/base.py +++ /dev/null @@ -1,450 +0,0 @@ -from __future__ import annotations - -import logging -import re -from collections.abc import Iterable, Callable -from hashlib import md5 -from typing import List, Optional, Union, Dict, Any, Tuple - -from events import Events - -from haystack import Pipeline, BaseComponent, Answer, Document -from haystack.agents.memory import Memory, NoMemory -from haystack.telemetry import send_event -from haystack.agents.agent_step import AgentStep -from haystack.agents.types import Color, AgentTokenStreamingHandler -from haystack.agents.utils import print_text, react_parameter_resolver -from haystack.nodes import PromptNode, BaseRetriever, PromptTemplate -from haystack.pipelines import ( - BaseStandardPipeline, - ExtractiveQAPipeline, - DocumentSearchPipeline, - GenerativeQAPipeline, - SearchSummarizationPipeline, - FAQPipeline, - TranslationWrapperPipeline, - RetrieverQuestionGenerationPipeline, - WebQAPipeline, -) - -logger = logging.getLogger(__name__) - - -class Tool: - """ - Agent uses tools to find the best answer. A tool is a pipeline or a node. When you add a tool to an Agent, the Agent - can invoke the underlying pipeline or node to answer questions. - - You must provide a name and a description for each tool. The name should be short and should indicate what the tool - can do. The description should explain what the tool is useful for. The Agent uses the description to decide when - to use a tool, so the wording you use is important. - - :param name: The name of the tool. The Agent uses this name to refer to the tool in the text the Agent generates. - The name should be short, ideally one token, and a good description of what the tool can do, for example: - "Calculator" or "Search". Use only letters (a-z, A-Z), digits (0-9) and underscores (_)." - :param pipeline_or_node: The pipeline or node to run when the Agent invokes this tool. - :param description: A description of what the tool is useful for. The Agent uses this description to decide - when to use which tool. For example, you can describe a tool for calculations by "useful for when you need to - - answer questions about math". - """ - - def __init__( - self, - name: str, - pipeline_or_node: Union[ - BaseComponent, - Pipeline, - ExtractiveQAPipeline, - DocumentSearchPipeline, - GenerativeQAPipeline, - SearchSummarizationPipeline, - FAQPipeline, - TranslationWrapperPipeline, - RetrieverQuestionGenerationPipeline, - WebQAPipeline, - Callable[[Any], str], - ], - description: str, - output_variable: str = "results", - logging_color: Color = Color.YELLOW, - ): - if re.search(r"\W", name): - raise ValueError( - f"Invalid name supplied for tool: '{name}'. Use only letters (a-z, A-Z), digits (0-9) and " - f"underscores (_)." - ) - self.name = name - self.pipeline_or_node = pipeline_or_node - self.description = description - self.output_variable = output_variable - self.logging_color = logging_color - - def run(self, tool_input: str, params: Optional[dict] = None) -> str: - # We can only pass params to pipelines but not to nodes - if isinstance(self.pipeline_or_node, (Pipeline, BaseStandardPipeline)): - result = self.pipeline_or_node.run(query=tool_input, params=params) - elif isinstance(self.pipeline_or_node, BaseRetriever): - result = self.pipeline_or_node.run(query=tool_input, root_node="Query") - elif callable(self.pipeline_or_node): - result = self.pipeline_or_node(tool_input) - else: - result = self.pipeline_or_node.run(query=tool_input) - return self._process_result(result) - - def _process_result(self, result: Any) -> str: - # Base case: string or an empty container - if not result or isinstance(result, str): - return str(result) - # Recursive case: process the result based on its type and return the result - else: - if isinstance(result, (tuple, list)): - return self._process_result(result[0] if result else []) - elif isinstance(result, dict): - if self.output_variable not in result: - raise ValueError( - f"Tool {self.name} returned result {result} but " - f"output variable '{self.output_variable}' not found." - ) - return self._process_result(result[self.output_variable]) - elif isinstance(result, Answer): - return self._process_result(result.answer) - elif isinstance(result, Document): - return self._process_result(result.content) - else: - return str(result) - - -class ToolsManager: - """ - The ToolsManager manages tools for an Agent. - """ - - def __init__( - self, - tools: Optional[List[Tool]] = None, - tool_pattern: str = r"Tool:\s*(\w+)\s*Tool Input:\s*(?:\"([\s\S]*?)\"|((?:.|\n)*))\s*", - ): - """ - :param tools: A list of tools to add to the ToolManager. Each tool must have a unique name. - :param tool_pattern: A regular expression pattern that matches the text that the Agent generates to invoke - a tool. - """ - self._tools: Dict[str, Tool] = {tool.name: tool for tool in tools} if tools else {} - self.tool_pattern = tool_pattern - self.callback_manager = Events(("on_tool_start", "on_tool_finish", "on_tool_error")) - - @property - def tools(self): - return self._tools - - def get_tool_names(self) -> str: - """ - Returns a string with the names of all registered tools. - """ - return ", ".join(self.tools.keys()) - - def get_tools(self) -> List[Tool]: - """ - Returns a list of all registered tool instances. - """ - return list(self.tools.values()) - - def get_tool_names_with_descriptions(self) -> str: - """ - Returns a string with the names and descriptions of all registered tools. - """ - return "\n".join([f"{tool.name}: {tool.description}" for tool in self.tools.values()]) - - def run_tool(self, llm_response: str, params: Optional[Dict[str, Any]] = None) -> str: - tool_result: str = "" - if self.tools: - tool_name, tool_input = self.extract_tool_name_and_tool_input(llm_response) - if tool_name and tool_input: - tool: Tool = self.tools[tool_name] - try: - self.callback_manager.on_tool_start(tool_input, tool=tool) - tool_result = tool.run(tool_input, params) - self.callback_manager.on_tool_finish( - tool_result, - observation_prefix="Observation: ", - llm_prefix="Thought: ", - color=tool.logging_color, - tool_name=tool.name, - tool_input=tool_input, - ) - except Exception as e: - self.callback_manager.on_tool_error(e, tool=self.tools[tool_name]) - raise e - return tool_result - - def extract_tool_name_and_tool_input(self, llm_response: str) -> Tuple[Optional[str], Optional[str]]: - """ - Parse the tool name and the tool input from the PromptNode response. - :param llm_response: The PromptNode response. - :return: A tuple containing the tool name and the tool input. - """ - tool_match = re.search(self.tool_pattern, llm_response) - if tool_match: - tool_name = tool_match.group(1) - tool_input = tool_match.group(2) or tool_match.group(3) - return tool_name.strip('" []\n').strip(), tool_input.strip('" \n') - return None, None - - -class Agent: - """ - An Agent answers queries using the tools you give to it. The tools are pipelines or nodes. The Agent uses a large - language model (LLM) through the PromptNode you initialize it with. To answer a query, the Agent follows this - sequence: - - 1. It generates a thought based on the query. - 2. It decides which tool to use. - 3. It generates the input for the tool. - 4. Based on the output it gets from the tool, the Agent can either stop if it now knows the answer or repeat the - process of 1) generate thought, 2) choose tool, 3) generate input. - - Agents are useful for questions containing multiple sub questions that can be answered step-by-step (Multi-hop QA) - using multiple pipelines and nodes as tools. - """ - - def __init__( - self, - prompt_node: PromptNode, - prompt_template: Optional[Union[str, PromptTemplate]] = None, - tools_manager: Optional[ToolsManager] = None, - memory: Optional[Memory] = None, - prompt_parameters_resolver: Optional[Callable] = None, - max_steps: int = 8, - final_answer_pattern: str = r"Final Answer\s*:\s*(.*)", - streaming: bool = True, - ): - """ - Creates an Agent instance. - - :param prompt_node: The PromptNode that the Agent uses to decide which tool to use and what input to provide to - it in each iteration. - :param prompt_template: A new PromptTemplate or the name of an existing PromptTemplate for the PromptNode. It's - used for generating thoughts and choosing tools to answer queries step-by-step. If it's not set, the PromptNode's - default template is used and if it's not set either, the Agent's default `zero-shot-react` template is used. - :param tools_manager: A ToolsManager instance that the Agent uses to run tools. Each tool must have a unique name. - You can also add tools with `add_tool()` before running the Agent. - :param memory: A Memory instance that the Agent uses to store information between iterations. - :param prompt_parameters_resolver: A callable that takes query, agent, and agent_step as parameters and returns - a dictionary of parameters to pass to the prompt_template. The default is a callable that returns a dictionary - of keys and values needed for the React agent prompt template. - :param max_steps: The number of times the Agent can run a tool +1 to let it infer it knows the final answer. - Set it to at least 2, so that the Agent can run one a tool once and then infer it knows the final answer. - The default is 8. - :param final_answer_pattern: A regular expression to extract the final answer from the text the Agent generated. - :param streaming: Whether to use streaming or not. If True, the Agent will stream response tokens from the LLM. - If False, the Agent will wait for the LLM to finish generating the response and then process it. The default is - True. - """ - self.max_steps = max_steps - self.tm = tools_manager or ToolsManager() - self.memory = memory or NoMemory() - self.callback_manager = Events( - ("on_agent_start", "on_agent_step", "on_agent_finish", "on_agent_final_answer", "on_new_token") - ) - self.prompt_node = prompt_node - prompt_template = prompt_template or prompt_node.default_prompt_template or "zero-shot-react" - resolved_prompt_template = prompt_node.get_prompt_template(prompt_template) - if not resolved_prompt_template: - raise ValueError( - f"Prompt template '{prompt_template}' not found. Please check the spelling of the template name." - ) - self.prompt_template = resolved_prompt_template - self.prompt_parameters_resolver = ( - prompt_parameters_resolver if prompt_parameters_resolver else react_parameter_resolver - ) - self.final_answer_pattern = final_answer_pattern - self.add_default_logging_callbacks(streaming=streaming) - self.hash = None - self.last_hash = None - self.update_hash() - - def update_hash(self): - """ - Used for telemetry. Hashes the tool classnames to send an event only when they change. - See haystack/telemetry.py::send_event - """ - try: - tool_names = " ".join([tool.pipeline_or_node.__class__.__name__ for tool in self.tm.get_tools()]) - self.hash = md5(tool_names.encode()).hexdigest() - except Exception as exc: - logger.debug("Telemetry exception: %s", str(exc)) - self.hash = "[an exception occurred during hashing]" - - def add_default_logging_callbacks(self, agent_color: Color = Color.GREEN, streaming: bool = False) -> None: - def on_tool_finish( - tool_output: str, - color: Optional[Color] = None, - observation_prefix: Optional[str] = None, - llm_prefix: Optional[str] = None, - **kwargs: Any, - ) -> None: - print_text(observation_prefix) # type: ignore - print_text(tool_output, color=color) - print_text(f"\n{llm_prefix}") - - def on_agent_start(**kwargs: Any) -> None: - agent_name = kwargs.pop("name", "react") - print_text(f"\nAgent {agent_name} started with {kwargs}\n") - - def on_agent_final_answer(final_answer: Dict[str, Any], **kwargs: Any) -> None: - pass - - self.tm.callback_manager.on_tool_finish += on_tool_finish - self.callback_manager.on_agent_start += on_agent_start - self.callback_manager.on_agent_final_answer += on_agent_final_answer - - if streaming: - self.callback_manager.on_new_token += lambda token, **kwargs: print_text(token, color=agent_color) - else: - self.callback_manager.on_agent_step += lambda agent_step: print_text( - agent_step.prompt_node_response, end="\n", color=agent_color - ) - - def add_tool(self, tool: Tool): - """ - Add a tool to the Agent. This also updates the PromptTemplate for the Agent's PromptNode with the tool name. - - :param tool: The tool to add to the Agent. Any previously added tool with the same name will be overwritten. - Example: - `agent.add_tool( - Tool( - name="Calculator", - pipeline_or_node=calculator - description="Useful when you need to answer questions about math" - ) - ) - """ - if tool.name in self.tm.tools: - logger.warning( - "The agent already has a tool named '%s'. The new tool will overwrite the existing one.", tool.name - ) - self.tm.tools[tool.name] = tool - - def has_tool(self, tool_name: str) -> bool: - """ - Check whether the Agent has a tool with the name you provide. - - :param tool_name: The name of the tool for which you want to check whether the Agent has it. - """ - return tool_name in self.tm.tools - - def run( - self, query: str, max_steps: Optional[int] = None, params: Optional[dict] = None - ) -> Dict[str, Union[str, List[Answer]]]: - """ - Runs the Agent given a query and optional parameters to pass on to the tools used. The result is in the - same format as a pipeline's result: a dictionary with a key `answers` containing a list of answers. - - :param query: The search query - :param max_steps: The number of times the Agent can run a tool +1 to infer it knows the final answer. - If you want to set it, make it at least 2 so that the Agent can run a tool once and then infer it knows the - final answer. - :param params: A dictionary of parameters you want to pass to the tools that are pipelines. - To pass a parameter to all nodes in those pipelines, use the format: `{"top_k": 10}`. - To pass a parameter to targeted nodes in those pipelines, use the format: - `{"Retriever": {"top_k": 10}, "Reader": {"top_k": 3}}`. - You can only pass parameters to tools that are pipelines, but not nodes. - """ - try: - if self.hash != self.last_hash: - self.last_hash = self.hash - send_event(event_name="Agent", event_properties={"llm.agent_hash": self.hash}) - except Exception as exc: - logger.debug("Telemetry exception: %s", exc) - - self.callback_manager.on_agent_start(name=self.prompt_template.name, query=query, params=params) - agent_step = self.create_agent_step(max_steps) - try: - while not agent_step.is_last(): - agent_step = self._step(query, agent_step, params) - finally: - self.callback_manager.on_agent_finish(agent_step) - final_answer = agent_step.final_answer(query=query) - self.callback_manager.on_agent_final_answer(final_answer) - return final_answer - - def _step(self, query: str, current_step: AgentStep, params: Optional[dict] = None): - # plan next step using the LLM - prompt_node_response = self._plan(query, current_step) - - # from the LLM response, create the next step - next_step = current_step.create_next_step(prompt_node_response) - self.callback_manager.on_agent_step(next_step) - - # run the tool selected by the LLM - observation = self.tm.run_tool(next_step.prompt_node_response, params) if not next_step.is_last() else None - - # save the input, output and observation to memory (if memory is enabled) - memory_data = self.prepare_data_for_memory(input=query, output=prompt_node_response, observation=observation) - self.memory.save(data=memory_data) - - # update the next step with the observation - next_step.completed(observation) - return next_step - - def _plan(self, query, current_step): - # first resolve prompt template params - template_params = self.prompt_parameters_resolver(query=query, agent=self, agent_step=current_step) - - # check for template parameters mismatch - self.check_prompt_template(template_params) - - # invoke via prompt node - prompt_node_response = self.prompt_node.prompt( - prompt_template=self.prompt_template, - stream_handler=AgentTokenStreamingHandler(self.callback_manager), - **template_params, - ) - return prompt_node_response - - def create_agent_step(self, max_steps: Optional[int] = None) -> AgentStep: - """ - Create an AgentStep object. Override this method to customize the AgentStep class used by the Agent. - """ - return AgentStep(max_steps=max_steps or self.max_steps, final_answer_pattern=self.final_answer_pattern) - - def prepare_data_for_memory(self, **kwargs) -> dict: - """ - Prepare data for saving to the Agent's memory. Override this method to customize the data saved to the memory. - """ - return { - k: v if isinstance(v, str) else next(iter(v)) for k, v in kwargs.items() if isinstance(v, (str, Iterable)) - } - - def check_prompt_template(self, template_params: Dict[str, Any]) -> None: - """ - Verifies that the Agent's prompt template is adequately populated with the correct parameters - provided by the prompt parameter resolver. - - If template_params contains a parameter that is not specified in the prompt template, a warning is logged - at DEBUG level. Sometimes the prompt parameter resolver may provide additional parameters that are not - used by the prompt template. However, if the prompt parameter resolver provides a 'transcript' - parameter that is not used in the prompt template, an error is logged. - - :param template_params: The parameters provided by the prompt parameter resolver. - - """ - unused_params = set(template_params.keys()) - set(self.prompt_template.prompt_params) - - if "transcript" in unused_params: - logger.warning( - "The 'transcript' parameter is missing from the Agent's prompt template. All ReAct agents " - "that go through multiple steps to reach a goal require this parameter. Please append {transcript} " - "to the end of the Agent's prompt template to ensure its proper functioning. A temporary prompt " - "template with {transcript} appended will be used for this run." - ) - new_prompt_text = self.prompt_template.prompt_text + "\n {transcript}" - self.prompt_template = PromptTemplate(prompt=new_prompt_text) - - elif unused_params: - logger.debug( - "The Agent's prompt template does not utilize the following parameters provided by the " - "prompt parameter resolver: %s. Note that these parameters are available for use if needed.", - list(unused_params), - ) diff --git a/haystack/agents/conversational.py b/haystack/agents/conversational.py deleted file mode 100644 index fce1f41647..0000000000 --- a/haystack/agents/conversational.py +++ /dev/null @@ -1,112 +0,0 @@ -from typing import Optional, List, Union -import logging - -from haystack.errors import AgentError -from haystack.agents.base import Tool, ToolsManager, Agent -from haystack.agents.memory import Memory, ConversationMemory -from haystack.nodes import PromptNode, PromptTemplate -from haystack.agents.utils import conversational_agent_parameter_resolver, agent_without_tools_parameter_resolver - -logger = logging.getLogger(__name__) - - -class ConversationalAgent(Agent): - """ - A ConversationalAgent is an extension of the Agent class that enables the use of tools with several default parameters. - ConversationalAgent can manage a set of tools and seamlessly integrate them into the conversation. - If no tools are provided, the agent will be initialized to have a basic chat application. - - Here is an example how you can create a chat application with tools: - - ```python - import os - - from haystack.agents.conversational import ConversationalAgent - from haystack.nodes import PromptNode - from haystack.agents.base import Tool - - # Initialize a PromptNode and the desired tools - prompt_node = PromptNode("gpt-3.5-turbo", api_key=os.environ.get("OPENAI_API_KEY"), max_length=256) - tools = [Tool(name="ExampleTool", pipeline_or_node=example_tool_node)] - - # Create the ConversationalAgent instance - agent = ConversationalAgent(prompt_node, tools=tools) - - # Use the agent in a chat application - while True: - user_input = input("Human (type 'exit' or 'quit' to quit): ") - if user_input.lower() == "exit" or user_input.lower() == "quit": - break - else: - assistant_response = agent.run(user_input) - print("Assistant:", assistant_response) - ``` - - If you don't want to have any tools in your chat app, you can create a ConversationalAgent only with a PromptNode: - - ```python - import os - - from haystack.agents.conversational import ConversationalAgent - from haystack.nodes import PromptNode - - # Initialize a PromptNode - prompt_node = PromptNode("gpt-3.5-turbo", api_key=os.environ.get("OPENAI_API_KEY"), max_length=256) - - # Create the ConversationalAgent instance - agent = ConversationalAgent(prompt_node) - ``` - - If you're looking for more customization, check out [Agent](https://docs.haystack.deepset.ai/reference/agent-api). - """ - - def __init__( - self, - prompt_node: PromptNode, - prompt_template: Optional[Union[str, PromptTemplate]] = None, - tools: Optional[List[Tool]] = None, - memory: Optional[Memory] = None, - max_steps: Optional[int] = None, - ): - """ - Creates a new ConversationalAgent instance. - - :param prompt_node: A PromptNode used by Agent to decide which tool to use and what input to provide to it - in each iteration. If there are no tools added, the model specified with PromptNode will be used for chatting. - :param prompt_template: A new PromptTemplate or the name of an existing PromptTemplate for the PromptNode. It's - used for keeping the chat history, generating thoughts and choosing tools (if provided) to answer queries. It defaults to - to "conversational-agent" if there is at least one tool provided and "conversational-agent-without-tools" otherwise. - :param tools: A list of tools to use in the Agent. Each tool must have a unique name. - :param memory: A memory object for storing conversation history and other relevant data, defaults to - ConversationMemory if no memory is provided. - :param max_steps: The number of times the Agent can run a tool +1 to let it infer it knows the final answer. It defaults to 5 if there is at least one tool provided and 2 otherwise. - """ - - if tools: - super().__init__( - prompt_node=prompt_node, - memory=memory if memory else ConversationMemory(), - tools_manager=ToolsManager(tools=tools), - max_steps=max_steps if max_steps else 5, - prompt_template=prompt_template if prompt_template else "conversational-agent", - final_answer_pattern=r"Final Answer\s*:\s*(.*)", - prompt_parameters_resolver=conversational_agent_parameter_resolver, - ) - else: - logger.warning("ConversationalAgent is created without tools") - - super().__init__( - prompt_node=prompt_node, - memory=memory if memory else ConversationMemory(), - max_steps=max_steps if max_steps else 2, - prompt_template=prompt_template if prompt_template else "conversational-agent-without-tools", - final_answer_pattern=r"^([\s\S]+)$", - prompt_parameters_resolver=agent_without_tools_parameter_resolver, - ) - - def add_tool(self, tool: Tool): - if len(self.tm.tools) == 0: - raise AgentError( - "You cannot add tools after initializing the ConversationalAgent without any tools. If you want to add tools, reinitialize the ConversationalAgent and provide `tools`." - ) - return super().add_tool(tool) diff --git a/haystack/agents/memory/__init__.py b/haystack/agents/memory/__init__.py deleted file mode 100644 index 4b8387c50f..0000000000 --- a/haystack/agents/memory/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from haystack.agents.memory.base import Memory -from haystack.agents.memory.no_memory import NoMemory -from haystack.agents.memory.conversation_memory import ConversationMemory -from haystack.agents.memory.conversation_summary_memory import ConversationSummaryMemory diff --git a/haystack/agents/memory/base.py b/haystack/agents/memory/base.py deleted file mode 100644 index b259b5db80..0000000000 --- a/haystack/agents/memory/base.py +++ /dev/null @@ -1,31 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Dict, Any, List, Optional - - -class Memory(ABC): - """ - Abstract base class for memory management in an Agent. - """ - - @abstractmethod - def load(self, keys: Optional[List[str]] = None, **kwargs) -> Any: - """ - Load the context of this model run from memory. - - :param keys: Optional list of keys to specify the data to load. - :return: The loaded data. - """ - - @abstractmethod - def save(self, data: Dict[str, Any]) -> None: - """ - Save the context of this model run to memory. - - :param data: A dictionary containing the data to save. - """ - - @abstractmethod - def clear(self) -> None: - """ - Clear memory contents. - """ diff --git a/haystack/agents/memory/conversation_memory.py b/haystack/agents/memory/conversation_memory.py deleted file mode 100644 index 3312517f1d..0000000000 --- a/haystack/agents/memory/conversation_memory.py +++ /dev/null @@ -1,60 +0,0 @@ -import collections -from typing import OrderedDict, List, Optional, Any, Dict - -from haystack.agents.memory import Memory - - -class ConversationMemory(Memory): - """ - A memory class that stores conversation history. - """ - - def __init__(self, input_key: str = "input", output_key: str = "output"): - """ - Initialize ConversationMemory with input and output keys. - - :param input_key: The key to use for storing user input. - :param output_key: The key to use for storing model output. - """ - self.list: List[OrderedDict] = [] - self.input_key = input_key - self.output_key = output_key - - def load(self, keys: Optional[List[str]] = None, **kwargs) -> str: - """ - Load conversation history as a formatted string. - - :param keys: Optional list of keys (ignored in this implementation). - :param kwargs: Optional keyword arguments - - window_size: integer specifying the number of most recent conversation snippets to load. - :return: A formatted string containing the conversation history. - """ - chat_transcript = "" - window_size = kwargs.get("window_size", None) - - if window_size is not None: - chat_list = self.list[-window_size:] # pylint: disable=invalid-unary-operand-type - else: - chat_list = self.list - - for chat_snippet in chat_list: - chat_transcript += f"Human: {chat_snippet['Human']}\n" - chat_transcript += f"AI: {chat_snippet['AI']}\n" - return chat_transcript - - def save(self, data: Dict[str, Any]) -> None: - """ - Save a conversation snippet to memory. - - :param data: A dictionary containing the conversation snippet to save. - """ - chat_snippet = collections.OrderedDict() - chat_snippet["Human"] = data[self.input_key] - chat_snippet["AI"] = data[self.output_key] - self.list.append(chat_snippet) - - def clear(self) -> None: - """ - Clear the conversation history. - """ - self.list = [] diff --git a/haystack/agents/memory/conversation_summary_memory.py b/haystack/agents/memory/conversation_summary_memory.py deleted file mode 100644 index 9d4d7bbd73..0000000000 --- a/haystack/agents/memory/conversation_summary_memory.py +++ /dev/null @@ -1,117 +0,0 @@ -from typing import Optional, Union, Dict, Any, List - -from haystack.agents.memory import ConversationMemory -from haystack.nodes import PromptTemplate, PromptNode - - -class ConversationSummaryMemory(ConversationMemory): - """ - A memory class that stores conversation history and periodically generates summaries. - """ - - def __init__( - self, - prompt_node: PromptNode, - prompt_template: Optional[Union[str, PromptTemplate]] = None, - input_key: str = "input", - output_key: str = "output", - summary_frequency: int = 3, - ): - """ - Initialize ConversationSummaryMemory with a PromptNode, optional prompt_template, - input and output keys, and a summary_frequency. - - :param prompt_node: A PromptNode object for generating conversation summaries. - :param prompt_template: Optional prompt template as a string or PromptTemplate object. - :param input_key: input key, default is "input". - :param output_key: output key, default is "output". - :param summary_frequency: integer specifying how often to generate a summary (default is 3). - """ - super().__init__(input_key, output_key) - self.save_count = 0 - self.prompt_node = prompt_node - - template = ( - prompt_template - if prompt_template is not None - else prompt_node.default_prompt_template or "conversational-summary" - ) - self.template = prompt_node.get_prompt_template(template) - self.summary_frequency = summary_frequency - self.summary = "" - - def load(self, keys: Optional[List[str]] = None, **kwargs) -> str: - """ - Load conversation history as a formatted string, including the latest summary. - - :param keys: Optional list of keys (ignored in this implementation). - :param kwargs: Optional keyword arguments - - window_size: integer specifying the number of most recent conversation snippets to load. - :return: A formatted string containing the conversation history with the latest summary. - """ - if self.has_unsummarized_snippets(): - unsummarized = self.load_recent_snippets(window_size=self.unsummarized_snippets()) - return f"{self.summary}\n{unsummarized}" - else: - return self.summary - - def load_recent_snippets(self, window_size: int = 1) -> str: - """ - Load the most recent conversation snippets as a formatted string. - - :param window_size: integer specifying the number of most recent conversation snippets to load. - :return: A formatted string containing the most recent conversation snippets. - """ - return super().load(window_size=window_size) - - def summarize(self) -> str: - """ - Generate a summary of the conversation history and clear the history. - - :return: A string containing the generated summary. - """ - most_recent_chat_snippets = self.load_recent_snippets(window_size=self.summary_frequency) - pn_response = self.prompt_node.prompt(self.template, chat_transcript=most_recent_chat_snippets) - return pn_response[0] - - def needs_summary(self) -> bool: - """ - Determine if a new summary should be generated. - - :return: True if a new summary should be generated, otherwise False. - """ - return self.save_count % self.summary_frequency == 0 - - def unsummarized_snippets(self) -> int: - """ - Returns how many conversation snippets have not been summarized. - :return: The number of conversation snippets that have not been summarized. - """ - return self.save_count % self.summary_frequency - - def has_unsummarized_snippets(self) -> bool: - """ - Returns True if there are any conversation snippets that have not been summarized. - :return: True if there are unsummarized snippets, otherwise False. - """ - return self.unsummarized_snippets() != 0 - - def save(self, data: Dict[str, Any]) -> None: - """ - Save a conversation snippet to memory and update the save count. - Generate a summary if needed. - - :param data: A dictionary containing the conversation snippet to save. - """ - super().save(data) - self.save_count += 1 - if self.needs_summary(): - self.summary += self.summarize() - - def clear(self) -> None: - """ - Clear the conversation history and the summary. - """ - super().clear() - self.save_count = 0 - self.summary = "" diff --git a/haystack/agents/memory/no_memory.py b/haystack/agents/memory/no_memory.py deleted file mode 100644 index 4f70ed3e8d..0000000000 --- a/haystack/agents/memory/no_memory.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Optional, List, Any, Dict - -from haystack.agents.memory import Memory - - -class NoMemory(Memory): - """ - A memory class that doesn't store any data. - """ - - def load(self, keys: Optional[List[str]] = None, **kwargs) -> str: - """ - Load an empty dictionary. - - :param keys: Optional list of keys (ignored in this implementation). - :return: An empty str. - """ - return "" - - def save(self, data: Dict[str, Any]) -> None: - """ - Save method that does nothing. - - :param data: A dictionary containing the data to save (ignored in this implementation). - """ - pass - - def clear(self) -> None: - """ - Clear method that does nothing. - """ - pass diff --git a/haystack/agents/types.py b/haystack/agents/types.py deleted file mode 100644 index 92101dec77..0000000000 --- a/haystack/agents/types.py +++ /dev/null @@ -1,44 +0,0 @@ -from enum import Enum -from typing import Any, Dict, List, Optional - -from events import Events -from haystack.nodes.prompt.invocation_layer.handlers import TokenStreamingHandler - - -class Color(Enum): - BLACK = "\033[30m" - RED = "\033[31m" - GREEN = "\033[32m" - YELLOW = "\033[33m" - BLUE = "\033[34m" - MAGENTA = "\033[35m" - CYAN = "\033[36m" - WHITE = "\033[37m" - RESET = "\x1b[0m" - - -class AgentTokenStreamingHandler(TokenStreamingHandler): - def __init__(self, events: Events): - self.events = events - - def __call__(self, token_received, **kwargs) -> str: - self.events.on_new_token(token_received, **kwargs) - return token_received - - -class AgentToolLogger: - def __init__(self, agent_events: Events, tool_events: Events): - agent_events.on_agent_start += self.on_agent_start - tool_events.on_tool_finish += self.on_tool_finish - self.logs: List[Dict[str, Any]] = [] - - def on_agent_start(self, **kwargs: Any) -> None: - self.logs = [] - - def on_tool_finish( - self, tool_result: str, tool_name: Optional[str] = None, tool_input: Optional[str] = None, **kwargs: Any - ) -> None: - self.logs.append({"tool_name": tool_name, "tool_input": tool_input, "tool_output": tool_result}) - - def __repr__(self): - return f"" diff --git a/haystack/agents/utils.py b/haystack/agents/utils.py deleted file mode 100644 index 668795dc1d..0000000000 --- a/haystack/agents/utils.py +++ /dev/null @@ -1,56 +0,0 @@ -from typing import Optional, TYPE_CHECKING, Dict, Any - -from haystack.agents.types import Color -from haystack.agents.agent_step import AgentStep - -if TYPE_CHECKING: - from haystack.agents import Agent - - -def print_text(text: str, end="", color: Optional[Color] = None) -> None: - """ - Print text with optional color. - :param text: Text to print. - :param end: End character to use (defaults to ""). - :param color: Color to print text in (defaults to None). - """ - if color: - print(f"{color.value}{text}{Color.RESET.value}", end=end, flush=True) - else: - print(text, end=end, flush=True) - - -def react_parameter_resolver(query: str, agent: "Agent", agent_step: AgentStep, **kwargs) -> Dict[str, Any]: - """ - A parameter resolver for ReAct-based agents that returns the query, the tool names, the tool names - with descriptions, and the transcript (internal monologue). - """ - return { - "query": query, - "tool_names": agent.tm.get_tool_names(), - "tool_names_with_descriptions": agent.tm.get_tool_names_with_descriptions(), - "transcript": agent_step.transcript, - } - - -def agent_without_tools_parameter_resolver(query: str, agent: "Agent", **kwargs) -> Dict[str, Any]: - """ - A parameter resolver for simple chat agents without tools that returns the query and the history. - """ - return {"query": query, "memory": agent.memory.load()} - - -def conversational_agent_parameter_resolver( - query: str, agent: "Agent", agent_step: AgentStep, **kwargs -) -> Dict[str, Any]: - """ - A parameter resolver for ReAct-based conversational agent that returns the query, the tool names, the tool names - with descriptions, the history of the conversation, and the transcript (internal monologue). - """ - return { - "query": query, - "tool_names": agent.tm.get_tool_names(), - "tool_names_with_descriptions": agent.tm.get_tool_names_with_descriptions(), - "transcript": agent_step.transcript, - "memory": agent.memory.load(), - } diff --git a/haystack/cli/README.md b/haystack/cli/README.md deleted file mode 100644 index dbdd74d00c..0000000000 --- a/haystack/cli/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Haystack CLI - -

- - - -

- -Haystack is an open source NLP framework by deepset to help you build production ready search systems or applications powered by various NLP tasks such as Question Answering. Haystack is designed to help you build systems that work intelligently over large document collections. It achieves this with the concept of Pipelines consisting of various Nodes such as a DocumentStore, a Retriever and a Reader. - - -This is the repository where we keep the code for the Haystack CLI. - -To contribute to the tutorials please check out our [Contributing Guidelines](./Contributing.md) - -## Available CLI commands - -### `haystack prompt fetch` - -**Usage:** - -``` -haystack prompt fetch [OPTIONS] [PROMPT_NAME] -``` - -Download a prompt from the official [Haystack PromptHub](https://prompthub.deepset.ai/) and save it locally -for easier use in environments with no network. - -You can specify multiple prompts to fetch at the same time. - -PROMPTHUB_CACHE_PATH environment variable can be set to change the default -folder in which the prompts will be saved in. You can find the default cache path on your machine by running the following code: - - ``` python - from haystack.nodes.prompt.prompt_template import PROMPTHUB_CACHE_PATH - print(PROMPTHUB_CACHE_PATH) - ``` - -If you set a custom PROMPTHUB_CACHE_PATH environment variable, remember to set it to the same value in your console before running Haystack. - -**Example:** - -``` -haystack prompt fetch deepset/conversational-agent-with-tools deepset/summarization -``` - -**Options:** - -`--help` Show options and exit. - -### `haystack --version` - - Show your current Haystack version and exit. diff --git a/haystack/cli/__init__.py b/haystack/cli/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/haystack/cli/entry_point.py b/haystack/cli/entry_point.py deleted file mode 100644 index 08e311bf8f..0000000000 --- a/haystack/cli/entry_point.py +++ /dev/null @@ -1,17 +0,0 @@ -import click - -from haystack import __version__ -from haystack.cli.prompt import prompt - - -@click.group() -@click.version_option(__version__) -def main_cli(): - pass - - -main_cli.add_command(prompt) - - -def main(): - main_cli() diff --git a/haystack/cli/prompt/__init__.py b/haystack/cli/prompt/__init__.py deleted file mode 100644 index 4baf81a063..0000000000 --- a/haystack/cli/prompt/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -import click - -from haystack.cli.prompt import fetch - - -@click.group(short_help="Prompts related commands") -def prompt(): - pass - - -prompt.add_command(fetch.fetch) diff --git a/haystack/cli/prompt/fetch.py b/haystack/cli/prompt/fetch.py deleted file mode 100644 index 383b5af823..0000000000 --- a/haystack/cli/prompt/fetch.py +++ /dev/null @@ -1,33 +0,0 @@ -import click - -from haystack.nodes.prompt.prompt_template import PromptNotFoundError, fetch_from_prompthub, cache_prompt - - -@click.command( - short_help="Downloads and saves prompts from Haystack PromptHub", - help=""" - Downloads a prompt from the official [Haystack PromptHub](https://prompthub.deepset.ai/) - and saves it locally for easier use in environments with no network. - - You can specify multiple prompts to fetch at the same time. - - PROMPTHUB_CACHE_PATH environment variable can be set to change the default - folder in which the prompts will be saved in. You can find the default cache path on your machine by running the following code: - - ``` - from haystack.nodes.prompt.prompt_template import PROMPTHUB_CACHE_PATH - print(PROMPTHUB_CACHE_PATH) - ``` - - If you set a custom PROMPTHUB_CACHE_PATH environment variable, remember to - set it to the same value in your console before running Haystack. - """, -) -@click.argument("prompt_name", nargs=-1) -def fetch(prompt_name): - for name in prompt_name: - try: - data = fetch_from_prompthub(name) - except PromptNotFoundError as err: - raise click.ClickException(str(err)) from err - cache_prompt(data) diff --git a/haystack/document_stores/__init__.py b/haystack/document_stores/__init__.py deleted file mode 100644 index 208d86e5d0..0000000000 --- a/haystack/document_stores/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from haystack.document_stores.base import BaseDocumentStore, KeywordDocumentStore - -from haystack.document_stores.memory import InMemoryDocumentStore -from haystack.document_stores.deepsetcloud import DeepsetCloudDocumentStore -from haystack.document_stores.utils import eval_data_from_json, eval_data_from_jsonl, squad_json_to_jsonl - -from haystack.document_stores.es_converter import elasticsearch_index_to_document_store -from haystack.document_stores.es_converter import open_search_index_to_document_store - -from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore -from haystack.document_stores.opensearch import OpenSearchDocumentStore -from haystack.document_stores.sql import SQLDocumentStore -from haystack.document_stores.faiss import FAISSDocumentStore -from haystack.document_stores.pinecone import PineconeDocumentStore -from haystack.document_stores.weaviate import WeaviateDocumentStore diff --git a/haystack/document_stores/base.py b/haystack/document_stores/base.py deleted file mode 100644 index 514b6eae0d..0000000000 --- a/haystack/document_stores/base.py +++ /dev/null @@ -1,898 +0,0 @@ -# pylint: disable=too-many-public-methods - -from typing import Generator, Optional, Dict, List, Set, Union, Any - -import logging -import collections -from pathlib import Path -from abc import abstractmethod - -import numpy as np - -from haystack.schema import Document, FilterType, Label, MultiLabel -from haystack.nodes.base import BaseComponent -from haystack.errors import DuplicateDocumentError, DocumentStoreError, HaystackError -from haystack.nodes.preprocessor import PreProcessor -from haystack.document_stores.utils import eval_data_from_json, eval_data_from_jsonl, squad_json_to_jsonl -from haystack.utils.labels import aggregate_labels -from haystack.utils.scipy_utils import expit - - -logger = logging.getLogger(__name__) - - -try: - from numba import njit # pylint: disable=import-error -except (ImportError, ModuleNotFoundError): - logger.debug("Numba not found, replacing njit() with no-op implementation. Enable it with 'pip install numba'.") - - def njit(f): - return f - - -class BaseDocumentStore(BaseComponent): - """ - Base class for implementing Document Stores. - """ - - outgoing_edges: int = 1 - - index: Optional[str] - label_index: Optional[str] - similarity: Optional[str] - duplicate_documents_options: tuple = ("skip", "overwrite", "fail") - ids_iterator = None - - @abstractmethod - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: int = 10_000, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Indexes documents for later queries. - - :param documents: a list of Python dictionaries or a list of Haystack Document objects. - For documents as dictionaries, the format is {"text": ""}. - Optionally: Include meta data via {"text": "", - "meta":{"name": ", "author": "somebody", ...}} - It can be used for filtering and is accessible in the responses of the Finder. - :param index: Optional name of index where the documents shall be written to. - If None, the DocumentStore's default index (self.index) will be used. - :param batch_size: Number of documents that are passed to bulk function at a time. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - - :return: None - """ - pass - - @abstractmethod - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Get documents from the document store. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - - :param return_embedding: Whether to return the document embeddings. - :param batch_size: Number of documents that are passed to bulk function at a time. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - """ - pass - - @abstractmethod - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> Generator[Document, None, None]: - """ - Get documents from the document store. Under-the-hood, documents are fetched in batches from the - document store and yielded as individual documents. This method can be used to iteratively process - a large number of documents without having to load all documents in memory. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - """ - pass - - def __iter__(self): - if not self.ids_iterator: - self.ids_iterator = [x.id for x in self.get_all_documents()] - return self - - def __next__(self): - if len(self.ids_iterator) == 0: - raise StopIteration - curr_id = self.ids_iterator[0] - ret = self.get_document_by_id(curr_id) - self.ids_iterator = self.ids_iterator[1:] - return ret - - @abstractmethod - def get_all_labels( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Label]: - pass - - def get_all_labels_aggregated( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - open_domain: bool = True, - drop_negative_labels: bool = False, - drop_no_answers: bool = False, - aggregate_by_meta: Optional[Union[str, list]] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[MultiLabel]: - """ - Return all labels in the DocumentStore, aggregated into MultiLabel objects. - This aggregation step helps, for example, if you collected multiple possible answers for one question and you - want now all answers bundled together in one place for evaluation. - How they are aggregated is defined by the open_domain and aggregate_by_meta parameters. - If the questions are being asked to a single document (i.e. SQuAD style), you should set open_domain=False to aggregate by question and document. - If the questions are being asked to your full collection of documents, you should set open_domain=True to aggregate just by question. - If the questions are being asked to a subslice of your document set (e.g. product review use cases), - you should set open_domain=True and populate aggregate_by_meta with the names of Label meta fields to aggregate by question and your custom meta fields. - For example, in a product review use case, you might set aggregate_by_meta=["product_id"] so that Labels - with the same question but different answers from different documents are aggregated into the one MultiLabel - object, provided that they have the same product_id (to be found in Label.meta["product_id"]) - - :param index: Name of the index to get the labels from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - - :param open_domain: When True, labels are aggregated purely based on the question text alone. - When False, labels are aggregated in a closed domain fashion based on the question text - and also the id of the document that the label is tied to. In this setting, this function - might return multiple MultiLabel objects with the same question string. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :param aggregate_by_meta: The names of the Label meta fields by which to aggregate. For example: ["product_id"] - :param drop_negative_labels: When True, labels with incorrect answers and documents are dropped. - :param drop_no_answers: When True, labels with no answers are dropped. - """ - all_labels = self.get_all_labels(index=index, filters=filters, headers=headers) - - aggregated_labels = aggregate_labels( - labels=all_labels, - add_closed_domain_filter=not open_domain, - add_meta_filters=aggregate_by_meta, - drop_negative_labels=drop_negative_labels, - drop_no_answers=drop_no_answers, - ) - - return aggregated_labels - - @abstractmethod - def get_document_by_id( - self, id: str, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ) -> Optional[Document]: - pass - - @abstractmethod - def get_document_count( - self, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - ) -> int: - pass - - @staticmethod - def normalize_embedding(emb: np.ndarray) -> None: - """ - Performs L2 normalization of embeddings vector inplace. Input can be a single vector (1D array) or a matrix - (2D array). - """ - # Might be extended to other normalizations in future - - # Single vec - if len(emb.shape) == 1: - BaseDocumentStore._normalize_embedding_1D(emb) - # 2D matrix - else: - BaseDocumentStore._normalize_embedding_2D(emb) - - @staticmethod - @njit # (fastmath=True) - def _normalize_embedding_1D(emb: np.ndarray) -> None: - norm = np.sqrt(emb.dot(emb)) # faster than np.linalg.norm() - if norm != 0.0: - emb /= norm - - @staticmethod - @njit # (fastmath=True) - def _normalize_embedding_2D(emb: np.ndarray) -> None: - for vec in emb: - vec = np.ascontiguousarray(vec) - norm = np.sqrt(vec.dot(vec)) - if norm != 0.0: - vec /= norm - - def scale_to_unit_interval(self, score: float, similarity: Optional[str]) -> float: - if similarity == "cosine": - return (score + 1) / 2 - else: - return float(expit(score / 100)) - - @abstractmethod - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - pass - - def query_by_embedding_batch( - self, - query_embs: Union[List[np.ndarray], np.ndarray], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[List[Document]]: - if isinstance(filters, list): - if len(filters) != len(query_embs): - raise HaystackError( - "Number of filters does not match number of query_embs. Please provide as many filters" - " as query_embs or a single filter that will be applied to each query_emb." - ) - else: - filters = [filters] * len(query_embs) - results = [] - for query_emb, filter in zip(query_embs, filters): - results.append( - self.query_by_embedding( - query_emb=query_emb, - filters=filter, - top_k=top_k, - index=index, - return_embedding=return_embedding, - headers=headers, - scale_score=scale_score, - ) - ) - return results - - @abstractmethod - def get_label_count(self, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None) -> int: - pass - - @abstractmethod - def write_labels( - self, - labels: Union[List[Label], List[dict]], - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - def add_eval_data( - self, - filename: str, - doc_index: str = "eval_document", - label_index: str = "label", - batch_size: Optional[int] = None, - preprocessor: Optional[PreProcessor] = None, - max_docs: Optional[Union[int, bool]] = None, - open_domain: bool = False, - headers: Optional[Dict[str, str]] = None, - ): - """ - Adds a SQuAD-formatted file to the DocumentStore in order to be able to perform evaluation on it. - If a jsonl file and a batch_size is passed to the function, documents are loaded batchwise - from disk and also indexed batchwise to the DocumentStore in order to prevent out of memory errors. - - :param filename: Name of the file containing evaluation data (json or jsonl) - :param doc_index: Elasticsearch index where evaluation documents should be stored - :param label_index: Elasticsearch index where labeled questions should be stored - :param batch_size: Optional number of documents that are loaded and processed at a time. - When set to None (default) all documents are processed at once. - :param preprocessor: Optional PreProcessor to preprocess evaluation documents. - It can be used for splitting documents into passages (and assigning labels to corresponding passages). - Currently the PreProcessor does not support split_by sentence, cleaning nor split_overlap != 0. - When set to None (default) preprocessing is disabled. - :param max_docs: Optional number of documents that will be loaded. - When set to None (default) all available eval documents are used. - :param open_domain: Set this to True if your file is an open domain dataset where two different answers to the - same question might be found in different contexts. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - - """ - # TODO improve support for PreProcessor when adding eval data - if preprocessor is not None: - assert preprocessor.split_by != "sentence", ( - "Split by sentence not supported.\n" - "Please set 'split_by' to either 'word' or 'passage' in the supplied PreProcessor." - ) - assert preprocessor.split_respect_sentence_boundary is False, ( - "split_respect_sentence_boundary not supported yet.\n" - "Please set 'split_respect_sentence_boundary' to False in the supplied PreProcessor." - ) - assert preprocessor.split_overlap == 0, ( - "Overlapping documents are currently not supported when adding eval data.\n" - "Please set 'split_overlap=0' in the supplied PreProcessor." - ) - assert preprocessor.clean_empty_lines is False, ( - "clean_empty_lines currently not supported when adding eval data.\n" - "Please set 'clean_empty_lines=False' in the supplied PreProcessor." - ) - assert preprocessor.clean_whitespace is False, ( - "clean_whitespace is currently not supported when adding eval data.\n" - "Please set 'clean_whitespace=False' in the supplied PreProcessor." - ) - assert preprocessor.clean_header_footer is False, ( - "clean_header_footer is currently not supported when adding eval data.\n" - "Please set 'clean_header_footer=False' in the supplied PreProcessor." - ) - - file_path = Path(filename) - if file_path.suffix == ".json": - if batch_size is None: - docs, labels = eval_data_from_json( - filename, max_docs=max_docs, preprocessor=preprocessor, open_domain=open_domain - ) - self.write_documents(docs, index=doc_index, headers=headers) - self.write_labels(labels, index=label_index, headers=headers) - else: - jsonl_filename = (file_path.parent / (file_path.stem + ".jsonl")).as_posix() - logger.info( - "Adding evaluation data batch-wise is not compatible with json-formatted SQuAD files. " - "Converting json to jsonl to: %s", - jsonl_filename, - ) - squad_json_to_jsonl(filename, jsonl_filename) - self.add_eval_data( - jsonl_filename, doc_index, label_index, batch_size, open_domain=open_domain, headers=headers - ) - - elif file_path.suffix == ".jsonl": - for docs, labels in eval_data_from_jsonl( - filename, batch_size, max_docs=max_docs, preprocessor=preprocessor, open_domain=open_domain - ): - if docs: - self.write_documents(docs, index=doc_index, headers=headers) - if labels: - self.write_labels(labels, index=label_index, headers=headers) - - else: - logger.error("File needs to be in json or jsonl format.") - - def delete_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - @abstractmethod - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - @abstractmethod - def delete_labels( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - @abstractmethod - def delete_index(self, index: str): - """ - Delete an existing index. The index including all data will be removed. - - :param index: The name of the index to delete. - :return: None - """ - pass - - @abstractmethod - def _create_document_field_map(self) -> Dict: - pass - - def run( # type: ignore - self, - documents: List[Union[dict, Document]], - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - id_hash_keys: Optional[List[str]] = None, - ): - """ - Run requests of document stores - - Comment: We will gradually introduce the primitives. The doument stores also accept dicts and parse them to documents. - In the future, however, only documents themselves will be accepted. Parsing the dictionaries in the run function - is therefore only an interim solution until the run function also accepts documents. - - :param documents: A list of dicts that are documents. - :param headers: A list of headers. - :param index: Optional name of index where the documents shall be written to. - If None, the DocumentStore's default index (self.index) will be used. - :param id_hash_keys: List of the fields that the hashes of the ids are generated from. - """ - - field_map = self._create_document_field_map() - doc_objects = [] - for d in documents: - if isinstance(d, dict): - d["id_hash_keys"] = id_hash_keys - doc_objects.append(Document.from_dict(d, field_map=field_map)) - else: - doc_objects.append(d) - self.write_documents(documents=doc_objects, index=index, headers=headers) - return {}, "output_1" - - def run_batch( # type: ignore - self, - documents: List[Union[dict, Document]], - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - id_hash_keys: Optional[List[str]] = None, - ): - return self.run(documents=documents, index=index, headers=headers, id_hash_keys=id_hash_keys) - - def describe_documents(self, index=None): - """ - Return a summary of the documents in the document store - """ - if index is None: - index = self.index - docs = self.get_all_documents(index) - - l = [len(d.content) for d in docs] - stats = { - "count": len(docs), - "chars_mean": np.mean(l), - "chars_max": max(l), - "chars_min": min(l), - "chars_median": np.median(l), - } - return stats - - @abstractmethod - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - pass - - @abstractmethod - def update_document_meta(self, id: str, meta: Dict[str, Any], index: Optional[str] = None): - pass - - def _drop_duplicate_documents(self, documents: List[Document], index: Optional[str] = None) -> List[Document]: - """ - Drop duplicates documents based on same hash ID - - :param documents: A list of Haystack Document objects. - :param index: name of the index - :return: A list of Haystack Document objects. - """ - _hash_ids: Set = set() - _documents: List[Document] = [] - - for document in documents: - if document.id in _hash_ids: - logger.info( - "Duplicate Documents: Document with id '%s' already exists in index '%s'", - document.id, - index or self.index, - ) - continue - _documents.append(document) - _hash_ids.add(document.id) - - return _documents - - def _handle_duplicate_documents( - self, - documents: List[Document], - index: Optional[str] = None, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Checks whether any of the passed documents is already existing in the chosen index and returns a list of - documents that are not in the index yet. - - :param documents: A list of Haystack Document objects. - :param index: name of the index - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip (default option): Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :return: A list of Haystack Document objects. - """ - - index = index or self.index - if duplicate_documents in ("skip", "fail"): - documents = self._drop_duplicate_documents(documents, index) - documents_found = self.get_documents_by_id(ids=[doc.id for doc in documents], index=index, headers=headers) - ids_exist_in_db: List[str] = [doc.id for doc in documents_found] - - if len(ids_exist_in_db) > 0 and duplicate_documents == "fail": - raise DuplicateDocumentError( - f"Document with ids '{', '.join(ids_exist_in_db)} already exists" f" in index = '{index}'." - ) - - documents = list(filter(lambda doc: doc.id not in ids_exist_in_db, documents)) - - return documents - - def _get_duplicate_labels( - self, labels: list, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ) -> List[Label]: - """ - Return all duplicate labels - :param labels: List of Label objects - :param index: add an optional index attribute to labels. It can be later used for filtering. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :return: List of labels - """ - index = index or self.label_index - new_ids: List[str] = [label.id for label in labels] - duplicate_ids: List[str] = [] - - for label_id, count in collections.Counter(new_ids).items(): - if count > 1: - duplicate_ids.append(label_id) - - for label in self.get_all_labels(index=index, headers=headers): - if label.id in new_ids: - duplicate_ids.append(label.id) - - return [label for label in labels if label.id in duplicate_ids] - - @classmethod - def _validate_embeddings_shape(cls, embeddings: np.ndarray, num_documents: int, embedding_dim: int): - """ - Validates the shape of model-generated embeddings against expected values for indexing. - - :param embeddings: Embeddings to validate - :param num_documents: Number of documents the embeddings were generated for - :param embedding_dim: Number of embedding dimensions to expect - """ - num_embeddings, embedding_size = embeddings.shape - if num_embeddings != num_documents: - raise DocumentStoreError( - "The number of embeddings does not match the number of documents: " - f"({num_embeddings} != {num_documents})" - ) - if embedding_size != embedding_dim: - raise RuntimeError( - f"Embedding dimensions of the model ({embedding_size}) don't match the embedding dimensions of the document store ({embedding_dim}). " - f"Initiate {cls.__name__} again with arg embedding_dim={embedding_size}." - ) - - -class KeywordDocumentStore(BaseDocumentStore): - """ - Base class for implementing Document Stores that support keyword searches. - """ - - @abstractmethod - def query( - self, - query: Optional[str], - filters: Optional[FilterType] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query as defined by keyword matching algorithms like BM25. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - - :param top_k: How many documents to return per query. - :param custom_query: Custom query to be executed. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to False. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - pass - - @abstractmethod - def query_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[List[Document]]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the provided queries as defined by keyword matching algorithms like BM25. - - This method lets you find relevant documents for a single query string (output: List of Documents), or a - a list of query strings (output: List of Lists of Documents). - - :param queries: Single query or list of queries. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - - :param top_k: How many documents to return per query. - :param custom_query: Custom query to be executed. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to False. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - pass diff --git a/haystack/document_stores/deepsetcloud.py b/haystack/document_stores/deepsetcloud.py deleted file mode 100644 index a9c8caccc5..0000000000 --- a/haystack/document_stores/deepsetcloud.py +++ /dev/null @@ -1,708 +0,0 @@ -from functools import wraps -from typing import List, Optional, Union, Dict, Generator, Any - -import json -import logging -import numpy as np - -from haystack.document_stores import KeywordDocumentStore -from haystack.errors import HaystackError -from haystack.schema import Document, FilterType, Label -from haystack.utils import DeepsetCloud, DeepsetCloudError, args_to_kwargs - -logger = logging.getLogger(__name__) - - -def disable_and_log(func): - """ - Decorator to disable write operation, shows warning and inputs instead. - """ - - @wraps(func) - def wrapper(self, *args, **kwargs): - if not self.disabled_write_warning_shown: - logger.warning( - "Note that DeepsetCloudDocumentStore does not support write operations. " - "In order to verify your pipeline works correctly, each input to write operations will be logged." - ) - self.disabled_write_warning_shown = True - - args_as_kwargs = args_to_kwargs(args, func) - parameters = {**args_as_kwargs, **kwargs} - logger.info("Input to %s: %s", func.__name__, parameters) - - return wrapper - - -class DeepsetCloudDocumentStore(KeywordDocumentStore): - def __init__( - self, - api_key: Optional[str] = None, - workspace: str = "default", - index: Optional[str] = None, - duplicate_documents: str = "overwrite", - api_endpoint: Optional[str] = None, - similarity: str = "dot_product", - return_embedding: bool = False, - label_index: str = "default", - embedding_dim: int = 768, - use_prefiltering: bool = False, - search_fields: Union[str, list] = "content", - ): - """ - A DocumentStore facade enabling you to interact with the documents stored in deepset Cloud. - Thus you can run experiments like trying new nodes, pipelines, etc. without having to index your data again. - - You can also use this DocumentStore to create new pipelines on deepset Cloud. To do that, take the following - steps: - - - create a new DeepsetCloudDocumentStore without an index (e.g. `DeepsetCloudDocumentStore()`) - - create query and indexing pipelines using this DocumentStore - - call `Pipeline.save_to_deepset_cloud()` passing the pipelines and a `pipeline_config_name` - - call `Pipeline.deploy_on_deepset_cloud()` passing the `pipeline_config_name` - - DeepsetCloudDocumentStore is not intended for use in production-like scenarios. - See [https://haystack.deepset.ai/components/document-store](https://haystack.deepset.ai/components/document-store) - for more information. - - :param api_key: Secret value of the API key. - If not specified, will be read from DEEPSET_CLOUD_API_KEY environment variable. - See docs on how to generate an API key for your workspace: https://docs.cloud.deepset.ai/docs/connect-deepset-cloud-to-your-application - :param workspace: workspace name in deepset Cloud - :param index: name of the index to access within the deepset Cloud workspace. This equals typically the name of - your pipeline. You can run Pipeline.list_pipelines_on_deepset_cloud() to see all available ones. - If you set index to `None`, this DocumentStore will always return empty results. - This is especially useful if you want to create a new Pipeline within deepset Cloud - (see Pipeline.save_to_deepset_cloud()` and `Pipeline.deploy_on_deepset_cloud()`). - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, will be read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If DEEPSET_CLOUD_API_ENDPOINT environment variable is not specified either, defaults to "https://api.cloud.deepset.ai/api/v1". - :param similarity: The similarity function used to compare document vectors. 'dot_product' is the default since it is - more performant with DPR embeddings. 'cosine' is recommended if you are using a Sentence Transformer model. - :param label_index: index for the evaluation set interface - :param return_embedding: To return document embedding. - :param embedding_dim: Specifies the dimensionality of the embedding vector (only needed when using a dense retriever, for example, DensePassageRetriever pr EmbeddingRetriever, on top). - :param use_prefiltering: By default, DeepsetCloudDocumentStore uses post-filtering when querying with filters. - To use pre-filtering instead, set this parameter to `True`. Note that pre-filtering - comes at the cost of higher latency. - :param search_fields: Names of fields BM25Retriever uses to find matches to the incoming query in the documents, for example: ["content", "title"]. - """ - self.index = index - self.label_index = label_index - self.duplicate_documents = duplicate_documents - self.similarity = similarity - self.return_embedding = return_embedding - self.embedding_dim = embedding_dim - self.use_prefiltering = use_prefiltering - self.search_fields = search_fields - self.client = DeepsetCloud.get_index_client( - api_key=api_key, api_endpoint=api_endpoint, workspace=workspace, index=index - ) - # Check if index exists - pipeline_client = DeepsetCloud.get_pipeline_client( - api_key=api_key, api_endpoint=api_endpoint, workspace=workspace - ) - deployed_pipelines = set() - deployed_unhealthy_pipelines = set() - try: - for pipe in pipeline_client.list_pipeline_configs(workspace=workspace): - if pipe["status"] == "DEPLOYED": - deployed_pipelines.add(pipe["name"]) - elif pipe["status"] == "DEPLOYED_UNHEALTHY": - deployed_unhealthy_pipelines.add(pipe["name"]) - except Exception as ie: - raise DeepsetCloudError(f"Could not connect to deepset Cloud:\n{ie}") from ie - - self.index_exists = index in deployed_pipelines | deployed_unhealthy_pipelines - - if self.index_exists: - index_info = self.client.info() - indexing_info = index_info["indexing"] - if indexing_info["pending_file_count"] > 0: - logger.warning( - "%s files are pending to be indexed. Indexing status: %s", - indexing_info["pending_file_count"], - indexing_info["status"], - ) - if index in deployed_unhealthy_pipelines: - logger.warning( - "The index '%s' is unhealthy and should be redeployed using " - "`Pipeline.undeploy_on_deepset_cloud()` and `Pipeline.deploy_on_deepset_cloud()`.", - index, - ) - else: - logger.info( - "You are using a DeepsetCloudDocumentStore with an index that does not exist on deepset Cloud. " - "This document store always returns empty responses. This can be useful if you want to " - "create a new pipeline within deepset Cloud.\n" - "In order to create a new pipeline on deepset Cloud, take the following steps: \n" - " - create query and indexing pipelines using this DocumentStore\n" - " - call `Pipeline.save_to_deepset_cloud()` passing the pipelines and a `pipeline_config_name`\n" - " - call `Pipeline.deploy_on_deepset_cloud()` passing the `pipeline_config_name`" - ) - - self.evaluation_set_client = DeepsetCloud.get_evaluation_set_client( - api_key=api_key, api_endpoint=api_endpoint, workspace=workspace, evaluation_set=label_index - ) - - self.disabled_write_warning_shown = False - - super().__init__() - - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Get documents from the document store. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - :param batch_size: Number of documents that are passed to bulk function at a time. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - """ - logger.warning( - "`get_all_documents()` can get very slow and resource-heavy since all documents must be loaded from deepset Cloud. " - "Consider using `get_all_documents_generator()` instead." - ) - - return list( - self.get_all_documents_generator( - index=index, filters=filters, return_embedding=return_embedding, batch_size=batch_size, headers=headers - ) - ) - - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> Generator[Document, None, None]: - """ - Get documents from the document store. Under-the-hood, documents are fetched in batches from the - document store and yielded as individual documents. This method can be used to iteratively process - a large number of documents without having to load all documents in memory. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - """ - if not self.index_exists: - return - - if batch_size != 10_000: - raise ValueError("DeepsetCloudDocumentStore does not support batching") - - if index is None: - index = self.index - - if return_embedding is None: - return_embedding = self.return_embedding - - raw_documents = self.client.stream_documents( - return_embedding=return_embedding, filters=filters, index=index, headers=headers - ) - for raw_doc in raw_documents: - dict_doc = json.loads(raw_doc.decode("utf-8")) - yield Document.from_dict(dict_doc) - - def get_document_by_id( - self, id: str, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ) -> Optional[Document]: - if not self.index_exists: - return None - - if index is None: - index = self.index - - doc_dict = self.client.get_document(id=id, index=index, headers=headers) - doc: Optional[Document] = None - if doc_dict: - doc = Document.from_dict(doc_dict) - - return doc - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - if not self.index_exists: - return [] - - if batch_size != 10_000: - raise ValueError("DeepsetCloudDocumentStore does not support batching") - - docs = (self.get_document_by_id(id, index=index, headers=headers) for id in ids) - return [doc for doc in docs if doc is not None] - - def get_document_count( - self, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - ) -> int: - if not self.index_exists: - return 0 - - count_result = self.client.count_documents( - filters=filters, - only_documents_without_embedding=only_documents_without_embedding, - index=index, - headers=headers, - ) - return count_result["count"] - - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - """ - Find the document that is most similar to the provided `query_emb` by using a vector similarity metric. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return - :param index: Index name for storing the docs and metadata - :param return_embedding: To return document embedding - :param headers: Custom HTTP headers to pass to requests - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :return: - """ - if not self.index_exists: - return [] - - if return_embedding is None: - return_embedding = self.return_embedding - - doc_dicts = self.client.query( - query_emb=query_emb.tolist(), - filters=filters, - top_k=top_k, - return_embedding=return_embedding, - index=index, - scale_score=scale_score, - headers=headers, - use_prefiltering=self.use_prefiltering, - ) - docs = [Document.from_dict(doc) for doc in doc_dicts] - return docs - - def query( - self, - query: Optional[str], - filters: Optional[FilterType] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query as defined by the BM25 algorithm. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param custom_query: Custom query to be executed. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to requests - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to False. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - if not self.index_exists: - return [] - - doc_dicts = self.client.query( - query=query, - filters=filters, - top_k=top_k, - custom_query=custom_query, - index=index, - all_terms_must_match=all_terms_must_match, - scale_score=scale_score, - headers=headers, - ) - docs = [Document.from_dict(doc) for doc in doc_dicts] - return docs - - def query_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[List[Document]]: - # TODO This method currently just calls query multiple times. Adapt this once there is a query_batch endpoint - # in DC. - - documents = [] - if isinstance(filters, list): - if len(filters) != len(queries): - raise HaystackError( - "Number of filters does not match number of queries. Please provide as many filters" - " as queries or a single filter that will be applied to each query." - ) - else: - filters = [filters] * len(queries) if filters is not None else [{}] * len(queries) - - for query, cur_filters in zip(queries, filters): - cur_docs = self.query( - query=query, - filters=cur_filters, - top_k=top_k, - custom_query=custom_query, - index=index, - headers=headers, - all_terms_must_match=all_terms_must_match, - scale_score=scale_score, - ) - documents.append(cur_docs) - - return documents - - def _create_document_field_map(self) -> Dict: - return {} - - @disable_and_log - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: int = 10_000, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Indexes documents for later queries. - - :param documents: a list of Python dictionaries or a list of Haystack Document objects. - For documents as dictionaries, the format is {"text": ""}. - Optionally: Include meta data via {"text": "", - "meta":{"name": ", "author": "somebody", ...}} - It can be used for filtering and is accessible in the responses of the Finder. - :param index: Optional name of index where the documents shall be written to. - If None, the DocumentStore's default index (self.index) will be used. - :param batch_size: Number of documents that are passed to bulk function at a time. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - - :return: None - """ - pass - - @disable_and_log - def update_document_meta(self, id: str, meta: Dict[str, Any], index: Optional[str] = None): - """ - Update the metadata dictionary of a document by specifying its string id. - - :param id: The ID of the Document whose metadata is being updated. - :param meta: A dictionary with key-value pairs that should be added / changed for the provided Document ID. - :param index: Name of the index the Document is located at. - """ - pass - - def get_evaluation_sets(self) -> List[dict]: - """ - Returns a list of uploaded evaluation sets to deepset cloud. - - :return: list of evaluation sets as dicts - These contain ("name", "evaluation_set_id", "created_at", "matched_labels", "total_labels") as fields. - """ - return self.evaluation_set_client.get_evaluation_sets() - - def get_all_labels( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Label]: - """ - Returns a list of labels for the given index name. - - :param index: Optional name of evaluation set for which labels should be searched. - If None, the DocumentStore's default label_index (self.label_index) will be used. - :filters: Not supported. - :param headers: Not supported. - - :return: list of Labels. - """ - return self.evaluation_set_client.get_labels(evaluation_set=index) - - def get_label_count(self, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None) -> int: - """ - Counts the number of labels for the given index and returns the value. - - :param index: Optional evaluation set name for which the labels should be counted. - If None, the DocumentStore's default label_index (self.label_index) will be used. - :param headers: Not supported. - - :return: number of labels for the given index - """ - return self.evaluation_set_client.get_labels_count(evaluation_set=index) - - @disable_and_log - def write_labels( - self, - labels: Union[List[Label], List[dict]], - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - @disable_and_log - def delete_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - @disable_and_log - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - @disable_and_log - def delete_labels( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - pass - - @disable_and_log - def delete_index(self, index: str): - pass diff --git a/haystack/document_stores/elasticsearch/__init__.py b/haystack/document_stores/elasticsearch/__init__.py deleted file mode 100644 index 68c17db66e..0000000000 --- a/haystack/document_stores/elasticsearch/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -try: - # Use appropriate ElasticsearchDocumentStore depending on ES client version - from elasticsearch import VERSION - - if VERSION[0] == 8: - from .es8 import ElasticsearchDocumentStore # type: ignore - else: - from .es7 import ElasticsearchDocumentStore # type: ignore - -except (ModuleNotFoundError, ImportError): - # Import ES 7 as default if ES is not installed to raise the error message that elasticsearch extra is needed - from .es7 import ElasticsearchDocumentStore # type: ignore diff --git a/haystack/document_stores/elasticsearch/base.py b/haystack/document_stores/elasticsearch/base.py deleted file mode 100644 index 39d07a30c9..0000000000 --- a/haystack/document_stores/elasticsearch/base.py +++ /dev/null @@ -1,337 +0,0 @@ -import logging -from typing import Dict, List, Optional - -import numpy as np - -from haystack.errors import DocumentStoreError -from haystack.schema import Document, FilterType -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.document_stores.search_engine import SearchEngineDocumentStore - - -logger = logging.getLogger(__name__) - - -class _ElasticsearchDocumentStore(SearchEngineDocumentStore): - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - """ - Find the document that is most similar to the provided `query_emb` by using a vector similarity metric. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return - :param index: Index name for storing the docs and metadata - :param return_embedding: To return document embedding - :param headers: Custom HTTP headers to pass to elasticsearch client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :return: - """ - if index is None: - index = self.index - - if return_embedding is None: - return_embedding = self.return_embedding - - if not self.embedding_field: - raise RuntimeError("Please specify arg `embedding_field` in ElasticsearchDocumentStore()") - - body = self._construct_dense_query_body( - query_emb=query_emb, filters=filters, top_k=top_k, return_embedding=return_embedding - ) - - try: - result = self._search(index=index, **body, headers=headers)["hits"]["hits"] - if len(result) == 0: - count_documents = self.get_document_count(index=index, headers=headers) - if count_documents == 0: - logger.warning("Index is empty. First add some documents to search them.") - count_embeddings = self.get_embedding_count(index=index, headers=headers) - if count_embeddings == 0: - logger.warning("No documents with embeddings. Run the document store's update_embeddings() method.") - except self._RequestError as e: - if e.error == "search_phase_execution_exception": - error_message: str = ( - "search_phase_execution_exception: Likely some of your stored documents don't have embeddings. " - "Run the document store's update_embeddings() method." - ) - raise self._RequestError(e.status_code, error_message, e.info) - raise e - - documents = [ - self._convert_es_hit_to_document(hit, adapt_score_for_embedding=True, scale_score=scale_score) - for hit in result - ] - return documents - - def _construct_dense_query_body( - self, query_emb: np.ndarray, return_embedding: bool, filters: Optional[FilterType] = None, top_k: int = 10 - ): - body = {"size": top_k, "query": self._get_vector_similarity_query(query_emb, top_k)} - if filters: - filter_ = {"bool": {"filter": LogicalFilterClause.parse(filters).convert_to_elasticsearch()}} - if body["query"]["script_score"]["query"] == {"match_all": {}}: - body["query"]["script_score"]["query"] = filter_ - else: - body["query"]["script_score"]["query"]["bool"]["filter"]["bool"]["must"].append(filter_) - - excluded_fields = self._get_excluded_fields(return_embedding=return_embedding) - if excluded_fields: - body["_source"] = {"excludes": excluded_fields} - - return body - - def _create_document_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - """ - Create a new index for storing documents. - """ - if self.custom_mapping: - mapping = self.custom_mapping - else: - mapping = { - "mappings": { - "properties": {self.name_field: {"type": "keyword"}, self.content_field: {"type": "text"}}, - "dynamic_templates": [ - {"strings": {"path_match": "*", "match_mapping_type": "string", "mapping": {"type": "keyword"}}} - ], - }, - "settings": {"analysis": {"analyzer": {"default": {"type": self.analyzer}}}}, - } - - if self.synonyms: - for field in self.search_fields: - mapping["mappings"]["properties"].update({field: {"type": "text", "analyzer": "synonym"}}) - mapping["mappings"]["properties"][self.content_field] = {"type": "text", "analyzer": "synonym"} - - mapping["settings"]["analysis"]["analyzer"]["synonym"] = { - "tokenizer": "whitespace", - "filter": ["lowercase", "synonym"], - } - mapping["settings"]["analysis"]["filter"] = { - "synonym": {"type": self.synonym_type, "synonyms": self.synonyms} - } - - else: - for field in self.search_fields: - mapping["mappings"]["properties"].update({field: {"type": "text"}}) - - if self.embedding_field: - mapping["mappings"]["properties"][self.embedding_field] = { - "type": "dense_vector", - "dims": self.embedding_dim, - } - - try: - self._index_create(index=index_name, **mapping, headers=headers) - except self._RequestError as e: - # With multiple workers we need to avoid race conditions, where: - # - there's no index in the beginning - # - both want to create one - # - one fails as the other one already created it - if not self._index_exists(index_name, headers=headers): - raise e - - def _create_label_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - mapping = { - "mappings": { - "properties": { - "query": {"type": "text"}, - "answer": {"type": "nested"}, - "document": {"type": "nested"}, - "is_correct_answer": {"type": "boolean"}, - "is_correct_document": {"type": "boolean"}, - "origin": {"type": "keyword"}, # e.g. user-feedback or gold-label - "document_id": {"type": "keyword"}, - "no_answer": {"type": "boolean"}, - "pipeline_id": {"type": "keyword"}, - "created_at": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"}, - "updated_at": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"} - # TODO add pipeline_hash and pipeline_name once we migrated the REST API to pipelines - } - } - } - try: - self._index_create(index=index_name, **mapping, headers=headers) - except self._RequestError as e: - # With multiple workers we need to avoid race conditions, where: - # - there's no index in the beginning - # - both want to create one - # - one fails as the other one already created it - if not self._index_exists(index_name, headers=headers): - raise e - - def _validate_and_adjust_document_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - """ - Validates an existing document index. If there's no embedding field, we'll add it. - """ - indices = self._index_get(index=index_name, headers=headers) - - if not any(indices): - logger.warning( - "To use an index, you must create it first. The index called '%s' doesn't exist. " - "You can create it by setting `create_index=True` on init or by calling `write_documents()` if you prefer to create it on demand. " - "Note that this instance doesn't validate the index after you create it.", - index_name, - ) - - # If the index name is an alias that groups multiple existing indices, each of them must have an embedding_field. - for index_id, index_info in indices.items(): - mapping = index_info["mappings"] - if self.search_fields: - for search_field in self.search_fields: - if search_field in mapping["properties"]: - if mapping["properties"][search_field]["type"] != "text": - raise DocumentStoreError( - f"Remove '{search_field}' from `search_fields` or use another index if you want to query it using full text search. " - f"'{search_field}' of index '{index_id}' has type '{mapping['properties'][search_field]['type']}' but needs 'text' for full text search." - f"This error might occur if you are trying to use Haystack 1.0 and above with an existing Elasticsearch index created with a previous version of Haystack. " - f"Recreating the index with `recreate_index=True` will fix your environment. " - f"Note that you'll lose all data stored in the index." - ) - else: - mapping["properties"][search_field] = ( - {"type": "text", "analyzer": "synonym"} if self.synonyms else {"type": "text"} - ) - self._index_put_mapping(index=index_id, body=mapping, headers=headers) - - if self.embedding_field: - if ( - self.embedding_field in mapping["properties"] - and mapping["properties"][self.embedding_field]["type"] != "dense_vector" - ): - raise DocumentStoreError( - f"Update the document store to use a different name for the `embedding_field` parameter. " - f"The index '{index_id}' in Elasticsearch already has a field called '{self.embedding_field}' " - f"of type '{mapping['properties'][self.embedding_field]['type']}'." - ) - mapping["properties"][self.embedding_field] = {"type": "dense_vector", "dims": self.embedding_dim} - self._index_put_mapping(index=index_id, body=mapping, headers=headers) - - def _validate_server_version(self, expected_version: int): - """ - Validate that the Elasticsearch server version is compatible with the used ElasticsearchDocumentStore. - """ - if self.server_version[0] != expected_version: - logger.warning( - "This ElasticsearchDocumentStore has been built for Elasticsearch %s, but the detected version of the " - "Elasticsearch server is %s. Unexpected behaviors or errors may occur due to version incompatibility.", - expected_version, - ".".join(map(str, self.server_version)), - ) - - def _get_vector_similarity_query(self, query_emb: np.ndarray, top_k: int): - """ - Generate Elasticsearch query for vector similarity. - """ - if self.similarity == "cosine": - similarity_fn_name = "cosineSimilarity" - elif self.similarity == "dot_product": - similarity_fn_name = "dotProduct" - elif self.similarity == "l2": - similarity_fn_name = "l2norm" - else: - raise DocumentStoreError( - "Invalid value for similarity in ElasticSearchDocumentStore constructor. Choose between 'cosine', 'dot_product' and 'l2'" - ) - - # To handle scenarios where embeddings may be missing - script_score_query: dict = {"match_all": {}} - if self.skip_missing_embeddings: - script_score_query = {"bool": {"filter": {"bool": {"must": [{"exists": {"field": self.embedding_field}}]}}}} - - # Elasticsearch 7.6 introduced a breaking change regarding the vector function signatures: - # https://www.elastic.co/guide/en/elasticsearch/reference/7.6/breaking-changes-7.6.html#_update_to_vector_function_signatures - if self.server_version[0] == 7 and self.server_version[1] < 6: - similarity_script_source = f"{similarity_fn_name}(params.query_vector,doc['{self.embedding_field}']) + 1000" - else: - similarity_script_source = f"{similarity_fn_name}(params.query_vector,'{self.embedding_field}') + 1000" - - query = { - "script_score": { - "query": script_score_query, - "script": { - # offset score to ensure a positive range as required by Elasticsearch - "source": similarity_script_source, - "params": {"query_vector": query_emb.tolist()}, - }, - } - } - return query - - def _get_raw_similarity_score(self, score): - return score - 1000 diff --git a/haystack/document_stores/elasticsearch/es7.py b/haystack/document_stores/elasticsearch/es7.py deleted file mode 100644 index 730f5bce22..0000000000 --- a/haystack/document_stores/elasticsearch/es7.py +++ /dev/null @@ -1,278 +0,0 @@ -import logging -from typing import List, Optional, Type, Union - -from haystack.lazy_imports import LazyImport -from haystack.document_stores.search_engine import prepare_hosts -from .base import _ElasticsearchDocumentStore - - -failed_import_message = ( - "Run 'pip install farm-haystack[elasticsearch]'.\n" - "Note that this installs the Elasticsearch 7 client and requires a running Elasticsearch 7 instance. Starting from " - "Haystack version 1.21 , the 'elasticsearch' extra will install the Elasticsearch 8 client and will require a " - "running Elasticsearch 8 instance. To continue using Elasticsearch 7 with Haystack 1.21 and beyond, install the " - "'elasticsearch7' extra.\n" - "If you want to already start using Elasticsearch 8, install the 'elasticsearch8' extra" -) -with LazyImport(failed_import_message) as es_import: - from elasticsearch import Connection, Elasticsearch, RequestsHttpConnection, Urllib3HttpConnection - from elasticsearch.helpers import bulk, scan - from elasticsearch.exceptions import RequestError - -logger = logging.getLogger(__name__) - - -class ElasticsearchDocumentStore(_ElasticsearchDocumentStore): - def __init__( - self, - host: Union[str, List[str]] = "localhost", - port: Union[int, List[int]] = 9200, - username: str = "", - password: str = "", - api_key_id: Optional[str] = None, - api_key: Optional[str] = None, - aws4auth=None, - index: str = "document", - label_index: str = "label", - search_fields: Union[str, list] = "content", - content_field: str = "content", - name_field: str = "name", - embedding_field: str = "embedding", - embedding_dim: int = 768, - custom_mapping: Optional[dict] = None, - excluded_meta_data: Optional[list] = None, - analyzer: str = "standard", - scheme: str = "http", - ca_certs: Optional[str] = None, - verify_certs: bool = True, - recreate_index: bool = False, - create_index: bool = True, - refresh_type: str = "wait_for", - similarity: str = "dot_product", - timeout: int = 300, - return_embedding: bool = False, - duplicate_documents: str = "overwrite", - scroll: str = "1d", - skip_missing_embeddings: bool = True, - synonyms: Optional[List] = None, - synonym_type: str = "synonym", - use_system_proxy: bool = False, - batch_size: int = 10_000, - ): - """ - A DocumentStore using Elasticsearch to store and query the documents for our search. - - * Keeps all the logic to store and query documents from Elastic, incl. mapping of fields, adding filters or boosts to your queries, and storing embeddings - * You can either use an existing Elasticsearch index or create a new one via haystack - * Retrievers operate on top of this DocumentStore to find the relevant documents for a query - - :param host: url(s) of elasticsearch nodes - :param port: port(s) of elasticsearch nodes - :param username: username (standard authentication via http_auth) - :param password: password (standard authentication via http_auth) - :param api_key_id: ID of the API key (alternative authentication mode to the above http_auth) - :param api_key: Secret value of the API key (alternative authentication mode to the above http_auth) - :param aws4auth: Authentication for usage with aws elasticsearch (can be generated with the requests-aws4auth package) - :param index: Name of index in elasticsearch to use for storing the documents that we want to search. If not existing yet, we will create one. - :param label_index: Name of index in elasticsearch to use for storing labels. If not existing yet, we will create one. - :param search_fields: Name of fields used by BM25Retriever to find matches in the docs to our incoming query (using elastic's multi_match query), e.g. ["title", "full_text"] - :param content_field: Name of field that might contain the answer and will therefore be passed to the Reader Model (e.g. "full_text"). - If no Reader is used (e.g. in FAQ-Style QA) the plain content of this field will just be returned. - :param name_field: Name of field that contains the title of the the doc - :param embedding_field: Name of field containing an embedding vector (Only needed when using a dense retriever (e.g. DensePassageRetriever, EmbeddingRetriever) on top) - :param embedding_dim: Dimensionality of embedding vector (Only needed when using a dense retriever (e.g. DensePassageRetriever, EmbeddingRetriever) on top) - :param custom_mapping: If you want to use your own custom mapping for creating a new index in Elasticsearch, you can supply it here as a dictionary. - :param analyzer: Specify the default analyzer from one of the built-ins when creating a new Elasticsearch Index. - Elasticsearch also has built-in analyzers for different languages (e.g. impacting tokenization). More info at: - https://www.elastic.co/guide/en/elasticsearch/reference/7.9/analysis-analyzers.html - :param excluded_meta_data: Name of fields in Elasticsearch that should not be returned (e.g. [field_one, field_two]). - Helpful if you have fields with long, irrelevant content that you don't want to display in results (e.g. embedding vectors). - :param scheme: 'https' or 'http', protocol used to connect to your elasticsearch instance - :param ca_certs: Root certificates for SSL: it is a path to certificate authority (CA) certs on disk. You can use certifi package with certifi.where() to find where the CA certs file is located in your machine. - :param verify_certs: Whether to be strict about ca certificates - :param recreate_index: If set to True, an existing elasticsearch index will be deleted and a new one will be - created using the config you are using for initialization. Be aware that all data in the old index will be - lost if you choose to recreate the index. Be aware that both the document_index and the label_index will - be recreated. - :param create_index: - Whether to try creating a new index (If the index of that name is already existing, we will just continue in any case) - ..deprecated:: 2.0 - This param is deprecated. In the next major version we will always try to create an index if there is no - existing index (the current behaviour when create_index=True). If you are looking to recreate an - existing index by deleting it first if it already exist use param recreate_index. - :param refresh_type: Type of ES refresh used to control when changes made by a request (e.g. bulk) are made visible to search. - If set to 'wait_for', continue only after changes are visible (slow, but safe). - If set to 'false', continue directly (fast, but sometimes unintuitive behaviour when docs are not immediately available after ingestion). - More info at https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-refresh.html - :param similarity: The similarity function used to compare document vectors. 'dot_product' is the default since it is - more performant with DPR embeddings. 'cosine' is recommended if you are using a Sentence BERT model. - :param timeout: Number of seconds after which an ElasticSearch request times out. - :param return_embedding: To return document embedding - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param scroll: Determines how long the current index is fixed, e.g. during updating all documents with embeddings. - Defaults to "1d" and should not be larger than this. Can also be in minutes "5m" or hours "15h" - For details, see https://www.elastic.co/guide/en/elasticsearch/reference/current/scroll-api.html - :param skip_missing_embeddings: Parameter to control queries based on vector similarity when indexed documents miss embeddings. - Parameter options: (True, False) - False: Raises exception if one or more documents do not have embeddings at query time - True: Query will ignore all documents without embeddings (recommended if you concurrently index and query) - :param synonyms: List of synonyms can be passed while elasticsearch initialization. - For example: [ "foo, bar => baz", - "foozball , foosball" ] - More info at https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-tokenfilter.html - :param synonym_type: Synonym filter type can be passed. - Synonym or Synonym_graph to handle synonyms, including multi-word synonyms correctly during the analysis process. - More info at https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-graph-tokenfilter.html - :param use_system_proxy: Whether to use system proxy. - :param batch_size: Number of Documents to index at once / Number of queries to execute at once. If you face - memory issues, decrease the batch_size. - - """ - # Ensure all the required inputs were successful - es_import.check() - # Let the base class trap the right exception from the specific client - self._RequestError = RequestError - # Initiate the Elasticsearch client for version 7.x - client = ElasticsearchDocumentStore._init_elastic_client( - host=host, - port=port, - username=username, - password=password, - api_key=api_key, - api_key_id=api_key_id, - aws4auth=aws4auth, - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - use_system_proxy=use_system_proxy, - ) - - super().__init__( - client=client, - index=index, - label_index=label_index, - search_fields=search_fields, - content_field=content_field, - name_field=name_field, - embedding_field=embedding_field, - embedding_dim=embedding_dim, - custom_mapping=custom_mapping, - excluded_meta_data=excluded_meta_data, - analyzer=analyzer, - recreate_index=recreate_index, - create_index=create_index, - refresh_type=refresh_type, - similarity=similarity, - return_embedding=return_embedding, - duplicate_documents=duplicate_documents, - scroll=scroll, - skip_missing_embeddings=skip_missing_embeddings, - synonyms=synonyms, - synonym_type=synonym_type, - batch_size=batch_size, - ) - - self._validate_server_version(expected_version=7) - - def _do_bulk(self, *args, **kwargs): - """Override the base class method to use the Elasticsearch client""" - return bulk(*args, **kwargs) - - def _do_scan(self, *args, **kwargs): - """Override the base class method to use the Elasticsearch client""" - return scan(*args, **kwargs) - - @staticmethod - def _init_elastic_client( - host: Union[str, List[str]], - port: Union[int, List[int]], - username: str, - password: str, - api_key_id: Optional[str], - api_key: Optional[str], - aws4auth, - scheme: str, - ca_certs: Optional[str], - verify_certs: bool, - timeout: int, - use_system_proxy: bool, - ) -> "Elasticsearch": - hosts = prepare_hosts(host, port) - - if (api_key or api_key_id) and not (api_key and api_key_id): - raise ValueError("You must provide either both or none of `api_key_id` and `api_key`") - - connection_class: Type[Connection] = Urllib3HttpConnection - if use_system_proxy: - connection_class = RequestsHttpConnection - - if api_key: - # api key authentication - client = Elasticsearch( - hosts=hosts, - api_key=(api_key_id, api_key), - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - connection_class=connection_class, - ) - elif aws4auth: - # aws elasticsearch with IAM - # see https://elasticsearch-py.readthedocs.io/en/v7.12.0/index.html?highlight=http_auth#running-on-aws-with-iam - if username: - logger.warning( - "aws4auth and a username are passed to the ElasticsearchDocumentStore. The username will be ignored and aws4auth will be used for authentication." - ) - client = Elasticsearch( - hosts=hosts, - http_auth=aws4auth, - connection_class=RequestsHttpConnection, - use_ssl=True, - verify_certs=True, - timeout=timeout, - ) - elif username: - # standard http_auth - client = Elasticsearch( - hosts=hosts, - http_auth=(username, password), - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - connection_class=connection_class, - ) - else: - # there is no authentication for this elasticsearch instance - client = Elasticsearch( - hosts=hosts, - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - connection_class=connection_class, - ) - - # Test connection - try: - # ping uses a HEAD request on the root URI. In some cases, the user might not have permissions for that, - # resulting in a HTTP Forbidden 403 response. - if username in ["", "elastic"]: - status = client.ping() - if not status: - raise ConnectionError( - f"Initial connection to Elasticsearch failed. Make sure you run an Elasticsearch instance " - f"at `{hosts}` and that it has finished the initial ramp up (can take > 30s)." - ) - except Exception: - raise ConnectionError( - f"Initial connection to Elasticsearch failed. Make sure you run an Elasticsearch instance at `{hosts}` and that it has finished the initial ramp up (can take > 30s)." - ) - return client diff --git a/haystack/document_stores/elasticsearch/es8.py b/haystack/document_stores/elasticsearch/es8.py deleted file mode 100644 index b9215e553f..0000000000 --- a/haystack/document_stores/elasticsearch/es8.py +++ /dev/null @@ -1,360 +0,0 @@ -import logging -from typing import List, Optional, Union, Dict, Any - -from haystack.lazy_imports import LazyImport -from haystack import Document - -with LazyImport("Run 'pip install farm-haystack[elasticsearch8]'") as es_import: - from elasticsearch import Elasticsearch, RequestError - from elasticsearch.helpers import bulk, scan - from elastic_transport import RequestsHttpNode, Urllib3HttpNode - -from .base import _ElasticsearchDocumentStore - -logger = logging.getLogger(__name__) - - -def _prepare_hosts(host: Union[str, List[str]], port: Union[int, List[int]], scheme: str): - """ - Create a list of host(s), port(s) and scheme to allow direct client connections to multiple nodes, - in the format expected by the client. - """ - if isinstance(host, list): - if isinstance(port, list): - if not len(port) == len(host): - raise ValueError("Length of list `host` must match length of list `port`") - hosts = [{"host": h, "port": p, "scheme": scheme} for h, p in zip(host, port)] - else: - hosts = [{"host": h, "port": port, "scheme": scheme} for h in host] - else: - hosts = [{"host": host, "port": port, "scheme": scheme}] - return hosts - - -class ElasticsearchDocumentStore(_ElasticsearchDocumentStore): - def __init__( - self, - host: Union[str, List[str]] = "localhost", - port: Union[int, List[int]] = 9200, - username: str = "", - password: str = "", - api_key_id: Optional[str] = None, - api_key: Optional[str] = None, - aws4auth=None, - index: str = "document", - label_index: str = "label", - search_fields: Union[str, list] = "content", - content_field: str = "content", - name_field: str = "name", - embedding_field: str = "embedding", - embedding_dim: int = 768, - custom_mapping: Optional[dict] = None, - excluded_meta_data: Optional[list] = None, - analyzer: str = "standard", - scheme: str = "http", - ca_certs: Optional[str] = None, - verify_certs: bool = True, - recreate_index: bool = False, - create_index: bool = True, - refresh_type: str = "wait_for", - similarity: str = "dot_product", - timeout: int = 300, - return_embedding: bool = False, - duplicate_documents: str = "overwrite", - scroll: str = "1d", - skip_missing_embeddings: bool = True, - synonyms: Optional[List] = None, - synonym_type: str = "synonym", - use_system_proxy: bool = False, - batch_size: int = 10_000, - ): - """ - A DocumentStore using Elasticsearch to store and query the documents for our search. - - * Keeps all the logic to store and query documents from Elastic, incl. mapping of fields, adding filters or boosts to your queries, and storing embeddings - * You can either use an existing Elasticsearch index or create a new one via haystack - * Retrievers operate on top of this DocumentStore to find the relevant documents for a query - - :param host: url(s) of elasticsearch nodes - :param port: port(s) of elasticsearch nodes - :param username: username (standard authentication via http_auth) - :param password: password (standard authentication via http_auth) - :param api_key_id: ID of the API key (alternative authentication mode to the above http_auth) - :param api_key: Secret value of the API key (alternative authentication mode to the above http_auth) - :param aws4auth: Authentication for usage with aws elasticsearch (can be generated with the requests-aws4auth package) - :param index: Name of index in elasticsearch to use for storing the documents that we want to search. If not existing yet, we will create one. - :param label_index: Name of index in elasticsearch to use for storing labels. If not existing yet, we will create one. - :param search_fields: Name of fields used by BM25Retriever to find matches in the docs to our incoming query (using elastic's multi_match query), e.g. ["title", "full_text"] - :param content_field: Name of field that might contain the answer and will therefore be passed to the Reader Model (e.g. "full_text"). - If no Reader is used (e.g. in FAQ-Style QA) the plain content of this field will just be returned. - :param name_field: Name of field that contains the title of the the doc - :param embedding_field: Name of field containing an embedding vector (Only needed when using a dense retriever (e.g. DensePassageRetriever, EmbeddingRetriever) on top) - :param embedding_dim: Dimensionality of embedding vector (Only needed when using a dense retriever (e.g. DensePassageRetriever, EmbeddingRetriever) on top) - :param custom_mapping: If you want to use your own custom mapping for creating a new index in Elasticsearch, you can supply it here as a dictionary. - :param analyzer: Specify the default analyzer from one of the built-ins when creating a new Elasticsearch Index. - Elasticsearch also has built-in analyzers for different languages (e.g. impacting tokenization). More info at: - https://www.elastic.co/guide/en/elasticsearch/reference/7.9/analysis-analyzers.html - :param excluded_meta_data: Name of fields in Elasticsearch that should not be returned (e.g. [field_one, field_two]). - Helpful if you have fields with long, irrelevant content that you don't want to display in results (e.g. embedding vectors). - :param scheme: 'https' or 'http', protocol used to connect to your elasticsearch instance - :param ca_certs: Root certificates for SSL: it is a path to certificate authority (CA) certs on disk. You can use certifi package with certifi.where() to find where the CA certs file is located in your machine. - :param verify_certs: Whether to be strict about ca certificates - :param recreate_index: If set to True, an existing elasticsearch index will be deleted and a new one will be - created using the config you are using for initialization. Be aware that all data in the old index will be - lost if you choose to recreate the index. Be aware that both the document_index and the label_index will - be recreated. - :param create_index: - Whether to try creating a new index (If the index of that name is already existing, we will just continue in any case) - ..deprecated:: 2.0 - This param is deprecated. In the next major version we will always try to create an index if there is no - existing index (the current behaviour when create_index=True). If you are looking to recreate an - existing index by deleting it first if it already exist use param recreate_index. - :param refresh_type: Type of ES refresh used to control when changes made by a request (e.g. bulk) are made visible to search. - If set to 'wait_for', continue only after changes are visible (slow, but safe). - If set to 'false', continue directly (fast, but sometimes unintuitive behaviour when docs are not immediately available after ingestion). - More info at https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-refresh.html - :param similarity: The similarity function used to compare document vectors. 'dot_product' is the default since it is - more performant with DPR embeddings. 'cosine' is recommended if you are using a Sentence BERT model. - :param timeout: Number of seconds after which an ElasticSearch request times out. - :param return_embedding: To return document embedding - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param scroll: Determines how long the current index is fixed, e.g. during updating all documents with embeddings. - Defaults to "1d" and should not be larger than this. Can also be in minutes "5m" or hours "15h" - For details, see https://www.elastic.co/guide/en/elasticsearch/reference/current/scroll-api.html - :param skip_missing_embeddings: Parameter to control queries based on vector similarity when indexed documents miss embeddings. - Parameter options: (True, False) - False: Raises exception if one or more documents do not have embeddings at query time - True: Query will ignore all documents without embeddings (recommended if you concurrently index and query) - :param synonyms: List of synonyms can be passed while elasticsearch initialization. - For example: [ "foo, bar => baz", - "foozball , foosball" ] - More info at https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-tokenfilter.html - :param synonym_type: Synonym filter type can be passed. - Synonym or Synonym_graph to handle synonyms, including multi-word synonyms correctly during the analysis process. - More info at https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-graph-tokenfilter.html - :param use_system_proxy: Whether to use system proxy. - :param batch_size: Number of Documents to index at once / Number of queries to execute at once. If you face - memory issues, decrease the batch_size. - - """ - # Ensure all the required inputs were successful - es_import.check() - # Let the base class trap the right exception from the specific client - self._RequestError = RequestError - # Initiate the Elasticsearch client for version 8.x - client = ElasticsearchDocumentStore._init_elastic_client( - host=host, - port=port, - username=username, - password=password, - api_key=api_key, - api_key_id=api_key_id, - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - use_system_proxy=use_system_proxy, - ) - - super().__init__( - client=client, - index=index, - label_index=label_index, - search_fields=search_fields, - content_field=content_field, - name_field=name_field, - embedding_field=embedding_field, - embedding_dim=embedding_dim, - custom_mapping=custom_mapping, - excluded_meta_data=excluded_meta_data, - analyzer=analyzer, - recreate_index=recreate_index, - create_index=create_index, - refresh_type=refresh_type, - similarity=similarity, - return_embedding=return_embedding, - duplicate_documents=duplicate_documents, - scroll=scroll, - skip_missing_embeddings=skip_missing_embeddings, - synonyms=synonyms, - synonym_type=synonym_type, - batch_size=batch_size, - ) - - self._validate_server_version(expected_version=8) - - def _do_bulk(self, *args, **kwargs): - """Override the base class method to use the Elasticsearch client""" - return bulk(*args, **kwargs) - - def _do_scan(self, *args, **kwargs): - """Override the base class method to use the Elasticsearch client""" - return scan(*args, **kwargs) - - @staticmethod - def _init_elastic_client( - host: Union[str, List[str]], - port: Union[int, List[int]], - username: str, - password: str, - api_key_id: Optional[str], - api_key: Optional[str], - scheme: str, - ca_certs: Optional[str], - verify_certs: bool, - timeout: int, - use_system_proxy: bool, - aws4auth: Optional[str] = "", - ) -> Elasticsearch: - hosts = _prepare_hosts(host, port, scheme) - - if aws4auth: - logger.warning("AWS authentication is not supported in Elasticsearch version 8 and later!") - - if (api_key or api_key_id) and not (api_key and api_key_id): - raise ValueError("You must provide either both or none of `api_key_id` and `api_key`.") - - node_class = RequestsHttpNode if use_system_proxy else Urllib3HttpNode - - if api_key_id and api_key: - # api key authentication - if ca_certs is not None: - client = Elasticsearch( - hosts=hosts, - api_key=(api_key_id, api_key), - ca_certs=ca_certs, - verify_certs=verify_certs, - request_timeout=timeout, - node_class=node_class, - ) - else: - client = Elasticsearch( - hosts=hosts, - api_key=(api_key_id, api_key), - verify_certs=verify_certs, - request_timeout=timeout, - node_class=node_class, - ) - elif username: - # standard http_auth - if ca_certs is not None: - client = Elasticsearch( - hosts=hosts, - basic_auth=(username, password), - ca_certs=ca_certs, - verify_certs=verify_certs, - request_timeout=timeout, - node_class=node_class, - ) - else: - client = Elasticsearch( - hosts=hosts, - basic_auth=(username, password), - verify_certs=verify_certs, - request_timeout=timeout, - node_class=node_class, - ) - else: - # there is no authentication for this elasticsearch instance - if ca_certs is not None: - client = Elasticsearch( - hosts=hosts, - ca_certs=ca_certs, - verify_certs=verify_certs, - request_timeout=timeout, - node_class=node_class, - ) - else: - client = Elasticsearch( - hosts=hosts, - basic_auth=(username, password), - verify_certs=verify_certs, - request_timeout=timeout, - node_class=node_class, - ) - - # Test connection - try: - # ping uses a HEAD request on the root URI. In some cases, the user might not have permissions for that, - # resulting in a HTTP Forbidden 403 response. - if username in ["", "elastic"]: - status = client.ping() - if not status: - raise ConnectionError( - f"Initial connection to Elasticsearch failed. Make sure you run an Elasticsearch instance " - f"at `{hosts}` and that it has finished the initial ramp up (can take > 30s). Also, make sure " - f"you are using the correct credentials if you are using a secured Elasticsearch instance." - ) - except Exception: - raise ConnectionError( - f"Initial connection to Elasticsearch failed. Make sure you run an Elasticsearch instance at `{hosts}` " - f"and that it has finished the initial ramp up (can take > 30s). Also, make sure you are using the " - f"correct credentials if you are using a secured Elasticsearch instance." - ) - return client - - def _index_exists(self, index_name: str, headers: Optional[Dict[str, str]] = None) -> bool: - if logger.isEnabledFor(logging.DEBUG) and self.client.options(headers=headers).indices.exists_alias( - name=index_name - ): - logger.debug("Index name %s is an alias.", index_name) - - return self.client.options(headers=headers).indices.exists(index=index_name) - - def _index_delete(self, index): - if self._index_exists(index): - self.client.options(ignore_status=[400, 404]).indices.delete(index=index) - logger.info("Index '%s' deleted.", index) - - def _index_refresh(self, index, headers): - if self._index_exists(index): - self.client.options(headers=headers).indices.refresh(index=index) - - def _index_create(self, *args, **kwargs): - headers = kwargs.pop("headers", {}) - return self.client.options(headers=headers).indices.create(*args, **kwargs) - - def _index_get(self, *args, **kwargs): - headers = kwargs.pop("headers", {}) - return self.client.options(headers=headers).indices.get(*args, **kwargs) - - def _index_put_mapping(self, *args, **kwargs): - headers = kwargs.pop("headers", {}) - body = kwargs.pop("body", {}) - return self.client.options(headers=headers).indices.put_mapping(*args, **kwargs, **body) - - def _search(self, *args, **kwargs): - headers = kwargs.pop("headers", {}) - return self.client.options(headers=headers).search(*args, **kwargs) - - def _update(self, *args, **kwargs): - headers = kwargs.pop("headers", {}) - return self.client.options(headers=headers).update(*args, **kwargs) - - def _count(self, *args, **kwargs): - headers = kwargs.pop("headers", {}) - body = kwargs.pop("body", {}) - return self.client.options(headers=headers).count(*args, **kwargs, **body) - - def _delete_by_query(self, *args, **kwargs): - headers = kwargs.pop("headers", {}) - ignore_status = kwargs.pop("ignore", []) - body = kwargs.pop("body", {}) - return self.client.options(headers=headers, ignore_status=ignore_status).delete_by_query( - *args, **kwargs, **body - ) - - def _execute_msearch(self, index: str, body: List[Dict[str, Any]], scale_score: bool) -> List[List[Document]]: - responses = self.client.msearch(index=index, body=body) - documents = [] - for response in responses["responses"]: - result = response["hits"]["hits"] - cur_documents = [self._convert_es_hit_to_document(hit, scale_score=scale_score) for hit in result] - documents.append(cur_documents) - - return documents diff --git a/haystack/document_stores/es_converter.py b/haystack/document_stores/es_converter.py deleted file mode 100644 index 1dade37388..0000000000 --- a/haystack/document_stores/es_converter.py +++ /dev/null @@ -1,260 +0,0 @@ -from typing import Dict, Optional, List, Union - -from tqdm import tqdm - -from haystack.schema import Document -from haystack.document_stores.base import BaseDocumentStore -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.nodes.preprocessor.preprocessor import PreProcessor -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install farm-haystack[elasticsearch]'") as es_import: - from elasticsearch.helpers import scan - - -def open_search_index_to_document_store( - document_store: BaseDocumentStore, - original_index_name: str, - original_content_field: str, - original_name_field: Optional[str] = None, - included_metadata_fields: Optional[List[str]] = None, - excluded_metadata_fields: Optional[List[str]] = None, - store_original_ids: bool = True, - index: Optional[str] = None, - preprocessor: Optional[PreProcessor] = None, - id_hash_keys: Optional[List[str]] = None, - batch_size: int = 10_000, - host: Union[str, List[str]] = "localhost", - port: Union[int, List[int]] = 9200, - username: str = "admin", - password: str = "admin", - api_key_id: Optional[str] = None, - api_key: Optional[str] = None, - aws4auth=None, - scheme: str = "https", - ca_certs: Optional[str] = None, - verify_certs: bool = False, - timeout: int = 30, - use_system_proxy: bool = False, -) -> BaseDocumentStore: - """ - This function provides brownfield support of existing OpenSearch indexes by converting each of the records in - the provided index to haystack `Document` objects and writing them to the specified `DocumentStore`. It can be used - on a regular basis in order to add new records of the OpenSearch index to the `DocumentStore`. - - :param document_store: The haystack `DocumentStore` to write the converted `Document` objects to. - :param original_index_name: OpenSearch index containing the records to be converted. - :param original_content_field: OpenSearch field containing the text to be put in the `content` field of the - resulting haystack `Document` objects. - :param original_name_field: Optional OpenSearch field containing the title of the Document. - :param included_metadata_fields: List of OpenSearch fields that shall be stored in the `meta` field of the - resulting haystack `Document` objects. If `included_metadata_fields` and `excluded_metadata_fields` are `None`, - all the fields found in the OpenSearch records will be kept as metadata. You can specify only one of the - `included_metadata_fields` and `excluded_metadata_fields` parameters. - :param excluded_metadata_fields: List of OpenSearch fields that shall be excluded from the `meta` field of the - resulting haystack `Document` objects. If `included_metadata_fields` and `excluded_metadata_fields` are `None`, - all the fields found in the OpenSearch records will be kept as metadata. You can specify only one of the - `included_metadata_fields` and `excluded_metadata_fields` parameters. - :param store_original_ids: Whether to store the ID a record had in the original OpenSearch index at the - `"_original_es_id"` metadata field of the resulting haystack `Document` objects. This should be set to `True` - if you want to continuously update the `DocumentStore` with new records inside your OpenSearch index. If this - parameter was set to `False` on the first call of `open_search_index_to_document_store`, - all the indexed Documents in the `DocumentStore` will be overwritten in the second call. - :param index: Name of index in `document_store` to use to store the resulting haystack `Document` objects. - :param preprocessor: Optional PreProcessor that will be applied on the content field of the original OpenSearch - record. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param batch_size: Number of records to process at once. - :param host: URL(s) of OpenSearch nodes. - :param port: Ports(s) of OpenSearch nodes. - :param username: Username (standard authentication via http_auth). - :param password: Password (standard authentication via http_auth). - :param api_key_id: ID of the API key (alternative authentication mode to the above http_auth). - :param api_key: Secret value of the API key (alternative authentication mode to the above http_auth). - :param aws4auth: Authentication for usage with AWS OpenSearch - (can be generated with the requests-aws4auth package). - :param scheme: `"https"` or `"http"`, protocol used to connect to your OpenSearch instance. - :param ca_certs: Root certificates for SSL: it is a path to certificate authority (CA) certs on disk. - You can use certifi package with `certifi.where()` to find where the CA certs file is located in your machine. - :param verify_certs: Whether to be strict about ca certificates. - :param timeout: Number of seconds after which an OpenSearch request times out. - :param use_system_proxy: Whether to use system proxy. - """ - - return elasticsearch_index_to_document_store( - document_store=document_store, - original_index_name=original_index_name, - original_content_field=original_content_field, - original_name_field=original_name_field, - included_metadata_fields=included_metadata_fields, - excluded_metadata_fields=excluded_metadata_fields, - store_original_ids=store_original_ids, - index=index, - preprocessor=preprocessor, - id_hash_keys=id_hash_keys, - batch_size=batch_size, - host=host, - port=port, - username=username, - password=password, - api_key_id=api_key_id, - api_key=api_key, - aws4auth=aws4auth, - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - use_system_proxy=use_system_proxy, - ) - - -def elasticsearch_index_to_document_store( - document_store: BaseDocumentStore, - original_index_name: str, - original_content_field: str, - original_name_field: Optional[str] = None, - included_metadata_fields: Optional[List[str]] = None, - excluded_metadata_fields: Optional[List[str]] = None, - store_original_ids: bool = True, - index: Optional[str] = None, - preprocessor: Optional[PreProcessor] = None, - id_hash_keys: Optional[List[str]] = None, - batch_size: int = 10_000, - host: Union[str, List[str]] = "localhost", - port: Union[int, List[int]] = 9200, - username: str = "", - password: str = "", - api_key_id: Optional[str] = None, - api_key: Optional[str] = None, - aws4auth=None, - scheme: str = "http", - ca_certs: Optional[str] = None, - verify_certs: bool = True, - timeout: int = 30, - use_system_proxy: bool = False, -) -> BaseDocumentStore: - """ - This function provides brownfield support of existing Elasticsearch indexes by converting each of the records in - the provided index to haystack `Document` objects and writing them to the specified `DocumentStore`. It can be used - on a regular basis in order to add new records of the Elasticsearch index to the `DocumentStore`. - - :param document_store: The haystack `DocumentStore` to write the converted `Document` objects to. - :param original_index_name: Elasticsearch index containing the records to be converted. - :param original_content_field: Elasticsearch field containing the text to be put in the `content` field of the - resulting haystack `Document` objects. - :param original_name_field: Optional Elasticsearch field containing the title of the Document. - :param included_metadata_fields: List of Elasticsearch fields that shall be stored in the `meta` field of the - resulting haystack `Document` objects. If `included_metadata_fields` and `excluded_metadata_fields` are `None`, - all the fields found in the Elasticsearch records will be kept as metadata. You can specify only one of the - `included_metadata_fields` and `excluded_metadata_fields` parameters. - :param excluded_metadata_fields: List of Elasticsearch fields that shall be excluded from the `meta` field of the - resulting haystack `Document` objects. If `included_metadata_fields` and `excluded_metadata_fields` are `None`, - all the fields found in the Elasticsearch records will be kept as metadata. You can specify only one of the - `included_metadata_fields` and `excluded_metadata_fields` parameters. - :param store_original_ids: Whether to store the ID a record had in the original Elasticsearch index at the - `"_original_es_id"` metadata field of the resulting haystack `Document` objects. This should be set to `True` - if you want to continuously update the `DocumentStore` with new records inside your Elasticsearch index. If this - parameter was set to `False` on the first call of `elasticsearch_index_to_document_store`, - all the indexed Documents in the `DocumentStore` will be overwritten in the second call. - :param index: Name of index in `document_store` to use to store the resulting haystack `Document` objects. - :param preprocessor: Optional PreProcessor that will be applied on the content field of the original Elasticsearch - record. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param batch_size: Number of records to process at once. - :param host: URL(s) of Elasticsearch nodes. - :param port: Ports(s) of Elasticsearch nodes. - :param username: Username (standard authentication via http_auth). - :param password: Password (standard authentication via http_auth). - :param api_key_id: ID of the API key (alternative authentication mode to the above http_auth). - :param api_key: Secret value of the API key (alternative authentication mode to the above http_auth). - :param aws4auth: Authentication for usage with AWS Elasticsearch - (can be generated with the requests-aws4auth package). - :param scheme: `"https"` or `"http"`, protocol used to connect to your Elasticsearch instance. - :param ca_certs: Root certificates for SSL: it is a path to certificate authority (CA) certs on disk. - You can use certifi package with `certifi.where()` to find where the CA certs file is located in your machine. - :param verify_certs: Whether to be strict about ca certificates. - :param timeout: Number of seconds after which an Elasticsearch request times out. - :param use_system_proxy: Whether to use system proxy. - """ - es_import.check() - - # This import cannot be at the beginning of the file, as this would result in a circular import - from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore - - # Initialize Elasticsearch client - es_client = ElasticsearchDocumentStore._init_elastic_client( - host=host, - port=port, - username=username, - password=password, - api_key=api_key, - api_key_id=api_key_id, - aws4auth=aws4auth, - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - use_system_proxy=use_system_proxy, - ) - - # Get existing original ES IDs inside DocumentStore in order to not reindex the corresponding records - existing_ids = [ - doc.meta["_original_es_id"] - for doc in document_store.get_all_documents_generator(index=index) - if "_original_es_id" in doc.meta - ] - - # Iterate over each individual record - query: Dict[str, Dict] = {"query": {"bool": {"must": [{"match_all": {}}]}}} - if existing_ids: - filters = LogicalFilterClause.parse({"_id": {"$nin": existing_ids}}).convert_to_elasticsearch() - query["query"]["bool"]["filter"] = filters - records = scan(client=es_client, query=query, index=original_index_name) - number_of_records = es_client.count(index=original_index_name, body=query)["count"] - haystack_documents: List[Document] = [] - for idx, record in enumerate(tqdm(records, total=number_of_records, desc="Converting ES Records")): - # Write batch_size number of documents to haystack DocumentStore - if (idx + 1) % batch_size == 0: - document_store.write_documents(haystack_documents, index=index) - haystack_documents = [] - - # Get content and metadata of current record - content = record["_source"].pop(original_content_field, "") - if content: - meta = {} - if original_name_field is not None and original_name_field in record["_source"]: - meta["name"] = record["_source"].pop(original_name_field) - # Only add selected metadata fields - if included_metadata_fields is not None: - for metadata_field in included_metadata_fields: - if metadata_field in record["_source"]: - meta[metadata_field] = record["_source"][metadata_field] - # Add all metadata fields except for those in excluded_metadata_fields - else: - if excluded_metadata_fields is not None: - for metadata_field in excluded_metadata_fields: - record["_source"].pop(metadata_field, None) - meta.update(record["_source"]) - - if store_original_ids: - meta["_original_es_id"] = record["_id"] - - record_doc = Document(content=content, meta=meta, id_hash_keys=id_hash_keys) - - # Apply preprocessor if provided - preprocessed_docs = [record_doc] - if preprocessor is not None: - preprocessed_docs = preprocessor.process(record_doc, id_hash_keys=id_hash_keys) - - haystack_documents.extend(preprocessed_docs) - - if haystack_documents: - document_store.write_documents(haystack_documents, index=index) - - return document_store diff --git a/haystack/document_stores/faiss.py b/haystack/document_stores/faiss.py deleted file mode 100644 index 258b874553..0000000000 --- a/haystack/document_stores/faiss.py +++ /dev/null @@ -1,737 +0,0 @@ -import copy -from typing import Union, List, Optional, Dict, Generator - -import json -import logging -import warnings -from pathlib import Path -from copy import deepcopy -from inspect import Signature, signature - -import numpy as np -from tqdm import tqdm - -from haystack.schema import Document, FilterType -from haystack.utils.batching import get_batches_from_generator -from haystack.nodes.retriever import DenseRetriever -from haystack.document_stores.sql import SQLDocumentStore -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install farm-haystack[faiss]'") as faiss_import: - import faiss - - -logger = logging.getLogger(__name__) - - -class FAISSDocumentStore(SQLDocumentStore): - """ - A DocumentStore for very large-scale, embedding-based dense Retrievers, like the DPR. - - It implements the [FAISS library](https://github.com/facebookresearch/faiss) - to perform similarity search on vectors. - - The document text and meta-data (for filtering) are stored using the SQLDocumentStore, while - the vector embeddings are indexed in a FAISS index. - - When you initialize the FAISSDocumentStore, the `faiss_document_store.db` database file is created on your disk. For more information, see [DocumentStore](https://docs.haystack.deepset.ai/docs/document_store). - """ - - def __init__( - self, - sql_url: str = "sqlite:///faiss_document_store.db", - vector_dim: Optional[int] = None, - embedding_dim: int = 768, - faiss_index_factory_str: str = "Flat", - faiss_index: Optional["faiss.swigfaiss.Index"] = None, - return_embedding: bool = False, - index: str = "document", - similarity: str = "dot_product", - embedding_field: str = "embedding", - progress_bar: bool = True, - duplicate_documents: str = "overwrite", - faiss_index_path: Optional[Union[str, Path]] = None, - faiss_config_path: Optional[Union[str, Path]] = None, - isolation_level: Optional[str] = None, - n_links: int = 64, - ef_search: int = 20, - ef_construction: int = 80, - validate_index_sync: bool = True, - batch_size: int = 10_000, - ): - """ - :param sql_url: SQL connection URL for the database. The default value is "sqlite:///faiss_document_store.db"`. It defaults to a local, file-based SQLite DB. For large scale deployment, we recommend Postgres. - :param vector_dim: Deprecated. Use embedding_dim instead. - :param embedding_dim: The embedding vector size. Default: 768. - :param faiss_index_factory_str: Creates a new FAISS index of the specified type. - It determines the type based on the string you pass to it, following the conventions - of the original FAISS index factory. - Recommended options: - - "Flat" (default): Best accuracy (= exact). Becomes slow and RAM-intense for > 1 Mio docs. - - "HNSW": Graph-based heuristic. If you don't specify it further, - we use the following configuration: - HNSW64, efConstruction=80 and efSearch=20. - - "IVFx,Flat": Inverted index. Replace x with the number of centroids aka nlist. - Rule of thumb: nlist = 10 * sqrt (num_docs) is a good starting point. - For more details see: - - [Overview of indices](https://github.com/facebookresearch/faiss/wiki/Faiss-indexes) - - [Guideline for choosing an index](https://github.com/facebookresearch/faiss/wiki/Guidelines-to-choose-an-index) - - [FAISS Index factory](https://github.com/facebookresearch/faiss/wiki/The-index-factory) - Benchmarks: XXX - :param faiss_index: Loads an existing FAISS index. This can be an empty index you configured manually - or an index with Documents you used in Haystack before and want to load again. You can use it to load a previously saved DocumentStore. - :param return_embedding: Returns document embedding. Unlike other document stores, FAISS will return normalized embeddings. - :param index: Specifies the name of the index in DocumentStore to use. - :param similarity: Specifies the similarity function used to compare document vectors. 'dot_product' is the default because it's - more performant with DPR embeddings. 'cosine' is recommended if you're using a Sentence-Transformer model. - In both cases, the returned values in Document.score are normalized to be in range [0,1]: - For `dot_product`: expit(np.asarray(raw_score / 100)) - For `cosine`: (raw_score + 1) / 2 - :param embedding_field: The name of the field containing an embedding vector. - :param progress_bar: Shows a tqdm progress bar. - You may want to disable it in production deployments to keep the logs clean. - :param duplicate_documents: Handles duplicates document based on parameter options. - Parameter options: ( 'skip','overwrite','fail') - skip: Ignores the duplicate documents. - overwrite: Updates any existing documents with the same ID when adding documents. - fail: Raises an error if the document ID of the document being added already - exists. - :param faiss_index_path: The stored FAISS index file. Call `save()` to create this file. Use the same index file path you specified when calling `save()`. - If you specify `faiss_index_path`, you can only pass `faiss_config_path`. - :param faiss_config_path: Stored FAISS initial configuration. It contains all the parameters used to initialize the DocumentStore. Call `save()` to create it and then use the same configuration file path you specified when calling `save()`. Don't set it if you haven't specified `config_path` when calling `save()`. - :param isolation_level: See SQLAlchemy's `isolation_level` parameter for [`create_engine()`](https://docs.sqlalchemy.org/en/14/core/engines.html#sqlalchemy.create_engine.params.isolation_level). - :param n_links: Used only if `index_factory == "HNSW"`. - :param ef_search: Used only if `index_factory == "HNSW"`. - :param ef_construction: Used only if `index_factory == "HNSW"`. - :param validate_index_sync: Checks if the document count equals the embedding count at initialization time. - :param batch_size: Number of Documents to index at once / Number of queries to execute at once. If you face - memory issues, decrease the batch_size. - """ - faiss_import.check() - # special case if we want to load an existing index from disk - # load init params from disk and run init again - if faiss_index_path is not None: - sig = signature(self.__class__.__init__) - self._validate_params_load_from_disk(sig, locals()) - init_params = self._load_init_params_from_config(faiss_index_path, faiss_config_path) - self.__class__.__init__(self, **init_params) # pylint: disable=non-parent-init-called - return - - if similarity in ("dot_product", "cosine"): - self.similarity = similarity - self.metric_type = faiss.METRIC_INNER_PRODUCT - elif similarity == "l2": - self.similarity = similarity - self.metric_type = faiss.METRIC_L2 - else: - raise ValueError( - "The FAISS document store can currently only support dot_product, cosine, and l2 similarity. " - "Set similarity to one of these values." - ) - - if vector_dim is not None: - warnings.warn( - message="Use `embedding_dim` as the 'vector_dim' parameter is deprecated.", - category=DeprecationWarning, - stacklevel=2, - ) - self.embedding_dim = vector_dim - else: - self.embedding_dim = embedding_dim - - self.faiss_index_factory_str = faiss_index_factory_str - self.faiss_indexes: Dict[str, faiss.swigfaiss.Index] = {} - if faiss_index: - self.faiss_indexes[index] = faiss_index - else: - self.faiss_indexes[index] = self._create_new_index( - embedding_dim=self.embedding_dim, - index_factory=faiss_index_factory_str, - metric_type=self.metric_type, - n_links=n_links, - ef_search=ef_search, - ef_construction=ef_construction, - ) - - self.return_embedding = return_embedding - self.embedding_field = embedding_field - self.batch_size = batch_size - - self.progress_bar = progress_bar - - super().__init__( - url=sql_url, index=index, duplicate_documents=duplicate_documents, isolation_level=isolation_level - ) - - if validate_index_sync: - self._validate_index_sync() - - def _validate_params_load_from_disk(self, sig: Signature, locals: dict): - allowed_params = ["faiss_index_path", "faiss_config_path", "self"] - invalid_param_set = False - - for param in sig.parameters.values(): - if param.name not in allowed_params and param.default != locals[param.name]: - invalid_param_set = True - break - - if invalid_param_set: - raise ValueError("If faiss_index_path is passed, no other params besides faiss_config_path are allowed.") - - def _validate_index_sync(self): - # This check ensures the correct document database was loaded. - # If it fails, make sure you provided the path to the database - # used when creating the original FAISS index - if not self.get_document_count() == self.get_embedding_count(): - raise ValueError( - f"The number of documents in the SQL database ({self.get_document_count()}) doesn't " - f"match the number of embeddings in FAISS ({self.get_embedding_count()}). Make sure your FAISS " - "configuration file points to the same database that " - "you used when you saved the original index." - ) - - def _create_new_index( - self, - embedding_dim: int, - metric_type, - index_factory: str = "Flat", - n_links: int = 64, - ef_search: int = 20, - ef_construction: int = 80, - ): - if index_factory == "HNSW": - # faiss index factory doesn't give the same results for HNSW IP, therefore direct init. - # defaults here are similar to DPR codebase (good accuracy, but very high RAM consumption) - index = faiss.IndexHNSWFlat(embedding_dim, n_links, metric_type) - index.hnsw.efSearch = ef_search - index.hnsw.efConstruction = ef_construction - - logger.info( - "HNSW params: n_links: %s, efSearch: %s, efConstruction: %s", - n_links, - index.hnsw.efSearch, - index.hnsw.efConstruction, - ) - else: - index = faiss.index_factory(embedding_dim, index_factory, metric_type) - return index - - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: Optional[int] = None, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ) -> None: - """ - Add new documents to the DocumentStore. - - :param documents: List of `Dicts` or List of `Documents`. If they already contain the embeddings, we'll index - them right away in FAISS. If not, you can later call update_embeddings() to create & index them. - :param index: (SQL) index name for storing the docs and metadata. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options: ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents. - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :raises DuplicateDocumentError: Exception trigger on duplicate document. - :return: None - """ - if headers: - raise NotImplementedError("FAISSDocumentStore does not support headers.") - - index = index or self.index - batch_size = batch_size or self.batch_size - - duplicate_documents = duplicate_documents or self.duplicate_documents - assert ( - duplicate_documents in self.duplicate_documents_options - ), f"duplicate_documents parameter must be {', '.join(self.duplicate_documents_options)}" - - if not self.faiss_indexes.get(index): - self.faiss_indexes[index] = self._create_new_index( - embedding_dim=self.embedding_dim, - index_factory=self.faiss_index_factory_str, - metric_type=faiss.METRIC_INNER_PRODUCT, - ) - - field_map = self._create_document_field_map() - document_objects = [Document.from_dict(d, field_map=field_map) if isinstance(d, dict) else d for d in documents] - document_objects = self._handle_duplicate_documents( - documents=document_objects, index=index, duplicate_documents=duplicate_documents - ) - - if len(document_objects) == 0: - return - - vector_id = self.faiss_indexes[index].ntotal - add_vectors = all(doc.embedding is not None for doc in document_objects) - - if vector_id > 0 and self.duplicate_documents == "overwrite" and add_vectors: - logger.warning( - "`FAISSDocumentStore` is adding new vectors to an existing `faiss_index`.\n" - "Please call `update_embeddings` method to correctly repopulate `faiss_index`" - ) - - with tqdm( - total=len(document_objects), disable=not self.progress_bar, position=0, desc="Writing Documents" - ) as progress_bar: - for i in range(0, len(document_objects), batch_size): - batch_documents = document_objects[i : i + batch_size] - if add_vectors: - if not self.faiss_indexes[index].is_trained: - raise ValueError( - f"FAISS index of type {self.faiss_index_factory_str} must be trained before adding vectors. Call `train_index()` " - "method before adding the vectors. For details, refer to the documentation: " - "[FAISSDocumentStore API](https://docs.haystack.deepset.ai/reference/document-store-api#faissdocumentstoretrain_index)." - ) - - embeddings = [doc.embedding for doc in batch_documents] - embeddings_to_index = np.array(embeddings, dtype="float32") - - if self.similarity == "cosine": - self.normalize_embedding(embeddings_to_index) - - self.faiss_indexes[index].add(embeddings_to_index) - - # write_documents method (duplicate_documents="overwrite") should properly work in combination with - # update_embeddings method (update_existing_embeddings=False). - # If no new embeddings are provided, we save the existing FAISS vector ids - elif self.duplicate_documents == "overwrite": - existing_docs = self.get_documents_by_id(ids=[doc.id for doc in batch_documents], index=index) - existing_docs_vector_ids = { - doc.id: doc.meta["vector_id"] for doc in existing_docs if doc.meta and "vector_id" in doc.meta - } - - docs_to_write_in_sql = [] - for doc in batch_documents: - meta = doc.meta - if add_vectors: - meta["vector_id"] = vector_id - vector_id += 1 - elif self.duplicate_documents == "overwrite" and doc.id in existing_docs_vector_ids: - meta["vector_id"] = existing_docs_vector_ids[doc.id] - docs_to_write_in_sql.append(doc) - - super(FAISSDocumentStore, self).write_documents( - docs_to_write_in_sql, index=index, duplicate_documents=duplicate_documents, batch_size=batch_size - ) - progress_bar.update(batch_size) - - def _create_document_field_map(self) -> Dict: - return {self.index: self.embedding_field} - - def update_embeddings( - self, - retriever: DenseRetriever, - index: Optional[str] = None, - update_existing_embeddings: bool = True, - filters: Optional[FilterType] = None, - batch_size: Optional[int] = None, - ): - """ - Updates the embeddings in the the document store using the encoding model specified in the retriever. - This can be useful if want to add or change the embeddings for your documents (e.g. after changing the retriever config). - - :param retriever: Retriever to use to get embeddings for text - :param index: Index name for which embeddings are to be updated. If set to None, the default self.index is used. - :param update_existing_embeddings: Whether to update existing embeddings of the documents. If set to False, - only documents without embeddings are processed. This mode can be used for - incremental updating of embeddings, wherein, only newly indexed documents - get processed. - :param filters: Optional filters to narrow down the documents for which embeddings are to be updated. - Example: {"name": ["some", "more"], "category": ["only_one"]} - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :return: None - """ - index = index or self.index - batch_size = batch_size or self.batch_size - - if update_existing_embeddings is True: - if filters is None: - self.faiss_indexes[index].reset() - self.reset_vector_ids(index) - else: - raise Exception("update_existing_embeddings=True is not supported with filters.") - - if not self.faiss_indexes.get(index): - raise ValueError("Couldn't find a FAISS index. Try to init the FAISSDocumentStore() again ...") - - if not self.faiss_indexes[index].is_trained: - raise ValueError( - "FAISS index of type {} must be trained before adding vectors. Call `train_index()` " - "method before adding the vectors. For details, refer to the documentation: " - "[FAISSDocumentStore API](https://docs.haystack.deepset.ai/reference/document-store-api#faissdocumentstoretrain_index)." - "".format(self.faiss_index_factory_str) - ) - - document_count = self.get_document_count(index=index) - if document_count == 0: - logger.warning("Calling DocumentStore.update_embeddings() on an empty index") - return - - logger.info("Updating embeddings for %s docs...", document_count) - vector_id = self.faiss_indexes[index].ntotal - - result = self._query( - index=index, - vector_ids=None, - batch_size=batch_size, - filters=filters, - only_documents_without_embedding=not update_existing_embeddings, - ) - batched_documents = get_batches_from_generator(result, batch_size) - with tqdm( - total=document_count, disable=not self.progress_bar, position=0, unit=" docs", desc="Updating Embedding" - ) as progress_bar: - for document_batch in batched_documents: - embeddings = retriever.embed_documents(document_batch) - self._validate_embeddings_shape( - embeddings=embeddings, num_documents=len(document_batch), embedding_dim=self.embedding_dim - ) - - if self.similarity == "cosine": - self.normalize_embedding(embeddings) - - self.faiss_indexes[index].add(embeddings.astype(np.float32)) - - vector_id_map = {} - for doc in document_batch: - vector_id_map[str(doc.id)] = str(vector_id) - vector_id += 1 - self.update_vector_ids(vector_id_map, index=index) - progress_bar.set_description_str("Documents Processed") - progress_bar.update(batch_size) - - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - batch_size = batch_size or self.batch_size - if headers: - raise NotImplementedError("FAISSDocumentStore does not support headers.") - - result = self.get_all_documents_generator( - index=index, filters=filters, return_embedding=return_embedding, batch_size=batch_size - ) - documents = list(result) - return documents - - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ) -> Generator[Document, None, None]: - """ - Get all documents from the document store. Under-the-hood, documents are fetched in batches from the - document store and yielded as individual documents. This method can be used to iteratively process - a large number of documents without having to load all documents in memory. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the documents to return. - Example: {"name": ["some", "more"], "category": ["only_one"]} - :param return_embedding: Whether to return the document embeddings. Unlike other document stores, FAISS will return normalized embeddings - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - """ - if headers: - raise NotImplementedError("FAISSDocumentStore does not support headers.") - - index = index or self.index - batch_size = batch_size or self.batch_size - documents = super(FAISSDocumentStore, self).get_all_documents_generator( - index=index, filters=filters, batch_size=batch_size, return_embedding=False - ) - if return_embedding is None: - return_embedding = self.return_embedding - - for doc in documents: - if return_embedding and doc.meta and doc.meta.get("vector_id") is not None: - doc.embedding = self.faiss_indexes[index].reconstruct(int(doc.meta["vector_id"])) - yield doc - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - if headers: - raise NotImplementedError("FAISSDocumentStore does not support headers.") - - index = index or self.index - batch_size = batch_size or self.batch_size - - documents = super(FAISSDocumentStore, self).get_documents_by_id(ids=ids, index=index, batch_size=batch_size) - if self.return_embedding: - for doc in documents: - if doc.meta and doc.meta.get("vector_id") is not None: - doc.embedding = self.faiss_indexes[index].reconstruct(int(doc.meta["vector_id"])) - return documents - - def get_embedding_count(self, index: Optional[str] = None, filters: Optional[FilterType] = None) -> int: - """ - Return the count of embeddings in the document store. - """ - if filters: - raise Exception("filters are not supported for get_embedding_count in FAISSDocumentStore") - index = index or self.index - return self.faiss_indexes[index].ntotal - - def train_index( - self, - documents: Optional[Union[List[dict], List[Document]]] = None, - embeddings: Optional[np.ndarray] = None, - index: Optional[str] = None, - ): - """ - Some FAISS indices (e.g. IVF) require initial "training" on a sample of vectors before you can add your final vectors. - The train vectors should come from the same distribution as your final ones. - You can pass either documents (incl. embeddings) or just the plain embeddings that the index shall be trained on. - - :param documents: Documents (incl. the embeddings) - :param embeddings: Plain embeddings - :param index: Name of the index to train. If None, the DocumentStore's default index (self.index) will be used. - :return: None - """ - index = index or self.index - if isinstance(embeddings, np.ndarray) and documents: - raise ValueError("Either pass `documents` or `embeddings`. You passed both.") - - if documents: - document_objects = [Document.from_dict(d) if isinstance(d, dict) else d for d in documents] - doc_embeddings = [doc.embedding for doc in document_objects if doc.embedding is not None] - embeddings_for_train = np.array(doc_embeddings, dtype="float32") - self.faiss_indexes[index].train(embeddings_for_train) - elif isinstance(embeddings, np.ndarray): - self.faiss_indexes[index].train(embeddings) - else: - logger.warning( - "When calling `train_index`, you must provide either Documents or embeddings. Because none of these values was provided, no training will be performed. " - ) - - def delete_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete all documents from the document store. - """ - if headers: - raise NotImplementedError("FAISSDocumentStore does not support headers.") - - logger.warning( - """DEPRECATION WARNINGS: - 1. delete_all_documents() method is deprecated, please use delete_documents method - For more details, please refer to the issue: https://github.com/deepset-ai/haystack/issues/1045 - """ - ) - self.delete_documents(index, None, filters) - - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents from the document store. All documents are deleted if no filters are passed. - - :param index: Index name to delete the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param ids: Optional list of IDs to narrow down the documents to be deleted. - :param filters: Optional filters to narrow down the documents to be deleted. - Example filters: {"name": ["some", "more"], "category": ["only_one"]}. - If filters are provided along with a list of IDs, this method deletes the - intersection of the two query results (documents that match the filters and - have their ID in the list). - :return: None - """ - if headers: - raise NotImplementedError("FAISSDocumentStore does not support headers.") - - index = index or self.index - if index in self.faiss_indexes.keys(): - if not filters and not ids: - self.faiss_indexes[index].reset() - else: - affected_docs = self.get_all_documents(filters=filters) - if ids: - affected_docs = [doc for doc in affected_docs if doc.id in ids] - doc_ids = [ - doc.meta.get("vector_id") - for doc in affected_docs - if doc.meta and doc.meta.get("vector_id") is not None - ] - self.faiss_indexes[index].remove_ids(np.array(doc_ids, dtype="int64")) - - super().delete_documents(index=index, ids=ids, filters=filters) - - def delete_index(self, index: str): - """ - Delete an existing index. The index including all data will be removed. - - :param index: The name of the index to delete. - :return: None - """ - if index == self.index: - logger.warning( - "Deletion of default index '%s' detected. " - "If you plan to use this index again, please reinstantiate '%s' in order to avoid side-effects.", - index, - self.__class__.__name__, - ) - if index in self.faiss_indexes: - del self.faiss_indexes[index] - logger.info("Index '%s' deleted.", index) - super().delete_index(index) - - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - """ - Find the document that is most similar to the provided `query_emb` by using a vector similarity metric. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param filters: Optional filters to narrow down the search space. - Example: {"name": ["some", "more"], "category": ["only_one"]} - :param top_k: How many documents to return - :param index: Index name to query the document from. - :param return_embedding: To return document embedding. Unlike other document stores, FAISS will return normalized embeddings - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :return: - """ - if headers: - raise NotImplementedError("FAISSDocumentStore does not support headers.") - - if filters: - logger.warning("Query filters are not implemented for the FAISSDocumentStore.") - - index = index or self.index - if not self.faiss_indexes.get(index): - raise Exception(f"Index named '{index}' does not exists. Use 'update_embeddings()' to create an index.") - - if return_embedding is None: - return_embedding = self.return_embedding - - query_emb = query_emb.reshape(1, -1).astype(np.float32) - - if self.similarity == "cosine": - self.normalize_embedding(query_emb) - - score_matrix, vector_id_matrix = self.faiss_indexes[index].search(query_emb, top_k) - vector_ids_for_query = [str(vector_id) for vector_id in vector_id_matrix[0] if vector_id != -1] - - documents = self.get_documents_by_vector_ids(vector_ids_for_query, index=index) - - # assign query score to each document - scores_for_vector_ids: Dict[str, float] = { - str(v_id): s for v_id, s in zip(vector_id_matrix[0], score_matrix[0]) - } - return_documents = [] - for doc in documents: - score = scores_for_vector_ids[doc.meta["vector_id"]] - if scale_score: - score = self.scale_to_unit_interval(score, self.similarity) - doc.score = score - if return_embedding is True: - doc.embedding = self.faiss_indexes[index].reconstruct(int(doc.meta["vector_id"])) - return_document = copy.copy(doc) - return_documents.append(return_document) - - return return_documents - - def save(self, index_path: Union[str, Path], config_path: Optional[Union[str, Path]] = None): - """ - Save FAISS Index to the specified file. - - The FAISS DocumentStore contains a SQL database and a FAISS index. The database is saved to your disk when you initialize the DocumentStore. The FAISS index is not. You must explicitly save it by calling the `save()` method. You can then use the saved index to load a different DocumentStore. - - Saving a FAISSDocumentStore creates two files on your disk: the index file and the configuration file. The configuration file contains all the parameters needed to initialize the DocumentStore. - For more information, see [DocumentStore](https://docs.haystack.deepset.ai/docs/document_store). - - :param index_path: The path where you want to save the index. - :param config_path: The path where you want to save the configuration file. This is the JSON file that contains all the parameters to initialize the DocumentStore. - It defaults to the same as the index file path, except the extension (.json). - This file contains all the parameters passed to FAISSDocumentStore() - at creation time (for example the `sql_url`, `embedding_dim`, and so on), and will be - used by the `load()` method to restore the index with the saved configuration. - :return: None - """ - if not config_path: - index_path = Path(index_path) - config_path = index_path.with_suffix(".json") - - faiss.write_index(self.faiss_indexes[self.index], str(index_path)) - - config_to_save = deepcopy(self._component_config["params"]) - keys_to_remove = ["faiss_index", "faiss_index_path"] - for key in keys_to_remove: - if key in config_to_save.keys(): - del config_to_save[key] - - with open(config_path, "w") as ipp: - json.dump(config_to_save, ipp, default=str) - - def _load_init_params_from_config( - self, index_path: Union[str, Path], config_path: Optional[Union[str, Path]] = None - ): - if not config_path: - index_path = Path(index_path) - config_path = index_path.with_suffix(".json") - - init_params: dict = {} - try: - with open(config_path, "r") as ipp: - init_params = json.load(ipp) - except OSError as e: - raise ValueError( - f"Can't open FAISS configuration file `{config_path}`. " - "Make sure the file exists and the you have the correct permissions " - "to access it." - ) from e - - faiss_index = faiss.read_index(str(index_path)) - - # Add other init params to override the ones defined in the init params file - init_params["faiss_index"] = faiss_index - init_params["embedding_dim"] = faiss_index.d - - return init_params - - @classmethod - def load(cls, index_path: Union[str, Path], config_path: Optional[Union[str, Path]] = None): - """ - Load a saved FAISS index from a file and connect to the SQL database. `load()` is a class method, so, you need to call it on the class itself instead of the instance. For more information, see [DocumentStore](https://docs.haystack.deepset.ai/docs/document_store). - - Note: To have a correct mapping from FAISS to SQL, - make sure to use the same SQL DB that you used when calling `save()`. - - :param index_path: The stored FAISS index file. Call `save()` to create this file. Use the same index file path you specified when calling `save()`. - :param config_path: Stored FAISS initial configuration parameters. - Call `save()` to create it. - """ - return cls(faiss_index_path=index_path, faiss_config_path=config_path) diff --git a/haystack/document_stores/filter_utils.py b/haystack/document_stores/filter_utils.py deleted file mode 100644 index f5997f89c7..0000000000 --- a/haystack/document_stores/filter_utils.py +++ /dev/null @@ -1,756 +0,0 @@ -import logging -from typing import Union, List, Dict, Optional, Tuple -from abc import ABC, abstractmethod -from collections import defaultdict - -from haystack.document_stores.utils import convert_date_to_rfc3339 -from haystack.errors import FilterError -from haystack.lazy_imports import LazyImport - -logger = logging.getLogger(__file__) - -with LazyImport("Run 'pip install farm-haystack[sql]'") as sql_import: - from sqlalchemy.sql import select - from sqlalchemy import and_, or_ - - -def nested_defaultdict() -> defaultdict: - """ - Data structure that recursively adds a dictionary as value if a key does not exist. Advantage: In nested dictionary - structures, we don't need to check if a key already exists (which can become hard to maintain in nested dictionaries - with many levels) but access the existing value if a key exists and create an empty dictionary if a key does not - exist. - """ - return defaultdict(nested_defaultdict) - - -class LogicalFilterClause(ABC): - """ - Class that is able to parse a filter and convert it to the format that the underlying databases of our - DocumentStores require. - - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, `"$gte"`, `"$lt"`, - `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take optionally a list of - dictionaries as value. - - Example: - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - - """ - - def __init__(self, conditions: List[Union["LogicalFilterClause", "ComparisonOperation"]]): - self.conditions = conditions - - @abstractmethod - def evaluate(self, fields) -> bool: - pass - - @classmethod - def parse(cls, filter_term: Union[dict, List[dict]]) -> Union["LogicalFilterClause", "ComparisonOperation"]: - """ - Parses a filter dictionary/list and returns a LogicalFilterClause instance. - - :param filter_term: Dictionary or list that contains the filter definition. - """ - conditions: List[Union[LogicalFilterClause, ComparisonOperation]] = [] - - if isinstance(filter_term, dict): - filter_term = [filter_term] - for item in filter_term: - for key, value in item.items(): - if key == "$not": - conditions.append(NotOperation.parse(value)) - elif key == "$and": - conditions.append(AndOperation.parse(value)) - elif key == "$or": - conditions.append(OrOperation.parse(value)) - # Key needs to be a metadata field - else: - conditions.extend(ComparisonOperation.parse(key, value)) - - if cls == LogicalFilterClause: - if len(conditions) == 1: - return conditions[0] - else: - return AndOperation(conditions) - else: - return cls(conditions) - - @abstractmethod - def convert_to_elasticsearch(self): - """ - Converts the LogicalFilterClause instance to an Elasticsearch filter. - """ - pass - - @abstractmethod - def convert_to_sql(self, meta_document_orm): - """ - Converts the LogicalFilterClause instance to an SQL filter. - """ - pass - - def convert_to_weaviate(self): - """ - Converts the LogicalFilterClause instance to a Weaviate filter. - """ - pass - - def convert_to_pinecone(self): - """ - Converts the LogicalFilterClause instance to a Pinecone filter. - """ - pass - - def _merge_es_range_queries(self, conditions: List[Dict]) -> List[Dict[str, Dict]]: - """ - Merges Elasticsearch range queries that perform on the same metadata field. - """ - - range_conditions = [cond["range"] for cond in filter(lambda condition: "range" in condition, conditions)] - if range_conditions: - conditions = [condition for condition in conditions if "range" not in condition] - range_conditions_dict = nested_defaultdict() - for condition in range_conditions: - field_name = list(condition.keys())[0] - operation = list(condition[field_name].keys())[0] - comparison_value = condition[field_name][operation] - range_conditions_dict[field_name][operation] = comparison_value - - for field_name, comparison_operations in range_conditions_dict.items(): - conditions.append({"range": {field_name: comparison_operations}}) - - return conditions - - @abstractmethod - def invert(self) -> Union["LogicalFilterClause", "ComparisonOperation"]: - """ - Inverts the LogicalOperation instance. - Necessary for Weaviate as Weaviate doesn't seem to support the 'Not' operator anymore. - (https://github.com/semi-technologies/weaviate/issues/1717) - """ - pass - - -class ComparisonOperation(ABC): - def __init__(self, field_name: str, comparison_value: Union[str, int, float, bool, List]): - self.field_name = field_name - self.comparison_value = comparison_value - - @abstractmethod - def evaluate(self, fields) -> bool: - pass - - @classmethod - def parse(cls, field_name, comparison_clause: Union[Dict, List, str, float]) -> List["ComparisonOperation"]: - comparison_operations: List[ComparisonOperation] = [] - - if isinstance(comparison_clause, dict): - for comparison_operation, comparison_value in comparison_clause.items(): - if comparison_operation == "$eq": - comparison_operations.append(EqOperation(field_name, comparison_value)) - elif comparison_operation == "$in": - comparison_operations.append(InOperation(field_name, comparison_value)) - elif comparison_operation == "$ne": - comparison_operations.append(NeOperation(field_name, comparison_value)) - elif comparison_operation == "$nin": - comparison_operations.append(NinOperation(field_name, comparison_value)) - elif comparison_operation == "$gt": - comparison_operations.append(GtOperation(field_name, comparison_value)) - elif comparison_operation == "$gte": - comparison_operations.append(GteOperation(field_name, comparison_value)) - elif comparison_operation == "$lt": - comparison_operations.append(LtOperation(field_name, comparison_value)) - elif comparison_operation == "$lte": - comparison_operations.append(LteOperation(field_name, comparison_value)) - - # No comparison operator is given, so we use the default operators "$in" if the comparison value is a list and - # "$eq" in every other case - elif isinstance(comparison_clause, list): - comparison_operations.append(InOperation(field_name, comparison_clause)) - else: - comparison_operations.append((EqOperation(field_name, comparison_clause))) - - return comparison_operations - - @abstractmethod - def convert_to_elasticsearch(self): - """ - Converts the ComparisonOperation instance to an Elasticsearch query. - """ - pass - - @abstractmethod - def convert_to_sql(self, meta_document_orm): - """ - Converts the ComparisonOperation instance to an SQL filter. - """ - pass - - @abstractmethod - def convert_to_weaviate(self): - """ - Converts the ComparisonOperation instance to a Weaviate comparison operator. - """ - pass - - def convert_to_pinecone(self): - """ - Converts the ComparisonOperation instance to a Pinecone comparison operator. - """ - pass - - @abstractmethod - def invert(self) -> "ComparisonOperation": - """ - Inverts the ComparisonOperation. - Necessary for Weaviate as Weaviate doesn't seem to support the 'Not' operator anymore. - (https://github.com/semi-technologies/weaviate/issues/1717) - """ - pass - - def _get_weaviate_datatype( - self, value: Optional[Union[str, int, float, bool]] = None - ) -> Tuple[str, Union[str, int, float, bool]]: - """ - Determines the type of the comparison value and converts it to RFC3339 format if it is as date, - as Weaviate requires dates to be in RFC3339 format including the time and timezone. - - """ - if value is None: - assert not isinstance(self.comparison_value, list) # Necessary for mypy - value = self.comparison_value - - if isinstance(value, str): - # Check if comparison value is a date - try: - value = convert_date_to_rfc3339(value) - data_type = "valueDate" - # Comparison value is a plain string - except ValueError: - if self.field_name == "content": - data_type = "valueText" - else: - data_type = "valueString" - elif isinstance(value, int): - data_type = "valueInt" - elif isinstance(value, float): - data_type = "valueNumber" - elif isinstance(value, bool): - data_type = "valueBoolean" - else: - raise ValueError( - f"Unsupported data type of comparison value for {self.__class__.__name__}." - f"Value needs to be of type str, int, float, or bool." - ) - - return data_type, value - - -class NotOperation(LogicalFilterClause): - """ - Handles conversion of logical 'NOT' operations. - """ - - def evaluate(self, fields) -> bool: - return not any(condition.evaluate(fields) for condition in self.conditions) - - def convert_to_elasticsearch(self) -> Dict[str, Dict]: - conditions = [condition.convert_to_elasticsearch() for condition in self.conditions] - conditions = self._merge_es_range_queries(conditions) - return {"bool": {"must_not": conditions}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - conditions = [ - meta_document_orm.document_id.in_(condition.convert_to_sql(meta_document_orm)) - for condition in self.conditions - ] - return select(meta_document_orm.document_id).filter(~or_(*conditions)) - - def convert_to_weaviate(self) -> Dict[str, Union[str, int, float, bool, List[Dict]]]: - conditions = [condition.invert().convert_to_weaviate() for condition in self.conditions] - if len(conditions) > 1: - # Conditions in self.conditions are by default combined with AND which becomes OR according to DeMorgan - return {"operator": "Or", "operands": conditions} - else: - return conditions[0] - - def convert_to_pinecone(self) -> Dict[str, Union[str, int, float, bool, List[Dict]]]: - conditions = [condition.invert().convert_to_pinecone() for condition in self.conditions] - if len(conditions) > 1: - # Conditions in self.conditions are by default combined with AND which becomes OR according to DeMorgan - return {"$or": conditions} - else: - return conditions[0] - - def invert(self) -> Union[LogicalFilterClause, ComparisonOperation]: - # This method is called when a "$not" operation is embedded in another "$not" operation. Therefore, we don't - # invert the operations here, as two "$not" operation annihilate each other. - # (If we have more than one condition, we return an AndOperation, the default logical operation for combining - # multiple conditions.) - if len(self.conditions) > 1: - return AndOperation(self.conditions) - else: - return self.conditions[0] - - -class AndOperation(LogicalFilterClause): - """ - Handles conversion of logical 'AND' operations. - """ - - def evaluate(self, fields) -> bool: - return all(condition.evaluate(fields) for condition in self.conditions) - - def convert_to_elasticsearch(self) -> Dict[str, Dict]: - conditions = [condition.convert_to_elasticsearch() for condition in self.conditions] - conditions = self._merge_es_range_queries(conditions) - return {"bool": {"must": conditions}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - conditions = [ - meta_document_orm.document_id.in_(condition.convert_to_sql(meta_document_orm)) - for condition in self.conditions - ] - return select(meta_document_orm.document_id).filter(and_(*conditions)) - - def convert_to_weaviate(self) -> Dict[str, Union[str, List[Dict]]]: - conditions = [condition.convert_to_weaviate() for condition in self.conditions] - return {"operator": "And", "operands": conditions} - - def convert_to_pinecone(self) -> Dict[str, Union[str, List[Dict]]]: - conditions = [condition.convert_to_pinecone() for condition in self.conditions] - return {"$and": conditions} - - def invert(self) -> "OrOperation": - return OrOperation([condition.invert() for condition in self.conditions]) - - -class OrOperation(LogicalFilterClause): - """ - Handles conversion of logical 'OR' operations. - """ - - def evaluate(self, fields) -> bool: - return any(condition.evaluate(fields) for condition in self.conditions) - - def convert_to_elasticsearch(self) -> Dict[str, Dict]: - conditions = [condition.convert_to_elasticsearch() for condition in self.conditions] - conditions = self._merge_es_range_queries(conditions) - return {"bool": {"should": conditions}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - conditions = [ - meta_document_orm.document_id.in_(condition.convert_to_sql(meta_document_orm)) - for condition in self.conditions - ] - return select(meta_document_orm.document_id).filter(or_(*conditions)) - - def convert_to_weaviate(self) -> Dict[str, Union[str, List[Dict]]]: - conditions = [condition.convert_to_weaviate() for condition in self.conditions] - return {"operator": "Or", "operands": conditions} - - def convert_to_pinecone(self) -> Dict[str, Union[str, List[Dict]]]: - conditions = [condition.convert_to_pinecone() for condition in self.conditions] - return {"$or": conditions} - - def invert(self) -> AndOperation: - return AndOperation([condition.invert() for condition in self.conditions]) - - -class EqOperation(ComparisonOperation): - """ - Handles conversion of the '$eq' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return False - return fields[self.field_name] == self.comparison_value - - def convert_to_elasticsearch( - self, - ) -> Dict[str, Dict[str, Union[str, int, float, bool, Dict[str, Union[list, Dict[str, str]]]]]]: - if isinstance(self.comparison_value, list): - return { - "terms_set": { - self.field_name: { - "terms": self.comparison_value, - "minimum_should_match_script": { - "source": f"Math.max(params.num_terms, doc['{self.field_name}'].size())" - }, - } - } - } - return {"term": {self.field_name: self.comparison_value}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value == self.comparison_value - ) - - def convert_to_weaviate(self) -> Dict[str, Union[List[str], str, int, float, bool]]: - comp_value_type, comp_value = self._get_weaviate_datatype() - return {"path": [self.field_name], "operator": "Equal", comp_value_type: comp_value} - - def convert_to_pinecone(self) -> Dict[str, Dict[str, Union[List[str], str, int, float, bool]]]: - return {self.field_name: {"$eq": self.comparison_value}} - - def invert(self) -> "NeOperation": - return NeOperation(self.field_name, self.comparison_value) - - -class InOperation(ComparisonOperation): - """ - Handles conversion of the '$in' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return False - - if not isinstance(self.comparison_value, list): - raise FilterError("'$in' operation requires comparison value to be a list.") - - # If the document field is a list, check if any of its values are in the comparison value - if isinstance(fields[self.field_name], list): - return any(field in self.comparison_value for field in fields[self.field_name]) - - return fields[self.field_name] in self.comparison_value - - def convert_to_elasticsearch(self) -> Dict[str, Dict[str, List]]: - if not isinstance(self.comparison_value, list): - raise FilterError("'$in' operation requires comparison value to be a list.") - return {"terms": {self.field_name: self.comparison_value}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value.in_(self.comparison_value) - ) - - def convert_to_weaviate(self) -> Dict[str, Union[str, List[Dict]]]: - filter_dict: Dict[str, Union[str, List[Dict]]] = {"operator": "Or", "operands": []} - if not isinstance(self.comparison_value, list): - raise FilterError("'$in' operation requires comparison value to be a list.") - for value in self.comparison_value: - comp_value_type, comp_value = self._get_weaviate_datatype(value) - assert isinstance(filter_dict["operands"], list) # Necessary for mypy - filter_dict["operands"].append( - {"path": [self.field_name], "operator": "Equal", comp_value_type: comp_value} - ) - - return filter_dict - - def convert_to_pinecone(self) -> Dict[str, Dict[str, List]]: - if not isinstance(self.comparison_value, list): - raise FilterError("'$in' operation requires comparison value to be a list.") - return {self.field_name: {"$in": self.comparison_value}} - - def invert(self) -> "NinOperation": - return NinOperation(self.field_name, self.comparison_value) - - -class NeOperation(ComparisonOperation): - """ - Handles conversion of the '$ne' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return False - return fields[self.field_name] != self.comparison_value - - def convert_to_elasticsearch(self) -> Dict[str, Dict[str, Dict[str, Dict[str, Union[str, int, float, bool]]]]]: - if isinstance(self.comparison_value, list): - raise FilterError("Use '$nin' operation for lists as comparison values.") - return {"bool": {"must_not": {"term": {self.field_name: self.comparison_value}}}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value != self.comparison_value - ) - - def convert_to_weaviate(self) -> Dict[str, Union[List[str], str, int, float, bool]]: - comp_value_type, comp_value = self._get_weaviate_datatype() - return {"path": [self.field_name], "operator": "NotEqual", comp_value_type: comp_value} - - def convert_to_pinecone(self) -> Dict[str, Dict[str, Union[List[str], str, int, float, bool]]]: - return {self.field_name: {"$ne": self.comparison_value}} - - def invert(self) -> "EqOperation": - return EqOperation(self.field_name, self.comparison_value) - - -class NinOperation(ComparisonOperation): - """ - Handles conversion of the '$nin' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return True - - if not isinstance(self.comparison_value, list): - raise FilterError("'$nin' operation requires comparison value to be a list.") - - # If the document field is a list, check if any of its values are in the comparison value - if isinstance(fields[self.field_name], list): - return not any(field in self.comparison_value for field in fields[self.field_name]) - - return fields[self.field_name] not in self.comparison_value - - def convert_to_elasticsearch(self) -> Dict[str, Dict[str, Dict[str, Dict[str, List]]]]: - if not isinstance(self.comparison_value, list): - raise FilterError("'$nin' operation requires comparison value to be a list.") - return {"bool": {"must_not": {"terms": {self.field_name: self.comparison_value}}}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value.notin_(self.comparison_value) - ) - - def convert_to_weaviate(self) -> Dict[str, Union[str, List[Dict]]]: - filter_dict: Dict[str, Union[str, List[Dict]]] = {"operator": "And", "operands": []} - if not isinstance(self.comparison_value, list): - raise FilterError("'$nin' operation requires comparison value to be a list.") - for value in self.comparison_value: - comp_value_type, comp_value = self._get_weaviate_datatype(value) - assert isinstance(filter_dict["operands"], list) # Necessary for mypy - filter_dict["operands"].append( - {"path": [self.field_name], "operator": "NotEqual", comp_value_type: comp_value} - ) - - return filter_dict - - def convert_to_pinecone(self) -> Dict[str, Dict[str, List]]: - if not isinstance(self.comparison_value, list): - raise FilterError("'$in' operation requires comparison value to be a list.") - return {self.field_name: {"$nin": self.comparison_value}} - - def invert(self) -> "InOperation": - return InOperation(self.field_name, self.comparison_value) - - -class GtOperation(ComparisonOperation): - """ - Handles conversion of the '$gt' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return False - - # If the document field is a list, check if any of its values are greater than the comparison value - if isinstance(fields[self.field_name], list): - return any(field > self.comparison_value for field in fields[self.field_name]) - - return fields[self.field_name] > self.comparison_value - - def convert_to_elasticsearch(self) -> Dict[str, Dict[str, Dict[str, Union[str, float, int]]]]: - if isinstance(self.comparison_value, list): - raise FilterError("Comparison value for '$gt' operation must not be a list.") - return {"range": {self.field_name: {"gt": self.comparison_value}}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value > self.comparison_value - ) - - def convert_to_weaviate(self) -> Dict[str, Union[List[str], str, float, int]]: - comp_value_type, comp_value = self._get_weaviate_datatype() - if isinstance(comp_value, list): - raise FilterError("Comparison value for '$gt' operation must not be a list.") - return {"path": [self.field_name], "operator": "GreaterThan", comp_value_type: comp_value} - - def convert_to_pinecone(self) -> Dict[str, Dict[str, Union[float, int]]]: - if not isinstance(self.comparison_value, (float, int)): - raise FilterError("Comparison value for '$gt' operation must be a float or int.") - return {self.field_name: {"$gt": self.comparison_value}} - - def invert(self) -> "LteOperation": - return LteOperation(self.field_name, self.comparison_value) - - -class GteOperation(ComparisonOperation): - """ - Handles conversion of the '$gte' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return False - - # If the document field is a list, check if any of its values are greater than or equal to the comparison value - if isinstance(fields[self.field_name], list): - return any(field >= self.comparison_value for field in fields[self.field_name]) - - return fields[self.field_name] >= self.comparison_value - - def convert_to_elasticsearch(self) -> Dict[str, Dict[str, Dict[str, Union[str, float, int]]]]: - if isinstance(self.comparison_value, list): - raise FilterError("Comparison value for '$gte' operation must not be a list.") - return {"range": {self.field_name: {"gte": self.comparison_value}}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value >= self.comparison_value - ) - - def convert_to_weaviate(self) -> Dict[str, Union[List[str], str, float, int]]: - comp_value_type, comp_value = self._get_weaviate_datatype() - if isinstance(comp_value, list): - raise FilterError("Comparison value for '$gte' operation must not be a list.") - return {"path": [self.field_name], "operator": "GreaterThanEqual", comp_value_type: comp_value} - - def convert_to_pinecone(self) -> Dict[str, Dict[str, Union[float, int]]]: - if not isinstance(self.comparison_value, (float, int)): - raise FilterError("Comparison value for '$gte' operation must be a float or int.") - return {self.field_name: {"$gte": self.comparison_value}} - - def invert(self) -> "LtOperation": - return LtOperation(self.field_name, self.comparison_value) - - -class LtOperation(ComparisonOperation): - """ - Handles conversion of the '$lt' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return False - - # If the document field is a list, check if any of its values are less than the comparison value - if isinstance(fields[self.field_name], list): - return any(field < self.comparison_value for field in fields[self.field_name]) - - return fields[self.field_name] < self.comparison_value - - def convert_to_elasticsearch(self) -> Dict[str, Dict[str, Dict[str, Union[str, float, int]]]]: - if isinstance(self.comparison_value, list): - raise FilterError("Comparison value for '$lt' operation must not be a list.") - return {"range": {self.field_name: {"lt": self.comparison_value}}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value < self.comparison_value - ) - - def convert_to_weaviate(self) -> Dict[str, Union[List[str], str, float, int]]: - comp_value_type, comp_value = self._get_weaviate_datatype() - if isinstance(comp_value, list): - raise FilterError("Comparison value for '$lt' operation must not be a list.") - return {"path": [self.field_name], "operator": "LessThan", comp_value_type: comp_value} - - def convert_to_pinecone(self) -> Dict[str, Dict[str, Union[float, int]]]: - if not isinstance(self.comparison_value, (float, int)): - raise FilterError("Comparison value for '$lt' operation must be a float or int.") - return {self.field_name: {"$lt": self.comparison_value}} - - def invert(self) -> "GteOperation": - return GteOperation(self.field_name, self.comparison_value) - - -class LteOperation(ComparisonOperation): - """ - Handles conversion of the '$lte' comparison operation. - """ - - def evaluate(self, fields) -> bool: - if self.field_name not in fields: - return False - - # If the document field is a list, check if any of its values are less than or equal to the comparison value - if isinstance(fields[self.field_name], list): - return any(field <= self.comparison_value for field in fields[self.field_name]) - - return fields[self.field_name] <= self.comparison_value - - def convert_to_elasticsearch(self) -> Dict[str, Dict[str, Dict[str, Union[str, float, int]]]]: - if isinstance(self.comparison_value, list): - raise FilterError("Comparison value for '$lte' operation must not be a list.") - return {"range": {self.field_name: {"lte": self.comparison_value}}} - - def convert_to_sql(self, meta_document_orm): - sql_import.check() - return select([meta_document_orm.document_id]).where( - meta_document_orm.name == self.field_name, meta_document_orm.value <= self.comparison_value - ) - - def convert_to_weaviate(self) -> Dict[str, Union[List[str], str, float, int]]: - comp_value_type, comp_value = self._get_weaviate_datatype() - if isinstance(comp_value, list): - raise FilterError("Comparison value for '$lte' operation must not be a list.") - return {"path": [self.field_name], "operator": "LessThanEqual", comp_value_type: comp_value} - - def convert_to_pinecone(self) -> Dict[str, Dict[str, Union[float, int]]]: - if not isinstance(self.comparison_value, (float, int)): - raise FilterError("Comparison value for '$lte' operation must be a float or int.") - return {self.field_name: {"$lte": self.comparison_value}} - - def invert(self) -> "GtOperation": - return GtOperation(self.field_name, self.comparison_value) diff --git a/haystack/document_stores/memory.py b/haystack/document_stores/memory.py deleted file mode 100644 index 56cc40e692..0000000000 --- a/haystack/document_stores/memory.py +++ /dev/null @@ -1,1050 +0,0 @@ -import copy -from typing import Any, Dict, List, Optional, Union, Generator, Literal - -import time -import logging -from copy import deepcopy -from collections import defaultdict -import re - -import numpy as np -from tqdm import tqdm -import rank_bm25 -import pandas as pd - -from haystack.schema import Document, FilterType, Label -from haystack.errors import DuplicateDocumentError, DocumentStoreError -from haystack.document_stores import KeywordDocumentStore -from haystack.utils.batching import get_batches_from_generator -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.nodes.retriever.dense import DenseRetriever -from haystack.utils.scipy_utils import expit -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_import: - import torch - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class InMemoryDocumentStore(KeywordDocumentStore): - # pylint: disable=R0904 - """ - In-memory document store - """ - - def __init__( - self, - index: str = "document", - label_index: str = "label", - embedding_field: Optional[str] = "embedding", - embedding_dim: int = 768, - return_embedding: bool = False, - similarity: str = "dot_product", - progress_bar: bool = True, - duplicate_documents: str = "overwrite", - use_gpu: bool = True, - scoring_batch_size: int = 500000, - devices: Optional[List[Union[str, "torch.device"]]] = None, - use_bm25: bool = False, - bm25_tokenization_regex: str = r"(?u)\b\w\w+\b", - bm25_algorithm: Literal["BM25Okapi", "BM25L", "BM25Plus"] = "BM25Okapi", - bm25_parameters: Optional[Dict] = None, - ): - """ - :param index: The documents are scoped to an index attribute that can be used when writing, querying, - or deleting documents. This parameter sets the default value for document index. - :param label_index: The default value of index attribute for the labels. - :param embedding_field: Name of field containing an embedding vector (Only needed when using a dense retriever (e.g. DensePassageRetriever, EmbeddingRetriever) on top) - :param embedding_dim: The size of the embedding vector. - :param return_embedding: To return document embedding - :param similarity: The similarity function used to compare document vectors. 'dot_product' is the default sine it is - more performant with DPR embeddings. 'cosine' is recommended if you are using a Sentence BERT model. - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param use_gpu: Whether to use a GPU or the CPU for calculating embedding similarity. - Falls back to CPU if no GPU is available. - :param scoring_batch_size: Batch size of documents to calculate similarity for. Very small batch sizes are inefficient. - Very large batch sizes can overrun GPU memory. In general you want to make sure - you have at least `embedding_dim`*`scoring_batch_size`*4 bytes available in GPU memory. - Since the data is originally stored in CPU memory there is little risk of overruning memory - when running on CPU. - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :param use_bm25: Whether to build a sparse representation of documents based on BM25. - `use_bm25=True` is required to connect `BM25Retriever` to this Document Store. - :param bm25_tokenization_regex: The regular expression to use for tokenization of the text. - :param bm25_algorithm: The specific BM25 implementation to adopt. - Parameter options : ( 'BM25Okapi', 'BM25L', 'BM25Plus') - :param bm25_parameters: Parameters for BM25 implementation in a dictionary format. - For example: {'k1':1.5, 'b':0.75, 'epsilon':0.25} - You can learn more about these parameters by visiting https://github.com/dorianbrown/rank_bm25 - By default, no parameters are set. - """ - torch_import.check() - if bm25_parameters is None: - bm25_parameters = {} - super().__init__() - - self.indexes: Dict[str, Dict] = defaultdict(dict) - self.index: str = index - self.label_index: str = label_index - self.embedding_field = embedding_field - self.embedding_dim = embedding_dim - self.return_embedding = return_embedding - self.similarity = similarity - self.progress_bar = progress_bar - self.duplicate_documents = duplicate_documents - self.use_gpu = use_gpu - self.scoring_batch_size = scoring_batch_size - self.use_bm25 = use_bm25 - self.bm25_tokenization_regex = bm25_tokenization_regex - self.bm25_algorithm = bm25_algorithm - self.bm25_parameters = bm25_parameters - self.bm25: Dict[str, rank_bm25.BM25] = {} - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=self.use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - self.main_device = self.devices[0] - - @property - def bm25_tokenization_regex(self): - return self._tokenizer - - @bm25_tokenization_regex.setter - def bm25_tokenization_regex(self, regex_string: str): - self._tokenizer = re.compile(regex_string).findall - - @property - def bm25_algorithm(self): - return self._bm25_class - - @bm25_algorithm.setter - def bm25_algorithm(self, algorithm: str): - self._bm25_class = getattr(rank_bm25, algorithm) - - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: int = 10_000, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Indexes documents for later queries. - - - :param documents: a list of Python dictionaries or a list of Haystack Document objects. - For documents as dictionaries, the format is {"content": ""}. - Optionally: Include meta data via {"content": "", - "meta": {"name": ", "author": "somebody", ...}} - It can be used for filtering and is accessible in the responses of the Finder. - :param index: write documents to a custom namespace. For instance, documents for evaluation can be indexed in a - separate index than the documents for search. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :raises DuplicateDocumentError: Exception trigger on duplicate document - :return: None - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.index - duplicate_documents = duplicate_documents or self.duplicate_documents - assert ( - duplicate_documents in self.duplicate_documents_options - ), f"duplicate_documents parameter must be {', '.join(self.duplicate_documents_options)}" - - field_map = self._create_document_field_map() - documents = deepcopy(documents) - documents_objects = [ - Document.from_dict(d, field_map=field_map) if isinstance(d, dict) else d for d in documents - ] - documents_objects = self._drop_duplicate_documents(documents=documents_objects) - modified_documents = 0 - for document in documents_objects: - if document.id in self.indexes[index]: - if duplicate_documents == "fail": - raise DuplicateDocumentError( - f"Document with id '{document.id} already " f"exists in index '{index}'" - ) - if duplicate_documents == "skip": - logger.warning( - "Duplicate Documents: Document with id '%s' already exists in index '%s'", document.id, index - ) - continue - self.indexes[index][document.id] = document - modified_documents += 1 - - if self.use_bm25 is True and modified_documents > 0: - self.update_bm25(index=index) - - def update_bm25(self, index: Optional[str] = None): - """ - Updates the BM25 sparse representation in the the document store. - - :param index: Index name for which the BM25 representation is to be updated. If set to None, the default self.index is used. - """ - index = index or self.index - - all_documents = self.get_all_documents(index=index) - textual_documents = [] - for doc in all_documents: - if doc.content_type == "text": - textual_documents.append(doc.content.lower()) - elif doc.content_type == "table": - if isinstance(doc.content, pd.DataFrame): - textual_documents.append(doc.content.astype(str).to_csv(index=False).lower()) - else: - raise DocumentStoreError("Documents of type 'table' need to have a pd.DataFrame as content field") - if len(textual_documents) < len(all_documents): - logger.warning( - "Some documents in %s index are non-textual." - " They will be written to the index, but the corresponding BM25 representations will not be generated.", - index, - ) - - tokenized_corpus = [ - self.bm25_tokenization_regex(doc) - for doc in tqdm(textual_documents, unit=" docs", desc="Updating BM25 representation...") - ] - self.bm25[index] = self.bm25_algorithm(tokenized_corpus, **self.bm25_parameters) - - def _create_document_field_map(self): - return {self.embedding_field: "embedding"} - - def write_labels( - self, - labels: Union[List[dict], List[Label]], - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Write annotation labels into document store. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.label_index - label_objects = [Label.from_dict(l) if isinstance(l, dict) else l for l in labels] - - duplicate_ids: list = [label.id for label in self._get_duplicate_labels(label_objects, index=index)] - if len(duplicate_ids) > 0: - logger.warning( - "Duplicate Label IDs: Inserting a Label whose id already exists in this document store." - " This will overwrite the old Label. Please make sure Label.id is a unique identifier of" - " the answer annotation and not the question." - " Problematic ids: %s", - ",".join(duplicate_ids), - ) - - for label in label_objects: - # create timestamps if not available yet - if not label.created_at: - label.created_at = time.strftime("%Y-%m-%d %H:%M:%S") - if not label.updated_at: - label.updated_at = label.created_at - self.indexes[index][label.id] = label - - def get_document_by_id( - self, id: str, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ) -> Optional[Document]: - """ - Fetch a document by specifying its text id string. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.index - documents = self.get_documents_by_id([id], index=index) - if documents: - return documents[0] - else: - return None - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Fetch documents by specifying a list of text id strings. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - if batch_size: - logger.warning( - "InMemoryDocumentStore does not support batching in `get_documents_by_id` method. This parameter is ignored." - ) - index = index or self.index - documents = [self.indexes[index][id] for id in ids] - return documents - - def _get_scores_torch(self, query_emb: np.ndarray, documents_to_search: List[Document]) -> List[float]: - """ - Calculate similarity scores between query embedding and a list of documents using torch. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param documents_to_search: List of documents to compare `query_emb` against. - """ - torch_import.check() - - query_emb_tensor = torch.tensor(query_emb, dtype=torch.float).to(self.main_device) - if query_emb_tensor.ndim == 1: - query_emb_tensor = query_emb_tensor.unsqueeze(dim=0) - - doc_embeds = np.array([doc.embedding for doc in documents_to_search]) - doc_embeds_tensor = torch.as_tensor(doc_embeds, dtype=torch.float) - if doc_embeds_tensor.ndim == 1: - # if there are no embeddings, return an empty list - if doc_embeds_tensor.shape[0] == 0: - return [] - doc_embeds_tensor = doc_embeds_tensor.unsqueeze(dim=0) - - if self.similarity == "cosine": - # cosine similarity is just a normed dot product - query_emb_norm = torch.norm(query_emb_tensor, dim=1) - query_emb_tensor = torch.div(query_emb_tensor, query_emb_norm) - - doc_embeds_norms = torch.norm(doc_embeds_tensor, dim=1) - doc_embeds_tensor = torch.div(doc_embeds_tensor.T, doc_embeds_norms).T - - curr_pos = 0 - scores: List[float] = [] - while curr_pos < len(doc_embeds_tensor): - doc_embeds_slice = doc_embeds_tensor[curr_pos : curr_pos + self.scoring_batch_size] - doc_embeds_slice = doc_embeds_slice.to(self.main_device) - with torch.inference_mode(): - slice_scores = torch.matmul(doc_embeds_slice, query_emb_tensor.T).cpu() - slice_scores = slice_scores.squeeze(dim=1) - slice_scores = slice_scores.numpy().tolist() - - scores.extend(slice_scores) - curr_pos += self.scoring_batch_size - - return scores - - def _get_scores_numpy(self, query_emb: np.ndarray, documents_to_search: List[Document]) -> List[float]: - """ - Calculate similarity scores between query embedding and a list of documents using numpy. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param documents_to_search: List of documents to compare `query_emb` against. - """ - if query_emb.ndim == 1: - query_emb = np.expand_dims(a=query_emb, axis=0) - - doc_embeds = np.array([doc.embedding for doc in documents_to_search]) - if doc_embeds.ndim == 1: - # if there are no embeddings, return an empty list - if doc_embeds.shape[0] == 0: - return [] - doc_embeds = np.expand_dims(a=doc_embeds, axis=0) - - if self.similarity == "cosine": - # cosine similarity is just a normed dot product - query_emb_norm = np.apply_along_axis(np.linalg.norm, 1, query_emb) - query_emb_norm = np.expand_dims(query_emb_norm, 1) - query_emb = np.divide(query_emb, query_emb_norm) - - doc_embeds_norms = np.apply_along_axis(np.linalg.norm, 1, doc_embeds) - doc_embeds_norms = np.expand_dims(doc_embeds_norms, 1) - doc_embeds = np.divide(doc_embeds, doc_embeds_norms) - - scores = np.dot(query_emb, doc_embeds.T)[0].tolist() - - return scores - - def _get_scores(self, query_emb: np.ndarray, documents_to_search: List[Document]) -> List[float]: - if self.main_device.type == "cuda": - scores = self._get_scores_torch(query_emb, documents_to_search) - else: - scores = self._get_scores_numpy(query_emb, documents_to_search) - - return scores - - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - """ - Find the document that is most similar to the provided `query_emb` by using a vector similarity metric. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - Example: - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return - :param index: Index name for storing the docs and metadata - :param return_embedding: To return document embedding - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :return: - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.index - if return_embedding is None: - return_embedding = self.return_embedding - - if query_emb is None: - return [] - - documents = self.get_all_documents(index=index, filters=filters, return_embedding=True) - documents_with_embeddings = [doc for doc in documents if doc.embedding is not None] - if len(documents) != len(documents_with_embeddings): - logger.warning( - "Skipping some of your documents that don't have embeddings. " - "To generate embeddings, run the document store's update_embeddings() method." - ) - scores = self._get_scores(query_emb, documents_with_embeddings) - - candidate_docs = [] - for doc, score in zip(documents_with_embeddings, scores): - curr_meta = deepcopy(doc.meta) - new_document = Document( - id=doc.id, content=doc.content, content_type=doc.content_type, meta=curr_meta, embedding=doc.embedding - ) - new_document.embedding = doc.embedding if return_embedding is True else None - - new_document.embedding = doc.embedding if return_embedding is True else None - if scale_score: - score = self.scale_to_unit_interval(score, self.similarity) - new_document.score = score - candidate_docs.append(new_document) - - return sorted(candidate_docs, key=lambda x: x.score if x.score is not None else 0.0, reverse=True)[0:top_k] - - def update_embeddings( - self, - retriever: DenseRetriever, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - update_existing_embeddings: bool = True, - batch_size: int = 10_000, - ): - """ - Updates the embeddings in the the document store using the encoding model specified in the retriever. - This can be useful if want to add or change the embeddings for your documents (e.g. after changing the retriever config). - - :param retriever: Retriever to use to get embeddings for text - :param index: Index name for which embeddings are to be updated. If set to None, the default self.index is used. - :param update_existing_embeddings: Whether to update existing embeddings of the documents. If set to False, - only documents without embeddings are processed. This mode can be used for - incremental updating of embeddings, wherein, only newly indexed documents - get processed. - :param filters: Narrow down the scope to documents that match the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :return: None - """ - if index is None: - index = self.index - - if not self.embedding_field: - raise RuntimeError("Specify the arg embedding_field when initializing InMemoryDocumentStore()") - - # TODO Index embeddings every X batches to avoid OOM for huge document collections - result = self._query( - index=index, filters=filters, only_documents_without_embedding=not update_existing_embeddings - ) - logger.info("Updating embeddings for %s docs ...", len(result) if logger.level > logging.DEBUG else 0) - batched_documents = get_batches_from_generator(result, batch_size) - with tqdm( - total=len(result), disable=not self.progress_bar, position=0, unit=" docs", desc="Updating Embedding" - ) as progress_bar: - for document_batch in batched_documents: - embeddings = retriever.embed_documents(document_batch) - self._validate_embeddings_shape( - embeddings=embeddings, num_documents=len(document_batch), embedding_dim=self.embedding_dim - ) - - for doc, emb in zip(document_batch, embeddings): - self.indexes[index][doc.id].embedding = emb - progress_bar.set_description_str("Documents Processed") - progress_bar.update(batch_size) - - def get_document_count( - self, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - ) -> int: - """ - Return the number of documents in the document store. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - documents = self._query( - index=index, filters=filters, only_documents_without_embedding=only_documents_without_embedding - ) - return len(documents) - - def update_document_meta(self, id: str, meta: Dict[str, Any], index: Optional[str] = None): - """ - Update the metadata dictionary of a document by specifying its string id. - - :param id: The ID of the Document whose metadata is being updated. - :param meta: A dictionary with key-value pairs that should be added / changed for the provided Document ID. - :param index: Name of the index the Document is located at. - """ - if index is None: - index = self.index - for key, value in meta.items(): - self.indexes[index][id].meta[key] = value - - def get_embedding_count(self, filters: Optional[FilterType] = None, index: Optional[str] = None) -> int: - """ - Return the count of embeddings in the document store. - """ - documents = self.get_all_documents_generator(filters=filters, index=index, return_embedding=True) - embedding_count = sum(doc.embedding is not None for doc in documents) - return embedding_count - - def get_label_count(self, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None) -> int: - """ - Return the number of labels in the document store. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.label_index - return len(self.indexes[index].items()) - - def _query( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - only_documents_without_embedding: bool = False, - ): - index = index or self.index - documents = deepcopy(list(self.indexes[index].values())) - documents = [d for d in documents if isinstance(d, Document)] - - if return_embedding is None: - return_embedding = self.return_embedding - if return_embedding is False: - for doc in documents: - doc.embedding = None - - if only_documents_without_embedding: - documents = [doc for doc in documents if doc.embedding is None] - if filters: - parsed_filter = LogicalFilterClause.parse(filters) - filtered_documents = list(filter(lambda doc: parsed_filter.evaluate(doc.meta), documents)) - else: - filtered_documents = documents - - return filtered_documents - - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Get all documents from the document store as a list. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Narrow down the scope to documents that match the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - result = self.get_all_documents_generator( - index=index, filters=filters, return_embedding=return_embedding, batch_size=batch_size - ) - documents = list(result) - return documents - - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> Generator[Document, None, None]: - """ - Get all documents from the document store. The methods returns a Python Generator that yields individual - documents. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Narrow down the scope to documents that match the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - result = self._query(index=index, filters=filters, return_embedding=return_embedding) - yield from result - - def get_all_labels( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Label]: - """ - Return all labels in the document store. - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.label_index - - if filters: - result = [] - for label in self.indexes[index].values(): - label_dict = label.to_dict() - is_hit = True - for key, value_or_values in filters.items(): - if isinstance(value_or_values, list): - if label_dict[key] not in value_or_values: - is_hit = False - break - else: - if label_dict[key] != value_or_values: - is_hit = False - break - if is_hit: - result.append(label) - else: - result = list(self.indexes[index].values()) - - return result - - def delete_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - - :param index: Index name to delete the document from. - :param filters: Narrow down the scope to documents that match the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :return: None - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - logger.warning( - """DEPRECATION WARNINGS: - 1. delete_all_documents() method is deprecated, please use delete_documents method - For more details, please refer to the issue: https://github.com/deepset-ai/haystack/issues/1045 - """ - ) - self.delete_documents(index, None, filters) - - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - - :param index: Index name to delete the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param ids: Optional list of IDs to narrow down the documents to be deleted. - :param filters: Narrow down the scope to documents that match the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :return: None - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.index - if not filters and not ids: - self.indexes[index] = {} - if index in self.bm25: - self.bm25[index] = {} - return - docs_to_delete = self.get_all_documents(index=index, filters=filters) - if ids: - docs_to_delete = [doc for doc in docs_to_delete if doc.id in ids] - for doc in docs_to_delete: - del self.indexes[index][doc.id] - if self.use_bm25 is True and len(docs_to_delete) > 0: - self.update_bm25(index=index) - - def delete_index(self, index: str): - """ - Delete an existing index. The index including all data will be removed. - - :param index: The name of the index to delete. - :return: None - """ - if index in self.indexes: - del self.indexes[index] - logger.info("Index '%s' deleted.", index) - - if index in self.bm25: - del self.bm25[index] - - def delete_labels( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete labels in an index. All labels are deleted if no filters are passed. - - :param index: Index name to delete the labels from. If None, the - DocumentStore's default label index (self.label_index) will be used. - :param ids: Optional list of IDs to narrow down the labels to be deleted. - :param filters: Narrow down the scope to documents that match the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - Example: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :return: None - """ - if headers: - raise NotImplementedError("InMemoryDocumentStore does not support headers.") - - index = index or self.label_index - if not filters and not ids: - self.indexes[index] = {} - return - labels_to_delete = self.get_all_labels(index=index, filters=filters) - if ids: - labels_to_delete = [label for label in labels_to_delete if label.id in ids] - for label in labels_to_delete: - del self.indexes[index][label.id] - - def query( - self, - query: Optional[str], - filters: Optional[FilterType] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number of documents - that are most relevant to the query as defined by the BM25 algorithm. - :param query: The query. - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - """ - - if headers: - logger.warning("InMemoryDocumentStore does not support headers. This parameter is ignored.") - if custom_query: - logger.warning("InMemoryDocumentStore does not support custom_query. This parameter is ignored.") - if all_terms_must_match is True: - logger.warning("InMemoryDocumentStore does not support all_terms_must_match. This parameter is ignored.") - if filters: - logger.warning( - "InMemoryDocumentStore does not support filters for BM25 retrieval. This parameter is ignored." - ) - - index = index or self.index - if index not in self.bm25: - raise DocumentStoreError( - f"No BM25 representation found for the index: {index}. The Document store should be initialized with use_bm25=True" - ) - - if query is None: - return [] - - tokenized_query = self.bm25_tokenization_regex(query.lower()) - docs_scores = self.bm25[index].get_scores(tokenized_query) - if scale_score is True: - # scaling probability from BM25 - docs_scores = [float(expit(np.asarray(score / 8))) for score in docs_scores] - top_docs_positions = np.argsort(docs_scores)[::-1][:top_k] - - textual_docs_list = [doc for doc in self.indexes[index].values() if doc.content_type in ["text", "table"]] - return_documents = [] - for i in top_docs_positions: - doc = textual_docs_list[i] - doc.score = docs_scores[i] - return_document = copy.copy(doc) - return_documents.append(return_document) - return return_documents - - def query_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[List[Document]]: - """ - Scan through documents in DocumentStore and return a small number of documents - that are most relevant to the provided queries as defined by keyword matching algorithms like BM25. - This method lets you find relevant documents for list of query strings (output: List of Lists of Documents). - :param query: The query. - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - """ - - if headers: - logger.warning("InMemoryDocumentStore does not support headers. This parameter is ignored.") - if custom_query: - logger.warning("InMemoryDocumentStore does not support custom_query. This parameter is ignored.") - if all_terms_must_match is True: - logger.warning("InMemoryDocumentStore does not support all_terms_must_match. This parameter is ignored.") - if filters: - logger.warning( - "InMemoryDocumentStore does not support filters for BM25 retrieval. This parameter is ignored." - ) - - index = index or self.index - if index not in self.bm25: - raise DocumentStoreError( - f"No BM25 representation found for the index: {index}. The Document store should be initialized with use_bm25=True" - ) - - result_documents = [] - for query in queries: - result_documents.append(self.query(query=query, top_k=top_k, index=index, scale_score=scale_score)) - - return result_documents diff --git a/haystack/document_stores/opensearch.py b/haystack/document_stores/opensearch.py deleted file mode 100644 index 0d6e776660..0000000000 --- a/haystack/document_stores/opensearch.py +++ /dev/null @@ -1,1635 +0,0 @@ -from typing import List, Optional, Union, Dict, Any - -import logging - -import numpy as np -from tqdm import tqdm -from tenacity import retry, wait_exponential, retry_if_not_result - -from haystack.schema import Document, FilterType -from haystack.utils.batching import get_batches_from_generator -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.errors import DocumentStoreError -from haystack.nodes.retriever import DenseRetriever -from haystack.lazy_imports import LazyImport -from .search_engine import SearchEngineDocumentStore, prepare_hosts - -with LazyImport("Run 'pip install farm-haystack[opensearch]'") as os_import: - from opensearchpy import OpenSearch, Urllib3HttpConnection, RequestsHttpConnection, NotFoundError, RequestError - from opensearchpy.helpers import bulk, scan - - -logger = logging.getLogger(__name__) - - -SIMILARITY_SPACE_TYPE_MAPPINGS = { - "nmslib": {"cosine": "cosinesimil", "dot_product": "innerproduct", "l2": "l2"}, - "score_script": {"cosine": "cosinesimil", "dot_product": "innerproduct", "l2": "l2"}, - "faiss": {"cosine": "innerproduct", "dot_product": "innerproduct", "l2": "l2"}, -} - - -class OpenSearchDocumentStore(SearchEngineDocumentStore): - valid_index_types = ["flat", "hnsw", "ivf", "ivf_pq"] - - def __init__( - self, - scheme: str = "https", # Mind this different default param - username: str = "admin", # Mind this different default param - password: str = "admin", # Mind this different default param - host: Union[str, List[str]] = "localhost", - port: Union[int, List[int]] = 9200, - api_key_id: Optional[str] = None, - api_key: Optional[str] = None, - aws4auth=None, - index: str = "document", - label_index: str = "label", - search_fields: Union[str, list] = "content", - content_field: str = "content", - name_field: str = "name", - embedding_field: str = "embedding", - embedding_dim: int = 768, - custom_mapping: Optional[dict] = None, - excluded_meta_data: Optional[list] = None, - analyzer: str = "standard", - ca_certs: Optional[str] = None, - verify_certs: bool = False, # Mind this different default param - recreate_index: bool = False, - create_index: bool = True, - refresh_type: str = "wait_for", - similarity: str = "dot_product", - timeout: int = 300, - return_embedding: bool = False, - duplicate_documents: str = "overwrite", - index_type: str = "flat", - scroll: str = "1d", - skip_missing_embeddings: bool = True, - synonyms: Optional[List] = None, - synonym_type: str = "synonym", - use_system_proxy: bool = False, - knn_engine: str = "nmslib", - knn_parameters: Optional[Dict] = None, - ivf_train_size: Optional[int] = None, - batch_size: int = 10_000, - ): - """ - Document Store using OpenSearch (https://opensearch.org/). It is compatible with the Amazon OpenSearch Service. - - In addition to native OpenSearch query & filtering, it provides efficient vector similarity search using - the KNN plugin that can scale to a large number of documents. - - :param host: url(s) of OpenSearch nodes - :param port: port(s) of OpenSearch nodes - :param username: username (standard authentication via http_auth) - :param password: password (standard authentication via http_auth) - :param api_key_id: ID of the API key (alternative authentication mode to the above http_auth) - :param api_key: Secret value of the API key (alternative authentication mode to the above http_auth) - :param aws4auth: Authentication for usage with AWS OpenSearch Service (can be generated with the requests-aws4auth package) - :param index: Name of index in OpenSearch to use for storing the documents that we want to search. If not existing yet, we will create one. - :param label_index: Name of index in OpenSearch to use for storing labels. If not existing yet, we will create one. - :param search_fields: Name of fields used by BM25Retriever to find matches in the docs to our incoming query (using OpenSearch's multi_match query), e.g. ["title", "full_text"] - :param content_field: Name of field that might contain the answer and will therefore be passed to the Reader Model (e.g. "full_text"). - If no Reader is used (e.g. in FAQ-Style QA) the plain content of this field will just be returned. - :param name_field: Name of field that contains the title of the the doc - :param embedding_field: Name of field containing an embedding vector (Only needed when using a dense retriever (e.g. DensePassageRetriever, EmbeddingRetriever) on top) - Note, that in OpenSearch the similarity type for efficient approximate vector similarity calculations is tied to the embedding field's data type which cannot be changed after creation. - :param embedding_dim: Dimensionality of embedding vector (Only needed when using a dense retriever (e.g. DensePassageRetriever, EmbeddingRetriever) on top) - :param custom_mapping: If you want to use your own custom mapping for creating a new index in OpenSearch, you can supply it here as a dictionary. - :param analyzer: Specify the default analyzer from one of the built-ins when creating a new OpenSearch Index. - OpenSearch also has built-in analyzers for different languages (e.g. impacting tokenization). More info at: - https://opensearch.org/docs/latest/analyzers/text-analyzers/ - :param excluded_meta_data: Name of fields in OpenSearch that should not be returned (e.g. [field_one, field_two]). - Helpful if you have fields with long, irrelevant content that you don't want to display in results (e.g. embedding vectors). - :param scheme: 'https' or 'http', protocol used to connect to your OpenSearch instance - :param ca_certs: Root certificates for SSL: it is a path to certificate authority (CA) certs on disk. You can use certifi package with certifi.where() to find where the CA certs file is located in your machine. - :param verify_certs: Whether to be strict about ca certificates - :param create_index: Whether to try creating a new index (If the index of that name is already existing, we will just continue in any case - :param refresh_type: Type of OpenSearch refresh used to control when changes made by a request (e.g. bulk) are made visible to search. - If set to 'wait_for', continue only after changes are visible (slow, but safe). - If set to 'false', continue directly (fast, but sometimes unintuitive behaviour when docs are not immediately available after ingestion). - More info at https://opensearch.org/docs/latest/api-reference/document-apis/bulk/#url-parameters - :param similarity: The similarity function used to compare document vectors. 'dot_product' is the default since it is - more performant with DPR embeddings. 'cosine' is recommended if you are using a Sentence BERT model. - Note, that the use of efficient approximate vector calculations in OpenSearch is tied to embedding_field's data type which cannot be changed after creation. - You won't be able to use approximate vector calculations on an embedding_field which was created with a different similarity value. - In such cases a fallback to exact but slow vector calculations will happen and a warning will be displayed. - :param timeout: Number of seconds after which an OpenSearch request times out. - :param return_embedding: To return document embedding - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param index_type: The type of index you want to create. Choose from 'flat', 'hnsw', 'ivf', or 'ivf_pq'. - 'ivf_pq' is an IVF index optimized for memory through product quantization. - ('ivf' and 'ivf_pq' are only available with 'faiss' as knn_engine.) - If index_type='flat', we use OpenSearch's default index settings (which is an hnsw index - optimized for accuracy and memory footprint), since OpenSearch does not require a special - index for exact vector similarity calculations. Note that OpenSearchDocumentStore will only - perform exact vector calculations if the selected knn_engine supports it (currently only - knn_engine='score_script'). For the other knn_engines we use hnsw, as this usually achieves - the best balance between nearly as good accuracy and latency. - :param scroll: Determines how long the current index is fixed, e.g. during updating all documents with embeddings. - Defaults to "1d" and should not be larger than this. Can also be in minutes "5m" or hours "15h" - For details, see https://opensearch.org/docs/latest/api-reference/scroll/ - :param skip_missing_embeddings: Parameter to control queries based on vector similarity when indexed documents miss embeddings. - Parameter options: (True, False) - False: Raises exception if one or more documents do not have embeddings at query time - True: Query will ignore all documents without embeddings (recommended if you concurrently index and query) - :param synonyms: List of synonyms can be passed while OpenSearch initialization. - For example: [ "foo, bar => baz", - "foozball , foosball" ] - More info at https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-tokenfilter.html - :param synonym_type: Synonym filter type can be passed. - Synonym or Synonym_graph to handle synonyms, including multi-word synonyms correctly during the analysis process. - More info at https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-graph-tokenfilter.html - :param knn_engine: The engine you want to use for the nearest neighbor search by OpenSearch's KNN plug-in. Possible values: "nmslib", "faiss" or "score_script". Defaults to "nmslib". - For more information, see [k-NN Index](https://opensearch.org/docs/latest/search-plugins/knn/knn-index/). - :param knn_parameters: Custom parameters for the KNN engine. Parameter names depend on the index type you use. - Configurable parameters for indices of type... - - `hnsw`: `"ef_construction"`, `"ef_search"`, `"m"` - - `ivf`: `"nlist"`, `"nprobes"` - - `ivf_pq`: `"nlist"`, `"nprobes"`, `"m"`, `"code_size"` - If you don't specify any parameters, the OpenSearch's default values are used. - (With the exception of index_type='hnsw', where we use values other than OpenSearch's - default ones to achieve comparability throughout DocumentStores in Haystack.) - For more information on configuration of knn indices, see - [OpenSearch Documentation](https://opensearch.org/docs/latest/search-plugins/knn/knn-index/#method-definitions). - :param ivf_train_size: Number of embeddings to use for training the IVF index. Training starts automatically - once the number of indexed embeddings exceeds ivf_train_size. If `None`, the minimum - number of embeddings recommended for training by FAISS is used (depends on the desired - index type and knn parameters). If `0`, training doesn't happen automatically but needs - to be triggered manually via the `train_index` method. - Default: `None` - :param batch_size: Number of Documents to index at once / Number of queries to execute at once. If you face - memory issues, decrease the batch_size. - """ - os_import.check() - # These parameters aren't used by Opensearch at the moment but could be in the future, see - # https://github.com/opensearch-project/security/issues/1504. Let's not deprecate them for - # now but send a warning to the user. - if api_key or api_key_id: - logger.warning("api_key and api_key_id will be ignored by the Opensearch client") - - # Base constructor needs the client to be ready, create it before calling super() - client = self._init_client( - host=host, - port=port, - username=username, - password=password, - aws4auth=aws4auth, - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - use_system_proxy=use_system_proxy, - ) - - # Test the connection - try: - client.indices.get(index) - except NotFoundError: - # We don't know which permissions the user has but we can assume they can write to the given index, so - # if we get a NotFoundError it means at least the connection is working. - pass - except Exception as e: - # If we get here, there's something fundamentally wrong with the connection and we can't continue - raise ConnectionError( - f"Initial connection to Opensearch failed with error '{e}'\n" - f"Make sure an Opensearch instance is running at `{host}` and that it has finished booting (can take > 30s)." - ) - - if knn_engine not in {"nmslib", "faiss", "score_script"}: - raise ValueError(f"knn_engine must be either 'nmslib', 'faiss' or 'score_script' but was {knn_engine}") - - if index_type in self.valid_index_types: - if index_type in ["ivf", "ivf_pq"] and knn_engine != "faiss": - raise DocumentStoreError("Use 'faiss' as knn_engine when using 'ivf' as index_type.") - self.index_type = index_type - else: - raise DocumentStoreError( - f"Invalid value for index_type in constructor. Choose one of these values: {self.valid_index_types}." - ) - - self.knn_engine = knn_engine - self.knn_parameters = {} if knn_parameters is None else knn_parameters - if ivf_train_size is not None: - if ivf_train_size <= 0: - raise DocumentStoreError("`ivf_train_on_write_size` must be None or a positive integer.") - self.ivf_train_size = ivf_train_size - elif self.index_type in ["ivf", "ivf_pq"]: - self.ivf_train_size = self._recommended_ivf_train_size() - self.space_type = SIMILARITY_SPACE_TYPE_MAPPINGS[knn_engine][similarity] - super().__init__( - client=client, - index=index, - label_index=label_index, - search_fields=search_fields, - content_field=content_field, - name_field=name_field, - embedding_field=embedding_field, - embedding_dim=embedding_dim, - custom_mapping=custom_mapping, - excluded_meta_data=excluded_meta_data, - analyzer=analyzer, - recreate_index=recreate_index, - create_index=create_index, - refresh_type=refresh_type, - similarity=similarity, - return_embedding=return_embedding, - duplicate_documents=duplicate_documents, - scroll=scroll, - skip_missing_embeddings=skip_missing_embeddings, - synonyms=synonyms, - synonym_type=synonym_type, - batch_size=batch_size, - ) - - # Let the base class catch the right error from the Opensearch client - self._RequestError = RequestError - - def _do_bulk(self, *args, **kwargs): - """Override the base class method to use the Opensearch client""" - return bulk(*args, **kwargs) - - def _do_scan(self, *args, **kwargs): - """Override the base class method to use the Opensearch client""" - return scan(*args, **kwargs) - - @classmethod - def _init_client( - cls, - host: Union[str, List[str]], - port: Union[int, List[int]], - username: str, - password: str, - aws4auth, - scheme: str, - ca_certs: Optional[str], - verify_certs: bool, - timeout: int, - use_system_proxy: bool, - ) -> "OpenSearch": - """ - Create an instance of the Opensearch client - """ - hosts = prepare_hosts(host, port) - connection_class = Urllib3HttpConnection - if use_system_proxy: - connection_class = RequestsHttpConnection # type: ignore [assignment] - - if aws4auth: - # Sign requests to Opensearch with IAM credentials - # see https://docs.aws.amazon.com/opensearch-service/latest/developerguide/request-signing.html#request-signing-python - if username: - logger.warning( - "aws4auth and a username or the default username 'admin' are passed to the OpenSearchDocumentStore. The username will be ignored and aws4auth will be used for authentication." - ) - client = OpenSearch( - hosts=hosts, - http_auth=aws4auth, - connection_class=RequestsHttpConnection, - use_ssl=True, - verify_certs=True, - timeout=timeout, - ) - elif username: - # standard http_auth - client = OpenSearch( - hosts=hosts, - http_auth=(username, password), - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - connection_class=connection_class, - ) - else: - # no authentication needed - client = OpenSearch( - hosts=hosts, - scheme=scheme, - ca_certs=ca_certs, - verify_certs=verify_certs, - timeout=timeout, - connection_class=connection_class, - ) - - return client - - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: Optional[int] = None, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Indexes documents for later queries in OpenSearch. - - If a document with the same ID already exists in OpenSearch: - a) (Default) Throw OpenSearch's standard error message for duplicate IDs. - b) If `self.update_existing_documents=True` for DocumentStore: Overwrite existing documents. - (This is only relevant if you pass your own ID when initializing a `Document`. - If you don't set custom IDs for your Documents or just pass a list of dictionaries here, - they automatically get UUIDs assigned. See the `Document` class for details.) - - :param documents: A list of Python dictionaries or a list of Haystack Document objects. - For documents as dictionaries, the format is {"content": ""}. - Optionally: Include meta data via {"content": "", - "meta":{"name": ", "author": "somebody", ...}} - You can use it for filtering and you can access it in the responses of the Finder. - Advanced: If you are using your own OpenSearch mapping, change the key names in the dictionary - to what you have set for self.content_field and self.name_field. - :param index: OpenSearch index where the documents should be indexed. If you don't specify it, self.index is used. - :param batch_size: Number of documents that are passed to OpenSearch's bulk function at a time. - :param duplicate_documents: Handle duplicate documents based on parameter options. - Parameter options: ( 'skip','overwrite','fail') - skip: Ignore the duplicate documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: Raises an error if the document ID of the document being added already - exists. - :param headers: Custom HTTP headers to pass to OpenSearch client (for example {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - For more information, see [HTTP/REST clients and security](https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html). - :raises DuplicateDocumentError: Exception trigger on duplicate document - :return: None - """ - if index is None: - index = self.index - - batch_size = batch_size or self.batch_size - - if self.knn_engine == "faiss" and self.similarity == "cosine": - field_map = self._create_document_field_map() - documents = [Document.from_dict(d, field_map=field_map) if isinstance(d, dict) else d for d in documents] - embeddings_to_index = np.array([d.embedding for d in documents], dtype="float32") - self.normalize_embedding(embeddings_to_index) - for document, embedding in zip(documents, embeddings_to_index): - document.embedding = None if np.isnan(embedding).any() else embedding - - super().write_documents( - documents=documents, - index=index, - batch_size=batch_size, - duplicate_documents=duplicate_documents, - headers=headers, - ) - - # Train IVF index if number of embeddings exceeds ivf_train_size - if ( - self.index_type in ["ivf", "ivf_pq"] - and not index.startswith(".") - and not self._ivf_model_exists(index=index) - ) and self.get_embedding_count(index=index, headers=headers) >= self.ivf_train_size: - train_docs = self.get_all_documents(index=index, return_embedding=True, headers=headers) - self._train_ivf_index(index=index, documents=train_docs, headers=headers) - - def _embed_documents(self, documents: List[Document], retriever: DenseRetriever) -> np.ndarray: - """ - Embed a list of documents using a Retriever. - :param documents: List of documents to embed. - :param retriever: Retriever to use for embedding. - :return: embeddings of documents. - """ - embeddings = super()._embed_documents(documents, retriever) - if self.knn_engine == "faiss" and self.similarity == "cosine": - self.normalize_embedding(embeddings) - return embeddings - - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - """ - Find the document that is most similar to the provided `query_emb` by using a vector similarity metric. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return - :param index: Index name for storing the docs and metadata - :param return_embedding: To return document embedding - :param headers: Custom HTTP headers to pass to OpenSearch client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :return: - """ - if index is None: - index = self.index - - if return_embedding is None: - return_embedding = self.return_embedding - - if self.index_type in ["ivf", "ivf_pq"] and not self._ivf_model_exists(index=index): - self._ivf_index_not_trained_error(index=index, headers=headers) - - if not self.embedding_field: - raise DocumentStoreError("Please set a valid `embedding_field` for OpenSearchDocumentStore") - body = self._construct_dense_query_body( - query_emb=query_emb, filters=filters, top_k=top_k, return_embedding=return_embedding - ) - - logger.debug("Retriever query: %s", body) - result = self.client.search(index=index, body=body, headers=headers)["hits"]["hits"] - - documents = [ - self._convert_es_hit_to_document(hit, adapt_score_for_embedding=True, scale_score=scale_score) - for hit in result - ] - - if self.index_type == "hnsw": - ef_search = self._get_ef_search_value() - if top_k > ef_search: - logger.warning( - "top_k (%i) is greater than ef_search (%i). " - "We recommend setting ef_search >= top_k for optimal performance.", - top_k, - ef_search, - ) - - return documents - - def query_by_embedding_batch( - self, - query_embs: Union[List[np.ndarray], np.ndarray], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - batch_size: Optional[int] = None, - ) -> List[List[Document]]: - """ - Find the documents that are most similar to the provided `query_embs` by using a vector similarity metric. - - :param query_embs: Embeddings of the queries (e.g. gathered from DPR). - Can be a list of one-dimensional numpy arrays or a two-dimensional numpy array. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return - :param index: Index name for storing the docs and metadata - :param return_embedding: To return document embedding - :param headers: Custom HTTP headers to pass to OpenSearch client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise, raw similarity scores (e.g. cosine or dot_product) will be used. - :param batch_size: Number of query embeddings to process at once. If not specified, self.batch_size is used. - """ - if index is None: - index = self.index - - batch_size = batch_size or self.batch_size - - if self.index_type in ["ivf", "ivf_pq"] and not self._ivf_model_exists(index=index): - self._ivf_index_not_trained_error(index=index, headers=headers) - - return super().query_by_embedding_batch( - query_embs, filters, top_k, index, return_embedding, headers, scale_score, batch_size - ) - - def query( - self, - query: Optional[str], - filters: Optional[FilterType] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query as defined by the BM25 algorithm. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param custom_query: The query string containing a mandatory `${query}` and an optional `${filters}` placeholder. - - :: - - **An example custom_query:** - ```python - { - "size": 10, - "query": { - "bool": { - "should": [{"multi_match": { - "query": ${query}, // mandatory query placeholder - "type": "most_fields", - "fields": ["content", "title"]}}], - "filter": ${filters} // optional filters placeholder - } - }, - } - ``` - - **For this custom_query, a sample `retrieve()` could be:** - ```python - self.retrieve(query="Why did the revenue increase?", - filters={"years": ["2019"], "quarters": ["Q1", "Q2"]}) - ``` - - Optionally, highlighting can be defined by specifying the highlight settings. - See https://www.elastic.co/guide/en/elasticsearch/reference/current/highlighting.html. - You will find the highlighted output in the returned Document's meta field by key "highlighted". - :: - - **Example custom_query with highlighting:** - ```python - { - "size": 10, - "query": { - "bool": { - "should": [{"multi_match": { - "query": ${query}, // mandatory query placeholder - "type": "most_fields", - "fields": ["content", "title"]}}], - } - }, - "highlight": { // enable highlighting - "fields": { // for fields content and title - "content": {}, - "title": {} - } - }, - } - ``` - - **For this custom_query, highlighting info can be accessed by:** - ```python - docs = self.retrieve(query="Why did the revenue increase?") - highlighted_content = docs[0].meta["highlighted"]["content"] - highlighted_title = docs[0].meta["highlighted"]["title"] - ``` - - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to false. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - - if index is None: - index = self.index - - body = self._construct_query_body( - query=query, - filters=filters, - top_k=top_k, - custom_query=custom_query, - all_terms_must_match=all_terms_must_match, - ) - - result = self.client.search(index=index, body=body, headers=headers)["hits"]["hits"] - - documents = [self._convert_es_hit_to_document(hit, scale_score=scale_score) for hit in result] - return documents - - def _construct_dense_query_body( - self, query_emb: np.ndarray, return_embedding: bool, filters: Optional[FilterType] = None, top_k: int = 10 - ): - body: Dict[str, Any] = {"size": top_k, "query": self._get_vector_similarity_query(query_emb, top_k)} - if filters: - filter_ = LogicalFilterClause.parse(filters).convert_to_elasticsearch() - if "script_score" in body["query"]: - # set filter for pre-filtering (see https://opensearch.org/docs/latest/search-plugins/knn/knn-score-script/) - body["query"]["script_score"]["query"] = {"bool": {"filter": filter_}} - else: - body["query"]["bool"]["filter"] = filter_ - - excluded_fields = self._get_excluded_fields(return_embedding=return_embedding) - if excluded_fields: - body["_source"] = {"excludes": excluded_fields} - - return body - - def _create_document_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - """ - Create a new index for storing documents. - """ - if self.custom_mapping: - index_definition = self.custom_mapping - else: - index_definition = { - "mappings": { - "properties": {self.name_field: {"type": "keyword"}, self.content_field: {"type": "text"}}, - "dynamic_templates": [ - {"strings": {"path_match": "*", "match_mapping_type": "string", "mapping": {"type": "keyword"}}} - ], - }, - "settings": {"analysis": {"analyzer": {"default": {"type": self.analyzer}}}}, - } - - if self.synonyms: - for field in self.search_fields: - index_definition["mappings"]["properties"].update({field: {"type": "text", "analyzer": "synonym"}}) - index_definition["mappings"]["properties"][self.content_field] = {"type": "text", "analyzer": "synonym"} - - index_definition["settings"]["analysis"]["analyzer"]["synonym"] = { - "tokenizer": "whitespace", - "filter": ["lowercase", "synonym"], - } - index_definition["settings"]["analysis"]["filter"] = { - "synonym": {"type": self.synonym_type, "synonyms": self.synonyms} - } - - else: - for field in self.search_fields: - index_definition["mappings"]["properties"].update({field: {"type": "text"}}) - - if self.embedding_field: - index_definition["settings"]["index"] = {"knn": True} # TODO: option to turn off for script scoring - # global ef_search setting affects only nmslib, for faiss it is set in the field mapping - if self.knn_engine == "nmslib" and self.index_type == "hnsw": - ef_search = self._get_ef_search_value() - index_definition["settings"]["index"]["knn.algo_param.ef_search"] = ef_search - index_definition["mappings"]["properties"][self.embedding_field] = self._get_embedding_field_mapping( - index=index_name - ) - - try: - self.client.indices.create(index=index_name, body=index_definition, headers=headers) - except RequestError as e: - # With multiple workers we need to avoid race conditions, where: - # - there's no index in the beginning - # - both want to create one - # - one fails as the other one already created it - if not self._index_exists(index_name, headers=headers): - raise e - - def train_index( - self, - documents: Optional[Union[List[dict], List[Document]]] = None, - embeddings: Optional[np.ndarray] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Trains an IVF index on the provided Documents or embeddings if the index hasn't been trained yet. - - The train vectors should come from the same distribution as your final vectors. - You can pass either Documents (including embeddings) or just plain embeddings you want to train the index on. - - :param documents: Documents (including the embeddings) you want to train the index on. - :param embeddings: Plain embeddings you want to train the index on. - :param index: Name of the index to train. If `None`, the DocumentStore's default index (self.index) is used. - :param headers: Custom HTTP headers to pass to the OpenSearch client (for example {'Authorization': 'Basic YWRtaW46cm9vdA=='}). - For more information, see [HTTP/REST clients and security](https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html). - """ - if self.index_type not in ["ivf", "ivf_pq"]: - raise DocumentStoreError( - "You can only train an index if you set `index_type` to 'ivf' or 'ivf_pq' in your DocumentStore. " - "Other index types don't require training." - ) - - if index is None: - index = self.index - - if isinstance(embeddings, np.ndarray) and documents: - raise ValueError("Pass either `documents` or `embeddings`. You passed both.") - - if documents: - document_objects = [Document.from_dict(d) if isinstance(d, dict) else d for d in documents] - document_objects = [doc for doc in document_objects if doc.embedding is not None] - self._train_ivf_index(index=index, documents=document_objects, headers=headers) - elif isinstance(embeddings, np.ndarray): - document_objects = [ - Document(content=f"Embedding {i}", embedding=embedding) for i, embedding in enumerate(embeddings) - ] - self._train_ivf_index(index=index, documents=document_objects, headers=headers) - else: - logger.warning( - "When calling `train_index`, you must provide either Documents or embeddings. " - "Because none of these values was provided, the index won't be trained." - ) - - def delete_index(self, index: str): - """ - Delete an existing search index. The index together with all data will be removed. - If the index is of type `"ivf"` or `"ivf_pq"`, this method also deletes the corresponding IVF and PQ model. - - :param index: The name of the index to delete. - :return: None - """ - # Check if index uses an IVF model and delete it - if self._index_exists(index): - index_mapping = self.client.indices.get(index)[index]["mappings"]["properties"] - if self.embedding_field in index_mapping and "model_id" in index_mapping[self.embedding_field]: - model_id = index_mapping[self.embedding_field]["model_id"] - self.client.transport.perform_request("DELETE", f"/_plugins/_knn/models/{model_id}") - - super().delete_index(index) - - def _validate_and_adjust_document_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - """ - Validates an existing document index. If there's no embedding field, we'll add it. - """ - indices = self.client.indices.get(index_name, headers=headers) - - if not any(indices): - # We don't want to raise here as creating a query-only document store before the index being created asynchronously is a valid use case. - logger.warning( - "Before you can use an index, you must create it first. The index '%s' doesn't exist. " - "You can create it by setting `create_index=True` on init or by calling `write_documents()` if you prefer to create it on demand. " - "Note that this instance doesn't validate the index after you created it.", - index_name, - ) - - # If the index name is an alias that groups multiple existing indices, each of them must have an embedding_field. - for index_id, index_info in indices.items(): - mappings = index_info["mappings"] - index_settings = index_info["settings"]["index"] - - # validate fulltext fields - if self.search_fields: - for search_field in self.search_fields: - if search_field in mappings["properties"]: - if mappings["properties"][search_field]["type"] != "text": - raise DocumentStoreError( - f"The index '{index_id}' needs the 'text' type for the search_field '{search_field}' to run full text search, but got type '{mappings['properties'][search_field]['type']}'. " - f"You can fix this issue in one of the following ways: " - f" - Recreate the index by setting `recreate_index=True` (Note that you'll lose all data stored in the index.) " - f" - Use another index name by setting `index='my_index_name'`. " - f" - Remove '{search_field}' from `search_fields`. " - ) - else: - mappings["properties"][search_field] = ( - {"type": "text", "analyzer": "synonym"} if self.synonyms else {"type": "text"} - ) - self.client.indices.put_mapping(index=index_id, body=mappings, headers=headers) - - # validate embedding field - existing_embedding_field = mappings["properties"].get(self.embedding_field, None) - - if existing_embedding_field is None: - # create embedding field - mappings["properties"][self.embedding_field] = self._get_embedding_field_mapping(index=index_name) - self.client.indices.put_mapping(index=index_id, body=mappings, headers=headers) - else: - # check type of existing embedding field - if existing_embedding_field["type"] != "knn_vector": - raise DocumentStoreError( - f"The index '{index_id}' needs the 'knn_vector' type for the embedding_field '{self.embedding_field}' to run vector search, but got type '{mappings['properties'][self.embedding_field]['type']}'. " - f"You can fix it in one of these ways: " - f" - Recreate the index by setting `recreate_index=True` (Note that you'll lose all data stored in the index.) " - f" - Use another index name by setting `index='my_index_name'`. " - f" - Use another embedding field name by setting `embedding_field='my_embedding_field_name'`. " - ) - - # Check if existing embedding field fits desired knn settings - training_required = self.index_type in ["ivf", "ivf_pq"] and "model_id" not in existing_embedding_field - if self.knn_engine != "score_script" and not training_required: - self._validate_approximate_knn_settings(existing_embedding_field, index_settings, index_id) - - # Adjust global ef_search setting (nmslib only). - if self.knn_engine == "nmslib": - ef_search = index_settings.get("knn.algo_param", {}).get("ef_search", 512) - desired_ef_search = self._get_ef_search_value() - if self.index_type == "hnsw" and ef_search != desired_ef_search: - body = {"knn.algo_param.ef_search": desired_ef_search} - self.client.indices.put_settings(index=index_id, body=body, headers=headers) - logger.info("Set ef_search to 20 for hnsw index '%s'.", index_id) - elif self.index_type == "flat" and ef_search != 512: - body = {"knn.algo_param.ef_search": 512} - self.client.indices.put_settings(index=index_id, body=body, headers=headers) - logger.info("Set ef_search to 512 for hnsw index '%s'.", index_id) - - def _validate_approximate_knn_settings( - self, existing_embedding_field: Dict[str, Any], index_settings: Dict[str, Any], index_id: str - ): - """ - Checks if the existing embedding field fits the desired approximate knn settings. - If not, it will raise an error. - If settings are not specified we infer the same default values as https://opensearch.org/docs/latest/search-plugins/knn/knn-index/ - """ - method = existing_embedding_field.get("method", {}) - if "model_id" in existing_embedding_field: - embedding_field_knn_engine = "faiss" - else: - embedding_field_knn_engine = method.get("engine", "nmslib") - embedding_field_space_type = method.get("space_type", "l2") - - # Validate knn engine - if embedding_field_knn_engine != self.knn_engine: - raise DocumentStoreError( - f"Existing embedding field '{self.embedding_field}' of OpenSearch index '{index_id}' has knn_engine " - f"'{embedding_field_knn_engine}', but knn_engine was set to '{self.knn_engine}'. " - f"To switch knn_engine to '{self.knn_engine}' consider one of these options: " - f" - Clone the embedding field in the same index, for example, `clone_embedding_field(knn_engine='{self.knn_engine}', ...)`. " - f" - Create a new index by selecting a different index name, for example, `index='my_new_{self.knn_engine}_index'`. " - f" - Overwrite the existing index by setting `recreate_index=True`. Note that you'll lose all existing data." - ) - - # Validate space type - if embedding_field_space_type != self.space_type: - supported_similaries = [ - k - for k, v in SIMILARITY_SPACE_TYPE_MAPPINGS[embedding_field_knn_engine].items() - if v == embedding_field_space_type - ] - raise DocumentStoreError( - f"Set `similarity` to one of '{supported_similaries}' to properly use the embedding field '{self.embedding_field}' of index '{index_id}'. " - f"Similarity '{self.similarity}' is not compatible with embedding field's space type '{embedding_field_space_type}', it requires '{self.space_type}'. " - f"If you do want to switch `similarity` of an existing index, note that the dense retriever models have an affinity for a specific similarity function. " - f"Switching the similarity function might degrade the performance of your model. " - f"\n" - f"If you don't want to change the existing index, you can still use similarity '{self.similarity}' by setting `knn_engine='score_script'`. " - f"This might be slower because of the exact vector calculation. " - f"For a fast ANN search with similarity '{self.similarity}', consider one of these options: " - f" - Clone the embedding field in the same index, for example, `clone_embedding_field(similarity='{self.similarity}', ...)`. " - f" - Create a new index by selecting a different index name, for example, `index='my_new_{self.similarity}_index'`. " - f" - Overwrite the existing index by setting `recreate_index=True`. Note that you'll lose all existing data." - ) - - # Validate HNSW indices - if self.index_type in ["flat", "hnsw"]: - self._validate_hnsw_settings(existing_embedding_field, index_settings, index_id) - # Validate IVF indices - elif self.index_type in ["ivf", "ivf_pq"]: - self._validate_ivf_settings(existing_embedding_field, index_settings, index_id) - else: - raise DocumentStoreError("Unknown index_type. Must be one of 'flat', 'hnsw', 'ivf', or 'ivf_pq'.") - - def _validate_hnsw_settings( - self, existing_embedding_field: Dict[str, Any], index_settings: Dict[str, Any], index_id: str - ): - method = existing_embedding_field.get("method", {}) - parameters = method.get("parameters", {}) - embedding_field_method_name = method.get("name", "hnsw") - embedding_field_ef_construction = parameters.get("ef_construction", 512) - embedding_field_m = parameters.get("m", 16) - embedding_field_knn_engine = method.get("engine", "nmslib") - # ef_search is configured in the index settings and not in the mapping for nmslib - if embedding_field_knn_engine == "nmslib": - embedding_field_ef_search = index_settings.get("knn.algo_param", {}).get("ef_search", 512) - else: - embedding_field_ef_search = parameters.get("ef_search", 512) - - # Check method params according to requested index_type - # Indices of type "flat" that don't use "score_script" as knn_engine use an HNSW index optimized for accuracy - if self.index_type == "flat": - self._assert_embedding_param( - name="method.name", actual=embedding_field_method_name, expected="hnsw", index_id=index_id - ) - self._assert_embedding_param( - name="ef_construction", actual=embedding_field_ef_construction, expected=512, index_id=index_id - ) - self._assert_embedding_param(name="m", actual=embedding_field_m, expected=16, index_id=index_id) - if self.knn_engine == "faiss": - self._assert_embedding_param( - name="ef_search", actual=embedding_field_ef_search, expected=512, index_id=index_id - ) - - elif self.index_type == "hnsw": - expected_ef_construction = self.knn_parameters.get("ef_construction", 80) - expected_m = self.knn_parameters.get("m", 64) - expected_ef_search = self.knn_parameters.get("ef_search", 20) - self._assert_embedding_param( - name="method.name", actual=embedding_field_method_name, expected="hnsw", index_id=index_id - ) - self._assert_embedding_param( - name="ef_construction", - actual=embedding_field_ef_construction, - expected=expected_ef_construction, - index_id=index_id, - ) - self._assert_embedding_param(name="m", actual=embedding_field_m, expected=expected_m, index_id=index_id) - if self.knn_engine == "faiss": - self._assert_embedding_param( - name="ef_search", actual=embedding_field_ef_search, expected=expected_ef_search, index_id=index_id - ) - - def _validate_ivf_settings( - self, existing_embedding_field: Dict[str, Any], index_settings: Dict[str, Any], index_id: str - ): - # Index is not trained yet and should therefore be an HNSW index with default settings until index is trained - if "model_id" in existing_embedding_field: - model_endpoint = f"/_plugins/_knn/models/{existing_embedding_field['model_id']}" - response = self.client.transport.perform_request("GET", url=model_endpoint) - model_settings_list = [setting.split(":") for setting in response["description"].split()] - model_settings = {k: (int(v) if v.isnumeric() else v) for k, v in model_settings_list} - - embedding_field_nlist = model_settings.get("nlist") - embedding_field_nprobes = model_settings.get("nprobes") - expected_nlist = self.knn_parameters.get("nlist", 4) - expected_nprobes = self.knn_parameters.get("nprobes", 1) - self._assert_embedding_param( - name="nlist", actual=embedding_field_nlist, expected=expected_nlist, index_id=index_id - ) - self._assert_embedding_param( - name="nprobes", actual=embedding_field_nprobes, expected=expected_nprobes, index_id=index_id - ) - if self.index_type == "ivf_pq": - embedding_field_m = model_settings.get("m") - embedding_field_code_size = model_settings.get("code_size") - expected_m = self.knn_parameters.get("m", 1) - expected_code_size = self.knn_parameters.get("code_size", 8) - self._assert_embedding_param(name="m", actual=embedding_field_m, expected=expected_m, index_id=index_id) - self._assert_embedding_param( - name="code_size", actual=embedding_field_code_size, expected=expected_code_size, index_id=index_id - ) - - def _assert_embedding_param(self, name: str, actual: Any, expected: Any, index_id: str) -> None: - if actual != expected: - message = ( - f"The index_type '{self.index_type}' needs '{expected}' as {name} value. " - f"Currently, the value for embedding field '{self.embedding_field}' of index '{index_id}' is '{actual}'. " - f"To use your embeddings with index_type '{self.index_type}', you can do one of the following: " - f" - Clone the embedding field in the same index, for example, `clone_embedding_field(index_type='{self.index_type}', ...)`. " - f" - Create a new index by selecting a different index name, for example, `index='my_new_{self.index_type}_index'`. " - f" - Overwrite the existing index by setting `recreate_index=True`. Note that you'll lose all existing data." - ) - raise DocumentStoreError(message) - - def _get_embedding_field_mapping( - self, - knn_engine: Optional[str] = None, - space_type: Optional[str] = None, - index_type: Optional[str] = None, - embedding_dim: Optional[int] = None, - index: Optional[str] = None, - ) -> Dict[str, Any]: - if space_type is None: - space_type = self.space_type - if knn_engine is None: - knn_engine = self.knn_engine - if index_type is None: - index_type = self.index_type - if embedding_dim is None: - embedding_dim = self.embedding_dim - if index is None: - index = self.index - - embeddings_field_mapping = {"type": "knn_vector", "dimension": embedding_dim} - if knn_engine != "score_script": - method: dict = {"space_type": space_type, "engine": knn_engine} - - ef_construction = ( - 80 if "ef_construction" not in self.knn_parameters else self.knn_parameters["ef_construction"] - ) - ef_search = self._get_ef_search_value() - m = 64 if "m" not in self.knn_parameters else self.knn_parameters["m"] - - if index_type == "flat": - # We're using HNSW with knn_engines nmslib and faiss as they do not support exact knn. - method["name"] = "hnsw" - # use default parameters from https://opensearch.org/docs/1.2/search-plugins/knn/knn-index/ - # we need to set them explicitly as aws managed instances starting from version 1.2 do not support empty parameters - method["parameters"] = {"ef_construction": 512, "m": 16} - elif index_type == "hnsw": - method["name"] = "hnsw" - method["parameters"] = {"ef_construction": ef_construction, "m": m} - # for nmslib this is a global index setting - if knn_engine == "faiss": - method["parameters"]["ef_search"] = ef_search - elif index_type in ["ivf", "ivf_pq"]: - if knn_engine != "faiss": - raise DocumentStoreError("To use 'ivf' or 'ivf_pq as index_type, set knn_engine to 'faiss'.") - # Check if IVF model already exists - if self._ivf_model_exists(index): - logger.info("Using existing IVF model '%s-ivf' for index '%s'.", index, index) - embeddings_field_mapping = {"type": "knn_vector", "model_id": f"{index}-ivf"} - method = {} - else: - # IVF indices require training before they can be initialized. Setting index_type to HNSW until - # index is trained - logger.info("Using index of type 'flat' for index '%s' until IVF model is trained.", index) - method = {} - else: - logger.error("Set index_type to either 'flat', 'hnsw', 'ivf', or 'ivf_pq'.") - method["name"] = "hnsw" - - if method: - embeddings_field_mapping["method"] = method - - return embeddings_field_mapping - - def _ivf_model_exists(self, index: str) -> bool: - if self._index_exists(".opensearch-knn-models"): - response = self.client.transport.perform_request("GET", "/_plugins/_knn/models/_search") - existing_ivf_models = { - model["_source"]["model_id"] - for model in response["hits"]["hits"] - if model["_source"]["state"] != "failed" - } - else: - existing_ivf_models = set() - - return f"{index}-ivf" in existing_ivf_models - - def _ivf_index_not_trained_error(self, index: str, headers: Optional[Dict[str, str]] = None): - add_num_of_embs = "" - if self.ivf_train_size != 0: - embs_to_add = self.get_embedding_count(index=index, headers=headers) - self.ivf_train_size - add_num_of_embs = ( - f"or add at least {embs_to_add} more embeddings to automatically start the " f"training process " - ) - raise DocumentStoreError( - f"Index of type '{self.index_type}' is not trained yet. Train the index manually using " - f"`train_index` {add_num_of_embs}before querying it." - ) - - def _create_label_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - mapping = { - "mappings": { - "properties": { - "query": {"type": "text"}, - "answer": { - "type": "nested" - }, # In elasticsearch we use type:flattened, but this is not supported in opensearch - "document": {"type": "nested"}, - "is_correct_answer": {"type": "boolean"}, - "is_correct_document": {"type": "boolean"}, - "origin": {"type": "keyword"}, # e.g. user-feedback or gold-label - "document_id": {"type": "keyword"}, - "no_answer": {"type": "boolean"}, - "pipeline_id": {"type": "keyword"}, - "created_at": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"}, - "updated_at": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"} - # TODO add pipeline_hash and pipeline_name once we migrated the REST API to pipelines - } - } - } - try: - self.client.indices.create(index=index_name, body=mapping, headers=headers) - except RequestError as e: - # With multiple workers we need to avoid race conditions, where: - # - there's no index in the beginning - # - both want to create one - # - one fails as the other one already created it - if not self._index_exists(index_name, headers=headers): - raise e - - def _get_vector_similarity_query(self, query_emb: np.ndarray, top_k: int): - """ - Generate OpenSearch query for vector similarity. - """ - if self.knn_engine == "score_script": - query: dict = { - "script_score": { - "query": {"match_all": {}}, - "script": { - "source": "knn_score", - "lang": "knn", - "params": { - "field": self.embedding_field, - "query_value": query_emb.tolist(), - "space_type": self.space_type, - }, - }, - } - } - else: - if self.knn_engine == "faiss" and self.similarity == "cosine": - self.normalize_embedding(query_emb) - - query = {"bool": {"must": [{"knn": {self.embedding_field: {"vector": query_emb.tolist(), "k": top_k}}}]}} - - return query - - def _get_raw_similarity_score(self, score): - # adjust scores according to https://opensearch.org/docs/latest/search-plugins/knn/approximate-knn - # and https://opensearch.org/docs/latest/search-plugins/knn/knn-score-script/ - - # space type is required as criterion as there is no consistent similarity-to-space-type mapping across knn engines - if self.space_type == "innerproduct": - if score > 1: - score = score - 1 - else: - score = -(1 / score - 1) - elif self.space_type == "l2": - score = 1 / score - 1 - elif self.space_type == "cosinesimil": - if self.knn_engine == "score_script": - score = score - 1 - else: - score = -(1 / score - 2) - - return score - - def _train_ivf_index( - self, index: Optional[str], documents: List[Document], headers: Optional[Dict[str, str]] = None - ): - """ - If the provided index is not an IVF index yet, this method trains it on the provided Documents - and converts the index to an IVF index. - """ - if index is None: - index = self.index - - # Check if IVF index is already trained by checking if embedding mapping contains a model_id field - if "model_id" in self.client.indices.get(index)[index]["mappings"]["properties"][self.embedding_field]: - logger.info("IVF index '%s' is already trained. Skipping training.", index) - # IVF model is not trained yet -> train it and convert HNSW index to IVF index - else: - nlist = self.knn_parameters.get("nlist", 4) - nprobes = self.knn_parameters.get("nprobes", 1) - recommended_train_size = self._recommended_ivf_train_size() - documents = [doc for doc in documents if doc.embedding is not None] - if len(documents) < nlist: - raise DocumentStoreError( - f"IVF training requires the number of training samples to be greater than or " - f"equal to `nlist`. Number of provided training samples is `{len(documents)}` " - f"and nlist is `{nlist}`." - ) - if len(documents) < recommended_train_size: - logger.warning( - "Consider increasing the number of training samples to at least " - "`%i` to get a reliable %s index.", - recommended_train_size, - self.index_type, - ) - # Create temporary index containing training embeddings - self._create_document_index(index_name=f".{index}_ivf_training", headers=headers) - self.write_documents(documents=documents, index=f".{index}_ivf_training", headers=headers) - - settings = f"index_type:{self.index_type} nlist:{nlist} nprobes:{nprobes}" - training_req_body: Dict = { - "training_index": f".{index}_ivf_training", - "training_field": self.embedding_field, - "dimension": self.embedding_dim, - "method": { - "name": "ivf", - "engine": "faiss", - "space_type": self.space_type, - "parameters": {"nlist": nlist, "nprobes": nprobes}, - }, - } - # Add product quantization - if self.index_type == "ivf_pq": - m = self.knn_parameters.get("m", 1) - code_size = self.knn_parameters.get("code_size", 8) - if code_size > 8: - raise DocumentStoreError( - f"code_size parameter for product quantization must be less than or equal to 8. " - f"Provided code_size is `{code_size}`." - ) - - # see FAISS doc for details: https://github.com/facebookresearch/faiss/wiki/FAQ#can-i-ignore-warning-clustering-xxx-points-to-yyy-centroids - n_clusters = 2**code_size - if len(documents) < n_clusters: - raise DocumentStoreError( - f"PQ training requires the number of training samples to be greater than or " - f"equal to the number of clusters. Number of provided training samples is `{len(documents)}` " - f"and the number of clusters is `{n_clusters}`." - ) - - encoder = {"name": "pq", "parameters": {"m": m, "code_size": code_size}} - settings += f" m:{m} code_size:{code_size}" - training_req_body["method"]["parameters"]["encoder"] = encoder - - training_req_body["description"] = settings - logger.info("Training IVF index '%s' using {len(documents)} embeddings.", index) - train_endpoint = f"/_plugins/_knn/models/{index}-ivf/_train" - response = self.client.transport.perform_request( - "POST", url=train_endpoint, headers=headers, body=training_req_body - ) - ivf_model = response["model_id"] - - # Wait until model training is finished, _knn_model_trained uses a retry decorator - if self._knn_model_trained(ivf_model, headers=headers): - logger.info("Training of IVF index '%s' finished.", index) - - # Delete temporary training index - self.client.indices.delete(index=f".{index}_ivf_training", headers=headers) - - # Clone original index to temporary one - self.client.indices.add_block(index=index, block="read_only") - self.client.indices.clone( - index=index, target=f".{index}_temp", body={"settings": {"index": {"blocks": {"read_only": False}}}} - ) - self.client.indices.put_settings(index=index, body={"index": {"blocks": {"read_only": False}}}) - self.client.indices.delete(index=index) - - # Reindex original index to newly created IVF index - self._create_document_index(index_name=index, headers=headers) - self.client.reindex( - body={"source": {"index": f".{index}_temp"}, "dest": {"index": index}}, - params={"request_timeout": 24 * 60 * 60}, - ) - self.client.indices.delete(index=f".{index}_temp") - - def _recommended_ivf_train_size(self) -> int: - """ - Calculates the minimum recommended number of training samples for IVF training as suggested in FAISS docs. - https://github.com/facebookresearch/faiss/wiki/FAQ#can-i-ignore-warning-clustering-xxx-points-to-yyy-centroids - """ - min_points_per_cluster = 39 - if self.index_type == "ivf": - n_clusters = self.knn_parameters.get("nlist", 4) - return n_clusters * min_points_per_cluster - elif self.index_type == "ivf_pq": - n_clusters = 2 ** self.knn_parameters.get("code_size", 8) - return n_clusters * min_points_per_cluster - else: - raise DocumentStoreError(f"Invalid index type '{self.index_type}'.") - - @retry(retry=retry_if_not_result(bool), wait=wait_exponential(min=1, max=10)) - def _knn_model_trained(self, model_name: str, headers: Optional[Dict[str, str]] = None) -> bool: - model_state_endpoint = f"/_plugins/_knn/models/{model_name}" - response = self.client.transport.perform_request("GET", url=model_state_endpoint, headers=headers) - model_state = response["state"] - if model_state == "created": - return True - elif model_state == "failed": - error_message = response["error"] - raise DocumentStoreError(f"Failed to train the KNN model. Error message: {error_message}") - - return False - - def _get_ef_search_value(self) -> int: - ef_search = 20 if "ef_search" not in self.knn_parameters else self.knn_parameters["ef_search"] - return ef_search - - def _index_delete(self, index: str): - if self._index_exists(index): - self.client.indices.delete(index=index, ignore=[400, 404]) - self._delete_ivf_model(index) - logger.info("Index '%s' deleted.", index) - - def _delete_ivf_model(self, index: str): - """ - If index is an index of type 'ivf' or 'ivf_pq', this method deletes the corresponding IVF model. - """ - if self._index_exists(".opensearch-knn-models"): - response = self.client.transport.perform_request("GET", "/_plugins/_knn/models/_search") - existing_ivf_models = {model["_source"]["model_id"] for model in response["hits"]["hits"]} - if f"{index}-ivf" in existing_ivf_models: - self.client.transport.perform_request("DELETE", f"/_plugins/_knn/models/{index}-ivf") - - def clone_embedding_field( - self, - new_embedding_field: str, - similarity: str, - batch_size: int = 10_000, - knn_engine: Optional[str] = None, - index_type: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - if knn_engine is None: - knn_engine = self.knn_engine - - mapping = self.client.indices.get(self.index, headers=headers)[self.index]["mappings"] - if new_embedding_field in mapping["properties"]: - raise DocumentStoreError( - f"{new_embedding_field} already exists with mapping {mapping['properties'][new_embedding_field]}" - ) - - space_type = SIMILARITY_SPACE_TYPE_MAPPINGS[knn_engine][similarity] - mapping["properties"][new_embedding_field] = self._get_embedding_field_mapping( - space_type=space_type, knn_engine=knn_engine, index_type=index_type - ) - self.client.indices.put_mapping(index=self.index, body=mapping, headers=headers) - - document_count = self.get_document_count(headers=headers) - result = self._get_all_documents_in_index(index=self.index, batch_size=batch_size, headers=headers) - - opensearch_logger = logging.getLogger("opensearch") - original_log_level = opensearch_logger.getEffectiveLevel() - try: - opensearch_logger.setLevel(logging.CRITICAL) - with tqdm(total=document_count, position=0, unit=" Docs", desc="Cloning embeddings") as progress_bar: - for result_batch in get_batches_from_generator(result, batch_size): - document_batch = [self._convert_es_hit_to_document(hit) for hit in result_batch] - doc_updates = [] - for doc in document_batch: - if doc.embedding is not None: - update = { - "_op_type": "update", - "_index": self.index, - "_id": doc.id, - "doc": {new_embedding_field: doc.embedding.tolist()}, - } - doc_updates.append(update) - - bulk(self.client, doc_updates, refresh=self.refresh_type, headers=headers) - progress_bar.update(batch_size) - finally: - opensearch_logger.setLevel(original_log_level) - - def get_metadata_values_by_key( - self, - key: str, - query: Optional[str] = None, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[dict]: - """ - Get values associated with a metadata key. The output is in the format: - [{"value": "my-value-1", "count": 23}, {"value": "my-value-2", "count": 12}, ... ] - - :param key: The meta key name to get the values for. - :param query: Narrow down the scope to documents matching the query string. - :param filters: Narrow down the scope to documents matching the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param index: The search index to search for the meta values. If not supplied, - self.index is used. - :param headers: Custom HTTP headers to pass to the client (for example, {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html) for more information. - """ - body: dict = { - "size": 0, - "aggs": {"metadata_agg": {"composite": {"sources": [{key: {"terms": {"field": key}}}]}}}, - } - if query: - body["query"] = { - "bool": { - "should": [{"multi_match": {"query": query, "type": "most_fields", "fields": self.search_fields}}] - } - } - if filters: - if not body.get("query"): - body["query"] = {"bool": {}} - body["query"]["bool"].update({"filter": LogicalFilterClause.parse(filters).convert_to_elasticsearch()}) - result = self.client.search(body=body, index=index, headers=headers) - - values = [] - current_buckets = result["aggregations"]["metadata_agg"]["buckets"] - after_key = result["aggregations"]["metadata_agg"].get("after_key", False) - for bucket in current_buckets: - values.append({"value": bucket["key"][key], "count": bucket["doc_count"]}) - - # Only 10 results get returned at a time, so apply pagination - while after_key: - body["aggs"]["metadata_agg"]["composite"]["after"] = after_key - result = self.client.search(body=body, index=index, headers=headers) - current_buckets = result["aggregations"]["metadata_agg"]["buckets"] - after_key = result["aggregations"]["metadata_agg"].get("after_key", False) - for bucket in current_buckets: - values.append({"value": bucket["key"][key], "count": bucket["doc_count"]}) - - return values - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Fetch documents by specifying a list of text ID strings. - - :param ids: List of document IDs. Be aware that passing a large number of IDs might lead to performance issues. - :param index: The search index where the documents are stored. If not supplied, - self.index is used. - :param batch_size: Maximum number of results for each query. - Limited to 10,000 documents by default. - To reduce the pressure on the cluster, you can lower this limit at the expense - of longer retrieval times. - :param headers: Custom HTTP headers to pass to the client (for example, {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html) for more information. - """ - index = index or self.index - documents = [] - for i in range(0, len(ids), batch_size): - ids_for_batch = ids[i : i + batch_size] - query = {"size": len(ids_for_batch), "query": {"ids": {"values": ids_for_batch}}} - if not self.return_embedding and self.embedding_field: - query["_source"] = {"excludes": [self.embedding_field]} - result = self.client.search(index=index, body=query, headers=headers)["hits"]["hits"] - documents.extend([self._convert_es_hit_to_document(hit) for hit in result]) - return documents - - def update_document_meta( - self, id: str, meta: Dict[str, str], index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ): - """ - Update the metadata dictionary of a document by specifying its ID string. - """ - if not index: - index = self.index - body = {"doc": meta} - self.client.update(index=index, id=id, body=body, refresh=self.refresh_type, headers=headers) diff --git a/haystack/document_stores/pinecone.py b/haystack/document_stores/pinecone.py deleted file mode 100644 index 33da45f1f2..0000000000 --- a/haystack/document_stores/pinecone.py +++ /dev/null @@ -1,1854 +0,0 @@ -import copy -import json -import logging -import operator -from copy import deepcopy -from datetime import datetime -from functools import reduce -from itertools import islice -from typing import Any, Dict, Generator, List, Literal, Optional, Set, Union - -import numpy as np -from tqdm import tqdm - -from haystack.document_stores import BaseDocumentStore -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.errors import DuplicateDocumentError, PineconeDocumentStoreError -from haystack.lazy_imports import LazyImport -from haystack.nodes.retriever import DenseRetriever -from haystack.schema import LABEL_DATETIME_FORMAT, Answer, Document, FilterType, Label, Span -from haystack.utils.batching import get_batches_from_generator - -with LazyImport("Run 'pip install farm-haystack[pinecone]'") as pinecone_import: - import pinecone - -logger = logging.getLogger(__name__) - -TYPE_METADATA_FIELD = "doc_type" -DOCUMENT_WITH_EMBEDDING = "vector" -DOCUMENT_WITHOUT_EMBEDDING = "no-vector" -LABEL = "label" - -AND_OPERATOR = "$and" -IN_OPERATOR = "$in" -EQ_OPERATOR = "$eq" - -DEFAULT_BATCH_SIZE = 128 - -PINECONE_STARTER_POD = "starter" - -DocTypeMetadata = Literal["vector", "no-vector", "label"] - - -def _sanitize_index(index: Optional[str]) -> Optional[str]: - if index: - return index.replace("_", "-").lower() - return None - - -def _get_by_path(root, items): - """Access a nested object in root by item sequence.""" - return reduce(operator.getitem, items, root) - - -def _set_by_path(root, items, value): - """Set a value in a nested object in root by item sequence.""" - _get_by_path(root, items[:-1])[items[-1]] = value - - -class PineconeDocumentStore(BaseDocumentStore): - """ - Document store for very large scale embedding based dense retrievers like the DPR. This is a hosted document store, - this means that your vectors will not be stored locally but in the cloud. This means that the similarity - search will be run on the cloud as well. - - It implements the Pinecone vector database ([https://www.pinecone.io](https://www.pinecone.io)) - to perform similarity search on vectors. In order to use this document store, you need an API key that you can - obtain by creating an account on the [Pinecone website](https://www.pinecone.io). - - The document text is stored using the SQLDocumentStore, while - the vector embeddings and metadata (for filtering) are indexed in a Pinecone Index. - """ - - top_k_limit = 10_000 - top_k_limit_vectors = 1_000 - - def __init__( - self, - api_key: str, - environment: str = "us-west1-gcp", - pinecone_index: Optional["pinecone.Index"] = None, - embedding_dim: int = 768, - return_embedding: bool = False, - index: str = "document", - similarity: str = "cosine", - replicas: int = 1, - shards: int = 1, - namespace: Optional[str] = None, - embedding_field: str = "embedding", - progress_bar: bool = True, - duplicate_documents: str = "overwrite", - recreate_index: bool = False, - metadata_config: Optional[Dict] = None, - validate_index_sync: bool = True, - ): - """ - :param api_key: Pinecone vector database API key ([https://app.pinecone.io](https://app.pinecone.io)). - :param environment: Pinecone cloud environment uses `"us-west1-gcp"` by default. Other GCP and AWS - regions are supported, contact Pinecone [here](https://www.pinecone.io/contact/) if required. - :param pinecone_index: pinecone-client Index object, an index will be initialized or loaded if not specified. - :param embedding_dim: The embedding vector size. - :param return_embedding: Whether to return document embeddings. - :param index: Name of index in document store to use. - :param similarity: The similarity function used to compare document vectors. `"cosine"` is the default - and is recommended if you are using a Sentence-Transformer model. `"dot_product"` is more performant - with DPR embeddings. - In both cases, the returned values in Document.score are normalized to be in range [0,1]: - - For `"dot_product"`: `expit(np.asarray(raw_score / 100))` - - For `"cosine"`: `(raw_score + 1) / 2` - :param replicas: The number of replicas. Replicas duplicate the index. They provide higher availability and - throughput. - :param shards: The number of shards to be used in the index. We recommend to use 1 shard per 1GB of data. - :param namespace: Optional namespace. If not specified, None is default. - :param embedding_field: Name of field containing an embedding vector. - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param duplicate_documents: Handle duplicate documents based on parameter options.\ - Parameter options: - - `"skip"`: Ignore the duplicate documents. - - `"overwrite"`: Update any existing documents with the same ID when adding documents. - - `"fail"`: An error is raised if the document ID of the document being added already exists. - :param recreate_index: If set to True, an existing Pinecone index will be deleted and a new one will be - created using the config you are using for initialization. Be aware that all data in the old index will be - lost if you choose to recreate the index. Be aware that both the document_index and the label_index will - be recreated. - :param metadata_config: Which metadata fields should be indexed, part of the - [selective metadata filtering](https://www.pinecone.io/docs/manage-indexes/#selective-metadata-indexing) feature. - Should be in the format `{"indexed": ["metadata-field-1", "metadata-field-2", "metadata-field-n"]}`. By default, - no fields are indexed. - """ - pinecone_import.check() - if metadata_config is None: - metadata_config = {"indexed": []} - # Connect to Pinecone server using python client binding - if not api_key: - raise PineconeDocumentStoreError( - "Pinecone requires an API key, please provide one. https://app.pinecone.io" - ) - - pinecone.init(api_key=api_key, environment=environment) - self._api_key = api_key - - # Formal similarity string - self._set_similarity_metric(similarity) - - self.similarity = similarity - self.index: str = self._index(index) - self.embedding_dim = embedding_dim - self.return_embedding = return_embedding - self.embedding_field = embedding_field - self.progress_bar = progress_bar - self.duplicate_documents = duplicate_documents - - # Pinecone index params - self.replicas = replicas - self.shards = shards - self.namespace = namespace - - # Add necessary metadata fields to metadata_config - fields = ["label-id", "query", TYPE_METADATA_FIELD] - metadata_config["indexed"] += fields - self.metadata_config = metadata_config - - # Initialize dictionary of index connections - self.pinecone_indexes: Dict[str, pinecone.Index] = {} - self.return_embedding = return_embedding - self.embedding_field = embedding_field - - # Initialize dictionary to store temporary set of document IDs - self.all_ids: dict = {} - - # Dummy query to be used during searches - self.dummy_query = [0.0] * self.embedding_dim - - if pinecone_index: - if not isinstance(pinecone_index, pinecone.Index): - raise PineconeDocumentStoreError( - f"The parameter `pinecone_index` needs to be a " - f"`pinecone.Index` object. You provided an object of " - f"type `{type(pinecone_index)}`." - ) - self.pinecone_indexes[self.index] = pinecone_index - else: - self.pinecone_indexes[self.index] = self._create_index( - embedding_dim=self.embedding_dim, - index=self.index, - metric_type=self.metric_type, - replicas=self.replicas, - shards=self.shards, - recreate_index=recreate_index, - metadata_config=self.metadata_config, - ) - - super().__init__() - - def _index(self, index) -> str: - index = _sanitize_index(index) or self.index - return index - - def _create_index( - self, - embedding_dim: int, - index: Optional[str] = None, - metric_type: Optional[str] = "cosine", - replicas: Optional[int] = 1, - shards: Optional[int] = 1, - recreate_index: bool = False, - metadata_config: Optional[Dict] = None, - ) -> "pinecone.Index": - """ - Create a new index for storing documents in case an index with the name - doesn't exist already. - """ - if metadata_config is None: - metadata_config = {"indexed": []} - - if recreate_index: - self.delete_index(index) - - # Skip if already exists - if index in self.pinecone_indexes: - index_connection = self.pinecone_indexes[index] - else: - # Search pinecone hosted indexes and create an index if it does not exist - if index not in pinecone.list_indexes(): - pinecone.create_index( - name=index, - dimension=embedding_dim, - metric=metric_type, - replicas=replicas, - shards=shards, - metadata_config=metadata_config, - ) - index_connection = pinecone.Index(index) - - # Get index statistics - stats = index_connection.describe_index_stats() - dims = stats["dimension"] - count = stats["namespaces"][""]["vector_count"] if stats["namespaces"].get("") else 0 - logger.info("Index statistics: name: %s embedding dimensions: %s, record count: %s", index, dims, count) - - # return index connection - return index_connection - - def _index_connection_exists(self, index: str, create: bool = False) -> Optional["pinecone.Index"]: - """ - Check if the index connection exists. If specified, create an index if it does not exist yet. - - :param index: Index name. - :param create: Indicates if an index needs to be created or not. If set to `True`, create an index - and return connection to it, otherwise raise `PineconeDocumentStoreError` error. - :raises PineconeDocumentStoreError: Exception trigger when index connection not found. - """ - if index not in self.pinecone_indexes: - if create: - return self._create_index( - embedding_dim=self.embedding_dim, - index=index, - metric_type=self.metric_type, - replicas=self.replicas, - shards=self.shards, - recreate_index=False, - metadata_config=self.metadata_config, - ) - raise PineconeDocumentStoreError( - f"Index named '{index}' does not exist. Try reinitializing PineconeDocumentStore() and running " - f"'update_embeddings()' to create and populate an index." - ) - return None - - def _set_similarity_metric(self, similarity: str): - """ - Set vector similarity metric. - """ - if similarity == "cosine": - self.metric_type = similarity - elif similarity == "dot_product": - self.metric_type = "dotproduct" - elif similarity in ["l2", "euclidean"]: - self.metric_type = "euclidean" - else: - raise ValueError( - "The Pinecone document store can currently only support dot_product, cosine and euclidean metrics. " - "Please set similarity to one of the above." - ) - - def _add_local_ids(self, index: str, ids: List[str]): - """ - Add all document IDs to the set of all IDs. - """ - if index not in self.all_ids: - self.all_ids[index] = set() - self.all_ids[index] = self.all_ids[index].union(set(ids)) - - def _add_type_metadata_filter(self, filters: FilterType, type_value: Optional[DocTypeMetadata]) -> FilterType: - """ - Add new filter for `doc_type` metadata field. - """ - all_filters = deepcopy(filters) - if type_value: - new_type_filter = {TYPE_METADATA_FIELD: {EQ_OPERATOR: type_value}} - if AND_OPERATOR not in all_filters and TYPE_METADATA_FIELD not in all_filters: - # extend filters with new `doc_type` filter and add $and operator - all_filters.update(new_type_filter) - return {AND_OPERATOR: all_filters} - - filters_content = all_filters[AND_OPERATOR] if AND_OPERATOR in all_filters else all_filters - if TYPE_METADATA_FIELD in filters_content: # type: ignore - current_type_filter = filters_content[TYPE_METADATA_FIELD] # type: ignore - type_values = {type_value} - if isinstance(current_type_filter, str): - type_values.add(current_type_filter) # type: ignore - elif isinstance(current_type_filter, dict): - if EQ_OPERATOR in current_type_filter: - # current `doc_type` filter has single value - type_values.add(current_type_filter[EQ_OPERATOR]) - else: - # current `doc_type` filter has multiple values - type_values.update(set(current_type_filter[IN_OPERATOR])) - new_type_filter = {TYPE_METADATA_FIELD: {IN_OPERATOR: list(type_values)}} # type: ignore - filters_content.update(new_type_filter) # type: ignore - - return all_filters - - def _remove_type_metadata_filter(self, filters: FilterType) -> FilterType: - """ - Remove filter for `doc_type` metadata field if it exists. - """ - all_filters = deepcopy(filters) - for key, value in all_filters.copy().items(): - if key == TYPE_METADATA_FIELD: - del all_filters[key] - elif isinstance(value, dict): - all_filters[key] = self._remove_type_metadata_filter(filters=value) - return all_filters - - def _get_default_type_metadata(self, index: Optional[str], namespace: Optional[str] = None) -> str: - """ - Get default value for `doc_type` metadata filed. If there is at least one embedding, default value - will be `vector`, otherwise it will be `no-vector`. - """ - if self.get_embedding_count(index=index, namespace=namespace) > 0: - return DOCUMENT_WITH_EMBEDDING - return DOCUMENT_WITHOUT_EMBEDDING - - def _get_vector_count( - self, index: str, filters: Optional[FilterType], namespace: Optional[str], types_metadata: Set[DocTypeMetadata] - ) -> int: - index = self._index(index) - self._index_connection_exists(index) - pinecone_index = self.pinecone_indexes[index] - - filters = filters or {} - for type_value in types_metadata: - # add filter for each `doc_type` metadata value - filters = self._add_type_metadata_filter(filters, type_value) - - pinecone_syntax_filter = LogicalFilterClause.parse(filters).convert_to_pinecone() if filters else None - - if pinecone.describe_index(index).pod_type != PINECONE_STARTER_POD: - stats = pinecone_index.describe_index_stats(filter=pinecone_syntax_filter) - namespaces = stats["namespaces"] - if namespace is None and namespace not in namespaces: - namespace = "" - return namespaces[namespace]["vector_count"] if namespace in namespaces else 0 - - # Due to missing support for metadata filtering in `describe_index_stats()` method for `gcp-starter`, - # use dummy query for getting vector count - res = self.pinecone_indexes[index].query( - self.dummy_query, - top_k=self.top_k_limit, - include_values=False, - include_metadata=False, - filter=pinecone_syntax_filter, - ) - vector_count = len(res["matches"]) - if vector_count >= self.top_k_limit: - logger.warning( - "Current index type 'Starter' doesn't support features 'Namespace' and metadata filtering as part of describe_index_stats operation. " - "Limit for fetching documents in 'Starter' index type is %s.", - self.top_k_limit, - ) - return vector_count - - def _delete_vectors(self, index: str, ids: List[str], namespace: Optional[str]) -> None: - batch_size = self.top_k_limit_vectors - for id_batch in get_batches_from_generator(ids, batch_size): - self.pinecone_indexes[index].delete(ids=list(id_batch), namespace=namespace) - - def get_document_count( - self, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - namespace: Optional[str] = None, - type_metadata: Optional[DocTypeMetadata] = None, - ) -> int: - """ - Return the count of documents in the document store. - - :param filters: Optional filters to narrow down the documents which will be counted. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`), or a metadata field name. - Logical operator keys take a dictionary of metadata field names or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param index: Optional index name to use for the query. If not provided, the default index name is used. - :param only_documents_without_embedding: If set to `True`, only documents without embeddings are counted. - :param headers: PineconeDocumentStore does not support headers. - :param namespace: Optional namespace to count documents from. If not specified, None is default. - :param type_metadata: Optional value for `doc_type` metadata to reference documents that need to be counted. - Parameter options: - - `"vector"`: Documents with embedding. - - `"no-vector"`: Documents without embedding (dummy embedding only). - - `"label"`: Labels. - """ - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - # add `doc_type` value if specified - if type_metadata: - types_metadata = {type_metadata} - # otherwise add default `doc_type` value which is related to documents without embeddings, - # but only if `doc_type` doesn't already exist in filters - elif TYPE_METADATA_FIELD not in str(filters): - types_metadata = {DOCUMENT_WITHOUT_EMBEDDING} # type: ignore - if not only_documents_without_embedding: - # add `doc_type` related to documents with embeddings - types_metadata.add(DOCUMENT_WITH_EMBEDDING) # type: ignore - else: - types_metadata = set() - - return self._get_vector_count(index, filters=filters, namespace=namespace, types_metadata=types_metadata) # type: ignore - - def get_embedding_count( - self, filters: Optional[FilterType] = None, index: Optional[str] = None, namespace: Optional[str] = None - ) -> int: - """ - Return the count of embeddings in the document store. - - :param index: Optional index name to retrieve all documents from. - :param filters: Optional filters to narrow down the documents with embedding which - will be counted. Filters are defined as nested dictionaries. The keys of the dictionaries - can be a logical operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, - `"$in"`, `"$gt"`, `"$gte"`, `"$lt"`, `"$lte"`), or a metadata field name. - Logical operator keys take a dictionary of metadata field names or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param namespace: Optional namespace to count embeddings from. If not specified, None is default. - """ - # drop filter for `doc_type` if exists - if TYPE_METADATA_FIELD in str(filters): - filters = self._remove_type_metadata_filter(filters) # type: ignore - return self._get_vector_count( - index, filters=filters, namespace=namespace, types_metadata={DOCUMENT_WITH_EMBEDDING} # type: ignore - ) - - def _validate_index_sync(self, index: Optional[str] = None): - """ - This check ensures the correct number of documents with embeddings and embeddings are found in the - Pinecone database. - """ - if self.get_document_count( - index=index, type_metadata=DOCUMENT_WITH_EMBEDDING # type: ignore - ) != self.get_embedding_count(index=index): - raise PineconeDocumentStoreError( - f"The number of documents present in Pinecone ({self.get_document_count(index=index)}) " - "does not match the number of embeddings in Pinecone " - f" ({self.get_embedding_count(index=index)}). This can happen if a document store " - "instance is deleted during write operations. Call " - "the `update_documents` method to fix it." - ) - - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - labels: Optional[bool] = False, - namespace: Optional[str] = None, - ): - """ - Add new documents to the DocumentStore. - - :param documents: List of `Dicts` or list of `Documents`. If they already contain embeddings, we'll index them - right away in Pinecone. If not, you can later call `update_embeddings()` to create & index them. - :param index: Index name for storing the docs and metadata. - :param batch_size: Number of documents to process at a time. When working with large number of documents, - batching can help to reduce the memory footprint. - :param duplicate_documents: handle duplicate documents based on parameter options. - Parameter options: - - `"skip"`: Ignore the duplicate documents. - - `"overwrite"`: Update any existing documents with the same ID when adding documents. - - `"fail"`: An error is raised if the document ID of the document being added already exists. - :param headers: PineconeDocumentStore does not support headers. - :param labels: Tells us whether these records are labels or not. Defaults to False. - :param namespace: Optional namespace to write documents to. If not specified, None is default. - :raises DuplicateDocumentError: Exception trigger on duplicate document. - """ - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - index = self._index(index) - duplicate_documents = duplicate_documents or self.duplicate_documents - assert ( - duplicate_documents in self.duplicate_documents_options - ), f"duplicate_documents parameter must be {', '.join(self.duplicate_documents_options)}" - - index_connection = self._index_connection_exists(index, create=True) - if index_connection: - self.pinecone_indexes[index] = index_connection - - field_map = self._create_document_field_map() - document_objects = [ - Document.from_dict(doc, field_map=field_map) if isinstance(doc, dict) else doc for doc in documents - ] - document_objects = self._handle_duplicate_documents( - documents=document_objects, index=index, duplicate_documents=duplicate_documents - ) - if document_objects: - add_vectors = document_objects[0].embedding is not None - # If these are not labels, we need to find the correct value for `doc_type` metadata field - if not labels: - type_metadata = DOCUMENT_WITH_EMBEDDING if add_vectors else DOCUMENT_WITHOUT_EMBEDDING - else: - type_metadata = LABEL - if not add_vectors: - # To store documents in Pinecone, we use dummy embeddings (to be replaced with real embeddings later) - embeddings_to_index = np.zeros((batch_size, self.embedding_dim), dtype="float32") - # Convert embeddings to list objects - embeddings = [embed.tolist() if embed is not None else None for embed in embeddings_to_index] - - with tqdm( - total=len(document_objects), disable=not self.progress_bar, position=0, desc="Writing Documents" - ) as progress_bar: - for document_batch in get_batches_from_generator(document_objects, batch_size): - document_batch = list(document_batch) - document_batch_copy = deepcopy(document_batch) - ids = [doc.id for doc in document_batch] - # If duplicate_documents set to `skip` or `fail`, we need to check for existing documents - if duplicate_documents in ["skip", "fail"]: - existing_documents = self.get_documents_by_id( - ids=ids, index=index, namespace=namespace, include_type_metadata=True - ) - # First check for documents in current batch that exist in the index - if existing_documents: - if duplicate_documents == "skip": - # If we should skip existing documents, we drop the ids that already exist - skip_ids = [doc.id for doc in existing_documents] - # We need to drop the affected document objects from the batch - document_batch = [doc for doc in document_batch if doc.id not in skip_ids] - # Now rebuild the ID list - ids = [doc.id for doc in document_batch] - progress_bar.update(len(skip_ids)) - elif duplicate_documents == "fail": - # Otherwise, we raise an error - raise DuplicateDocumentError( - f"Document ID {existing_documents[0].id} already exists in index {index}" - ) - # Now check for duplicate documents within the batch itself - if len(ids) != len(set(ids)): - if duplicate_documents == "skip": - # We just keep the first instance of each duplicate document - ids = [] - temp_document_batch = [] - for doc in document_batch: - if doc.id not in ids: - ids.append(doc.id) - temp_document_batch.append(doc) - document_batch = temp_document_batch - elif duplicate_documents == "fail": - # Otherwise, we raise an error - raise DuplicateDocumentError(f"Duplicate document IDs found in batch: {ids}") - metadata = [ - self._meta_for_pinecone( - { - TYPE_METADATA_FIELD: type_metadata, # add `doc_type` in metadata - "content": doc.content, - "content_type": doc.content_type, - **doc.meta, - } - ) - for doc in document_batch_copy - ] - if add_vectors: - embeddings = [doc.embedding for doc in document_batch_copy] - embeddings_to_index = np.array(embeddings, dtype="float32") - if self.similarity == "cosine": - # Normalize embeddings inplace - self.normalize_embedding(embeddings_to_index) - # Convert embeddings to list objects - embeddings = [embed.tolist() if embed is not None else None for embed in embeddings_to_index] - data_to_write_to_pinecone = zip(ids, embeddings, metadata) - # Metadata fields and embeddings are stored in Pinecone - self.pinecone_indexes[index].upsert(vectors=data_to_write_to_pinecone, namespace=namespace) - # Add IDs to ID list - self._add_local_ids(index, ids) - progress_bar.update(batch_size) - progress_bar.close() - - def _create_document_field_map(self) -> Dict: - return {self.embedding_field: "embedding"} - - def update_embeddings( - self, - retriever: DenseRetriever, - index: Optional[str] = None, - update_existing_embeddings: bool = True, - filters: Optional[FilterType] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - namespace: Optional[str] = None, - ): - """ - Updates the embeddings in the document store using the encoding model specified in the retriever. - This can be useful if you want to add or change the embeddings for your documents (e.g. after changing the - retriever config). - - :param retriever: Retriever to use to get embeddings for text. - :param index: Index name for which embeddings are to be updated. If set to `None`, the default `self.index` is - used. - :param update_existing_embeddings: Whether to update existing embeddings of the documents. If set to `False`, - only documents without embeddings are processed. This mode can be used for incremental updating of - embeddings, wherein, only newly indexed documents get processed. - :param filters: Optional filters to narrow down the documents for which embeddings are to be updated. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param batch_size: Number of documents to process at a time. When working with large number of documents, - batching can help reduce memory footprint. - :param namespace: Optional namespace to retrieve document from. If not specified, None is default. - """ - index = self._index(index) - if index not in self.pinecone_indexes: - raise ValueError( - f"Couldn't find a the index '{index}' in Pinecone. Try to init the " - f"PineconeDocumentStore() again ..." - ) - document_count = self.get_document_count( - index=index, - filters=filters, - only_documents_without_embedding=not update_existing_embeddings, - namespace=namespace, - ) - if document_count == 0: - logger.warning("Calling DocumentStore.update_embeddings() on an empty index") - return - - logger.info("Updating embeddings for %s docs...", document_count) - - # If embeddings don't exist or the user doesn't want to update existing embeddings, update dummy embeddings - if self.get_embedding_count(index=index) == 0 or not update_existing_embeddings: - type_value = DOCUMENT_WITHOUT_EMBEDDING - else: - type_value = DOCUMENT_WITH_EMBEDDING - - documents = self.get_all_documents_generator( - index=index, - type_metadata=type_value, # type: ignore - filters=filters, - return_embedding=False, - batch_size=batch_size, - namespace=namespace, - include_type_metadata=True, - ) - - with tqdm( - total=document_count, disable=not self.progress_bar, position=0, unit=" docs", desc="Updating Embedding" - ) as progress_bar: - for _ in range(0, document_count, batch_size): - document_batch = list(islice(documents, batch_size)) - embeddings = retriever.embed_documents(document_batch) - if embeddings.size == 0: - # Skip batch if there are no embeddings. Otherwise, incorrect embedding shape will be inferred and - # Pinecone APi will return a "No vectors provided" Bad Request Error - progress_bar.set_description_str("Documents Processed") - progress_bar.update(batch_size) - continue - self._validate_embeddings_shape( - embeddings=embeddings, num_documents=len(document_batch), embedding_dim=self.embedding_dim - ) - - if self.similarity == "cosine": - self.normalize_embedding(embeddings) - - metadata = [] - ids = [] - for doc in document_batch: - metadata.append( - self._meta_for_pinecone( - { - "content": doc.content, - "content_type": doc.content_type, - **doc.meta, - # set `doc_type` metadata field to `vector` since the dummy embedding is updated - TYPE_METADATA_FIELD: DOCUMENT_WITH_EMBEDDING, - } - ) - ) - ids.append(doc.id) - # Update existing vectors in pinecone index - self.pinecone_indexes[index].upsert( - vectors=zip(ids, embeddings.tolist(), metadata), namespace=namespace - ) - # Add these vector IDs to local store - self._add_local_ids(index, ids) - progress_bar.set_description_str("Documents Processed") - progress_bar.update(batch_size) - - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - headers: Optional[Dict[str, str]] = None, - type_metadata: Optional[DocTypeMetadata] = None, - namespace: Optional[str] = None, - ) -> List[Document]: - """ - Retrieves all documents in the index. - - :param index: Optional index name to retrieve all documents from. - :param filters: Optional filters to narrow down the documents that will be retrieved. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Optional flag to return the embedding of the document. - :param batch_size: Number of documents to process at a time. When working with large number of documents, - batching can help reduce memory footprint. - :param headers: Pinecone does not support headers. - :param type_metadata: Value of `doc_type` metadata that indicates which documents need to be retrieved. - :param namespace: Optional namespace to retrieve documents from. If not specified, None is default. - """ - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - if not type_metadata and TYPE_METADATA_FIELD not in str(filters): - # set default value for `doc_type` metadata field - type_metadata = self._get_default_type_metadata(index, namespace) # type: ignore - - result = self.get_all_documents_generator( - index=index, - type_metadata=type_metadata, - filters=filters, - return_embedding=return_embedding, - batch_size=batch_size, - namespace=namespace, - ) - documents: List[Document] = list(result) - return documents - - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - headers: Optional[Dict[str, str]] = None, - namespace: Optional[str] = None, - type_metadata: Optional[DocTypeMetadata] = None, - include_type_metadata: Optional[bool] = False, - ) -> Generator[Document, None, None]: - """ - Get all documents from the document store. Under-the-hood, documents are fetched in batches from the - document store and yielded as individual documents. This method can be used to iteratively process - a large number of documents without having to load all documents in memory. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the documents for which embeddings are to be updated. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param headers: PineconeDocumentStore does not support headers. - :param namespace: Optional namespace to retrieve document from. If not specified, None is default. - :param type_metadata: Value of `doc_type` metadata that indicates which documents need to be retrieved. - :param include_type_metadata: Indicates if `doc_type` value will be included in document metadata or not. - If not specified, `doc_type` field will be dropped from document metadata. - """ - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - if return_embedding is None: - return_embedding = self.return_embedding - - index = self._index(index) - self._index_connection_exists(index) - - if not type_metadata and TYPE_METADATA_FIELD not in str(filters): - # set default value for `doc_type` metadata field - type_metadata = self._get_default_type_metadata(index, namespace) # type: ignore - - ids = self._get_all_document_ids( - index=index, type_metadata=type_metadata, filters=filters, namespace=namespace, batch_size=batch_size - ) - - if filters is not None and not ids: - logger.warning( - "This query might have been done without metadata indexed and thus no DOCUMENTS were retrieved. " - "Make sure the desired metadata you want to filter with is indexed." - ) - - for id_batch in get_batches_from_generator(ids, batch_size): - documents = self.get_documents_by_id( - ids=list(id_batch), - index=index, - batch_size=batch_size, - return_embedding=return_embedding, - namespace=namespace, - include_type_metadata=include_type_metadata, - ) - for doc in documents: - yield doc - - def _get_all_document_ids( - self, - index: Optional[str] = None, - type_metadata: Optional[DocTypeMetadata] = None, - filters: Optional[FilterType] = None, - namespace: Optional[str] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - ) -> List[str]: - index = self._index(index) - self._index_connection_exists(index) - - document_count = self.get_document_count( - index=index, namespace=namespace, type_metadata=type_metadata, filters=filters - ) - - if index not in self.all_ids: - self.all_ids[index] = set() - if len(self.all_ids[index]) == document_count and filters is None: - # We have all of the IDs and don't need to extract from Pinecone - return list(self.all_ids[index]) - else: - if pinecone.describe_index(index).pod_type == PINECONE_STARTER_POD: - # Due to missing support for Namespace in Starter Pinecone index type, retrieve up to 10000 vectors - logger.warning( - "Current index type 'Starter' doesn't support 'Namespace' feature. " - "Limit for fetching documents in 'Starter' index type is %s.", - self.top_k_limit, - ) - all_ids = self._get_ids( - index=index, filters=filters, type_metadata=type_metadata, batch_size=self.top_k_limit - ) - else: - # If we don't have all IDs, we must query and extract IDs from the original namespace, then move the - # retrieved documents to a temporary namespace and query again for new items. We repeat this process - # until all documents have been retrieved. - target_namespace = f"{namespace}-copy" if namespace is not None else "copy" - all_ids: Set[str] = set() # type: ignore - with tqdm( - total=document_count, disable=not self.progress_bar, position=0, unit=" ids", desc="Retrieving IDs" - ) as progress_bar: - while True: - # Retrieve IDs from Pinecone - vector_id_matrix = self._get_ids( - index=index, - namespace=namespace, - filters=filters, - type_metadata=type_metadata, - batch_size=batch_size, - ) - if not vector_id_matrix: - break - # Save IDs - unique_ids = set(vector_id_matrix) - all_ids = all_ids.union(unique_ids) # type: ignore - # Move these IDs to new namespace - self._move_documents_by_id_namespace( - ids=vector_id_matrix, - index=index, - source_namespace=namespace, - target_namespace=target_namespace, - batch_size=batch_size, - ) - progress_bar.set_description_str("Retrieved IDs") - progress_bar.update(len(unique_ids)) - - # Now move all documents back to source namespace - self._namespace_cleanup( - index=index, ids=list(all_ids), namespace=target_namespace, batch_size=batch_size - ) - - self._add_local_ids(index, list(all_ids)) - return list(all_ids) - - def _move_documents_by_id_namespace( - self, - ids: List[str], - index: Optional[str] = None, - source_namespace: Optional[str] = None, - target_namespace: Optional[str] = "copy", - batch_size: int = DEFAULT_BATCH_SIZE, - ): - index = self._index(index) - if index not in self.pinecone_indexes: - raise PineconeDocumentStoreError( - f"Index named '{index}' does not exist. Try reinitializing PineconeDocumentStore() and running " - f"'update_embeddings()' to create and populate an index." - ) - - if source_namespace == target_namespace: - raise PineconeDocumentStoreError( - f"Source namespace '{source_namespace}' cannot be the same as target namespace '{target_namespace}'." - ) - with tqdm( - total=len(ids), disable=not self.progress_bar, position=0, unit=" docs", desc="Moving Documents" - ) as progress_bar: - for id_batch in get_batches_from_generator(ids, batch_size): - id_batch = list(id_batch) - # Retrieve documents from source_namespace - result = self.pinecone_indexes[index].fetch(ids=id_batch, namespace=source_namespace) - vector_id_matrix = result["vectors"].keys() - meta_matrix = [result["vectors"][_id]["metadata"] for _id in vector_id_matrix] - embedding_matrix = [result["vectors"][_id]["values"] for _id in vector_id_matrix] - data_to_write_to_pinecone = list(zip(vector_id_matrix, embedding_matrix, meta_matrix)) - # Store metadata nd embeddings in new target_namespace - self.pinecone_indexes[index].upsert(vectors=data_to_write_to_pinecone, namespace=target_namespace) - # Delete vectors from source_namespace - self.delete_documents(index=index, ids=id_batch, namespace=source_namespace, drop_ids=False) - progress_bar.set_description_str("Documents Moved") - progress_bar.update(len(id_batch)) - - def _namespace_cleanup(self, index: str, ids: List[str], namespace: str, batch_size: int = DEFAULT_BATCH_SIZE): - """ - Shifts vectors back from "*-copy" namespace to the original namespace. - """ - with tqdm( - total=1, disable=not self.progress_bar, position=0, unit=" namespaces", desc="Cleaning Namespace" - ) as progress_bar: - target_namespace = namespace[:-5] if namespace != "copy" else None - for id_batch in get_batches_from_generator(ids, batch_size): - id_batch = list(id_batch) - if not id_batch: - break - self._move_documents_by_id_namespace( - ids=id_batch, - index=index, - source_namespace=namespace, - target_namespace=target_namespace, - batch_size=batch_size, - ) - progress_bar.set_description_str("Cleaned Namespace") - progress_bar.update(1) - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - headers: Optional[Dict[str, str]] = None, - return_embedding: Optional[bool] = None, - namespace: Optional[str] = None, - include_type_metadata: Optional[bool] = False, - ) -> List[Document]: - """ - Retrieves all documents in the index using their IDs. - - :param ids: List of IDs to retrieve. - :param index: Optional index name to retrieve all documents from. - :param batch_size: Number of documents to retrieve at a time. When working with large number of documents, - batching can help reduce memory footprint. - :param headers: Pinecone does not support headers. - :param return_embedding: Optional flag to return the embedding of the document. - :param namespace: Optional namespace to retrieve document from. If not specified, None is default. - :param include_type_metadata: Indicates if `doc_type` value will be included in document metadata or not. - If not specified, `doc_type` field will be dropped from document metadata. - """ - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - if return_embedding is None: - return_embedding = self.return_embedding - - index = self._index(index) - self._index_connection_exists(index) - - documents = [] - for id_batch in get_batches_from_generator(ids, batch_size): - result = self.pinecone_indexes[index].fetch(ids=list(id_batch), namespace=namespace) - - vector_id_matrix = [] - meta_matrix = [] - embedding_matrix = [] - for _id in result["vectors"]: - vector_id_matrix.append(_id) - metadata = result["vectors"][_id]["metadata"] - if not include_type_metadata and TYPE_METADATA_FIELD in metadata: - metadata.pop(TYPE_METADATA_FIELD) - meta_matrix.append(self._pinecone_meta_format(metadata)) - if return_embedding: - embedding_matrix.append(result["vectors"][_id]["values"]) - if return_embedding: - values = embedding_matrix - else: - values = None - document_batch = self._get_documents_by_meta( - vector_id_matrix, meta_matrix, values=values, index=index, return_embedding=return_embedding - ) - documents.extend(document_batch) - - return documents - - def get_document_by_id( - self, - id: str, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - return_embedding: Optional[bool] = None, - namespace: Optional[str] = None, - ) -> Document: - """ - Returns a single Document retrieved using an ID. - - :param id: ID string to retrieve. - :param index: Optional index name to retrieve all documents from. - :param headers: Pinecone does not support headers. - :param return_embedding: Optional flag to return the embedding of the document. - :param namespace: Optional namespace to retrieve document from. If not specified, None is default. - """ - documents = self.get_documents_by_id( - ids=[id], index=index, headers=headers, return_embedding=return_embedding, namespace=namespace - ) - return documents[0] - - def update_document_meta(self, id: str, meta: Dict[str, str], index: Optional[str] = None): - """ - Update the metadata dictionary of a document by specifying its string ID. - - :param id: ID of the Document to update. - :param meta: Dictionary of new metadata. - :param namespace: Optional namespace to update documents from. - :param index: Optional index name to update documents from. - """ - - index = self._index(index) - self._index_connection_exists(index) - - doc = self.get_document_by_id(id=id, index=index, return_embedding=True) - - if doc.embedding is not None: - meta = {"content": doc.content, "content_type": doc.content_type, **meta} - self.pinecone_indexes[index].upsert(vectors=[(id, doc.embedding.tolist(), meta)], namespace=self.namespace) - - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - drop_ids: Optional[bool] = True, - namespace: Optional[str] = None, - type_metadata: Optional[DocTypeMetadata] = None, - ): - """ - Delete documents from the document store. - - :param index: Index name to delete the documents from. If `None`, the DocumentStore's default index - name (`self.index`) will be used. - :param ids: Optional list of IDs to narrow down the documents to be deleted. - :param filters: Optional filters to narrow down the documents for which embeddings are to be updated. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param headers: PineconeDocumentStore does not support headers. - :param drop_ids: Specifies if the locally stored IDs should be deleted. The default is True. - :param namespace: Optional namespace. If not specified, None is default. - :param type_metadata: Optional value for `doc_type` metadata field as reference for documents to delete. - :return None: - """ - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - index = self._index(index) - self._index_connection_exists(index) - - if type_metadata: - # add filter for `doc_type` metadata field - filters = filters or {} - filters = self._add_type_metadata_filter(filters, type_metadata) - - pinecone_syntax_filter = LogicalFilterClause.parse(filters).convert_to_pinecone() if filters else None - - if index not in self.all_ids: - self.all_ids[index] = set() - if ids is None and pinecone_syntax_filter is None: - # If no filters or IDs we delete everything - self.pinecone_indexes[index].delete(delete_all=True, namespace=namespace) - id_values = list(self.all_ids[index]) - else: - id_values = ids or [] - if pinecone_syntax_filter: - # Extract IDs for all documents that satisfy given filters - doc_ids = self._get_all_document_ids(index=index, namespace=namespace, filters=filters) - # Extend the list of document IDs that should be deleted - id_values = list(set(id_values).union(set(doc_ids))) - if id_values: - self._delete_vectors(index, id_values, namespace) - - if drop_ids: - self.all_ids[index] = self.all_ids[index].difference(set(id_values)) - - def delete_index(self, index: Optional[str]): - """ - Delete an existing index. The index including all data will be removed. - - :param index: The name of the index to delete. - :return: None - """ - index = self._index(index) - - if index in pinecone.list_indexes(): - pinecone.delete_index(index) - logger.info("Index '%s' deleted.", index) - if index in self.pinecone_indexes: - del self.pinecone_indexes[index] - if index in self.all_ids: - self.all_ids[index] = set() - - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - namespace: Optional[str] = None, - type_metadata: Optional[DocTypeMetadata] = None, - ) -> List[Document]: - """ - Find the document that is most similar to the provided `query_emb` by using a vector similarity metric. - - :param query_emb: Embedding of the query (e.g. gathered from DPR). - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return. - :param index: The name of the index from which to retrieve documents. - :param return_embedding: Whether to return document embedding. - :param headers: PineconeDocumentStore does not support headers. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param namespace: Optional namespace to query document from. If not specified, None is default. - :param type_metadata: Value of `doc_type` metadata that indicates which documents need to be queried. - """ - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - if return_embedding is None: - return_embedding = self.return_embedding - self._limit_check(top_k, include_values=return_embedding) - - index = self._index(index) - self._index_connection_exists(index) - - query_emb = query_emb.astype(np.float32) - - if self.similarity == "cosine": - self.normalize_embedding(query_emb) - - # if `doc_type` metadata not set, set to documents with embeddings - if type_metadata is None: - type_metadata = DOCUMENT_WITH_EMBEDDING # type: ignore - - filters = filters or {} - filters = self._add_type_metadata_filter(filters, type_metadata) - - pinecone_syntax_filter = LogicalFilterClause.parse(filters).convert_to_pinecone() if filters else None - - res = self.pinecone_indexes[index].query( - query_emb.tolist(), - namespace=namespace, - top_k=top_k, - include_values=return_embedding, - include_metadata=True, - filter=pinecone_syntax_filter, - ) - - score_matrix = [] - vector_id_matrix = [] - meta_matrix = [] - embedding_matrix = [] - for match in res["matches"]: - score_matrix.append(match["score"]) - vector_id_matrix.append(match["id"]) - meta_matrix.append(match["metadata"]) - if return_embedding: - embedding_matrix.append(match["values"]) - if return_embedding: - values = embedding_matrix - else: - values = None - documents = self._get_documents_by_meta( - vector_id_matrix, meta_matrix, values=values, index=index, return_embedding=return_embedding - ) - - if filters is not None and not documents: - logger.warning( - "This query might have been done without metadata indexed and thus no results were retrieved. " - "Make sure the desired metadata you want to filter with is indexed." - ) - - # assign query score to each document - scores_for_vector_ids: Dict[str, float] = {str(v_id): s for v_id, s in zip(vector_id_matrix, score_matrix)} - return_documents = [] - for doc in documents: - score = scores_for_vector_ids[doc.id] - if scale_score: - score = self.scale_to_unit_interval(score, self.similarity) - doc.score = score - return_document = copy.copy(doc) - return_documents.append(return_document) - - return return_documents - - def _get_documents_by_meta( - self, - ids: List[str], - metadata: List[dict], - values: Optional[List[List[float]]] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - return_embedding: Optional[bool] = None, - ) -> List[Document]: - if headers: - raise NotImplementedError("PineconeDocumentStore does not support headers.") - - if return_embedding is None: - return_embedding = self.return_embedding - - index = self._index(index) - - # extract ID, content, and metadata to create Documents - documents = [] - for _id, meta in zip(ids, metadata): - content = meta.pop("content") - content_type = meta.pop("content_type") - if "_split_overlap" in meta: - meta["_split_overlap"] = json.loads(meta["_split_overlap"]) - doc = Document(id=_id, content=content, content_type=content_type, meta=meta) - documents.append(doc) - if return_embedding: - if values is None: - # If no embedding values are provided, we must request the embeddings from Pinecone - for doc in documents: - self._attach_embedding_to_document(document=doc, index=index) - else: - # If embedding values are given, we just add - for doc, embedding in zip(documents, values): - doc.embedding = np.asarray(embedding, dtype=np.float32) - - return documents - - def _attach_embedding_to_document(self, document: Document, index: str): - """ - Fetches the Document's embedding from the specified Pinecone index and attaches it to the Document's - embedding field. - """ - result = self.pinecone_indexes[index].fetch(ids=[document.id]) - if result["vectors"].get(document.id, False): - embedding = result["vectors"][document.id].get("values", None) - document.embedding = np.asarray(embedding, dtype=np.float32) - - def _limit_check(self, top_k: int, include_values: Optional[bool] = None): - """ - Confirms the top_k value does not exceed Pinecone vector database limits. - """ - if include_values: - if top_k > self.top_k_limit_vectors: - raise PineconeDocumentStoreError( - f"PineconeDocumentStore allows requests of no more than {self.top_k_limit_vectors} records " - f"when returning embedding values. This request is attempting to return {top_k} records." - ) - else: - if top_k > self.top_k_limit: - raise PineconeDocumentStoreError( - f"PineconeDocumentStore allows requests of no more than {self.top_k_limit} records. " - f"This request is attempting to return {top_k} records." - ) - - def _list_namespaces(self, index: str) -> List[str]: - """ - Returns a list of namespaces. - """ - res = self.pinecone_indexes[index].describe_index_stats() - namespaces = res["namespaces"].keys() - return namespaces - - def _check_exists(self, id: str, index: str, namespace: str) -> bool: - """ - Checks if the specified ID exists in the specified index and namespace. - """ - res = self.pinecone_indexes[index].fetch(ids=[id], namespace=namespace) - return bool(res["vectors"].get(id, False)) - - def _get_ids( - self, - index: str, - namespace: Optional[str] = None, - type_metadata: Optional[DocTypeMetadata] = None, - filters: Optional[FilterType] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - ) -> List[str]: - """ - Retrieves a list of IDs that satisfy a particular filter condition (or any) using - a dummy query embedding. - """ - filters = filters or {} - if type_metadata: - filters = self._add_type_metadata_filter(filters, type_value=type_metadata) - pinecone_syntax_filter = LogicalFilterClause.parse(filters).convert_to_pinecone() if filters else None - - # Retrieve embeddings from Pinecone - try: - res = self.pinecone_indexes[index].query( - self.dummy_query, - top_k=batch_size, - include_values=False, - include_metadata=False, - filter=pinecone_syntax_filter, - namespace=namespace, - ) - except pinecone.ApiException as e: - raise PineconeDocumentStoreError( - f"The API returned an exception.\nReason: {e.reason}\nHeaders: {e.headers}\nBody: {e.body}" - ) from e - - ids = [] - for match in res["matches"]: - ids.append(match["id"]) - return ids - - @classmethod - def load(cls): - """ - Default class method used for loading indexes. Not applicable to PineconeDocumentStore. - """ - raise NotImplementedError("load method not supported for PineconeDocumentStore") - - def _meta_for_pinecone(self, meta: Dict[str, Any], parent_key: str = "", labels: bool = False) -> Dict[str, Any]: - """ - Converts the meta dictionary to a format that can be stored in Pinecone. - :param meta: Metadata dictionary to be converted. - :param parent_key: Optional, used for recursive calls to keep track of parent keys, for example: - ``` - {"parent1": {"parent2": {"child": "value"}}} - ``` - On the second recursive call, parent_key would be "parent1", and the final key would be "parent1.parent2.child". - :param labels: Optional, used to indicate whether the metadata is being stored as a label or not. If True the - the flattening of dictionaries is not required. - """ - items: list = [] - if labels: - # Replace any None values with empty strings - for key, value in meta.items(): - if value is None: - meta[key] = "" - else: - # Explode dict of dicts into single flattened dict - for key, value in meta.items(): - # Replace any None values with empty strings - if value is None: - value = "" - if key == "_split_overlap": - value = json.dumps(value) - # format key - new_key = f"{parent_key}.{key}" if parent_key else key - # if value is dict, expand - if isinstance(value, dict): - items.extend(self._meta_for_pinecone(value, parent_key=new_key).items()) - else: - items.append((new_key, value)) - # Create new flattened dictionary - meta = dict(items) - return meta - - def _pinecone_meta_format(self, meta: Dict[str, Any], labels: bool = False) -> Dict[str, Any]: - """ - Converts the meta extracted from Pinecone into a better format for Python. - :param meta: Metadata dictionary to be converted. - :param labels: Optional, used to indicate whether the metadata is being stored as a label or not. If True the - the flattening of dictionaries is not required. - """ - new_meta: Dict[str, Any] = {} - - if labels: - # Replace any empty strings with None values - for key, value in meta.items(): - if value == "": - meta[key] = None - return meta - else: - for key, value in meta.items(): - # Replace any empty strings with None values - if value == "": - value = None - if "." in key: - # We must split into nested dictionary - keys = key.split(".") - # Iterate through each dictionary level - for i in range(len(keys)): - path = keys[: i + 1] - # Check if path exists - try: - _get_by_path(new_meta, path) - except KeyError: - # Create path - if i == len(keys) - 1: - _set_by_path(new_meta, path, value) - else: - _set_by_path(new_meta, path, {}) - else: - new_meta[key] = value - return new_meta - - def _label_to_meta(self, labels: list) -> dict: - """ - Converts a list of labels to a dictionary of ID: metadata mappings. - """ - metadata = {} - for label in labels: - # Get main labels data - meta = { - "label-id": label.id, - "query": label.query, - "label-is-correct-answer": label.is_correct_answer, - "label-is-correct-document": label.is_correct_document, - "label-document-content": label.document.content, - "label-document-id": label.document.id, - "label-no-answer": label.no_answer, - "label-origin": label.origin, - "label-created-at": label.created_at, - "label-updated-at": label.updated_at, - "label-pipeline-id": label.pipeline_id, - } - # Get document metadata - if label.document.meta is not None: - for k, v in label.document.meta.items(): - meta[f"label-document-meta-{k}"] = v - # Get label metadata - if label.meta is not None: - for k, v in label.meta.items(): - meta[f"label-meta-{k}"] = v - # Get Answer data - if label.answer is not None: - meta.update( - { - "label-answer-answer": label.answer.answer, - "label-answer-type": label.answer.type, - "label-answer-score": label.answer.score, - "label-answer-context": label.answer.context, - "label-answer-document-ids": label.answer.document_ids, - } - ) - # Get offset data - if label.answer.offsets_in_document: - meta["label-answer-offsets-in-document-start"] = label.answer.offsets_in_document[0].start - meta["label-answer-offsets-in-document-end"] = label.answer.offsets_in_document[0].end - else: - meta["label-answer-offsets-in-document-start"] = None - meta["label-answer-offsets-in-document-end"] = None - if label.answer.offsets_in_context: - meta["label-answer-offsets-in-context-start"] = label.answer.offsets_in_context[0].start - meta["label-answer-offsets-in-context-end"] = label.answer.offsets_in_context[0].end - else: - meta["label-answer-offsets-in-context-start"] = None - meta["label-answer-offsets-in-context-end"] = None - metadata[label.id] = meta - metadata = self._meta_for_pinecone(metadata, labels=True) - return metadata - - def _meta_to_labels(self, documents: List[Document]) -> List[Label]: - """ - Converts a list of metadata dictionaries to a list of Labels. - """ - labels = [] - for d in documents: - label_meta = {k: v for k, v in d.meta.items() if k[:6] == "label-" or k == "query"} - other_meta = {k: v for k, v in d.meta.items() if k[:6] != "label-" and k != "query"} - # Create document - doc = Document( - id=label_meta["label-document-id"], content=d.content, meta={}, score=d.score, embedding=d.embedding - ) - # Extract document metadata - for k, v in d.meta.items(): - if k.startswith("label-document-meta-"): - doc.meta[k[20:]] = v - # Extract offsets - offsets: Dict[str, Optional[List[Span]]] = {"document": None, "context": None} - for mode in offsets: - if label_meta.get(f"label-answer-offsets-in-{mode}-start") is not None: - offsets[mode] = [ - Span( - label_meta[f"label-answer-offsets-in-{mode}-start"], - label_meta[f"label-answer-offsets-in-{mode}-end"], - ) - ] - # Extract Answer - answer = None - if label_meta.get("label-answer-answer") is not None: - # backwards compatibility: if legacy answer object with `document_id` is present, convert to `document_ids - if "label-answer-document-id" in label_meta: - document_id = label_meta["label-answer-document-id"] - document_ids = [document_id] if document_id is not None else None - else: - document_ids = label_meta["label-answer-document-ids"] - - answer = Answer( - answer=label_meta["label-answer-answer"] - or "", # If we leave as None a schema validation error will be thrown - type=label_meta["label-answer-type"], - score=label_meta["label-answer-score"], - context=label_meta["label-answer-context"], - offsets_in_document=offsets["document"], - offsets_in_context=offsets["context"], - document_ids=document_ids, - meta=other_meta, - ) - # Extract Label metadata - label_meta_metadata = {} - for k, v in d.meta.items(): - if k.startswith("label-meta-"): - label_meta_metadata[k[11:]] = v - # Rebuild Label object - created_at = label_meta.get("label-created-at") - updated_at = label_meta.get("label-updated-at") - if created_at and isinstance(created_at, datetime): - created_at = created_at.strftime(LABEL_DATETIME_FORMAT) - if updated_at and isinstance(updated_at, datetime): - updated_at = updated_at.strftime(LABEL_DATETIME_FORMAT) - label = Label( - id=label_meta["label-id"], - query=label_meta["query"], - document=doc, - answer=answer, - pipeline_id=label_meta["label-pipeline-id"], - created_at=created_at, - updated_at=updated_at, - is_correct_answer=label_meta["label-is-correct-answer"], - is_correct_document=label_meta["label-is-correct-document"], - origin=label_meta["label-origin"], - meta=label_meta_metadata, - filters=None, - ) - labels.append(label) - return labels - - def delete_labels( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: int = DEFAULT_BATCH_SIZE, - namespace: Optional[str] = None, - ): - """ - Default class method used for deleting labels. Not supported by PineconeDocumentStore. - """ - index = self._index(index) - self._index_connection_exists(index) - - i = 0 - dummy_query = np.asarray(self.dummy_query) - - type_metadata = LABEL - - while True: - if ids is None: - # Iteratively upsert new records without the labels metadata - docs = self.query_by_embedding( - dummy_query, - filters=filters, - top_k=batch_size, - index=index, - return_embedding=True, - namespace=namespace, - type_metadata=type_metadata, # type: ignore - ) - update_ids = [doc.id for doc in docs] - else: - i_end = min(i + batch_size, len(ids)) - update_ids = ids[i:i_end] - if filters: - filters["label-id"] = {IN_OPERATOR: update_ids} - else: - filters = {"label-id": {IN_OPERATOR: update_ids}} - # Retrieve embeddings and metadata for the batch of documents - docs = self.query_by_embedding( - dummy_query, - filters=filters, - top_k=batch_size, - index=index, - return_embedding=True, - namespace=namespace, - type_metadata=type_metadata, # type: ignore - ) - # Apply filter to update IDs, finding intersection - update_ids = list(set(update_ids).intersection({doc.id for doc in docs})) - i = i_end - if not update_ids: - break - # Delete the documents - self.delete_documents(ids=update_ids, index=index, namespace=namespace) - - def get_all_labels( - self, - index=None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - namespace: Optional[str] = None, - ): - """ - Default class method used for getting all labels. - """ - index = self._index(index) - self._index_connection_exists(index) - - documents = self.get_all_documents( - index=index, filters=filters, headers=headers, namespace=namespace, type_metadata=LABEL # type: ignore - ) - for doc in documents: - doc.meta = self._pinecone_meta_format(doc.meta, labels=True) - labels = self._meta_to_labels(documents) - return labels - - def get_label_count(self, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None): - """ - Default class method used for counting labels. Not supported by PineconeDocumentStore. - """ - raise NotImplementedError("Labels are not supported by PineconeDocumentStore.") - - def write_labels( - self, labels, index=None, headers: Optional[Dict[str, str]] = None, namespace: Optional[str] = None - ): - """ - Default class method used for writing labels. - """ - index = self._index(index) - index_connection = self._index_connection_exists(index, create=True) - if index_connection: - self.pinecone_indexes[index] = index_connection - - # Convert Label objects to dictionary of metadata - metadata = self._label_to_meta(labels) - ids = list(metadata.keys()) - - # Check if labels exist - existing_documents = self.get_documents_by_id( - ids=ids, index=index, namespace=namespace, return_embedding=True, include_type_metadata=True - ) - if existing_documents: - # If they exist, we loop through and partial update their metadata with the new labels - existing_ids = [doc.id for doc in existing_documents] - for _id in existing_ids: - meta = self._meta_for_pinecone(metadata[_id]) - self.pinecone_indexes[index].update(id=_id, set_metadata=meta, namespace=namespace) - # After update, we delete the ID from the metadata list - del metadata[_id] - # If there are any remaining IDs, we create new documents with the remaining metadata - if metadata: - documents = [] - for _id, meta in metadata.items(): - metadata[_id] = self._meta_for_pinecone(meta) - documents.append(Document(id=_id, content=meta["label-document-content"], meta=meta)) - self.write_documents(documents, index=index, labels=True, namespace=namespace) diff --git a/haystack/document_stores/search_engine.py b/haystack/document_stores/search_engine.py deleted file mode 100644 index eac2a6ec7a..0000000000 --- a/haystack/document_stores/search_engine.py +++ /dev/null @@ -1,1656 +0,0 @@ -# pylint: disable=too-many-public-methods - - -from copy import deepcopy -from typing import List, Optional, Union, Dict, Any, Generator -from abc import abstractmethod -import json -import logging -import time -from string import Template - -import numpy as np -from tqdm import tqdm -from pydantic.error_wrappers import ValidationError - -from haystack.document_stores import KeywordDocumentStore -from haystack.schema import Document, FilterType, Label -from haystack.utils.batching import get_batches_from_generator -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.errors import DocumentStoreError, HaystackError -from haystack.nodes.retriever import DenseRetriever -from haystack.utils.scipy_utils import expit - - -logger = logging.getLogger(__name__) - - -def prepare_hosts(host, port): - """ - Create a list of host(s) + port(s) to allow direct client connections to multiple nodes, - in the format expected by the client. - """ - if isinstance(host, list): - if isinstance(port, list): - if not len(port) == len(host): - raise ValueError("Length of list `host` must match length of list `port`") - hosts = [{"host": h, "port": p} for h, p in zip(host, port)] - else: - hosts = [{"host": h, "port": port} for h in host] - else: - hosts = [{"host": host, "port": port}] - return hosts - - -class SearchEngineDocumentStore(KeywordDocumentStore): - """ - Base class implementing the common logic for Elasticsearch and Opensearch - """ - - def __init__( - self, - client: Any, - index: str = "document", - label_index: str = "label", - search_fields: Union[str, list] = "content", - content_field: str = "content", - name_field: str = "name", - embedding_field: str = "embedding", - embedding_dim: int = 768, - custom_mapping: Optional[dict] = None, - excluded_meta_data: Optional[list] = None, - analyzer: str = "standard", - recreate_index: bool = False, - create_index: bool = True, - refresh_type: str = "wait_for", - similarity: str = "dot_product", - return_embedding: bool = False, - duplicate_documents: str = "overwrite", - scroll: str = "1d", - skip_missing_embeddings: bool = True, - synonyms: Optional[List] = None, - synonym_type: str = "synonym", - batch_size: int = 10_000, - ): - super().__init__() - - self.client = client - self._RequestError: Any = Exception - - # configure mappings to ES fields that will be used for querying / displaying results - if type(search_fields) == str: - search_fields = [search_fields] - - self.search_fields = search_fields - self.content_field = content_field - self.name_field = name_field - self.embedding_field = embedding_field - self.embedding_dim = embedding_dim - self.excluded_meta_data = excluded_meta_data - self.analyzer = analyzer - self.return_embedding = return_embedding - - self.custom_mapping = custom_mapping - self.synonyms = synonyms - self.synonym_type = synonym_type - self.index: str = index - self.label_index: str = label_index - self.scroll = scroll - self.skip_missing_embeddings: bool = skip_missing_embeddings - self.duplicate_documents = duplicate_documents - self.refresh_type = refresh_type - self.batch_size = batch_size - if similarity in ["cosine", "dot_product", "l2"]: - self.similarity: str = similarity - else: - raise DocumentStoreError( - f"Invalid value {similarity} for similarity, choose between 'cosine', 'l2' and 'dot_product'" - ) - client_info = self.client.info() - self.server_version = tuple(int(num) for num in client_info["version"]["number"].split(".")) - - self._init_indices( - index=index, label_index=label_index, create_index=create_index, recreate_index=recreate_index - ) - - def _init_indices(self, index: str, label_index: str, create_index: bool, recreate_index: bool) -> None: - if recreate_index: - self._index_delete(index) - self._index_delete(label_index) - - if not self._index_exists(index) and (create_index or recreate_index): - self._create_document_index(index) - - if self.custom_mapping: - logger.warning("Cannot validate index for custom mappings. Skipping index validation.") - else: - self._validate_and_adjust_document_index(index) - - if not self._index_exists(label_index) and (create_index or recreate_index): - self._create_label_index(label_index) - - def _split_document_list( - self, documents: Union[List[dict], List[Document]], number_of_lists: int - ) -> Generator[Union[List[dict], List[Document]], None, None]: - chunk_size = max((len(documents) + 1) // number_of_lists, 1) - for i in range(0, len(documents), chunk_size): - yield documents[i : i + chunk_size] - - @abstractmethod - def _do_bulk(self, *args, **kwargs): - pass - - @abstractmethod - def _do_scan(self, *args, **kwargs): - pass - - @abstractmethod - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - pass - - @abstractmethod - def _create_document_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - pass - - @abstractmethod - def _create_label_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - pass - - @abstractmethod - def _validate_and_adjust_document_index(self, index_name: str, headers: Optional[Dict[str, str]] = None): - pass - - @abstractmethod - def _get_vector_similarity_query(self, query_emb: np.ndarray, top_k: int): - pass - - @abstractmethod - def _get_raw_similarity_score(self, score): - pass - - def _bulk( - self, - documents: Union[List[dict], List[Document]], - headers: Optional[Dict[str, str]] = None, - refresh: str = "wait_for", - _timeout: int = 1, - _remaining_tries: int = 10, - ) -> None: - """ - Bulk index documents using a custom retry logic with - exponential backoff and exponential batch size reduction to avoid overloading the cluster. - - The ingest node returns '429 Too Many Requests' when the write requests can't be - processed because there are too many requests in the queue or the single request is too large and exceeds the - memory of the nodes. Since the error code is the same for both of these cases we need to wait - and reduce the batch size simultaneously. - - :param documents: List of documents to index - :param headers: Optional headers to pass to the bulk request - :param refresh: Refresh policy for the bulk request - :param _timeout: Timeout for the exponential backoff - :param _remaining_tries: Number of remaining retries - """ - - try: - self._do_bulk(self.client, documents, refresh=self.refresh_type, headers=headers) - except Exception as e: - if hasattr(e, "status_code") and e.status_code == 429: # type: ignore - logger.warning( - "Failed to insert a batch of '%s' documents because of a 'Too Many Requests' response. " - "Splitting the number of documents into two chunks with the same size and retrying in %s seconds.", - len(documents), - _timeout, - ) - if len(documents) == 1: - logger.warning( - "Failed to index a single document. Your indexing queue on the cluster is probably full. Try resizing your cluster or reducing the number of parallel processes that are writing to the cluster." - ) - - time.sleep(_timeout) - - _remaining_tries -= 1 - if _remaining_tries == 0: - raise DocumentStoreError("Last try of bulk indexing documents failed.") - - for split_docs in self._split_document_list(documents, 2): - self._bulk( - documents=split_docs, - headers=headers, - refresh=refresh, - _timeout=_timeout * 2, - _remaining_tries=_remaining_tries, - ) - return - raise e - - # TODO: Add flexibility to define other non-meta and meta fields expected by the Document class - def _create_document_field_map(self) -> Dict: - return {self.content_field: "content", self.embedding_field: "embedding"} - - def get_document_by_id( - self, id: str, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ) -> Optional[Document]: - """Fetch a document by specifying its text id string""" - index = index or self.index - documents = self.get_documents_by_id([id], index=index, headers=headers) - if documents: - return documents[0] - else: - return None - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Fetch documents by specifying a list of text id strings. - - :param ids: List of document IDs. Be aware that passing a large number of ids might lead to performance issues. - :param index: search index where the documents are stored. If not supplied, - self.index will be used. - :param batch_size: Maximum number of results for each query. - Limited to 10,000 documents by default. - To reduce the pressure on the cluster, you can lower this limit, at the expense - of longer retrieval times. - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - """ - index = index or self.index - documents = [] - for i in range(0, len(ids), batch_size): - ids_for_batch = ids[i : i + batch_size] - query = {"size": len(ids_for_batch), "query": {"ids": {"values": ids_for_batch}}} - if not self.return_embedding and self.embedding_field: - query["_source"] = {"excludes": [self.embedding_field]} - result = self._search(index=index, **query, headers=headers)["hits"]["hits"] - documents.extend([self._convert_es_hit_to_document(hit) for hit in result]) - return documents - - def get_metadata_values_by_key( - self, - key: str, - query: Optional[str] = None, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[dict]: - """ - Get values associated with a metadata key. The output is in the format: - [{"value": "my-value-1", "count": 23}, {"value": "my-value-2", "count": 12}, ... ] - - :param key: the meta key name to get the values for. - :param query: narrow down the scope to documents matching the query string. - :param filters: Narrow down the scope to documents that match the given filters. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param index: search index where the meta values should be searched. If not supplied, - self.index will be used. - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - """ - body: dict = { - "size": 0, - "aggs": {"metadata_agg": {"composite": {"sources": [{key: {"terms": {"field": key}}}]}}}, - } - if query: - body["query"] = { - "bool": { - "should": [{"multi_match": {"query": query, "type": "most_fields", "fields": self.search_fields}}] - } - } - if filters: - if not body.get("query"): - body["query"] = {"bool": {}} - body["query"]["bool"].update({"filter": LogicalFilterClause.parse(filters).convert_to_elasticsearch()}) - result = self._search(**body, index=index, headers=headers) - - values = [] - current_buckets = result["aggregations"]["metadata_agg"]["buckets"] - after_key = result["aggregations"]["metadata_agg"].get("after_key", False) - for bucket in current_buckets: - values.append({"value": bucket["key"][key], "count": bucket["doc_count"]}) - - # Only 10 results get returned at a time, so apply pagination - while after_key: - body["aggs"]["metadata_agg"]["composite"]["after"] = after_key - result = self._search(**body, index=index, headers=headers) - current_buckets = result["aggregations"]["metadata_agg"]["buckets"] - after_key = result["aggregations"]["metadata_agg"].get("after_key", False) - for bucket in current_buckets: - values.append({"value": bucket["key"][key], "count": bucket["doc_count"]}) - - return values - - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: Optional[int] = None, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Indexes documents for later queries. - - If a document with the same ID already exists: - a) (Default) Manage duplication according to the `duplicate_documents` parameter. - b) If `self.update_existing_documents=True` for DocumentStore: Overwrite existing documents. - (This is only relevant if you pass your own ID when initializing a `Document`. - If you don't set custom IDs for your Documents or just pass a list of dictionaries here, - they automatically get UUIDs assigned. See the `Document` class for details.) - - :param documents: A list of Python dictionaries or a list of Haystack Document objects. - For documents as dictionaries, the format is {"content": ""}. - Optionally: Include meta data via {"content": "", - "meta":{"name": ", "author": "somebody", ...}} - You can use it for filtering and you can access it in the responses of the Finder. - Advanced: If you are using your own field mapping, change the key names in the dictionary - to what you have set for self.content_field and self.name_field. - :param index: search index where the documents should be indexed. If you don't specify it, self.index is used. - :param batch_size: Number of documents that are passed to the bulk function at each round. - If not specified, self.batch_size is used. - :param duplicate_documents: Handle duplicate documents based on parameter options. - Parameter options: ( 'skip','overwrite','fail') - skip: Ignore the duplicate documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: Raises an error if the document ID of the document being added already - exists. - :param headers: Custom HTTP headers to pass to the client (for example {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - For more information, see [HTTP/REST clients and security](https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html). - :raises DuplicateDocumentError: Exception trigger on duplicate document - :return: None - """ - - if index and not self._index_exists(index, headers=headers): - self._create_document_index(index, headers=headers) - - if index is None: - index = self.index - - batch_size = batch_size or self.batch_size - - duplicate_documents = duplicate_documents or self.duplicate_documents - assert ( - duplicate_documents in self.duplicate_documents_options - ), f"duplicate_documents parameter must be {', '.join(self.duplicate_documents_options)}" - - field_map = self._create_document_field_map() - document_objects = [Document.from_dict(d, field_map=field_map) if isinstance(d, dict) else d for d in documents] - document_objects = self._handle_duplicate_documents( - documents=document_objects, index=index, duplicate_documents=duplicate_documents, headers=headers - ) - documents_to_index = [] - for doc in document_objects: - index_message: Dict[str, Any] = { - "_op_type": "index" if duplicate_documents == "overwrite" else "create", - "_index": index, - "_id": str(doc.id), - # use _source explicitly to avoid conflicts with automatic field detection by ES/OS clients (e.g. "version") - "_source": self._get_source(doc, field_map), - } - documents_to_index.append(index_message) - - # Pass batch_size number of documents to bulk - if len(documents_to_index) % batch_size == 0: - self._bulk(documents_to_index, refresh=self.refresh_type, headers=headers) - documents_to_index = [] - - if documents_to_index: - self._bulk(documents_to_index, refresh=self.refresh_type, headers=headers) - - def _get_source(self, doc: Document, field_map: Dict[str, Any]) -> Dict[str, Any]: - """Convert a Document object to a dictionary that can be used as the "_source" field in an ES/OS index message.""" - - _source: Dict[str, Any] = doc.to_dict(field_map=field_map) - - # cast embedding type as ES/OS cannot deal with np.array - if isinstance(_source.get(self.embedding_field), np.ndarray): - _source[self.embedding_field] = _source[self.embedding_field].tolist() - - # we already have the id in the index message - _source.pop("id", None) - - # don't index query score and empty fields - _source.pop("score", None) - _source = {k: v for k, v in _source.items() if v is not None} - - # In order to have a flat structure in ES/OS + similar behavior to the other DocumentStores, - # we "unnest" all value within "meta" - _source.update(_source.pop("meta", None) or {}) - return _source - - def write_labels( - self, - labels: Union[List[Label], List[dict]], - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: int = 10_000, - ): - """Write annotation labels into document store. - - :param labels: A list of Python dictionaries or a list of Haystack Label objects. - :param index: search index where the labels should be stored. If not supplied, self.label_index will be used. - :param batch_size: Number of labels that are passed to the bulk function at each round. - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - """ - index = index or self.label_index - if index and not self._index_exists(index, headers=headers): - self._create_label_index(index, headers=headers) - - label_list: List[Label] = [Label.from_dict(label) if isinstance(label, dict) else label for label in labels] - duplicate_ids: list = [label.id for label in self._get_duplicate_labels(label_list, index=index)] - if len(duplicate_ids) > 0: - logger.warning( - "Duplicate Label IDs: Inserting a Label whose id already exists in this document store." - " This will overwrite the old Label. Please make sure Label.id is a unique identifier of" - " the answer annotation and not the question." - " Problematic ids: %s", - ",".join(duplicate_ids), - ) - labels_to_index = [] - for label in label_list: - # create timestamps if not available yet - if not label.created_at: - label.created_at = time.strftime("%Y-%m-%d %H:%M:%S") - if not label.updated_at: - label.updated_at = label.created_at - - index_message: Dict[str, Any] = { - "_op_type": "index" - if self.duplicate_documents == "overwrite" or label.id in duplicate_ids - else "create", - "_index": index, - } - - _source = label.to_dict() - - # set id for elastic - if _source.get("id") is not None: - index_message["_id"] = str(_source.pop("id")) - - # use _source explicitly to avoid conflicts with automatic field detection by ES/OS clients (e.g. "version") - index_message["_source"] = _source - labels_to_index.append(index_message) - - # Pass batch_size number of labels to bulk - if len(labels_to_index) % batch_size == 0: - self._bulk(labels_to_index, refresh=self.refresh_type, headers=headers) - labels_to_index = [] - - if labels_to_index: - self._bulk(labels_to_index, refresh=self.refresh_type, headers=headers) - - def update_document_meta( - self, id: str, meta: Dict[str, str], index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ): - """ - Update the metadata dictionary of a document by specifying its string id - """ - if not index: - index = self.index - body = {"doc": meta} - self._update(index=index, id=id, **body, refresh=self.refresh_type, headers=headers) - - def get_document_count( - self, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - ) -> int: - """ - Return the number of documents in the document store. - """ - index = index or self.index - - body: dict = {"query": {"bool": {}}} - if only_documents_without_embedding: - body["query"]["bool"]["must_not"] = [{"exists": {"field": self.embedding_field}}] - - if filters: - body["query"]["bool"]["filter"] = LogicalFilterClause.parse(filters).convert_to_elasticsearch() - - result = self._count(index=index, body=body, headers=headers) - count = result["count"] - return count - - def get_label_count(self, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None) -> int: - """ - Return the number of labels in the document store - """ - index = index or self.label_index - return self.get_document_count(index=index, headers=headers) - - def get_embedding_count( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ) -> int: - """ - Return the count of embeddings in the document store. - """ - - index = index or self.index - - body: dict = {"query": {"bool": {"must": [{"exists": {"field": self.embedding_field}}]}}} - if filters: - body["query"]["bool"]["filter"] = LogicalFilterClause.parse(filters).convert_to_elasticsearch() - - result = self._count(index=index, body=body, headers=headers) - count = result["count"] - return count - - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Get documents from the document store. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the documents to return. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - """ - result = self.get_all_documents_generator( - index=index, filters=filters, return_embedding=return_embedding, batch_size=batch_size, headers=headers - ) - documents = list(result) - return documents - - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> Generator[Document, None, None]: - """ - Get documents from the document store. Under-the-hood, documents are fetched in batches from the - document store and yielded as individual documents. This method can be used to iteratively process - a large number of documents without having to load all documents in memory. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the documents to return. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - """ - - if index is None: - index = self.index - - if return_embedding is None: - return_embedding = self.return_embedding - - excludes = None - if not return_embedding and self.embedding_field: - excludes = [self.embedding_field] - - result = self._get_all_documents_in_index( - index=index, filters=filters, batch_size=batch_size, headers=headers, excludes=excludes - ) - for hit in result: - document = self._convert_es_hit_to_document(hit) - yield document - - def get_all_labels( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: int = 10_000, - ) -> List[Label]: - """ - Return all labels in the document store - """ - index = index or self.label_index - result = list( - self._get_all_documents_in_index(index=index, filters=filters, batch_size=batch_size, headers=headers) - ) - try: - labels = [Label.from_dict({**hit["_source"], "id": hit["_id"]}) for hit in result] - except ValidationError as e: - raise DocumentStoreError( - f"Failed to create labels from the content of index '{index}'. Are you sure this index contains labels?" - ) from e - return labels - - def _get_all_documents_in_index( - self, - index: str, - filters: Optional[FilterType] = None, - batch_size: int = 10_000, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - excludes: Optional[List[str]] = None, - ) -> Generator[dict, None, None]: - """ - Return all documents in a specific index in the document store - """ - body: dict = {"query": {"bool": {}}} - - if filters: - body["query"]["bool"]["filter"] = LogicalFilterClause.parse(filters).convert_to_elasticsearch() - - if only_documents_without_embedding: - body["query"]["bool"]["must_not"] = [{"exists": {"field": self.embedding_field}}] - - if excludes: - body["_source"] = {"excludes": excludes} - - result = self._do_scan( - self.client, query=body, index=index, size=batch_size, scroll=self.scroll, headers=headers - ) - yield from result - - def query( - self, - query: Optional[str], - filters: Optional[FilterType] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query as defined by the BM25 algorithm. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param custom_query: query string containing a mandatory `${query}` and an optional `${filters}` placeholder. - - :: - - **An example custom_query:** - ```python - { - "size": 10, - "query": { - "bool": { - "should": [{"multi_match": { - "query": ${query}, // mandatory query placeholder - "type": "most_fields", - "fields": ["content", "title"]}}], - "filter": ${filters} // optional filters placeholder - } - }, - } - ``` - - **For this custom_query, a sample retrieve() could be:** - ```python - self.retrieve(query="Why did the revenue increase?", - filters={"years": ["2019"], "quarters": ["Q1", "Q2"]}) - ``` - - Optionally, highlighting can be defined by specifying the highlight settings. - See https://www.elastic.co/guide/en/elasticsearch/reference/current/highlighting.html. - You will find the highlighted output in the returned Document's meta field by key "highlighted". - :: - - **Example custom_query with highlighting:** - ```python - { - "size": 10, - "query": { - "bool": { - "should": [{"multi_match": { - "query": ${query}, // mandatory query placeholder - "type": "most_fields", - "fields": ["content", "title"]}}], - } - }, - "highlight": { // enable highlighting - "fields": { // for fields content and title - "content": {}, - "title": {} - } - }, - } - ``` - - **For this custom_query, highlighting info can be accessed by:** - ```python - docs = self.retrieve(query="Why did the revenue increase?") - highlighted_content = docs[0].meta["highlighted"]["content"] - highlighted_title = docs[0].meta["highlighted"]["title"] - ``` - - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to false. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - - if index is None: - index = self.index - - body = self._construct_query_body( - query=query, - filters=filters, - top_k=top_k, - custom_query=custom_query, - all_terms_must_match=all_terms_must_match, - ) - - result = self._search(index=index, **body, headers=headers)["hits"]["hits"] - - documents = [self._convert_es_hit_to_document(hit, scale_score=scale_score) for hit in result] - return documents - - def query_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - batch_size: Optional[int] = None, - ) -> List[List[Document]]: - """ - Scan through documents in DocumentStore and return a small number of documents - that are most relevant to the provided queries as defined by keyword matching algorithms like BM25. - - This method lets you find relevant documents for list of query strings (output: List of Lists of Documents). - - :param queries: List of query strings. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. Can be a single filter that will be applied to each query or a list of filters - (one filter per query). - - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - - :param top_k: How many documents to return per query. - :param custom_query: Custom query to be executed. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise, at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to False. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise, raw similarity scores (e.g. cosine or dot_product) will be used. - :param batch_size: Number of queries that are processed at once. If not specified, self.batch_size is used. - """ - - if index is None: - index = self.index - if headers is None: - headers = {} - batch_size = batch_size or self.batch_size - - if isinstance(filters, list): - if len(filters) != len(queries): - raise HaystackError( - "Number of filters does not match number of queries. Please provide as many filters" - " as queries or a single filter that will be applied to each query." - ) - else: - filters = [filters] * len(queries) - - body = [] - all_documents = [] - for query, cur_filters in tqdm(zip(queries, filters)): - cur_query_body = self._construct_query_body( - query=query, - filters=cur_filters, - top_k=top_k, - custom_query=custom_query, - all_terms_must_match=all_terms_must_match, - ) - body.append(headers) - body.append(cur_query_body) - - if len(body) == 2 * batch_size: - cur_documents = self._execute_msearch(index=index, body=body, scale_score=scale_score) - all_documents.extend(cur_documents) - body = [] - - if len(body) > 0: - cur_documents = self._execute_msearch(index=index, body=body, scale_score=scale_score) - all_documents.extend(cur_documents) - - return all_documents - - def _execute_msearch(self, index: str, body: List[Dict[str, Any]], scale_score: bool) -> List[List[Document]]: - responses = self.client.msearch(index=index, body=body) - documents = [] - for response in responses["responses"]: - result = response["hits"]["hits"] - cur_documents = [self._convert_es_hit_to_document(hit, scale_score=scale_score) for hit in result] - documents.append(cur_documents) - - return documents - - def _construct_query_body( - self, - query: Optional[str], - filters: Optional[FilterType], - top_k: int, - custom_query: Optional[str], - all_terms_must_match: bool, - ) -> Dict[str, Any]: - # Naive retrieval without BM25, only filtering - if query is None: - body = {"query": {"bool": {"must": {"match_all": {}}}}} # type: Dict[str, Any] - body["size"] = "10000" # Set to the ES default max_result_window - if filters: - body["query"]["bool"]["filter"] = LogicalFilterClause.parse(filters).convert_to_elasticsearch() - - # Retrieval via custom query - elif custom_query: - template = Template(custom_query) - # substitute placeholder for query and filters for the custom_query template string - substitutions = { - "query": json.dumps(query), - "filters": json.dumps(LogicalFilterClause.parse(filters or {}).convert_to_elasticsearch()), - } - custom_query_json = template.substitute(**substitutions) - body = json.loads(custom_query_json) - # add top_k - body["size"] = str(top_k) - - # Default Retrieval via BM25 using the user query on `self.search_fields` - else: - if not isinstance(query, str): - logger.warning( - "The query provided seems to be not a string, but an object " - "of type %s. This can cause the query to fail.", - type(query), - ) - operator = "AND" if all_terms_must_match else "OR" - body = { - "size": str(top_k), - "query": { - "bool": { - "must": [ - { - "multi_match": { - "query": query, - "type": "most_fields", - "fields": self.search_fields, - "operator": operator, - } - } - ] - } - }, - } - - if filters: - body["query"]["bool"]["filter"] = LogicalFilterClause.parse(filters).convert_to_elasticsearch() - - excluded_fields = self._get_excluded_fields(return_embedding=self.return_embedding) - if excluded_fields: - body["_source"] = {"excludes": excluded_fields} - - return body - - def _get_excluded_fields(self, return_embedding: bool) -> Optional[List[str]]: - excluded_meta_data: Optional[list] = None - - if self.excluded_meta_data: - excluded_meta_data = deepcopy(self.excluded_meta_data) - - if return_embedding is True and self.embedding_field in excluded_meta_data: - excluded_meta_data.remove(self.embedding_field) - elif return_embedding is False and self.embedding_field not in excluded_meta_data: - excluded_meta_data.append(self.embedding_field) - elif return_embedding is False: - excluded_meta_data = [self.embedding_field] - return excluded_meta_data - - def _convert_es_hit_to_document( - self, hit: dict, adapt_score_for_embedding: bool = False, scale_score: bool = True - ) -> Document: - # We put all additional data of the doc into meta_data and return it in the API - try: - meta_data = { - k: v - for k, v in hit["_source"].items() - if k not in (self.content_field, "content_type", "id_hash_keys", self.embedding_field) - } - name = meta_data.pop(self.name_field, None) - if name: - meta_data["name"] = name - - if "highlight" in hit: - meta_data["highlighted"] = hit["highlight"] - - score = hit["_score"] - if score: - if adapt_score_for_embedding: - score = self._get_raw_similarity_score(score) - - if scale_score: - if adapt_score_for_embedding: - score = self.scale_to_unit_interval(score, self.similarity) - else: - score = float(expit(np.asarray(score / 8))) # scaling probability from TFIDF/BM25 - - embedding = None - embedding_list = hit["_source"].get(self.embedding_field) - if embedding_list: - embedding = np.asarray(embedding_list, dtype=np.float32) - - doc_dict = { - "id": hit["_id"], - "content": hit["_source"].get(self.content_field), - "content_type": hit["_source"].get("content_type", None), - "id_hash_keys": hit["_source"].get("id_hash_keys", None), - "meta": meta_data, - "score": score, - "embedding": embedding, - } - document = Document.from_dict(doc_dict) - except (KeyError, ValidationError) as e: - raise DocumentStoreError( - "Failed to create documents from the content of the document store. Make sure the index you specified contains documents." - ) from e - return document - - def query_by_embedding_batch( - self, - query_embs: Union[List[np.ndarray], np.ndarray], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - batch_size: Optional[int] = None, - ) -> List[List[Document]]: - """ - Find the documents that are most similar to the provided `query_embs` by using a vector similarity metric. - - :param query_embs: Embeddings of the queries (e.g. gathered from DPR). - Can be a list of one-dimensional numpy arrays or a two-dimensional numpy array. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return - :param index: Index name for storing the docs and metadata - :param return_embedding: To return document embedding - :param headers: Custom HTTP headers to pass to elasticsearch client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise, raw similarity scores (e.g. cosine or dot_product) will be used. - :param batch_size: Number of query embeddings to process at once. If not specified, self.batch_size is used. - """ - if index is None: - index = self.index - - if return_embedding is None: - return_embedding = self.return_embedding - - if headers is None: - headers = {} - - batch_size = batch_size or self.batch_size - - if not self.embedding_field: - raise DocumentStoreError("Please set a valid `embedding_field` for OpenSearchDocumentStore") - - if isinstance(filters, list): - if len(filters) != len(query_embs): - raise HaystackError( - "Number of filters does not match number of query_embs. Please provide as many filters" - " as query_embs or a single filter that will be applied to each query_emb." - ) - else: - filters = [filters] * len(query_embs) if filters is not None else [{}] * len(query_embs) - - body = [] - all_documents = [] - for query_emb, cur_filters in zip(query_embs, filters): - cur_query_body = self._construct_dense_query_body( - query_emb=query_emb, filters=cur_filters, top_k=top_k, return_embedding=return_embedding - ) - body.append(headers) - body.append(cur_query_body) - - if len(body) >= batch_size * 2: - logger.debug("Retriever query: %s", body) - cur_documents = self._execute_msearch(index=index, body=body, scale_score=scale_score) - all_documents.extend(cur_documents) - body = [] - - if len(body) > 0: - logger.debug("Retriever query: %s", body) - cur_documents = self._execute_msearch(index=index, body=body, scale_score=scale_score) - all_documents.extend(cur_documents) - - return all_documents - - @abstractmethod - def _construct_dense_query_body( - self, query_emb: np.ndarray, return_embedding: bool, filters: Optional[FilterType] = None, top_k: int = 10 - ): - pass - - def update_embeddings( - self, - retriever: DenseRetriever, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - update_existing_embeddings: bool = True, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Updates the embeddings in the the document store using the encoding model specified in the retriever. - This can be useful if want to add or change the embeddings for your documents (e.g. after changing the retriever config). - - :param retriever: Retriever to use to update the embeddings. - :param index: Index name to update - :param update_existing_embeddings: Whether to update existing embeddings of the documents. If set to False, - only documents without embeddings are processed. This mode can be used for - incremental updating of embeddings, wherein, only newly indexed documents - get processed. - :param filters: Optional filters to narrow down the documents for which embeddings are to be updated. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :return: None - """ - if index is None: - index = self.index - - batch_size = batch_size or self.batch_size - - if self.refresh_type == "false": - self._index_refresh(index, headers) - - if not self.embedding_field: - raise RuntimeError("Please specify the arg `embedding_field` when initializing the Document Store") - - if update_existing_embeddings: - document_count = self.get_document_count(index=index, headers=headers) - else: - document_count = self.get_document_count( - index=index, filters=filters, only_documents_without_embedding=True, headers=headers - ) - - logger.info( - "Updating embeddings for all %s docs %s...", - document_count, - "without embeddings" if not update_existing_embeddings else "", - ) - - result = self._get_all_documents_in_index( - index=index, - filters=filters, - batch_size=batch_size, - only_documents_without_embedding=not update_existing_embeddings, - headers=headers, - excludes=[self.embedding_field], - ) - - logging.getLogger(__name__).setLevel(logging.CRITICAL) - - with tqdm(total=document_count, position=0, unit=" Docs", desc="Updating embeddings") as progress_bar: - for result_batch in get_batches_from_generator(result, batch_size): - document_batch = [self._convert_es_hit_to_document(hit) for hit in result_batch] - embeddings = self._embed_documents(document_batch, retriever) - - doc_updates = [] - for doc, emb in zip(document_batch, embeddings): - update = { - "_op_type": "update", - "_index": index, - "_id": doc.id, - "doc": {self.embedding_field: emb.tolist()}, - } - doc_updates.append(update) - - self._bulk(documents=doc_updates, refresh=self.refresh_type, headers=headers) - progress_bar.update(batch_size) - - def _embed_documents(self, documents: List[Document], retriever: DenseRetriever) -> np.ndarray: - """ - Embed a list of documents using a Retriever. - :param documents: List of documents to embed. - :param retriever: Retriever to use for embedding. - :return: embeddings of documents. - """ - embeddings = retriever.embed_documents(documents) - self._validate_embeddings_shape( - embeddings=embeddings, num_documents=len(documents), embedding_dim=self.embedding_dim - ) - - return embeddings - - def delete_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - - :param index: Index name to delete the document from. - :param filters: Optional filters to narrow down the documents to be deleted. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :return: None - """ - logger.warning( - """DEPRECATION WARNINGS: - 1. delete_all_documents() method is deprecated, please use delete_documents method - For more details, please refer to the issue: https://github.com/deepset-ai/haystack/issues/1045 - """ - ) - self.delete_documents(index, None, filters, headers=headers) - - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - - :param index: Index name to delete the documents from. If None, the - DocumentStore's default index (self.index) will be used - :param ids: Optional list of IDs to narrow down the documents to be deleted. - :param filters: Optional filters to narrow down the documents to be deleted. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - - If filters are provided along with a list of IDs, this method deletes the - intersection of the two query results (documents that match the filters and - have their ID in the list). - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :return: None - """ - index = index or self.index - query: Dict[str, Any] = {"query": {}} - if filters: - query["query"]["bool"] = {"filter": LogicalFilterClause.parse(filters).convert_to_elasticsearch()} - - if ids: - query["query"]["bool"]["must"] = {"ids": {"values": ids}} - - elif ids: - query["query"]["ids"] = {"values": ids} - else: - query["query"] = {"match_all": {}} - self._delete_by_query(index=index, body=query, ignore=[404], headers=headers) - # We want to be sure that all docs are deleted before continuing (delete_by_query doesn't support wait_for) - if self.refresh_type == "wait_for": - self._index_refresh(index, headers) - - def delete_labels( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete labels in an index. All labels are deleted if no filters are passed. - - :param index: Index name to delete the labels from. If None, the - DocumentStore's default label index (self.label_index) will be used - :param ids: Optional list of IDs to narrow down the labels to be deleted. - :param filters: Optional filters to narrow down the labels to be deleted. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param headers: Custom HTTP headers to pass to the client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :return: None - """ - index = index or self.label_index - self.delete_documents(index=index, ids=ids, filters=filters, headers=headers) - - def delete_index(self, index: str): - """ - Delete an existing search index. The index including all data will be removed. - - :param index: The name of the index to delete. - :return: None - """ - if index == self.index: - logger.warning( - "Deletion of default index '%s' detected. " - "If you plan to use this index again, please reinstantiate '%s' in order to avoid side-effects.", - index, - self.__class__.__name__, - ) - self._index_delete(index) - - def _index_exists(self, index_name: str, headers: Optional[Dict[str, str]] = None) -> bool: - if logger.isEnabledFor(logging.DEBUG) and self.client.indices.exists_alias(name=index_name): - logger.debug("Index name %s is an alias.", index_name) - - return self.client.indices.exists(index=index_name, headers=headers) - - def _index_delete(self, index): - if self._index_exists(index): - self.client.indices.delete(index=index, ignore=[400, 404]) - logger.info("Index '%s' deleted.", index) - - def _index_refresh(self, index, headers): - if self._index_exists(index): - self.client.indices.refresh(index=index, headers=headers) - - def _index_create(self, *args, **kwargs): - return self.client.indices.create(*args, **kwargs) - - def _index_get(self, *args, **kwargs): - return self.client.indices.get(*args, **kwargs) - - def _index_put_mapping(self, *args, **kwargs): - return self.client.indices.put_mapping(*args, **kwargs) - - def _search(self, *args, **kwargs): - return self.client.search(*args, **kwargs) - - def _update(self, *args, **kwargs): - return self.client.update(*args, **kwargs) - - def _count(self, *args, **kwargs): - return self.client.count(*args, **kwargs) - - def _delete_by_query(self, *args, **kwargs): - return self.client.delete_by_query(*args, **kwargs) diff --git a/haystack/document_stores/sql.py b/haystack/document_stores/sql.py deleted file mode 100644 index 0c56259498..0000000000 --- a/haystack/document_stores/sql.py +++ /dev/null @@ -1,802 +0,0 @@ -from typing import Any, Dict, Union, List, Optional, Generator - -import logging -import itertools -import json -from uuid import uuid4 - -import numpy as np - -from haystack.schema import Document, Label, Answer -from haystack.document_stores.base import BaseDocumentStore, FilterType -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.lazy_imports import LazyImport - -with LazyImport(message="Run 'pip install farm-haystack[sql]'") as sqlalchemy_import: - from sqlalchemy import ( - and_, - func, - create_engine, - Column, - String, - DateTime, - Boolean, - Text, - text, - JSON, - ForeignKeyConstraint, - UniqueConstraint, - TypeDecorator, - ) - from sqlalchemy.ext.declarative import declarative_base - from sqlalchemy.orm import relationship, sessionmaker, aliased - from sqlalchemy.sql import case, null - - Base = declarative_base() # type: Any - - class ArrayType(TypeDecorator): - impl = String - cache_ok = True - - def process_bind_param(self, value, dialect): - return json.dumps(value) - - def process_result_value(self, value, dialect): - if value is not None: - return json.loads(value) - return value - - class ORMBase(Base): - __abstract__ = True - - id = Column(String(100), default=lambda: str(uuid4()), primary_key=True) - created_at = Column(DateTime, server_default=func.now()) - updated_at = Column(DateTime, server_default=func.now(), server_onupdate=func.now()) - - class DocumentORM(ORMBase): - __tablename__ = "document" - - content = Column(JSON, nullable=False) - content_type = Column(Text, nullable=True) - # primary key in combination with id to allow the same doc in different indices - index = Column(String(100), nullable=False, primary_key=True) - vector_id = Column(String(100), nullable=True) - # speeds up queries for get_documents_by_vector_ids() by having a single query that returns joined metadata - meta = relationship("MetaDocumentORM", back_populates="documents", lazy="joined") - - __table_args__ = (UniqueConstraint("index", "vector_id", name="index_vector_id_uc"),) - - class MetaDocumentORM(ORMBase): - __tablename__ = "meta_document" - - name = Column(String(100), index=True) - value = Column(ArrayType(1000), index=True) - documents = relationship("DocumentORM", back_populates="meta") - - document_id = Column(String(100), nullable=False, index=True) - document_index = Column(String(100), nullable=False, index=True) - __table_args__ = ( # type: ignore - ForeignKeyConstraint( - [document_id, document_index], - [DocumentORM.id, DocumentORM.index], - ondelete="CASCADE", - onupdate="CASCADE", - ), - {}, - ) - - class LabelORM(ORMBase): - __tablename__ = "label" - - index = Column(String(100), nullable=False, primary_key=True) - query = Column(Text, nullable=False) - answer = Column(JSON, nullable=True) - document = Column(JSON, nullable=False) - no_answer = Column(Boolean, nullable=False) - origin = Column(String(100), nullable=False) - is_correct_answer = Column(Boolean, nullable=False) - is_correct_document = Column(Boolean, nullable=False) - pipeline_id = Column(String(500), nullable=True) - - meta = relationship("MetaLabelORM", back_populates="labels", lazy="joined") - - class MetaLabelORM(ORMBase): - __tablename__ = "meta_label" - - name = Column(String(100), index=True) - value = Column(String(1000), index=True) - labels = relationship("LabelORM", back_populates="meta") - - label_id = Column(String(100), nullable=False, index=True) - label_index = Column(String(100), nullable=False, index=True) - __table_args__ = ( # type: ignore - ForeignKeyConstraint( - [label_id, label_index], [LabelORM.id, LabelORM.index], ondelete="CASCADE", onupdate="CASCADE" - ), - {}, - ) - - -logger = logging.getLogger(__name__) - - -class SQLDocumentStore(BaseDocumentStore): - def __init__( - self, - url: str = "sqlite://", - index: str = "document", - label_index: str = "label", - duplicate_documents: str = "overwrite", - check_same_thread: bool = False, - isolation_level: Optional[str] = None, - ): - """ - An SQL backed DocumentStore. Currently supports SQLite, PostgreSQL and MySQL backends. - - :param url: URL for SQL database as expected by SQLAlchemy. More info here: https://docs.sqlalchemy.org/en/13/core/engines.html#database-urls - :param index: The documents are scoped to an index attribute that can be used when writing, querying, or deleting documents. - This parameter sets the default value for document index. - :param label_index: The default value of index attribute for the labels. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :param check_same_thread: Set to False to mitigate multithreading issues in older SQLite versions (see https://docs.sqlalchemy.org/en/14/dialects/sqlite.html?highlight=check_same_thread#threading-pooling-behavior) - :param isolation_level: see SQLAlchemy's `isolation_level` parameter for `create_engine()` (https://docs.sqlalchemy.org/en/14/core/engines.html#sqlalchemy.create_engine.params.isolation_level) - """ - # ensure the required dependencies were actually imported - sqlalchemy_import.check() - - super().__init__() - - create_engine_params = {} - if isolation_level: - create_engine_params["isolation_level"] = isolation_level - if "sqlite" in url: - engine = create_engine(url, connect_args={"check_same_thread": check_same_thread}, **create_engine_params) - else: - engine = create_engine(url, **create_engine_params) - Base.metadata.create_all(engine) - Session = sessionmaker(bind=engine) - self.session = Session() - self.index: str = index - self.label_index = label_index - self.duplicate_documents = duplicate_documents - if getattr(self, "similarity", None) is None: - self.similarity = None - self.use_windowed_query = True - if "sqlite" in url: - import sqlite3 - - if sqlite3.sqlite_version < "3.25": - self.use_windowed_query = False - - def get_document_by_id( - self, id: str, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ) -> Optional[Document]: - """Fetch a document by specifying its text id string""" - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - documents = self.get_documents_by_id([id], index) - document = documents[0] if documents else None - return document - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """Fetch documents by specifying a list of text id strings""" - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - index = index or self.index - - documents = [] - for i in range(0, len(ids), batch_size): - query = self.session.query(DocumentORM).filter( - DocumentORM.id.in_(ids[i : i + batch_size]), DocumentORM.index == index - ) - for row in query.all(): - documents.append(self._convert_sql_row_to_document(row)) - - return documents - - def get_documents_by_vector_ids(self, vector_ids: List[str], index: Optional[str] = None, batch_size: int = 10_000): - """Fetch documents by specifying a list of text vector id strings""" - index = index or self.index - - documents = [] - for i in range(0, len(vector_ids), batch_size): - query = self.session.query(DocumentORM).filter( - DocumentORM.vector_id.in_(vector_ids[i : i + batch_size]), DocumentORM.index == index - ) - for row in query.all(): - documents.append(self._convert_sql_row_to_document(row)) - - sorted_documents = sorted(documents, key=lambda doc: vector_ids.index(doc.meta["vector_id"])) - return sorted_documents - - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - documents = list( - self.get_all_documents_generator( - index=index, filters=filters, return_embedding=return_embedding, batch_size=batch_size - ) - ) - return documents - - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: int = 10_000, - headers: Optional[Dict[str, str]] = None, - ) -> Generator[Document, None, None]: - """ - Get documents from the document store. Under-the-hood, documents are fetched in batches from the - document store and yielded as individual documents. This method can be used to iteratively process - a large number of documents without having to load all documents in memory. - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the documents to return. - Example: {"name": ["some", "more"], "category": ["only_one"]} - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - """ - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - if return_embedding is True: - raise Exception("return_embeddings is not supported by SQLDocumentStore.") - result = self._query(index=index, filters=filters, batch_size=batch_size) - yield from result - - def _create_document_field_map(self) -> Dict: - """ - There is no field mapping required - """ - return {} - - def _query( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - vector_ids: Optional[List[str]] = None, - only_documents_without_embedding: bool = False, - batch_size: int = 10_000, - ): - """ - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the documents to return. - Example: {"name": ["some", "more"], "category": ["only_one"]} - :param vector_ids: List of vector_id strings to filter the documents by. - :param only_documents_without_embedding: return only documents without an embedding. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - """ - index = index or self.index - # Generally ORM objects kept in memory cause performance issue - # Hence using directly column name improve memory and performance. - # Refer https://stackoverflow.com/questions/23185319/why-is-loading-sqlalchemy-objects-via-the-orm-5-8x-slower-than-rows-via-a-raw-my - documents_query = self.session.query( - DocumentORM.id, DocumentORM.content, DocumentORM.content_type, DocumentORM.vector_id - ).filter_by(index=index) - - if filters: - logger.warning("filters won't work on metadata fields containing compound data types") - parsed_filter = LogicalFilterClause.parse(filters) - select_ids = parsed_filter.convert_to_sql(MetaDocumentORM) - documents_query = documents_query.filter(DocumentORM.id.in_(select_ids)) - - if only_documents_without_embedding: - documents_query = documents_query.filter(DocumentORM.vector_id.is_(None)) - if vector_ids: - documents_query = documents_query.filter(DocumentORM.vector_id.in_(vector_ids)) - - documents_map = {} - - if self.use_windowed_query: - documents_query = self._windowed_query(documents_query, DocumentORM.id, batch_size) - - for i, row in enumerate(documents_query, start=1): - documents_map[row.id] = Document.from_dict( - { - "id": row.id, - "content": row.content, - "content_type": row.content_type, - "meta": {} if row.vector_id is None else {"vector_id": row.vector_id}, - } - ) - if i % batch_size == 0: - documents_map = self._get_documents_meta(documents_map) - yield from documents_map.values() - documents_map = {} - if documents_map: - documents_map = self._get_documents_meta(documents_map) - yield from documents_map.values() - - def _get_documents_meta(self, documents_map): - doc_ids = documents_map.keys() - meta_query = self.session.query( - MetaDocumentORM.document_id, MetaDocumentORM.name, MetaDocumentORM.value - ).filter(MetaDocumentORM.document_id.in_(doc_ids)) - - for row in meta_query.all(): - documents_map[row.document_id].meta[row.name] = row.value - return documents_map - - def get_all_labels( - self, index=None, filters: Optional[FilterType] = None, headers: Optional[Dict[str, str]] = None - ): - """ - Return all labels in the document store - """ - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - index = index or self.label_index - # TODO: Use batch_size - label_rows = self.session.query(LabelORM).filter_by(index=index).all() - labels = [self._convert_sql_row_to_label(row) for row in label_rows] - - return labels - - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: int = 10_000, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ) -> None: - """ - Indexes documents for later queries. - - :param documents: a list of Python dictionaries or a list of Haystack Document objects. - For documents as dictionaries, the format is {"text": ""}. - Optionally: Include meta data via {"text": "", - "meta":{"name": ", "author": "somebody", ...}} - It can be used for filtering and is accessible in the responses of the Finder. - :param index: add an optional index attribute to documents. It can be later used for filtering. For instance, - documents for evaluation can be indexed in a separate index than the documents for search. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents - but is considerably slower (default). - fail: an error is raised if the document ID of the document being added already - exists. - - :return: None - """ - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - index = index or self.index - duplicate_documents = duplicate_documents or self.duplicate_documents - if len(documents) == 0: - return - # Make sure we comply to Document class format - document_objects = [Document.from_dict(d) if isinstance(d, dict) else d for d in documents] - - document_objects = self._handle_duplicate_documents( - documents=document_objects, index=index, duplicate_documents=duplicate_documents - ) - for i in range(0, len(document_objects), batch_size): - docs_orm = [] - for doc in document_objects[i : i + batch_size]: - meta_fields = doc.meta or {} - if "classification" in meta_fields: - meta_fields = self._flatten_classification_meta_fields(meta_fields) - vector_id = meta_fields.pop("vector_id", None) - meta_orms = [MetaDocumentORM(name=key, value=value) for key, value in meta_fields.items()] - doc_orm = DocumentORM( - id=doc.id, - content=doc.to_dict()["content"], - content_type=doc.content_type, - vector_id=vector_id, - meta=meta_orms, - index=index, - ) - if duplicate_documents == "overwrite": - # First old meta data cleaning is required - self.session.query(MetaDocumentORM).filter_by(document_id=doc.id).delete() - self.session.merge(doc_orm) - else: - docs_orm.append(doc_orm) - - if docs_orm: - self.session.add_all(docs_orm) - - try: - self.session.commit() - except Exception as ex: - logger.error("Transaction rollback: %s", ex.__cause__) - # Rollback is important here otherwise self.session will be in inconsistent state and next call will fail - self.session.rollback() - raise ex - - def write_labels(self, labels, index=None, headers: Optional[Dict[str, str]] = None): - """Write annotation labels into document store.""" - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - labels = [Label.from_dict(l) if isinstance(l, dict) else l for l in labels] - index = index or self.label_index - - duplicate_ids: list = [label.id for label in self._get_duplicate_labels(labels, index=index)] - if len(duplicate_ids) > 0: - logger.warning( - "Duplicate Label IDs: Inserting a Label whose id already exists in this document store." - " This will overwrite the old Label. Please make sure Label.id is a unique identifier of" - " the answer annotation and not the question." - " Problematic ids: %s", - ",".join(duplicate_ids), - ) - # TODO: Use batch_size - - for label in labels: - # TODO As of now, we write documents as part of the Label table as this is consistent with the other - # document stores (e.g. elasticsearch) where "indices" are completely independent. - # We should eventually switch to an approach here that writes related documents to the document table if not already existing. - # See Issue XXX - - # self.write_documents(documents=[label.document], index=index, duplicate_documents="skip") - - # TODO: Handle label meta data - - # Sanitize fields to adhere to SQL constraints - answer = label.answer - if answer is not None: - answer = answer.to_json() - - no_answer = label.no_answer - if label.no_answer is None: - no_answer = False - - document = label.document - if document is not None: - document = document.to_json() - - label_orm = LabelORM( - id=label.id, - no_answer=no_answer, - # document_id=label.document.id, - document=document, - origin=label.origin, - query=label.query, - is_correct_answer=label.is_correct_answer, - is_correct_document=label.is_correct_document, - answer=answer, - pipeline_id=label.pipeline_id, - index=index, - ) - if label.id in duplicate_ids: - self.session.merge(label_orm) - else: - self.session.add(label_orm) - - # TODO: investigate why test_multilabel() failed when not committing within the loop - # Seems that in some cases only the last label get than "committed" - self.session.commit() - - def update_vector_ids(self, vector_id_map: Dict[str, str], index: Optional[str] = None, batch_size: int = 10_000): - """ - Update vector_ids for given document_ids. - - :param vector_id_map: dict containing mapping of document_id -> vector_id. - :param index: filter documents by the optional index attribute for documents in database. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - """ - index = index or self.index - for chunk_map in self.chunked_dict(vector_id_map, size=batch_size): - self.session.query(DocumentORM).filter(DocumentORM.id.in_(chunk_map), DocumentORM.index == index).update( - {DocumentORM.vector_id: case(chunk_map, value=DocumentORM.id)}, synchronize_session=False - ) - try: - self.session.commit() - except Exception as ex: - logger.error("Transaction rollback: %s", ex.__cause__) - self.session.rollback() - raise ex - - def reset_vector_ids(self, index: Optional[str] = None): - """ - Set vector IDs for all documents as None - """ - index = index or self.index - self.session.query(DocumentORM).filter_by(index=index).update({DocumentORM.vector_id: null()}) - self.session.commit() - - def update_document_meta(self, id: str, meta: Dict[str, str], index: Optional[str] = None): - """ - Update the metadata dictionary of a document by specifying its string id - """ - if not index: - index = self.index - self.session.query(MetaDocumentORM).filter_by(document_id=id, document_index=index).delete() - meta_orms = [ - MetaDocumentORM(name=key, value=value, document_id=id, document_index=index) for key, value in meta.items() - ] - for m in meta_orms: - self.session.add(m) - self.session.commit() - - def get_document_count( - self, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - ) -> int: - """ - Return the number of documents in the document store. - """ - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - index = index or self.index - query = self.session.query(DocumentORM).filter_by(index=index) - - if filters: - for key, values in filters.items(): - query = query.join(MetaDocumentORM, aliased=True).filter( - MetaDocumentORM.name == key, MetaDocumentORM.value.in_(values) - ) - - if only_documents_without_embedding: - query = query.filter(DocumentORM.vector_id.is_(None)) - - count = query.count() - return count - - def get_label_count(self, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None) -> int: - """ - Return the number of labels in the document store - """ - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - index = index or self.label_index - return self.session.query(LabelORM).filter_by(index=index).count() - - def _convert_sql_row_to_document(self, row) -> Document: - doc_dict = { - "id": row.id, - "content": row.content, - "content_type": row.content_type, - "meta": {meta.name: meta.value for meta in row.meta}, - } - document = Document.from_dict(doc_dict) - - if row.vector_id: - document.meta["vector_id"] = row.vector_id - return document - - def _convert_sql_row_to_label(self, row) -> Label: - answer = row.answer - if answer is not None: - answer = Answer.from_json(answer) - - label = Label( - query=row.query, - answer=answer, - document=Document.from_json(row.document), - is_correct_answer=row.is_correct_answer, - is_correct_document=row.is_correct_document, - origin=row.origin, - id=row.id, - pipeline_id=row.pipeline_id, - created_at=str(row.created_at), - updated_at=str(row.updated_at), - meta=row.meta, - ) - return label - - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - raise NotImplementedError( - "SQLDocumentStore is currently not supporting embedding queries. " - "Change the query type (e.g. by choosing a different retriever) " - "or change the DocumentStore (e.g. to ElasticsearchDocumentStore)" - ) - - def delete_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - - :param index: Index name to delete the document from. - :param filters: Optional filters to narrow down the documents to be deleted. - :return: None - """ - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - logger.warning( - """DEPRECATION WARNINGS: - 1. delete_all_documents() method is deprecated, please use delete_documents method - For more details, please refer to the issue: https://github.com/deepset-ai/haystack/issues/1045 - """ - ) - self.delete_documents(index, None, filters) - - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - - :param index: Index name to delete the document from. If None, the - DocumentStore's default index (self.index) will be used. - :param ids: Optional list of IDs to narrow down the documents to be deleted. - :param filters: Optional filters to narrow down the documents to be deleted. - Example filters: {"name": ["some", "more"], "category": ["only_one"]}. - If filters are provided along with a list of IDs, this method deletes the - intersection of the two query results (documents that match the filters and - have their ID in the list). - :return: None - """ - index = index or self.index - if not filters and not ids: - self.session.query(DocumentORM).filter_by(index=index).delete(synchronize_session=False) - else: - document_ids_to_delete = self.session.query(DocumentORM.id).filter(DocumentORM.index == index) - if filters: - for key, values in filters.items(): - document_ids_to_delete = document_ids_to_delete.join(MetaDocumentORM, aliased=True).filter( - MetaDocumentORM.name == key, MetaDocumentORM.value.in_(values) - ) - if ids: - document_ids_to_delete = document_ids_to_delete.filter(DocumentORM.id.in_(ids)) - - inner_query = document_ids_to_delete.subquery() - self.session.query(DocumentORM).filter(DocumentORM.id.in_(aliased(inner_query))).delete( - synchronize_session=False - ) - - self.session.commit() - - def delete_index(self, index: str): - """ - Delete an existing index. The index including all data will be removed. - - :param index: The name of the index to delete. - :return: None - """ - SQLDocumentStore.delete_documents(self, index) - - def delete_labels( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete labels from the document store. All labels are deleted if no filters are passed. - - :param index: Index name to delete the labels from. If None, the - DocumentStore's default label index (self.label_index) will be used. - :param ids: Optional list of IDs to narrow down the labels to be deleted. - :param filters: Optional filters to narrow down the labels to be deleted. - Example filters: {"id": ["9a196e41-f7b5-45b4-bd19-5feb7501c159", "9a196e41-f7b5-45b4-bd19-5feb7501c159"]} or {"query": ["question2"]} - :return: None - """ - if headers: - raise NotImplementedError("SQLDocumentStore does not support headers.") - - index = index or self.label_index - if not filters and not ids: - self.session.query(LabelORM).filter_by(index=index).delete(synchronize_session=False) - else: - label_ids_to_delete = self.session.query(LabelORM.id).filter_by(index=index) - if filters: - for key, values in filters.items(): - label_attribute = getattr(LabelORM, key) - label_ids_to_delete = label_ids_to_delete.filter(label_attribute.in_(values)) - - if ids: - label_ids_to_delete = label_ids_to_delete.filter(LabelORM.id.in_(ids)) - - inner_query = label_ids_to_delete.subquery() - self.session.query(LabelORM).filter(LabelORM.id.in_(aliased(inner_query))).delete(synchronize_session=False) - - self.session.commit() - - def _get_or_create(self, session, model, **kwargs): - instance = session.query(model).filter_by(**kwargs).first() - if instance: - return instance - else: - instance = model(**kwargs) - session.add(instance) - session.commit() - return instance - - def chunked_dict(self, dictionary, size): - it = iter(dictionary) - for _ in range(0, len(dictionary), size): - yield {k: dictionary[k] for k in itertools.islice(it, size)} - - def _column_windows(self, session, column, windowsize): - """Return a series of WHERE clauses against - a given column that break it into windows. - - Result is an iterable of tuples, consisting of - ((start, end), whereclause), where (start, end) are the ids. - - The code is taken from: https://github.com/sqlalchemy/sqlalchemy/wiki/RangeQuery-and-WindowedRangeQuery - """ - - def int_for_range(start_id, end_id): - if end_id: - return and_(column >= start_id, column < end_id) - else: - return column >= start_id - - q = session.query(column, func.row_number().over(order_by=column).label("rownum")).from_self(column) - if windowsize > 1: - q = q.filter(text("rownum %% %d=1" % windowsize)) - - intervals = [id for id, in q] - - while intervals: - start = intervals.pop(0) - if intervals: - end = intervals[0] - else: - end = None - yield int_for_range(start, end) - - def _windowed_query(self, q, column, windowsize): - """ "Break a Query into windows on a given column.""" - - for whereclause in self._column_windows(q.session, column, windowsize): - for row in q.filter(whereclause).order_by(column): - yield row - - def _flatten_classification_meta_fields(self, meta_fields: dict) -> dict: - """ - Since SQLDocumentStore does not support dictionaries for metadata values, - the DocumentClassifier output is flattened - """ - meta_fields["classification.label"] = meta_fields["classification"]["label"] - meta_fields["classification.score"] = meta_fields["classification"]["score"] - meta_fields["classification.details"] = str(meta_fields["classification"]["details"]) - del meta_fields["classification"] - return meta_fields diff --git a/haystack/document_stores/utils.py b/haystack/document_stores/utils.py deleted file mode 100644 index 70c2b29cdc..0000000000 --- a/haystack/document_stores/utils.py +++ /dev/null @@ -1,285 +0,0 @@ -import typing -from typing import Dict, List, Optional, Tuple, Union, Generator - -import json -import logging -from datetime import datetime - -from haystack.schema import Document, Label, Answer, Span -from haystack.nodes.preprocessor import PreProcessor - -if typing.TYPE_CHECKING: - # This results in a circular import if we don't use typing.TYPE_CHECKING - from haystack.document_stores.base import BaseDocumentStore - - -logger = logging.getLogger(__name__) - - -def eval_data_from_json( - filename: str, - max_docs: Optional[Union[int, bool]] = None, - preprocessor: Optional[PreProcessor] = None, - open_domain: bool = False, -) -> Tuple[List[Document], List[Label]]: - """ - Read Documents + Labels from a SQuAD-style file. - Document and Labels can then be indexed to the DocumentStore and be used for evaluation. - - :param filename: Path to file in SQuAD format - :param max_docs: This sets the number of documents that will be loaded. By default, this is set to None, thus reading in all available eval documents. - :param open_domain: Set this to True if your file is an open domain dataset where two different answers to the same question might be found in different contexts. - """ - docs: List[Document] = [] - labels = [] - problematic_ids = [] - - with open(filename, "r", encoding="utf-8") as file: - data = json.load(file) - if "title" not in data["data"][0]: - logger.warning("No title information found for documents in QA file: %s", filename) - - for squad_document in data["data"]: - if max_docs and len(docs) > max_docs: - break - # Extracting paragraphs and their labels from a SQuAD document dict - cur_docs, cur_labels, cur_problematic_ids = _extract_docs_and_labels_from_dict( - squad_document, preprocessor, open_domain - ) - docs.extend(cur_docs) - labels.extend(cur_labels) - problematic_ids.extend(cur_problematic_ids) - if len(problematic_ids) > 0: - logger.warning( - "Could not convert an answer for %s questions.\nThere were conversion errors for question ids: %s", - len(problematic_ids), - problematic_ids, - ) - return docs, labels - - -def eval_data_from_jsonl( - filename: str, - batch_size: Optional[int] = None, - max_docs: Optional[Union[int, bool]] = None, - preprocessor: Optional[PreProcessor] = None, - open_domain: bool = False, -) -> Generator[Tuple[List[Document], List[Label]], None, None]: - """ - Read Documents + Labels from a SQuAD-style file in jsonl format, i.e. one document per line. - Document and Labels can then be indexed to the DocumentStore and be used for evaluation. - - This is a generator which will yield one tuple per iteration containing a list - of batch_size documents and a list with the documents' labels. - If batch_size is set to None, this method will yield all documents and labels. - - :param filename: Path to file in SQuAD format - :param max_docs: This sets the number of documents that will be loaded. By default, this is set to None, thus reading in all available eval documents. - :param open_domain: Set this to True if your file is an open domain dataset where two different answers to the same question might be found in different contexts. - """ - docs: List[Document] = [] - labels = [] - problematic_ids = [] - - with open(filename, "r", encoding="utf-8") as file: - for document in file: - if max_docs and len(docs) > max_docs: - break - # Extracting paragraphs and their labels from a SQuAD document dict - squad_document = json.loads(document) - cur_docs, cur_labels, cur_problematic_ids = _extract_docs_and_labels_from_dict( - squad_document, preprocessor, open_domain - ) - docs.extend(cur_docs) - labels.extend(cur_labels) - problematic_ids.extend(cur_problematic_ids) - - if batch_size is not None and len(docs) >= batch_size: - if len(problematic_ids) > 0: - logger.warning( - "Could not convert an answer for %s questions.\n" - "There were conversion errors for question ids: %s", - len(problematic_ids), - problematic_ids, - ) - yield docs, labels - docs = [] - labels = [] - problematic_ids = [] - - yield docs, labels - - -def squad_json_to_jsonl(squad_file: str, output_file: str): - """ - Converts a SQuAD-json-file into jsonl format with one document per line. - - :param squad_file: SQuAD-file in json format. - :param output_file: Name of output file (SQuAD in jsonl format) - """ - with open(squad_file, encoding="utf-8") as json_file, open(output_file, "w", encoding="utf-8") as jsonl_file: - squad_json = json.load(json_file) - - for doc in squad_json["data"]: - json.dump(doc, jsonl_file) - jsonl_file.write("\n") - - -def _extract_docs_and_labels_from_dict( - document_dict: Dict, preprocessor: Optional[PreProcessor] = None, open_domain: bool = False -): - """ - Set open_domain to True if you are trying to load open_domain labels (i.e. labels without doc id or start idx) - """ - docs = [] - labels = [] - problematic_ids = [] - - # get all extra fields from document level (e.g. title) - meta_doc = {k: v for k, v in document_dict.items() if k not in ("paragraphs", "title")} - for paragraph in document_dict["paragraphs"]: - ## Create Metadata - cur_meta = {"name": document_dict.get("title", None)} - # all other fields from paragraph level - meta_paragraph = {k: v for k, v in paragraph.items() if k not in ("qas", "context")} - cur_meta.update(meta_paragraph) - # meta from parent document - cur_meta.update(meta_doc) - - ## Create Document - cur_full_doc = Document(content=paragraph["context"], meta=cur_meta) - if preprocessor is not None: - splits_docs = preprocessor.process(documents=[cur_full_doc]) - # we need to pull in _split_id into the document id for unique reference in labels - splits: List[Document] = [] - offset = 0 - for d in splits_docs: - id = f"{d.id}-{d.meta['_split_id']}" - d.meta["_split_offset"] = offset - offset += len(d.content) - # offset correction based on splitting method - if preprocessor.split_by == "word": - offset += 1 - elif preprocessor.split_by == "passage": - offset += 2 - else: - raise NotImplementedError - mydoc = Document(content=d.content, id=id, meta=d.meta) - splits.append(mydoc) - else: - splits = [cur_full_doc] - docs.extend(splits) - - ## Assign Labels to corresponding documents - for qa in paragraph["qas"]: - meta_qa = { - k: v for k, v in qa.items() if k not in ("is_impossible", "answers", "question", "id", "missing") - } - if not qa.get("is_impossible", False): - for answer in qa["answers"]: - ans = answer["text"] - # TODO The following block of code means that answer_start is never calculated - # and cur_id is always None for open_domain - # This can be rewritten so that this function could try to calculate offsets - # and populate id in open_domain mode - if open_domain: - # TODO check with Branden why we want to treat open_domain here differently. - # Shouldn't this be something configured at eval time only? - cur_ans_start = answer.get("answer_start", 0) - # cur_id = '0' - label = Label( - query=qa["question"], - answer=Answer(answer=ans, type="extractive", score=0.0), - document=None, # type: ignore - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - meta=meta_qa, - ) - labels.append(label) - else: - ans_position = cur_full_doc.content[ - answer["answer_start"] : answer["answer_start"] + len(str(ans)) - ] - if ans != ans_position: - # do not use answer - problematic_ids.append(qa.get("id", "missing")) - break - # find corresponding document or split - if len(splits) == 1: - # cur_id = splits[0].id - cur_ans_start = answer["answer_start"] - cur_doc = splits[0] - else: - for s in splits: - # If answer start offset is contained in passage we assign the label to that passage - if (answer["answer_start"] >= s.meta["_split_offset"]) and ( - answer["answer_start"] < (s.meta["_split_offset"] + len(s.content)) - ): - cur_doc = s - cur_ans_start = answer["answer_start"] - s.meta["_split_offset"] - # If a document is splitting an answer we add the whole answer text to the document - if s.content[cur_ans_start : cur_ans_start + len(ans)] != ans: - s.content = s.content[:cur_ans_start] + ans - break - cur_answer = Answer( - answer=ans, - type="extractive", - score=0.0, - context=cur_doc.content, - offsets_in_document=[Span(start=cur_ans_start, end=cur_ans_start + len(ans))], - offsets_in_context=[Span(start=cur_ans_start, end=cur_ans_start + len(ans))], - document_ids=[cur_doc.id], - ) - label = Label( - query=qa["question"], - answer=cur_answer, - document=cur_doc, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - meta=meta_qa, - ) - labels.append(label) - else: - # for no_answer we need to assign each split as not fitting to the question - for s in splits: - label = Label( - query=qa["question"], - answer=Answer( - answer="", - type="extractive", - score=0.0, - offsets_in_document=[Span(start=0, end=0)], - offsets_in_context=[Span(start=0, end=0)], - ), - document=s, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - meta=meta_qa, - ) - - labels.append(label) - - return docs, labels, problematic_ids - - -def convert_date_to_rfc3339(date: str) -> str: - """ - Converts a date to RFC3339 format, as Weaviate requires dates to be in RFC3339 format including the time and - timezone. - - If the provided date string does not contain a time and/or timezone, we use 00:00 as default time - and UTC as default time zone. - - This method cannot be part of WeaviateDocumentStore, as this would result in a circular import between weaviate.py - and filter_utils.py. - """ - parsed_datetime = datetime.fromisoformat(date) - if parsed_datetime.utcoffset() is None: - converted_date = parsed_datetime.isoformat() + "Z" - else: - converted_date = parsed_datetime.isoformat() - - return converted_date diff --git a/haystack/document_stores/weaviate.py b/haystack/document_stores/weaviate.py deleted file mode 100644 index 5484ca16c6..0000000000 --- a/haystack/document_stores/weaviate.py +++ /dev/null @@ -1,1714 +0,0 @@ -import hashlib -import json -import logging -import re -import uuid -from typing import Any, Dict, Generator, List, Optional, Union - -import numpy as np -from tqdm import tqdm - -from haystack.schema import Document, FilterType, Label -from haystack.document_stores import KeywordDocumentStore -from haystack.utils.batching import get_batches_from_generator -from haystack.document_stores.filter_utils import LogicalFilterClause -from haystack.document_stores.utils import convert_date_to_rfc3339 -from haystack.errors import DocumentStoreError, HaystackError -from haystack.nodes.retriever import DenseRetriever -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install farm-haystack[weaviate]'") as weaviate_import: - import weaviate - from weaviate import AuthApiKey, AuthBearerToken, AuthClientCredentials, AuthClientPassword, client, gql - -logger = logging.getLogger(__name__) -UUID_PATTERN = re.compile(r"^[\da-f]{8}-([\da-f]{4}-){3}[\da-f]{12}$", re.IGNORECASE) -SUPPORTED_PROPERTY_TYPES = { - "string", - "string[]", - "int", - "int[]", - "boolean", - "boolean[]", - "number", - "number[]", - "date", - "date[]", - "text", - "text[]", -} - - -class WeaviateDocumentStoreError(DocumentStoreError): - pass - - -class WeaviateDocumentStore(KeywordDocumentStore): - """ - - Weaviate is a cloud-native, modular, real-time vector search engine built to scale your machine learning models. - (See https://weaviate.io/developers/weaviate/current/index.html#what-is-weaviate) - - Some of the key differences in contrast to FAISS: - 1. Stores everything in one place: documents, meta data and vectors - so less network overhead when scaling this up - 2. Allows combination of vector search and scalar filtering, i.e. you can filter for a certain tag and do dense retrieval on that subset - 3. Has less variety of ANN algorithms, as of now only HNSW. - 4. Requires document ids to be in uuid-format. If wrongly formatted ids are provided at indexing time they will be replaced with uuids automatically. - - Weaviate python client is used to connect to the server, more details are here - https://weaviate.io/developers/weaviate/client-libraries/python - - Usage: - 1. Start a Weaviate server (see https://weaviate.io/developers/weaviate/current/getting-started/installation.html) - 2. Init a WeaviateDocumentStore in Haystack - - Connection Parameters Precedence: - The selection and priority of connection parameters are as follows: - 1. If `use_embedded` is set to True, an embedded Weaviate instance will be used, and all other connection parameters will be ignored. - 2. If `use_embedded` is False or not provided and an `api_key` is provided, the `api_key` will be used to authenticate through AuthApiKey, assuming a connection to a Weaviate Cloud Service (WCS) instance. - 3. If neither `use_embedded` nor `api_key` is provided, but a `username` and `password` are provided, they will be used to authenticate through AuthClientPassword, assuming an OIDC Resource Owner Password flow. - 4. If none of the above conditions are met, no authentication method will be used and a connection will be attempted with the provided `host` and `port` values without any authentication. - - Limitations: - The current implementation is not supporting the storage of labels, so you cannot run any evaluation workflows. - """ - - def __init__( - self, - host: Union[str, List[str]] = "http://localhost", - port: Union[int, List[int]] = 8080, - timeout_config: tuple = (5, 15), - username: Optional[str] = None, - password: Optional[str] = None, - scope: Optional[str] = "offline_access", - api_key: Optional[str] = None, - use_embedded: bool = False, - embedded_options: Optional[dict] = None, - additional_headers: Optional[Dict[str, Any]] = None, - index: str = "Document", - embedding_dim: int = 768, - content_field: str = "content", - name_field: str = "name", - similarity: str = "cosine", - index_type: str = "hnsw", - custom_schema: Optional[dict] = None, - return_embedding: bool = False, - embedding_field: str = "embedding", - progress_bar: bool = True, - duplicate_documents: str = "overwrite", - recreate_index: bool = False, - replication_factor: int = 1, - batch_size: int = 10_000, - ): - """ - :param host: Weaviate server connection URL for storing and processing documents and vectors. - For more details, see [Weaviate installation](https://weaviate.io/developers/weaviate/current/getting-started/installation.html). - :param port: The port of the Weaviate instance. - :param timeout_config: The Weaviate timeout config as a tuple of (retries, time out seconds). - :param username: The Weaviate username (standard authentication using http_auth). - :param password: Weaviate password (standard authentication using http_auth). - :param scope: The scope of the credentials when using the OIDC Resource Owner Password or Client Credentials authentication flow. - :param api_key: The Weaviate Cloud Services (WCS) API key (for WCS authentication). - :param use_embedded: Whether to use an embedded Weaviate instance. Default: False. - :param embedded_options: Custom options for the embedded Weaviate instance. Default: None. - :param additional_headers: Additional headers to be included in the requests sent to Weaviate, for example the bearer token. - :param index: Index name for document text, embedding, and metadata (in Weaviate terminology, this is a "Class" in the Weaviate schema). - :param embedding_dim: The embedding vector size. Default: 768. - :param content_field: Name of the field that might contain the answer and is passed to the Reader model (for example, "full_text"). - If no Reader is used (for example, in FAQ-Style QA), the plain content of this field is returned. - :param name_field: Name of the field that contains the title of the doc. - :param similarity: The similarity function used to compare document vectors. Available options are 'cosine' (default), 'dot_product', and 'l2'. - 'cosine' is recommended for Sentence Transformers. - :param index_type: Index type of any vector object defined in the Weaviate schema. The vector index type is pluggable. - Currently, only HSNW is supported. - See also [Weaviate documentation](https://weaviate.io/developers/weaviate/current/more-resources/performance.html). - :param custom_schema: Allows to create a custom schema in Weaviate. For more details, - see [Weaviate documentation](https://weaviate.io/developers/weaviate/current/schema/schema-configuration.html). - :param module_name: Vectorization module to convert data into vectors. Default is "text2vec-trasnformers" - For more details, see [Weaviate documentation](https://weaviate.io/developers/weaviate/current/modules/). - :param return_embedding: Returns document embedding. - :param embedding_field: Name of the field containing an embedding vector. - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param duplicate_documents:Handle duplicates document based on parameter options. - Parameter options: 'skip','overwrite','fail' - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: Raises an error if the document ID of the document being added already exists. - :param recreate_index: If set to True, deletes an existing Weaviate index and creates a new one using the config you are using for initialization. Note that all data in the old index is - lost if you choose to recreate the index. - :param replication_factor: Sets the Weaviate Class's replication factor in Weaviate at the time of Class creation. - See also [Weaviate documentation](https://weaviate.io/developers/weaviate/current/configuration/replication.html). - :param batch_size: The number of documents to index at once. - """ - weaviate_import.check() - super().__init__() - - # Connect to Weaviate server using python binding - if not use_embedded: - weaviate_url = f"{host}:{port}" - auth_client_secret = self._get_auth_secret(username, password, api_key, scope) - embedded_options = None - else: - weaviate_url = None - auth_client_secret = None - embedded_options = self._get_embedded_options(embedded_options) - - # Timeout config can only be defined as a list in YAML, but Weaviate expects a tuple - if isinstance(timeout_config, list): - timeout_config = tuple(timeout_config) - self.weaviate_client = client.Client( - url=weaviate_url, - embedded_options=embedded_options, - auth_client_secret=auth_client_secret, - timeout_config=timeout_config, - additional_headers=additional_headers, - ) - # Test Weaviate connection - try: - status = self.weaviate_client.is_ready() - if not status: - raise ConnectionError( - f"Initial connection to Weaviate failed. Make sure you run Weaviate instance " - f"at `{weaviate_url}` and that it has finished the initial ramp up (can take > 30s)." - ) - except Exception: - raise ConnectionError( - f"Initial connection to Weaviate failed. Make sure you run Weaviate instance " - f"at `{weaviate_url}` and that it has finished the initial ramp up (can take > 30s)." - ) - self.index = self._sanitize_index_name(index) - self.embedding_dim = embedding_dim - self.content_field = content_field - self.name_field = name_field - if similarity == "cosine": - self.similarity = "cosine" - elif similarity == "dot_product": - self.similarity = "dot" - elif similarity == "l2": - self.similarity = "l2-squared" - else: - raise DocumentStoreError( - f"It looks like you provided value '{similarity}' for similarity in the WeaviateDocumentStore constructor. Choose one of these values: 'cosine', 'l2', and 'dot_product'" - ) - self.index_type = index_type - self.custom_schema = custom_schema - self.return_embedding = return_embedding - self.embedding_field = embedding_field - self.progress_bar = progress_bar - self.duplicate_documents = duplicate_documents - self.replication_factor = replication_factor - self.batch_size = batch_size - - self._create_schema_and_index(self.index, recreate_index=recreate_index) - self.uuid_format_warning_raised = False - - @staticmethod - def _get_auth_secret( - username: Optional[str] = None, - password: Optional[str] = None, - api_key: Optional[str] = None, - scope: Optional[str] = "offline_access", - ) -> Optional[Union["AuthClientPassword", "AuthClientCredentials", "AuthBearerToken"]]: - if api_key: - return AuthApiKey(api_key=api_key) - elif username and password: - return AuthClientPassword(username, password, scope=scope) - return None - - @staticmethod - def _get_embedded_options(embedded_options: Optional[Dict[str, Any]] = None) -> "weaviate.EmbeddedOptions": - embedded_options = embedded_options or {} - return weaviate.EmbeddedOptions(**embedded_options) - - def _sanitize_index_name(self, index: Optional[str]) -> Optional[str]: - if index is None: - return None - elif "_" in index: - return "".join(x.capitalize() for x in index.split("_")) - else: - return index[0].upper() + index[1:] - - def _create_schema_and_index(self, index: Optional[str] = None, recreate_index: bool = False): - """ - Create a new index (schema/class in Weaviate) for storing documents in case if an - index (schema) with the name doesn't exist already. - """ - index = self._sanitize_index_name(index) or self.index - - if self.custom_schema: - schema = self.custom_schema - else: - schema = { - "classes": [ - { - "class": index, - "description": "Haystack index, it's a class in Weaviate", - "invertedIndexConfig": {"cleanupIntervalSeconds": 60}, - "vectorizer": "none", - "properties": [ - {"dataType": ["string"], "description": "Name Field", "name": self.name_field}, - { - "dataType": ["text"], - "description": "Document Content (e.g. the text)", - "name": self.content_field, - }, - ], - "vectorIndexConfig": {"distance": self.similarity}, - "replicationConfig": {"factor": self.replication_factor}, - } - ] - } - - if not self.weaviate_client.schema.contains(schema): - self.weaviate_client.schema.create(schema) - elif recreate_index and index is not None: - self._delete_index(index) - self.weaviate_client.schema.create(schema) - else: - # The index already exists in Weaviate. We need to check if the index's similarity metrics matches - # the one this class is initialized with, as Weaviate doesn't allow switching similarity - # metrics once an index alreadty exists in Weaviate. - _db_similarity = self.weaviate_client.schema.get(class_name=index)["vectorIndexConfig"]["distance"] - if _db_similarity != self.similarity: - raise ValueError( - f"This index already exists in Weaviate with similarity '{_db_similarity}'. " - f"If there is a Weaviate index created with a certain similarity, you can't " - f"query with a different similarity. If you need a different similarity, " - f"recreate the index. To do this, set the `recreate_index=True` argument." - ) - - def _convert_weaviate_result_to_document( - self, - result: dict, - return_embedding: bool, - scale_score: bool = True, - json_properties: Optional[List[str]] = None, - ) -> Document: - """ - Convert weaviate result dict into haystack document object. This is more involved because - weaviate search result dict varies between get and query interfaces. - Weaviate get methods return the data items in properties key, whereas the query doesn't. - """ - json_properties = json_properties or [] - - score = None - content = "" - - # Sample result dict from a get method: - # { - # 'class': 'Document', - # 'creationTimeUnix': 1621075584724, - # 'id': '1bad51b7-bd77-485d-8871-21c50fab248f', - # 'properties': { - # 'meta': "{'key1':'value1'}", - # 'name': 'name_5', - # 'content': 'text_5' - # }, - # 'vector': [] - # } - id = result.get("id") - embedding = result.get("vector") - - # If properties key is present, get all the document fields from it. - # otherwise, a direct lookup in result root dict - props = result.get("properties") - if not props: - props = result - - if props.get(self.content_field) is not None: - # Converting JSON-string to original datatype (string or nested list) - content = json.loads(str(props.get(self.content_field))) - - content_type = None - if props.get("content_type") is not None: - content_type = str(props.pop("content_type")) - - id_hash_keys = None - if props.get("id_hash_keys") is not None: - id_hash_keys = props.pop("id_hash_keys") - - # Weaviate creates "_additional" key for semantic search - if "_additional" in props: - if "certainty" in props["_additional"]: - score = props["_additional"]["certainty"] - # weaviate returns already scaled values - if score and not scale_score: - score = score * 2 - 1 - elif "distance" in props["_additional"]: - score = props["_additional"]["distance"] - if score: - # Weaviate returns the negative dot product. To make score comparable - # to other document stores, we take the negative. - if self.similarity == "dot": - score = -1 * score - if scale_score: - score = self.scale_to_unit_interval(score, self.similarity) - if "id" in props["_additional"]: - id = props["_additional"]["id"] - if "vector" in props["_additional"]: - embedding = props["_additional"]["vector"] - props.pop("_additional", None) - - # We put all additional data of the doc into meta_data and return it in the API - meta_data = {} - for k, v in props.items(): - if k in (self.content_field, self.embedding_field): - continue - if v is None: - continue - # Weaviate doesn't support dict as a property type. We store them as JSON strings and convert them back here. - if k in json_properties: - if isinstance(v, list): - v = [json.loads(str(item)) for item in v] - else: - v = json.loads(str(v)) - meta_data[k] = v - - document = Document.from_dict( - { - "id": id, - "content": content, - "content_type": content_type, - "meta": meta_data, - "score": score, - "id_hash_keys": id_hash_keys, - } - ) - - if return_embedding and embedding: - document.embedding = np.asarray(embedding, dtype=np.float32) - - return document - - def _create_document_field_map(self) -> Dict: - return {self.content_field: "content", self.embedding_field: "embedding"} - - def get_document_by_id( - self, id: str, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None - ) -> Optional[Document]: - """Fetch a document by specifying its uuid string""" - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - index = self._sanitize_index_name(index) or self.index - document = None - - id = self._sanitize_id(id=id, index=index) - result = None - try: - result = self.weaviate_client.data_object.get_by_id(id, class_name=index, with_vector=True) - except weaviate.exceptions.UnexpectedStatusCodeException as usce: - logger.debug("Weaviate could not get the document requested: %s", usce) - if result: - # We retrieve the JSON properties from the schema and convert them back to the Python dicts - json_properties = self._get_json_properties(index=index) - document = self._convert_weaviate_result_to_document( - result, return_embedding=True, json_properties=json_properties - ) - return document - - def get_documents_by_id( - self, - ids: List[str], - index: Optional[str] = None, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Fetch documents by specifying a list of uuid strings. - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - index = self._sanitize_index_name(index) or self.index - batch_size = batch_size or self.batch_size - # We retrieve the JSON properties from the schema and convert them back to the Python dicts - json_properties = self._get_json_properties(index=index) - documents = [] - # TODO: better implementation with multiple where filters instead of chatty call below? - for id in ids: - id = self._sanitize_id(id=id, index=index) - result = None - try: - result = self.weaviate_client.data_object.get_by_id(id, class_name=index, with_vector=True) - except weaviate.exceptions.UnexpectedStatusCodeException as usce: - logger.debug("Weaviate could not get the document requested: %s", usce) - if result: - document = self._convert_weaviate_result_to_document( - result, return_embedding=True, json_properties=json_properties - ) - documents.append(document) - return documents - - def _sanitize_id(self, id: str, index: Optional[str] = None) -> str: - """ - Generate a valid uuid if the provided id is not in uuid format. - Two documents with the same provided id and index name will get the same uuid. - """ - index = self._sanitize_index_name(index) or self.index - if not UUID_PATTERN.match(id): - hashed_id = hashlib.sha256((id + index).encode("utf-8")) # type: ignore - generated_uuid = str(uuid.UUID(hashed_id.hexdigest()[::2])) - if not self.uuid_format_warning_raised: - logger.warning( - "Document id %s is not in uuid format. Such ids will be replaced by uuids, in this case %s.", - id, - generated_uuid, - ) - self.uuid_format_warning_raised = True - id = generated_uuid - return id - - def _get_current_properties(self, index: Optional[str] = None) -> List[str]: - """ - Get all the existing properties in the schema, excluding those with complex types - like cross-reference - """ - index = self._sanitize_index_name(index) or self.index - cur_properties = [] - for class_item in self.weaviate_client.schema.get()["classes"]: - if class_item["class"] == index: - cur_properties = [ - item["name"] - for item in class_item.get("properties", []) - # dataType should be always there and contain only one item unless - # it's a cross-reference but here we try to be defensive against - # unexpected schemas - if set(item.get("dataType", [])).issubset(SUPPORTED_PROPERTY_TYPES) - ] - - return cur_properties - - def _get_date_properties(self, index: Optional[str] = None) -> List[str]: - """ - Get all existing properties of type 'date' in the schema. - """ - index = self._sanitize_index_name(index) or self.index - cur_properties = [] - for class_item in self.weaviate_client.schema.get()["classes"]: - if class_item["class"] == index: - cur_properties = [item["name"] for item in class_item["properties"] if item["dataType"][0] == "date"] - - return cur_properties - - def _get_json_properties(self, index: Optional[str] = None) -> List[str]: - """ - Get all existing properties that store JSON strings in the indexes' schema. - """ - index = self._sanitize_index_name(index) or self.index - cur_properties = [] - for class_item in self.weaviate_client.schema.get()["classes"]: - if class_item["class"] == index: - cur_properties = [ - item["name"] - for item in class_item["properties"] - if item["description"].startswith("JSON dynamic property") - ] - - return cur_properties - - def _update_schema( - self, new_prop: str, property_value: Union[List, str, int, float, bool], index: Optional[str] = None - ): - """ - Updates the schema with a new property. - """ - index = self._sanitize_index_name(index) or self.index - data_type = self._get_weaviate_type_of_value(property_value) - - description = f"dynamic property {new_prop}" - if data_type.startswith("dict"): - # Weaviate does not support dict type, so we use string or list of string instead - data_type = "string" + data_type[4:] - description = f"JSON dynamic property {new_prop}" - - property_dict = {"dataType": [data_type], "description": description, "name": new_prop} - self.weaviate_client.schema.property.create(index, property_dict) - - @staticmethod - def _get_weaviate_type_of_value(value: Union[List, str, int, float, bool]) -> str: - """ - Infers corresponding Weaviate data type for a value. - """ - data_type = "" - list_of_values = False - if isinstance(value, list): - list_of_values = True - value = value[0] - - if isinstance(value, str): - # If the value is parsable by datetime, it is a date - try: - convert_date_to_rfc3339(value) - data_type = "date" - # Otherwise, the value is a string - except ValueError: - data_type = "string" - elif isinstance(value, int): - data_type = "int" - elif isinstance(value, float): - data_type = "number" - elif isinstance(value, bool): - data_type = "boolean" - # Weaviate doesn't support dictionaries as property types, we'll convert them to JSON strings. - elif isinstance(value, dict): - data_type = "dict" - - if list_of_values: - data_type += "[]" - - return data_type - - def _check_document(self, cur_props: List[str], doc: dict) -> List[str]: - """ - Find the properties in the document that don't exist in the existing schema. - """ - return [item for item in doc.keys() if item not in cur_props] - - def write_documents( - self, - documents: Union[List[dict], List[Document]], - index: Optional[str] = None, - batch_size: Optional[int] = None, - duplicate_documents: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Add new documents to the DocumentStore. - - :param documents: List of `Dicts` or List of `Documents`. A dummy embedding vector for each document is automatically generated if it is not provided. The document id needs to be in uuid format. Otherwise a correctly formatted uuid will be automatically generated based on the provided id. - :param index: index name for storing the docs and metadata - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - If no batch_size is provided, self.batch_size is used. - :param duplicate_documents: Handle duplicates document based on parameter options. - Parameter options : ( 'skip','overwrite','fail') - skip: Ignore the duplicates documents - overwrite: Update any existing documents with the same ID when adding documents. - fail: an error is raised if the document ID of the document being added already - exists. - :raises DuplicateDocumentError: Exception trigger on duplicate document - :return: None - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - index = self._sanitize_index_name(index) or self.index - batch_size = batch_size or self.batch_size - self._create_schema_and_index(index, recreate_index=False) - field_map = self._create_document_field_map() - - duplicate_documents = duplicate_documents or self.duplicate_documents - assert ( - duplicate_documents in self.duplicate_documents_options - ), f"duplicate_documents parameter must be {', '.join(self.duplicate_documents_options)}" - - if len(documents) == 0: - logger.warning("Calling DocumentStore.write_documents() with empty list") - return - - # Auto schema feature https://github.com/semi-technologies/weaviate/issues/1539 - # Get and cache current properties in the schema - current_properties = self._get_current_properties(index) - - document_objects = [Document.from_dict(d, field_map=field_map) if isinstance(d, dict) else d for d in documents] - - # Weaviate has strict requirements for what ids can be used. - # We check the id format and sanitize it if no uuid was provided. - # Duplicate document ids will be mapped to the same generated uuid. - for do in document_objects: - do.id = self._sanitize_id(id=do.id, index=index) - - document_objects = self._handle_duplicate_documents( - documents=document_objects, index=index, duplicate_documents=duplicate_documents - ) - - # Weaviate requires that documents contain a vector in order to be indexed. These lines add a - # dummy vector so that indexing can still happen - dummy_embed_warning_raised = False - for do in document_objects: - if do.embedding is None: - dummy_embedding = np.random.rand(self.embedding_dim).astype(np.float32) - do.embedding = dummy_embedding - if not dummy_embed_warning_raised: - logger.warning( - "No embedding found in Document object being written into Weaviate. A dummy " - "embedding is being supplied so that indexing can still take place. This " - "embedding should be overwritten in order to perform vector similarity searches." - ) - dummy_embed_warning_raised = True - - # get the date properties of the index - date_fields = self._get_date_properties(index) - - batched_documents = get_batches_from_generator(document_objects, batch_size) - with tqdm(total=len(document_objects), disable=not self.progress_bar) as progress_bar: - for document_batch in batched_documents: - json_fields = [] - for doc in document_batch: - _doc = {**doc.to_dict(field_map=self._create_document_field_map())} - _ = _doc.pop("score", None) - - # In order to have a flat structure in elastic + similar behaviour to the other DocumentStores, - # we "unnest" all value within "meta" - if "meta" in _doc.keys(): - for k, v in _doc["meta"].items(): - if k in _doc.keys(): - raise ValueError( - f'"meta" info contains duplicate key "{k}" with the top-level document structure' - ) - # Weaviate doesn't support dictionaries as property types, so we convert them to JSON strings - if isinstance(v, dict): - json_fields.append(k) - v = json.dumps(v) - elif isinstance(v, list) and len(v) > 0 and isinstance(v[0], dict): - json_fields.append(k) - v = [json.dumps(item) for item in v] - _doc[k] = v - _doc.pop("meta") - - doc_id = str(_doc.pop("id")) - vector = _doc.pop(self.embedding_field) - - if self.similarity == "cosine": - self.normalize_embedding(vector) - - # Converting content to JSON-string as Weaviate doesn't allow other nested list for tables - _doc["content"] = json.dumps(_doc["content"]) - - # Check if additional properties are in the document, if so, - # append the schema with all the additional properties - missing_props = self._check_document(current_properties, _doc) - if missing_props: - for property in missing_props: - property_value = _doc[property] - if property in json_fields: - property_value = doc.meta[property] - self._update_schema(property, property_value, index) - current_properties.append(property) - # update the date fields as there might be new ones - date_fields = self._get_date_properties(index) - - # Weaviate requires dates to be in RFC3339 format - for date_field in date_fields: - _doc[date_field] = convert_date_to_rfc3339(_doc[date_field]) - - self.weaviate_client.batch.add_data_object( - data_object=_doc, class_name=index, uuid=doc_id, vector=vector - ) - # Ingest a batch of documents - results = self.weaviate_client.batch.create_objects() - # Weaviate returns errors for every failed document in the batch - if results is not None: - for result in results: - if ( - "result" in result - and "errors" in result["result"] - and "error" in result["result"]["errors"] - ): - for message in result["result"]["errors"]["error"]: - logger.error(message["message"]) - progress_bar.update(batch_size) - progress_bar.close() - - def update_document_meta( - self, id: str, meta: Dict[str, Union[List, str, int, float, bool]], index: Optional[str] = None - ): - """ - Update the metadata dictionary of a document by specifying its string id. - Overwrites only the specified fields, the unspecified ones remain unchanged. - """ - if not index: - index = self.index - - current_properties = self._get_current_properties(index) - - # Check if the new metadata contains additional properties and append them to the schema - missing_props = self._check_document(current_properties, meta) - if missing_props: - for property in missing_props: - self._update_schema(property, meta[property], index) - current_properties.append(property) - - # Weaviate requires dates to be in RFC3339 format - date_fields = self._get_date_properties(index) - for date_field in date_fields: - if date_field in meta and isinstance(meta[date_field], str): - meta[date_field] = convert_date_to_rfc3339(str(meta[date_field])) - - self.weaviate_client.data_object.update(meta, class_name=index, uuid=id) - - def get_embedding_count(self, filters: Optional[FilterType] = None, index: Optional[str] = None) -> int: - """ - Return the number of embeddings in the document store, which is the same as the number of documents since - every document has a default embedding. - """ - return self.get_document_count(filters=filters, index=index) - - def get_document_count( - self, - filters: Optional[FilterType] = None, - index: Optional[str] = None, - only_documents_without_embedding: bool = False, - headers: Optional[Dict[str, str]] = None, - ) -> int: - """ - Return the number of documents in the document store. - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - if only_documents_without_embedding: - return 0 - - index = self._sanitize_index_name(index) or self.index - doc_count = 0 - if filters: - filter_dict = LogicalFilterClause.parse(filters).convert_to_weaviate() - result = self.weaviate_client.query.aggregate(index).with_meta_count().with_where(filter_dict).do() - else: - result = self.weaviate_client.query.aggregate(index).with_meta_count().do() - - if "data" in result and "Aggregate" in result.get("data") and result.get("data").get("Aggregate").get(index): - doc_count = result.get("data").get("Aggregate").get(index)[0]["meta"]["count"] - - return doc_count - - def get_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Document]: - """ - Get documents from the document store. - - Note this limitation from the changelog of Weaviate 1.8.0: - - .. quote:: - Due to the increasing cost of each page outlined above, there is a limit to - how many objects can be retrieved using pagination. By default setting the sum - of offset and limit to higher than 10,000 objects, will lead to an error. - If you must retrieve more than 10,000 objects, you can increase this limit by - setting the environment variable `QUERY_MAXIMUM_RESULTS=`. - - Warning: Setting this to arbitrarily high values can make the memory consumption - of a single query explode and single queries can slow down the entire cluster. - We recommend setting this value to the lowest possible value that does not - interfere with your users' expectations. - - (https://github.com/semi-technologies/weaviate/releases/tag/v1.8.0) - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - If no batch_size is provided, self.batch_size is used. - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - index = self._sanitize_index_name(index) or self.index - batch_size = batch_size or self.batch_size - result = self.get_all_documents_generator( - index=index, filters=filters, return_embedding=return_embedding, batch_size=batch_size - ) - documents = list(result) - return documents - - def _get_all_documents_in_index( - self, - index: Optional[str], - filters: Optional[FilterType] = None, - batch_size: Optional[int] = None, - only_documents_without_embedding: bool = False, - ) -> Generator[dict, None, None]: - """ - Return all documents in a specific index in the document store - """ - index = self._sanitize_index_name(index) or self.index - batch_size = batch_size or self.batch_size - - # Build the properties to retrieve from Weaviate - properties = self._get_current_properties(index) - if self.similarity == "cosine": - properties.append("_additional {id, certainty, vector}") - else: - properties.append("_additional {id, distance, vector}") - - if filters: - filter_dict = LogicalFilterClause.parse(filters).convert_to_weaviate() - result = ( - self.weaviate_client.query.get(class_name=index, properties=properties).with_where(filter_dict).do() - ) - else: - result = self.weaviate_client.query.get(class_name=index, properties=properties).do() - - # Inherent Weaviate limitation to 100 elements forces us to loop here: - # https://weaviate-python-client.readthedocs.io/en/latest/weaviate.data.html?highlight=100#weaviate.data.DataObject.get - base_query = self.weaviate_client.query.get(class_name=index, properties=properties) - all_docs: List[Any] = [] - num_of_documents = self.get_document_count(index=index, filters=filters) - - while len(all_docs) < num_of_documents: - query = base_query - if filters: - filter_dict = LogicalFilterClause.parse(filters).convert_to_weaviate() - query = query.with_where(filter_dict) - - if all_docs: - # Passing offset:0 raises an error, so we pass it only after the first round - # `.with_limit()` must be used with `.with_offset`, or the latter won't work properly - # https://weaviate-python-client.readthedocs.io/en/latest/weaviate.gql.html?highlight=offset#weaviate.gql.get.GetBuilder.with_offset - query = query.with_limit(100).with_offset(offset=len(all_docs)) - - try: - result = query.do() - except Exception as e: - raise WeaviateDocumentStoreError(f"Weaviate raised an exception: {e}") - - if "errors" in result: - raise WeaviateDocumentStoreError(f"Query results contain errors: {result['errors']}") - - # If `query.do` didn't raise and `result` doesn't contain errors, - # we are good accessing data - docs = result.get("data").get("Get").get(index) - - # `docs` can be empty if the query returned less documents than the actual - # number. This can happen when the number of document stored is greater - # than QUERY_MAXIMUM_RESULTS. - # See: https://weaviate.io/developers/weaviate/current/graphql-references/filters.html#offset-argument-pagination - if not docs: - logger.warning( - "The query returned less documents than expected: this can happen when " - "the value of the QUERY_MAXIMUM_RESULTS environment variable is lower than " - "the total number of documents stored. See Weaviate documentation for " - "more details." - ) - break - - all_docs += docs - - yield from all_docs - - def get_all_documents_generator( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - return_embedding: Optional[bool] = None, - batch_size: Optional[int] = None, - headers: Optional[Dict[str, str]] = None, - ) -> Generator[Document, None, None]: - """ - Get documents from the document store. Under-the-hood, documents are fetched in batches from the - document store and yielded as individual documents. This method can be used to iteratively process - a large number of documents without having to load all documents in memory. - - Note this limitation from the changelog of Weaviate 1.8.0: - - .. quote:: - Due to the increasing cost of each page outlined above, there is a limit to - how many objects can be retrieved using pagination. By default setting the sum - of offset and limit to higher than 10,000 objects, will lead to an error. - If you must retrieve more than 10,000 objects, you can increase this limit by - setting the environment variable `QUERY_MAXIMUM_RESULTS=`. - - Warning: Setting this to arbitrarily high values can make the memory consumption - of a single query explode and single queries can slow down the entire cluster. - We recommend setting this value to the lowest possible value that does not - interfere with your users' expectations. - - (https://github.com/semi-technologies/weaviate/releases/tag/v1.8.0) - - :param index: Name of the index to get the documents from. If None, the - DocumentStore's default index (self.index) will be used. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param return_embedding: Whether to return the document embeddings. - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - If no batch_size is provided, self.batch_size is used. - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - index = self._sanitize_index_name(index) or self.index - batch_size = batch_size or self.batch_size - - if return_embedding is None: - return_embedding = self.return_embedding - - results = self._get_all_documents_in_index(index=index, filters=filters, batch_size=batch_size) - # We retrieve the JSON properties from the schema and convert them back to the Python dicts - json_properties = self._get_json_properties(index=index) - for result in results: - document = self._convert_weaviate_result_to_document( - result, return_embedding=return_embedding, json_properties=json_properties - ) - yield document - - def query( - self, - query: Optional[str], - filters: Optional[FilterType] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query as defined by Weaviate semantic search. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param all_terms_must_match: Not used in Weaviate. - :param custom_query: Custom query that will executed using query.raw method, for more details refer - https://weaviate.io/developers/weaviate/current/graphql-references/filters.html - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Not used in Weaviate. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - if headers: - raise NotImplementedError("Weaviate does not support Custom HTTP headers!") - - if all_terms_must_match: - raise NotImplementedError("The `all_terms_must_match` option is not supported in Weaviate!") - - index = self._sanitize_index_name(index) or self.index - - # Build the properties to retrieve from Weaviate - properties = self._get_current_properties(index) - if self.similarity == "cosine": - properties.append("_additional {id, certainty, vector}") - else: - properties.append("_additional {id, distance, vector}") - - if query is None: - # Retrieval via custom query, no BM25 - if custom_query: - query_output = self.weaviate_client.query.raw(custom_query) - - # Naive retrieval without BM25, only filtering - elif filters: - filter_dict = LogicalFilterClause.parse(filters).convert_to_weaviate() - query_output = ( - self.weaviate_client.query.get(class_name=index, properties=properties) - .with_where(filter_dict) - .with_limit(top_k) - .do() - ) - else: - raise NotImplementedError( - "Weaviate does not support the retrieval of records without specifying a query or a filter!" - ) - - # Default Retrieval via BM25 using the user's query on `self.content_field` - else: - # Retrieval with BM25 AND filtering - if filters: - filter_dict = LogicalFilterClause.parse(filters).convert_to_weaviate() - gql_query = ( - gql.get.GetBuilder(class_name=index, properties=properties, connection=self.weaviate_client) - .with_limit(top_k) - .with_bm25(query=query, properties=[self.content_field]) - .with_where(filter_dict) - .build() - ) - else: - # BM25 retrieval without filtering - gql_query = ( - gql.get.GetBuilder(class_name=index, properties=properties, connection=self.weaviate_client) - .with_limit(top_k) - .with_bm25(query=query, properties=[self.content_field]) - .build() - ) - - query_output = self.weaviate_client.query.raw(gql_query) - - results = [] - if ( - query_output - and "data" in query_output - and "Get" in query_output.get("data") - and query_output.get("data").get("Get").get(index) - ): - results = query_output.get("data").get("Get").get(index) - - # We retrieve the JSON properties from the schema and convert them back to the Python dicts - json_properties = self._get_json_properties(index=index) - documents = [] - for result in results: - doc = self._convert_weaviate_result_to_document( - result, return_embedding=True, scale_score=scale_score, json_properties=json_properties - ) - documents.append(doc) - - return documents - - def query_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - all_terms_must_match: bool = False, - scale_score: bool = True, - ) -> List[List[Document]]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the provided queries as defined by keyword matching algorithms like BM25. - - This method lets you find relevant documents for a single query string (output: List of Documents), or a - a list of query strings (output: List of Lists of Documents). - - :param queries: Single query or list of queries. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - - :param top_k: How many documents to return per query. - :param custom_query: Custom query to be executed. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to False. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - # TODO - This method currently just calls query multiple times. Adapt this once there is a batch querying - # endpoint in Weaviate, which is currently not available, - # see https://stackoverflow.com/questions/71558676/does-weaviate-support-bulk-query#comment126569547_71561939 - - documents = [] - - if isinstance(filters, list): - if len(filters) != len(queries): - raise HaystackError( - "Number of filters does not match number of queries. Please provide as many filters" - " as queries or a single filter that will be applied to each query." - ) - else: - filters = [filters] * len(queries) if filters is not None else [{}] * len(queries) - - # run each query against Weaviate separately and combine the returned documents - for query, cur_filters in zip(queries, filters): - cur_docs = self.query( - query=query, - filters=cur_filters, - top_k=top_k, - custom_query=custom_query, - index=index, - headers=headers, - all_terms_must_match=all_terms_must_match, - scale_score=scale_score, - ) - documents.append(cur_docs) - - return documents - - def query_by_embedding( - self, - query_emb: np.ndarray, - filters: Optional[FilterType] = None, - top_k: int = 10, - index: Optional[str] = None, - return_embedding: Optional[bool] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: bool = True, - ) -> List[Document]: - """ - Find the document that is most similar to the provided `query_emb` by using a vector similarity metric. - - :param query_emb: Embedding of the query (e.g. gathered from DPR) - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return - :param index: index name for storing the docs and metadata - :param return_embedding: To return document embedding - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :return: - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - if return_embedding is None: - return_embedding = self.return_embedding - index = self._sanitize_index_name(index) or self.index - - # Build the properties to retrieve from Weaviate - properties = self._get_current_properties(index) - if self.similarity == "cosine": - properties.append("_additional {id, certainty, vector}") - else: - properties.append("_additional {id, distance, vector}") - - if self.similarity == "cosine": - self.normalize_embedding(query_emb) - - query_emb = query_emb.reshape(1, -1).astype(np.float32) - - query_string = {"vector": query_emb} - if filters: - filter_dict = LogicalFilterClause.parse(filters).convert_to_weaviate() - query_output = ( - self.weaviate_client.query.get(class_name=index, properties=properties) - .with_where(filter_dict) - .with_near_vector(query_string) - .with_limit(top_k) - .do() - ) - else: - query_output = ( - self.weaviate_client.query.get(class_name=index, properties=properties) - .with_near_vector(query_string) - .with_limit(top_k) - .do() - ) - - results = [] - if ( - query_output - and "data" in query_output - and "Get" in query_output.get("data") - and query_output.get("data").get("Get").get(index) - ): - results = query_output.get("data").get("Get").get(index) - - # We retrieve the JSON properties from the schema and convert them back to the Python dicts - json_properties = self._get_json_properties(index=index) - documents = [] - for result in results: - doc = self._convert_weaviate_result_to_document( - result, return_embedding=return_embedding, scale_score=scale_score, json_properties=json_properties - ) - documents.append(doc) - - return documents - - def update_embeddings( - self, - retriever: DenseRetriever, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - update_existing_embeddings: bool = True, - batch_size: Optional[int] = None, - ): - """ - Updates the embeddings in the document store using the encoding model specified in the retriever. - This can be useful if you want to change the embeddings for your documents (e.g. after changing the retriever config). - - :param retriever: Retriever to use to update the embeddings. - :param index: Index name to update - :param update_existing_embeddings: Weaviate mandates an embedding while creating the document itself. - This option must be always true for weaviate and it will update the embeddings for all the documents. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :param batch_size: When working with large number of documents, batching can help reduce memory footprint. - If no batch_size is specified, self.batch_size is used. - :return: None - """ - index = self._sanitize_index_name(index) or self.index - batch_size = batch_size or self.batch_size - - if not self.embedding_field: - raise RuntimeError("Specify the arg `embedding_field` when initializing WeaviateDocumentStore()") - - if update_existing_embeddings: - logger.info( - "Updating embeddings for all %s docs ...", - self.get_document_count(index=index) if logger.level > logging.DEBUG else 0, - ) - else: - raise RuntimeError( - "All the documents in Weaviate store have an embedding by default. Only update is allowed!" - ) - - result = self._get_all_documents_in_index(index=index, filters=filters, batch_size=batch_size) - # We retrieve the JSON properties from the schema and convert them back to the Python dicts - json_properties = self._get_json_properties(index=index) - - for result_batch in get_batches_from_generator(result, batch_size): - document_batch = [ - self._convert_weaviate_result_to_document(hit, return_embedding=False, json_properties=json_properties) - for hit in result_batch - ] - embeddings = retriever.embed_documents(document_batch) - self._validate_embeddings_shape( - embeddings=embeddings, num_documents=len(document_batch), embedding_dim=self.embedding_dim - ) - - if self.similarity == "cosine": - self.normalize_embedding(embeddings) - - for doc, emb in zip(document_batch, embeddings): - # Using update method to only update the embeddings, other properties will be in tact - self.weaviate_client.data_object.update({}, class_name=index, uuid=doc.id, vector=emb) - - def delete_all_documents( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - :param index: Index name to delete the document from. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - :return: None - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - logger.warning( - """DEPRECATION WARNINGS: - 1. delete_all_documents() method is deprecated, please use delete_documents method - For more details, please refer to the issue: https://github.com/deepset-ai/haystack/issues/1045 - """ - ) - self.delete_documents(index, None, filters) - - def delete_documents( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Delete documents in an index. All documents are deleted if no filters are passed. - - :param index: Index name to delete the document from. If None, the - DocumentStore's default index (self.index) will be used. - :param ids: Optional list of IDs to narrow down the documents to be deleted. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - ``` - If filters are provided along with a list of IDs, this method deletes the - intersection of the two query results (documents that match the filters and - have their ID in the list). - :return: None - """ - if headers: - raise NotImplementedError("WeaviateDocumentStore does not support headers.") - - index = self._sanitize_index_name(index) or self.index - - if not filters and not ids: - # Delete the existing index, then create an empty new one - self._create_schema_and_index(index, recreate_index=True) - return - - # Create index if it doesn't exist yet - self._create_schema_and_index(index, recreate_index=False) - - if ids and not filters: - for id in ids: - self.weaviate_client.data_object.delete(id, class_name=index) - - else: - # Use filters to restrict list of retrieved documents, before checking these against provided ids - docs_to_delete = self.get_all_documents(index, filters=filters) - if ids: - docs_to_delete = [doc for doc in docs_to_delete if doc.id in ids] - for doc in docs_to_delete: - self.weaviate_client.data_object.delete(doc.id, class_name=index) - - def delete_index(self, index: str): - """ - Delete an existing index. The index including all data will be removed. - - :param index: The name of the index to delete. - :return: None - """ - if index == self.index: - logger.warning( - "Deletion of default index '%s' detected. " - "If you plan to use this index again, please reinstantiate '%s' in order to avoid side-effects.", - index, - self.__class__.__name__, - ) - self._delete_index(index) - - def _delete_index(self, index: str): - index = self._sanitize_index_name(index) or index - if any(c for c in self.weaviate_client.schema.get()["classes"] if c["class"] == index): - self.weaviate_client.schema.delete_class(index) - logger.info("Index '%s' deleted.", index) - - def delete_labels( - self, - index: Optional[str] = None, - ids: Optional[List[str]] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Implemented to respect BaseDocumentStore's contract. - - Weaviate does not support labels (yet). - """ - raise NotImplementedError("Weaviate does not support labels (yet).") - - def get_all_labels( - self, - index: Optional[str] = None, - filters: Optional[FilterType] = None, - headers: Optional[Dict[str, str]] = None, - ) -> List[Label]: - """ - Implemented to respect BaseDocumentStore's contract. - - Weaviate does not support labels (yet). - """ - raise NotImplementedError("Weaviate does not support labels (yet).") - - def get_label_count(self, index: Optional[str] = None, headers: Optional[Dict[str, str]] = None) -> int: - """ - Implemented to respect BaseDocumentStore's contract. - - Weaviate does not support labels (yet). - """ - raise NotImplementedError("Weaviate does not support labels (yet).") - - def write_labels( - self, - labels: Union[List[Label], List[dict]], - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - Implemented to respect BaseDocumentStore's contract. - - Weaviate does not support labels (yet). - """ - raise NotImplementedError("Weaviate does not support labels (yet).") diff --git a/haystack/environment.py b/haystack/environment.py deleted file mode 100644 index 60f4304a94..0000000000 --- a/haystack/environment.py +++ /dev/null @@ -1,132 +0,0 @@ -# pylint: disable=global-statement -import logging -import os -import platform -import sys -from typing import Any, Dict, Optional - -from haystack import __version__ -from haystack.lazy_imports import LazyImport - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_import: - import torch - -with LazyImport() as transformers_import: - import transformers - - -# Any remote API (OpenAI, Cohere etc.) -HAYSTACK_REMOTE_API_BACKOFF_SEC = "HAYSTACK_REMOTE_API_BACKOFF_SEC" -HAYSTACK_REMOTE_API_MAX_RETRIES = "HAYSTACK_REMOTE_API_MAX_RETRIES" -HAYSTACK_REMOTE_API_TIMEOUT_SEC = "HAYSTACK_REMOTE_API_TIMEOUT_SEC" -HAYSTACK_PROMPT_TEMPLATE_ALLOWED_FUNCTIONS = "HAYSTACK_PROMPT_TEMPLATE_ALLOWED_FUNCTIONS" - -logger = logging.getLogger(__name__) - -# IS_DOCKER cache copy -IS_DOCKER_CACHE = None - - -def set_pytorch_secure_model_loading(flag_val="1"): - # To load secure only model pytorch requires value of - # TORCH_FORCE_WEIGHTS_ONLY_LOAD to be ["1", "y", "yes", "true"] - os_flag_val = os.getenv("TORCH_FORCE_WEIGHTS_ONLY_LOAD") - if os_flag_val is None: - os.environ["TORCH_FORCE_WEIGHTS_ONLY_LOAD"] = flag_val - else: - logger.info("TORCH_FORCE_WEIGHTS_ONLY_LOAD is already set to %s, Haystack will use the same.", os_flag_val) - - -def in_podman() -> bool: - """ - Podman run would create the file /run/.containernv, see: - https://github.com/containers/podman/blob/main/docs/source/markdown/podman-run.1.md.in#L31 - """ - return os.path.exists("/run/.containerenv") - - -def has_dockerenv() -> bool: - """ - This might not work anymore at some point (even if it's been a while now), see: - https://github.com/moby/moby/issues/18355#issuecomment-220484748 - """ - return os.path.exists("/.dockerenv") - - -def has_docker_cgroup_v1() -> bool: - """ - This only works with cgroups v1 - """ - path = "/proc/self/cgroup" # 'self' should be always symlinked to the actual PID - return os.path.isfile(path) and any("docker" in line for line in open(path)) - - -def has_docker_cgroup_v2() -> bool: - """ - cgroups v2 version, inspired from - https://github.com/jenkinsci/docker-workflow-plugin/blob/master/src/main/java/org/jenkinsci/plugins/docker/workflow/client/DockerClient.java - """ - path = "/proc/self/mountinfo" # 'self' should be always symlinked to the actual PID - return os.path.isfile(path) and any("/docker/containers/" in line for line in open(path)) - - -def is_containerized() -> Optional[bool]: - """ - This code is based on the popular 'is-docker' package for node.js - """ - global IS_DOCKER_CACHE - - if IS_DOCKER_CACHE is None: - IS_DOCKER_CACHE = in_podman() or has_dockerenv() or has_docker_cgroup_v1() or has_docker_cgroup_v2() - - return IS_DOCKER_CACHE - - -def collect_static_system_specs() -> Dict[str, Any]: - """ - Collects meta data about the setup that is used with Haystack, such as: - operating system, python version, Haystack version, transformers version, - pytorch version, number of GPUs, execution environment. - """ - specs = { - "libraries.haystack": __version__, - "os.containerized": is_containerized(), - # FIXME review these - "os.version": platform.release(), - "os.family": platform.system(), - "os.machine": platform.machine(), - "python.version": platform.python_version(), # FIXME verify - "hardware.cpus": os.cpu_count(), # FIXME verify - } - try: - transformers_import.check() - specs["libraries.transformers"] = transformers.__version__ - except ImportError: - specs["libraries.transformers"] = False - - try: - torch_import.check() - has_mps = ( - hasattr(torch.backends, "mps") - and torch.backends.mps.is_available() - and os.getenv("HAYSTACK_MPS_ENABLED", "true") != "false" - ) - specs.update( - { - "libraries.torch": torch.__version__, - "libraries.cuda": torch.version.cuda if torch.cuda.is_available() else False, - "hardware.gpus": torch.cuda.device_count() if torch.cuda.is_available() else 1 if has_mps else 0, - } - ) - except ImportError: - specs.update({"libraries.torch": False, "libraries.cuda": False, "hardware.gpus": 0}) - return specs - - -def collect_dynamic_system_specs() -> Dict[str, Any]: - return { - "libraries.pytest": sys.modules["pytest"].__version__ if "pytest" in sys.modules.keys() else False, - "libraries.ray": sys.modules["ray"].__version__ if "ray" in sys.modules.keys() else False, - "libraries.ipython": sys.modules["ipython"].__version__ if "ipython" in sys.modules.keys() else False, - "libraries.colab": sys.modules["google.colab"].__version__ if "google.colab" in sys.modules.keys() else False, - } diff --git a/haystack/errors.py b/haystack/errors.py deleted file mode 100644 index f2b27aa318..0000000000 --- a/haystack/errors.py +++ /dev/null @@ -1,284 +0,0 @@ -"""Custom Errors for Haystack""" - -from typing import Optional - - -class HaystackError(Exception): - """ - Any error generated by Haystack. - - This error wraps its source transparently in such a way that its attributes - can be accessed directly: for example, if the original error has a `message` attribute, - `HaystackError.message` will exist and have the expected content. - The messages of errors that might contain user-specific information will not be sent, e.g., DocumentStoreError or OpenAIError. - """ - - def __init__( - self, message: Optional[str] = None, docs_link: Optional[str] = None, send_message_in_event: bool = True - ): - super().__init__() - if message: - self.message = message - self.docs_link = None - - def __getattr__(self, attr): - # If self.__cause__ is None, it will raise the expected AttributeError - getattr(self.__cause__, attr) - - def __str__(self): - if self.docs_link: - docs_message = f"\n\nCheck out the documentation at {self.docs_link}" - return self.message + docs_message - return self.message - - def __repr__(self): - return str(self) - - -class ModelingError(HaystackError): - """Exception for issues raised by the modeling module""" - - def __init__(self, message: Optional[str] = None, docs_link: Optional[str] = "https://haystack.deepset.ai/"): - super().__init__(message=message, docs_link=docs_link) - - -class AgentError(HaystackError): - """Exception for issues raised within an agent""" - - def __init__( - self, message: Optional[str] = None, docs_link: Optional[str] = "https://docs.haystack.deepset.ai/docs/agents" - ): - super().__init__(message=message, docs_link=docs_link) - - -class PipelineError(HaystackError): - """Exception for issues raised within a pipeline""" - - def __init__( - self, - message: Optional[str] = None, - docs_link: Optional[str] = "https://docs.haystack.deepset.ai/docs/pipelines", - ): - super().__init__(message=message, docs_link=docs_link) - - -class DatasetsError(HaystackError): - """Exception for issues raised within a dataset""" - - def __init__( - self, - message: Optional[str] = None, - docs_link: Optional[str] = "https://docs.haystack.deepset.ai/docs/documents_answers_labels#document", - ): - super().__init__(message=message, docs_link=docs_link) - - -class PipelineSchemaError(PipelineError): - """Exception for issues arising when reading/building the JSON schema of pipelines""" - - def __init__(self, message: Optional[str] = None): - super().__init__(message=message) - - -class PipelineConfigError(PipelineError): - """Exception for issues raised within a pipeline's config file""" - - def __init__( - self, - message: Optional[str] = None, - docs_link: Optional[str] = "https://docs.haystack.deepset.ai/docs/pipelines#yaml-file-definitions", - ): - super().__init__(message=message, docs_link=docs_link) - - -class DocumentStoreError(HaystackError): - """Exception for issues that occur in a document store""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, send_message_in_event=send_message_in_event) - - -class FilterError(DocumentStoreError): - """Exception for issues that occur building complex filters""" - - def __init__(self, message: Optional[str] = None): - super().__init__(message=message) - - -class PineconeDocumentStoreError(DocumentStoreError): - """Exception for issues that occur in a Pinecone document store""" - - def __init__(self, message: Optional[str] = None): - super().__init__(message=message) - - -class DuplicateDocumentError(DocumentStoreError, ValueError): - """Exception for Duplicate document""" - - def __init__(self, message: Optional[str] = None): - super().__init__(message=message) - - -class NodeError(HaystackError): - """Exception for issues that occur in a node""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = True): - super().__init__(message=message, send_message_in_event=send_message_in_event) - - -class OpenAIError(NodeError): - """Exception for issues that occur in the OpenAI APIs""" - - def __init__( - self, message: Optional[str] = None, status_code: Optional[int] = None, send_message_in_event: bool = False - ): - super().__init__(message=message, send_message_in_event=send_message_in_event) - self.status_code = status_code - - -class OpenAIRateLimitError(OpenAIError): - """ - Rate limit error for OpenAI API (status code 429) - See https://help.openai.com/en/articles/5955604-how-can-i-solve-429-too-many-requests-errors - See https://help.openai.com/en/articles/5955598-is-api-usage-subject-to-any-rate-limits - """ - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=429, send_message_in_event=send_message_in_event) - - -class OpenAIUnauthorizedError(OpenAIError): - """ - Unauthorized error for OpenAI API (status code 401) - See https://platform.openai.com/docs/guides/error-codes/api-errors - """ - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=401, send_message_in_event=send_message_in_event) - - -class CohereError(NodeError): - """Exception for issues that occur in the Cohere APIs""" - - def __init__( - self, message: Optional[str] = None, status_code: Optional[int] = None, send_message_in_event: bool = False - ): - super().__init__(message=message, send_message_in_event=send_message_in_event) - self.status_code = status_code - - -class CohereUnauthorizedError(CohereError): - """Exception for unauthorized access to Cohere APIs""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=401, send_message_in_event=send_message_in_event) - - -class ImageToTextError(NodeError): - """Exception for issues that occur in the ImageToText node""" - - def __init__(self, message: Optional[str] = None): - super().__init__(message=message) - - -class HuggingFaceInferenceError(NodeError): - """Exception for issues that occur in the HuggingFace inference node""" - - def __init__( - self, message: Optional[str] = None, status_code: Optional[int] = None, send_message_in_event: bool = False - ): - super().__init__(message=message, send_message_in_event=send_message_in_event) - self.status_code = status_code - - -class HuggingFaceInferenceLimitError(HuggingFaceInferenceError): - """Exception for issues that occur in the HuggingFace inference node due to rate limiting""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=429, send_message_in_event=send_message_in_event) - - -class HuggingFaceInferenceUnauthorizedError(HuggingFaceInferenceError): - """Exception for issues that occur in the HuggingFace inference node due to unauthorized access""" - - -class AWSConfigurationError(NodeError): - """Exception raised when AWS is not configured correctly""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, send_message_in_event=send_message_in_event) - - -class AmazonBedrockConfigurationError(NodeError): - """Exception raised when AmazonBedrock node is not configured correctly""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, send_message_in_event=send_message_in_event) - - -class AmazonBedrockInferenceError(NodeError): - """Exception for issues that occur in the Bedrock inference node""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, send_message_in_event=send_message_in_event) - - -class SageMakerInferenceError(NodeError): - """Exception for issues that occur in the SageMaker inference node""" - - def __init__( - self, message: Optional[str] = None, status_code: Optional[int] = None, send_message_in_event: bool = False - ): - super().__init__(message=message, send_message_in_event=send_message_in_event) - self.status_code = status_code - - -class SageMakerConfigurationError(NodeError): - """Exception raised when SageMaker node is not configured correctly""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, send_message_in_event=send_message_in_event) - - -class SageMakerModelNotReadyError(SageMakerInferenceError): - """Exception for when a model is still under provisioning""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=429, send_message_in_event=send_message_in_event) - - -class AnthropicError(NodeError): - """Exception for issues that occur in the Anthropic APIs""" - - def __init__( - self, message: Optional[str] = None, status_code: Optional[int] = None, send_message_in_event: bool = False - ): - super().__init__(message=message, send_message_in_event=send_message_in_event) - self.status_code = status_code - - -class AnthropicRateLimitError(AnthropicError): - """ - Rate limit error for Anthropic API (status code 429) - See https://console.anthropic.com/docs/api/errors - """ - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=429, send_message_in_event=send_message_in_event) - - -class AnthropicUnauthorizedError(AnthropicError): - """ - Unauthorized error for Anthropic API (status code 401) - https://console.anthropic.com/docs/api/errors - """ - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=401, send_message_in_event=send_message_in_event) - - -class CohereInferenceLimitError(CohereError): - """Exception for issues that occur in the Cohere inference node due to rate limiting""" - - def __init__(self, message: Optional[str] = None, send_message_in_event: bool = False): - super().__init__(message=message, status_code=429, send_message_in_event=send_message_in_event) diff --git a/haystack/lazy_imports.py b/haystack/lazy_imports.py deleted file mode 100644 index 5f474beef9..0000000000 --- a/haystack/lazy_imports.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Optional, Type -from types import TracebackType -from lazy_imports.try_import import _DeferredImportExceptionContextManager - - -DEFAULT_IMPORT_ERROR_MSG = "Try 'pip install {}'" - - -class LazyImport(_DeferredImportExceptionContextManager): - """ - Wrapper on top of lazy_import's _DeferredImportExceptionContextManager that adds the possibility to customize the - error messages. - """ - - def __init__(self, message: str = DEFAULT_IMPORT_ERROR_MSG) -> None: - super().__init__() - self.import_error_msg = message - - def __exit__( - self, exc_type: Optional[Type[Exception]], exc_value: Optional[Exception], traceback: Optional[TracebackType] - ) -> Optional[bool]: - """Exit the context manager. - - Args: - exc_type: - Raised exception type. :obj:`None` if nothing is raised. - exc_value: - Raised exception object. :obj:`None` if nothing is raised. - traceback: - Associated traceback. :obj:`None` if nothing is raised. - - Returns: - :obj:`None` if nothing is deferred, otherwise :obj:`True`. - :obj:`True` will suppress any exceptions avoiding them from propagating. - - """ - if isinstance(exc_value, ImportError): - message = ( - f"Failed to import '{exc_value.name}'. {self.import_error_msg.format(exc_value.name)}. " - f"Original error: {exc_value}" - ) - self._deferred = (exc_value, message) - return True - return None diff --git a/haystack/mmh3.py b/haystack/mmh3.py deleted file mode 100644 index c9b08286a4..0000000000 --- a/haystack/mmh3.py +++ /dev/null @@ -1,347 +0,0 @@ -import sys as _sys - -# based on https://github.com/wc-duck/pymmh3/blob/master/pymmh3.py - -if _sys.version_info > (3, 0): - - def xrange(a, b, c): - return range(a, b, c) - - def xencode(x): - if isinstance(x, (bytes, bytearray)): - return x - else: - return x.encode() - -else: - - def xencode(x): - return x - - -del _sys - - -def hash128(key, seed=0x0, x64arch=True): # noqa: C901,PLR0915 - """Implements 128bit murmur3 hash.""" - # This function has a very high McCabe cyclomatic complexity score of 44 - # (recommended is 10) and contains 212 statements (recommended is 50). - - def hash128_x64(key, seed): - """Implements 128bit murmur3 hash for x64.""" - - def fmix(k): - k ^= k >> 33 - k = (k * 0xFF51AFD7ED558CCD) & 0xFFFFFFFFFFFFFFFF - k ^= k >> 33 - k = (k * 0xC4CEB9FE1A85EC53) & 0xFFFFFFFFFFFFFFFF - k ^= k >> 33 - return k - - length = len(key) - nblocks = int(length / 16) - - h1 = seed - h2 = seed - - c1 = 0x87C37B91114253D5 - c2 = 0x4CF5AD432745937F - - # body - for block_start in xrange(0, nblocks * 8, 8): - # ??? big endian? - k1 = ( - key[2 * block_start + 7] << 56 - | key[2 * block_start + 6] << 48 - | key[2 * block_start + 5] << 40 - | key[2 * block_start + 4] << 32 - | key[2 * block_start + 3] << 24 - | key[2 * block_start + 2] << 16 - | key[2 * block_start + 1] << 8 - | key[2 * block_start + 0] - ) - - k2 = ( - key[2 * block_start + 15] << 56 - | key[2 * block_start + 14] << 48 - | key[2 * block_start + 13] << 40 - | key[2 * block_start + 12] << 32 - | key[2 * block_start + 11] << 24 - | key[2 * block_start + 10] << 16 - | key[2 * block_start + 9] << 8 - | key[2 * block_start + 8] - ) - - k1 = (c1 * k1) & 0xFFFFFFFFFFFFFFFF - k1 = (k1 << 31 | k1 >> 33) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64 - k1 = (c2 * k1) & 0xFFFFFFFFFFFFFFFF - h1 ^= k1 - - h1 = (h1 << 27 | h1 >> 37) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64 - h1 = (h1 + h2) & 0xFFFFFFFFFFFFFFFF - h1 = (h1 * 5 + 0x52DCE729) & 0xFFFFFFFFFFFFFFFF - - k2 = (c2 * k2) & 0xFFFFFFFFFFFFFFFF - k2 = (k2 << 33 | k2 >> 31) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64 - k2 = (c1 * k2) & 0xFFFFFFFFFFFFFFFF - h2 ^= k2 - - h2 = (h2 << 31 | h2 >> 33) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64 - h2 = (h1 + h2) & 0xFFFFFFFFFFFFFFFF - h2 = (h2 * 5 + 0x38495AB5) & 0xFFFFFFFFFFFFFFFF - - # tail - tail_index = nblocks * 16 - k1 = 0 - k2 = 0 - tail_size = length & 15 - - if tail_size >= 15: - k2 ^= key[tail_index + 14] << 48 - if tail_size >= 14: - k2 ^= key[tail_index + 13] << 40 - if tail_size >= 13: - k2 ^= key[tail_index + 12] << 32 - if tail_size >= 12: - k2 ^= key[tail_index + 11] << 24 - if tail_size >= 11: - k2 ^= key[tail_index + 10] << 16 - if tail_size >= 10: - k2 ^= key[tail_index + 9] << 8 - if tail_size >= 9: - k2 ^= key[tail_index + 8] - - if tail_size > 8: - k2 = (k2 * c2) & 0xFFFFFFFFFFFFFFFF - k2 = (k2 << 33 | k2 >> 31) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64 - k2 = (k2 * c1) & 0xFFFFFFFFFFFFFFFF - h2 ^= k2 - - if tail_size >= 8: - k1 ^= key[tail_index + 7] << 56 - if tail_size >= 7: - k1 ^= key[tail_index + 6] << 48 - if tail_size >= 6: - k1 ^= key[tail_index + 5] << 40 - if tail_size >= 5: - k1 ^= key[tail_index + 4] << 32 - if tail_size >= 4: - k1 ^= key[tail_index + 3] << 24 - if tail_size >= 3: - k1 ^= key[tail_index + 2] << 16 - if tail_size >= 2: - k1 ^= key[tail_index + 1] << 8 - if tail_size >= 1: - k1 ^= key[tail_index + 0] - - if tail_size > 0: - k1 = (k1 * c1) & 0xFFFFFFFFFFFFFFFF - k1 = (k1 << 31 | k1 >> 33) & 0xFFFFFFFFFFFFFFFF # inlined ROTL64 - k1 = (k1 * c2) & 0xFFFFFFFFFFFFFFFF - h1 ^= k1 - - # finalization - h1 ^= length - h2 ^= length - - h1 = (h1 + h2) & 0xFFFFFFFFFFFFFFFF - h2 = (h1 + h2) & 0xFFFFFFFFFFFFFFFF - - h1 = fmix(h1) - h2 = fmix(h2) - - h1 = (h1 + h2) & 0xFFFFFFFFFFFFFFFF - h2 = (h1 + h2) & 0xFFFFFFFFFFFFFFFF - - return h2 << 64 | h1 - - def hash128_x86(key, seed): # noqa: PLR0915 - """Implements 128bit murmur3 hash for x86.""" - # This function contains 125 statements (recommended is 50). - - def fmix(h): - h ^= h >> 16 - h = (h * 0x85EBCA6B) & 0xFFFFFFFF - h ^= h >> 13 - h = (h * 0xC2B2AE35) & 0xFFFFFFFF - h ^= h >> 16 - return h - - length = len(key) - nblocks = int(length / 16) - - h1 = seed - h2 = seed - h3 = seed - h4 = seed - - c1 = 0x239B961B - c2 = 0xAB0E9789 - c3 = 0x38B34AE5 - c4 = 0xA1E38B93 - - # body - for block_start in xrange(0, nblocks * 16, 16): - k1 = ( - key[block_start + 3] << 24 - | key[block_start + 2] << 16 - | key[block_start + 1] << 8 - | key[block_start + 0] - ) - - k2 = ( - key[block_start + 7] << 24 - | key[block_start + 6] << 16 - | key[block_start + 5] << 8 - | key[block_start + 4] - ) - - k3 = ( - key[block_start + 11] << 24 - | key[block_start + 10] << 16 - | key[block_start + 9] << 8 - | key[block_start + 8] - ) - - k4 = ( - key[block_start + 15] << 24 - | key[block_start + 14] << 16 - | key[block_start + 13] << 8 - | key[block_start + 12] - ) - - k1 = (c1 * k1) & 0xFFFFFFFF - k1 = (k1 << 15 | k1 >> 17) & 0xFFFFFFFF # inlined ROTL32 - k1 = (c2 * k1) & 0xFFFFFFFF - h1 ^= k1 - - h1 = (h1 << 19 | h1 >> 13) & 0xFFFFFFFF # inlined ROTL32 - h1 = (h1 + h2) & 0xFFFFFFFF - h1 = (h1 * 5 + 0x561CCD1B) & 0xFFFFFFFF - - k2 = (c2 * k2) & 0xFFFFFFFF - k2 = (k2 << 16 | k2 >> 16) & 0xFFFFFFFF # inlined ROTL32 - k2 = (c3 * k2) & 0xFFFFFFFF - h2 ^= k2 - - h2 = (h2 << 17 | h2 >> 15) & 0xFFFFFFFF # inlined ROTL32 - h2 = (h2 + h3) & 0xFFFFFFFF - h2 = (h2 * 5 + 0x0BCAA747) & 0xFFFFFFFF - - k3 = (c3 * k3) & 0xFFFFFFFF - k3 = (k3 << 17 | k3 >> 15) & 0xFFFFFFFF # inlined ROTL32 - k3 = (c4 * k3) & 0xFFFFFFFF - h3 ^= k3 - - h3 = (h3 << 15 | h3 >> 17) & 0xFFFFFFFF # inlined ROTL32 - h3 = (h3 + h4) & 0xFFFFFFFF - h3 = (h3 * 5 + 0x96CD1C35) & 0xFFFFFFFF - - k4 = (c4 * k4) & 0xFFFFFFFF - k4 = (k4 << 18 | k4 >> 14) & 0xFFFFFFFF # inlined ROTL32 - k4 = (c1 * k4) & 0xFFFFFFFF - h4 ^= k4 - - h4 = (h4 << 13 | h4 >> 19) & 0xFFFFFFFF # inlined ROTL32 - h4 = (h1 + h4) & 0xFFFFFFFF - h4 = (h4 * 5 + 0x32AC3B17) & 0xFFFFFFFF - - # tail - tail_index = nblocks * 16 - k1 = 0 - k2 = 0 - k3 = 0 - k4 = 0 - tail_size = length & 15 - - if tail_size >= 15: - k4 ^= key[tail_index + 14] << 16 - if tail_size >= 14: - k4 ^= key[tail_index + 13] << 8 - if tail_size >= 13: - k4 ^= key[tail_index + 12] - - if tail_size > 12: - k4 = (k4 * c4) & 0xFFFFFFFF - k4 = (k4 << 18 | k4 >> 14) & 0xFFFFFFFF # inlined ROTL32 - k4 = (k4 * c1) & 0xFFFFFFFF - h4 ^= k4 - - if tail_size >= 12: - k3 ^= key[tail_index + 11] << 24 - if tail_size >= 11: - k3 ^= key[tail_index + 10] << 16 - if tail_size >= 10: - k3 ^= key[tail_index + 9] << 8 - if tail_size >= 9: - k3 ^= key[tail_index + 8] - - if tail_size > 8: - k3 = (k3 * c3) & 0xFFFFFFFF - k3 = (k3 << 17 | k3 >> 15) & 0xFFFFFFFF # inlined ROTL32 - k3 = (k3 * c4) & 0xFFFFFFFF - h3 ^= k3 - - if tail_size >= 8: - k2 ^= key[tail_index + 7] << 24 - if tail_size >= 7: - k2 ^= key[tail_index + 6] << 16 - if tail_size >= 6: - k2 ^= key[tail_index + 5] << 8 - if tail_size >= 5: - k2 ^= key[tail_index + 4] - - if tail_size > 4: - k2 = (k2 * c2) & 0xFFFFFFFF - k2 = (k2 << 16 | k2 >> 16) & 0xFFFFFFFF # inlined ROTL32 - k2 = (k2 * c3) & 0xFFFFFFFF - h2 ^= k2 - - if tail_size >= 4: - k1 ^= key[tail_index + 3] << 24 - if tail_size >= 3: - k1 ^= key[tail_index + 2] << 16 - if tail_size >= 2: - k1 ^= key[tail_index + 1] << 8 - if tail_size >= 1: - k1 ^= key[tail_index + 0] - - if tail_size > 0: - k1 = (k1 * c1) & 0xFFFFFFFF - k1 = (k1 << 15 | k1 >> 17) & 0xFFFFFFFF # inlined ROTL32 - k1 = (k1 * c2) & 0xFFFFFFFF - h1 ^= k1 - - # finalization - h1 ^= length - h2 ^= length - h3 ^= length - h4 ^= length - - h1 = (h1 + h2) & 0xFFFFFFFF - h1 = (h1 + h3) & 0xFFFFFFFF - h1 = (h1 + h4) & 0xFFFFFFFF - h2 = (h1 + h2) & 0xFFFFFFFF - h3 = (h1 + h3) & 0xFFFFFFFF - h4 = (h1 + h4) & 0xFFFFFFFF - - h1 = fmix(h1) - h2 = fmix(h2) - h3 = fmix(h3) - h4 = fmix(h4) - - h1 = (h1 + h2) & 0xFFFFFFFF - h1 = (h1 + h3) & 0xFFFFFFFF - h1 = (h1 + h4) & 0xFFFFFFFF - h2 = (h1 + h2) & 0xFFFFFFFF - h3 = (h1 + h3) & 0xFFFFFFFF - h4 = (h1 + h4) & 0xFFFFFFFF - - return h4 << 96 | h3 << 64 | h2 << 32 | h1 - - key = bytearray(xencode(key)) - - if x64arch: - return hash128_x64(key, seed) - else: - return hash128_x86(key, seed) diff --git a/haystack/modeling/__init__.py b/haystack/modeling/__init__.py deleted file mode 100644 index 4fcb504bad..0000000000 --- a/haystack/modeling/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -import logging - -logger = logging.getLogger(__name__) - -try: - import torch -except (ModuleNotFoundError, ImportError): - raise ImportError( - "torch not installed, haystack.modeling won't work. Run 'pip install transformers[torch]' to fix this problem." - ) diff --git a/haystack/modeling/data_handler/__init__.py b/haystack/modeling/data_handler/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/haystack/modeling/data_handler/data_silo.py b/haystack/modeling/data_handler/data_silo.py deleted file mode 100644 index ac6e45f760..0000000000 --- a/haystack/modeling/data_handler/data_silo.py +++ /dev/null @@ -1,851 +0,0 @@ -from typing import TYPE_CHECKING, Optional, List, Tuple, Dict, Union - -import hashlib -import json -import logging -import random -from itertools import groupby -from pathlib import Path -import numpy as np -from tqdm import tqdm -import torch -from torch.utils.data import ConcatDataset, Dataset -from torch.utils.data.distributed import DistributedSampler -from torch.utils.data.sampler import RandomSampler, SequentialSampler - -from haystack.modeling.data_handler.dataloader import NamedDataLoader -from haystack.modeling.data_handler.processor import Processor, SquadProcessor -from haystack.utils.experiment_tracking import Tracker as tracker -from haystack.modeling.visual import TRACTOR_SMALL - -if TYPE_CHECKING: - from haystack.nodes import FARMReader - -logger = logging.getLogger(__name__) - - -class DataSilo: - """Generates and stores PyTorch DataLoader objects for the train, dev and test datasets. - Relies upon functionality in the processor to do the conversion of the data. Will also - calculate and display some statistics. - """ - - def __init__( - self, - processor: Processor, - batch_size: int, - eval_batch_size: Optional[int] = None, - distributed: bool = False, - automatic_loading: bool = True, - max_multiprocessing_chunksize: int = 512, - max_processes: int = 128, - multiprocessing_strategy: Optional[str] = None, - caching: bool = False, - cache_path: Path = Path("cache/data_silo"), - ): - """ - :param processor: A dataset specific Processor object which will turn input (file or dict) into a Pytorch Dataset. - :param batch_size: The size of batch that should be returned by the DataLoader for the training set. - :param eval_batch_size: The size of batch that should be returned by the DataLoaders for the dev and test set. - :param distributed: Set to True if you are running in a distributed evn, e.g. using DistributedDataParallel. - The DataSilo will init the DataLoader with a DistributedSampler() to distribute batches. - :param automatic_loading: Set to False, if you don't want to automatically load data at initialization. - :param max_multiprocessing_chunksize: max possible value for chunksize as calculated by `calc_chunksize()` - in `haystack.basics.utils`. For certain cases like lm_finetuning, a smaller value can be set, as the default chunksize - values are rather large that might cause memory issues. - :param max_processes: the maximum number of processes to spawn in the multiprocessing.Pool used in DataSilo. - It can be set to 1 to disable the use of multiprocessing or make debugging easier. - .. deprecated:: 1.9 - Multiprocessing has been removed in 1.9. This parameter will be ignored. - :multiprocessing_strategy: Set the multiprocessing sharing strategy, this can be one of file_descriptor/file_system depending on your OS. - If your system has low limits for the number of open file descriptors, and you can’t raise them, - you should use the file_system strategy. - .. deprecated:: 1.9 - Multiprocessing has been removed in 1.9. This parameter will be ignored. - :param caching: save the processed datasets on disk to save time/compute if the same train data is used to run - multiple experiments. Each cache has a checksum based on the train_filename of the Processor - and the batch size. - :param cache_path: root dir for storing the datasets' cache. - """ - self.distributed = distributed - self.processor = processor - self.data = {} # type: Dict - self.batch_size = batch_size - self.class_weights = None - self.max_processes = max_processes - self.multiprocessing_strategy = multiprocessing_strategy - self.max_multiprocessing_chunksize = max_multiprocessing_chunksize - self.caching = caching - self.cache_path = cache_path - self.tensor_names = None - if eval_batch_size is None: - self.eval_batch_size = batch_size - else: - self.eval_batch_size = eval_batch_size - - if len(self.processor.tasks) == 0: - raise Exception( - "No task initialized. Try initializing the processor with a metric and a label list. " - "Alternatively you can add a task using Processor.add_task()" - ) - - loaded_from_cache = False - if self.caching: # Check if DataSets are present in cache - checksum = self._get_checksum() - dataset_path = self.cache_path / checksum - - if dataset_path.exists(): - self._load_dataset_from_cache(dataset_path) - loaded_from_cache = True - - if not loaded_from_cache and automatic_loading: - # In most cases we want to load all data automatically, but in some cases we rather want to do this - # later or load from dicts instead of file - self._load_data() - - def _get_dataset(self, filename: Optional[Union[str, Path]], dicts: Optional[List[Dict]] = None): - if not filename and not dicts: - raise ValueError("You must either supply `filename` or `dicts`") - - # loading dicts from file (default) - if dicts is None: - dicts = list(self.processor.file_to_dicts(filename)) # type: ignore - # shuffle list of dicts here if we later want to have a random dev set split from train set - if ( - str(self.processor.train_filename) in str(filename) - and not self.processor.dev_filename - and self.processor.dev_split > 0.0 - ): - random.shuffle(dicts) - - num_dicts = len(dicts) - datasets = [] - problematic_ids_all = set() - batch_size = self.max_multiprocessing_chunksize - for i in tqdm(range(0, num_dicts, batch_size), desc="Preprocessing dataset", unit=" Dicts"): - processing_batch = dicts[i : i + batch_size] - dataset, tensor_names, problematic_sample_ids = self.processor.dataset_from_dicts( - dicts=processing_batch, indices=list(range(len(processing_batch))) # TODO remove indices - ) - datasets.append(dataset) - problematic_ids_all.update(problematic_sample_ids) - - self.processor.log_problematic(problematic_ids_all) - datasets = [d for d in datasets if d] - concat_datasets = ConcatDataset(datasets) # type: Dataset - return concat_datasets, tensor_names - - def _load_data( - self, - train_dicts: Optional[List[Dict]] = None, - dev_dicts: Optional[List[Dict]] = None, - test_dicts: Optional[List[Dict]] = None, - ): - """ - Loading the train, dev and test datasets either from files (default) or from supplied dicts. - The processor is called to handle the full conversion from "raw data" to a Pytorch Dataset. - The resulting datasets are loaded into DataSilo.data - - :param train_dicts: (Optional) dicts containing examples for training. - :param dev_dicts: (Optional) dicts containing examples for dev. - :param test_dicts: (Optional) dicts containing examples for test. - :return: None - """ - - logger.info("\nLoading data into the data silo ... %s", TRACTOR_SMALL) - # train data - logger.info("LOADING TRAIN DATA") - logger.info("==================") - if train_dicts: - # either from supplied dicts - logger.info("Loading train set from supplied dicts ") - self.data["train"], self.tensor_names = self._get_dataset(filename=None, dicts=train_dicts) - elif self.processor.train_filename: - # or from a file (default) - train_file = self.processor.data_dir / self.processor.train_filename - logger.info("Loading train set from: %s ", train_file) - self.data["train"], self.tensor_names = self._get_dataset(train_file) - else: - logger.info("No train set is being loaded") - self.data["train"] = None - - # dev data - logger.info("") - logger.info("LOADING DEV DATA") - logger.info("=================") - if dev_dicts: - # either from supplied dicts - logger.info("Loading train set from supplied dicts ") - self.data["dev"], self.tensor_names = self._get_dataset(filename=None, dicts=dev_dicts) - elif self.processor.dev_filename: - # or from file (default) - dev_file = self.processor.data_dir / self.processor.dev_filename - logger.info("Loading dev set from: %s", dev_file) - self.data["dev"], _ = self._get_dataset(dev_file) - elif self.processor.dev_split > 0.0: - # or split it apart from train set - logger.info("Loading dev set as a slice of train set") - self._create_dev_from_train() - else: - logger.info("No dev set is being loaded") - self.data["dev"] = None - - logger.info("") - logger.info("LOADING TEST DATA") - logger.info("=================") - # test data - if test_dicts: - # either from supplied dicts - logger.info("Loading train set from supplied dicts ") - self.data["test"], self.tensor_names = self._get_dataset(filename=None, dicts=test_dicts) - elif self.processor.test_filename: - # or from file (default) - test_file = self.processor.data_dir / self.processor.test_filename - logger.info("Loading test set from: %s", test_file) - if self.tensor_names: - self.data["test"], _ = self._get_dataset(test_file) - else: - self.data["test"], self.tensor_names = self._get_dataset(test_file) - else: - logger.info("No test set is being loaded") - self.data["test"] = None - - if self.caching: - self._save_dataset_to_cache() - - # derive stats and meta data - self._calculate_statistics() - # self.calculate_class_weights() - - self._initialize_data_loaders() - - def _load_dataset_from_cache(self, cache_dir: Path): - """ - Load serialized dataset from a cache. - """ - logger.info("Loading datasets from cache at %s", cache_dir) - self.data["train"] = torch.load(cache_dir / "train_dataset") - - dev_dataset_path = cache_dir / "dev_dataset" - if dev_dataset_path.exists(): - self.data["dev"] = torch.load(dev_dataset_path) - else: - self.data["dev"] = None - - test_dataset_path = cache_dir / "test_dataset" - if test_dataset_path.exists(): - self.data["test"] = torch.load(test_dataset_path) - else: - self.data["test"] = None - - self.tensor_names = torch.load(cache_dir / "tensor_names") - - # derive stats and meta data - self._calculate_statistics() - # self.calculate_class_weights() - - self._initialize_data_loaders() - - def _get_checksum(self): - """ - Get checksum based on a dict to ensure validity of cached DataSilo - """ - # keys in the dict identifies uniqueness for a given DataSilo. - payload_dict = { - "train_filename": str(Path(self.processor.train_filename).absolute()), - "data_dir": str(self.processor.data_dir.absolute()), - "max_seq_len": self.processor.max_seq_len, - "dev_split": self.processor.dev_split, - "tasks": self.processor.tasks, - } - checksum = get_dict_checksum(payload_dict) - return checksum - - def _save_dataset_to_cache(self): - """ - Serialize and save dataset to a cache. - """ - checksum = self._get_checksum() - - cache_dir = self.cache_path / checksum - cache_dir.mkdir(parents=True, exist_ok=True) - - torch.save(self.data["train"], cache_dir / "train_dataset") - - if self.data["dev"]: - torch.save(self.data["dev"], cache_dir / "dev_dataset") - - if self.data["test"]: - torch.save(self.data["test"], cache_dir / "test_dataset") - - torch.save(self.tensor_names, cache_dir / "tensor_names") - logger.info("Cached the datasets at %s", cache_dir) - - def _initialize_data_loaders(self): - """ - Initializing train, dev and test data loaders for the already loaded datasets. - """ - - if self.data["train"] is not None: - if self.distributed: - sampler_train = DistributedSampler(self.data["train"]) - else: - sampler_train = RandomSampler(self.data["train"]) - - data_loader_train = NamedDataLoader( - dataset=self.data["train"], - sampler=sampler_train, - batch_size=self.batch_size, - tensor_names=self.tensor_names, - ) - else: - data_loader_train = None - - if self.data["dev"] is not None: - data_loader_dev = NamedDataLoader( - dataset=self.data["dev"], - sampler=SequentialSampler(self.data["dev"]), - batch_size=self.eval_batch_size, - tensor_names=self.tensor_names, - ) - else: - data_loader_dev = None - - if self.data["test"] is not None: - data_loader_test = NamedDataLoader( - dataset=self.data["test"], - sampler=SequentialSampler(self.data["test"]), - batch_size=self.eval_batch_size, - tensor_names=self.tensor_names, - ) - else: - data_loader_test = None - - self.loaders = {"train": data_loader_train, "dev": data_loader_dev, "test": data_loader_test} - - def _create_dev_from_train(self): - """ - Split a dev set apart from the train dataset. - """ - n_dev = int(self.processor.dev_split * len(self.data["train"])) - n_train = len(self.data["train"]) - n_dev - - train_dataset, dev_dataset = self.random_split_ConcatDataset(self.data["train"], lengths=[n_train, n_dev]) - self.data["train"] = train_dataset - if len(dev_dataset) > 0: - self.data["dev"] = dev_dataset - else: - logger.warning("No dev set created. Please adjust the dev_split parameter.") - - logger.info( - "Took %s samples out of train set to create dev set (dev split is roughly %s)", - len(dev_dataset), - self.processor.dev_split, - ) - - def random_split_ConcatDataset(self, ds: ConcatDataset, lengths: List[int]): - """ - Roughly split a Concatdataset into non-overlapping new datasets of given lengths. - Samples inside Concatdataset should already be shuffled. - - :param ds: Dataset to be split. - :param lengths: Lengths of splits to be produced. - """ - if sum(lengths) != len(ds): - raise ValueError("Sum of input lengths does not equal the length of the input dataset!") - - try: - idx_dataset = np.where(np.array(ds.cumulative_sizes) > lengths[0])[0][0] - except IndexError: - raise Exception( - "All dataset chunks are being assigned to train set leaving no samples for dev set. " - "Either consider increasing dev_split or setting it to 0.0\n" - f"Cumulative chunk sizes: {ds.cumulative_sizes}\n" - f"train/dev split: {lengths}" - ) - - assert idx_dataset >= 1, ( - "Dev_split ratio is too large, there is no data in train set. " - f"Please lower dev_split = {self.processor.dev_split}" - ) - - train = ConcatDataset(ds.datasets[:idx_dataset]) # type: Dataset - test = ConcatDataset(ds.datasets[idx_dataset:]) # type: Dataset - return train, test - - def _calculate_statistics(self): - """Calculate and log simple summary statistics of the datasets""" - logger.info("") - logger.info("DATASETS SUMMARY") - logger.info("================") - - self.counts = {} - clipped = -1 - ave_len = -1 - - if self.data["train"]: - self.counts["train"] = len(self.data["train"]) - if "input_ids" in self.tensor_names: - clipped, ave_len, seq_lens, max_seq_len = self._calc_length_stats_single_encoder() - elif "query_input_ids" in self.tensor_names and "passage_input_ids" in self.tensor_names: - clipped, ave_len, seq_lens, max_seq_len = self._calc_length_stats_biencoder() - else: - logger.warning( - "Could not compute length statistics because 'input_ids' or 'query_input_ids' and 'passage_input_ids' are missing." - ) - clipped = -1 - ave_len = -1 - else: - self.counts["train"] = 0 - - if self.data["dev"]: - self.counts["dev"] = len(self.data["dev"]) - else: - self.counts["dev"] = 0 - - if self.data["test"]: - self.counts["test"] = len(self.data["test"]) - else: - self.counts["test"] = 0 - - logger.info("Examples in train: %s", self.counts["train"]) - logger.info("Examples in dev : %s", self.counts["dev"]) - logger.info("Examples in test : %s", self.counts["test"]) - logger.info("Total examples : %s", self.counts["train"] + self.counts["dev"] + self.counts["test"]) - logger.info("") - if self.data["train"]: - # SquadProcessor does not clip sequences, but splits them into multiple samples - if "input_ids" in self.tensor_names and not isinstance(self.processor, SquadProcessor): - logger.info("Longest sequence length observed after clipping: %s", max(seq_lens)) - logger.info("Average sequence length after clipping: %s", ave_len) - logger.info("Proportion clipped: %s", clipped) - if clipped > 0.5: - logger.info( - "[Haystack Tip] %s%% of your samples got cut down to %s tokens. " - "Consider increasing max_seq_len " - "(the maximum value allowed with the current model is max_seq_len=%s, " - "if this is not enough consider splitting the document in smaller units or changing the model). " - "This will lead to higher memory consumption but is likely to improve your model performance", - round(clipped * 100, 1), - max_seq_len, - self.processor.tokenizer.model_max_length, - ) - elif "query_input_ids" in self.tensor_names and "passage_input_ids" in self.tensor_names: - logger.info( - "Longest query length observed after clipping: %s - for max_query_len: %s", - max(seq_lens[0]), - max_seq_len[0], - ) - logger.info("Average query length after clipping: %s", ave_len[0]) - logger.info("Proportion queries clipped: %s", clipped[0]) - logger.info("") - logger.info( - "Longest passage length observed after clipping: %s - for max_passage_len: %s", - max(seq_lens[1]), - max_seq_len[1], - ) - logger.info("Average passage length after clipping: %s", ave_len[1]) - logger.info("Proportion passages clipped: %s", clipped[1]) - - tracker.track_params( - { - "n_samples_train": self.counts["train"], - "n_samples_dev": self.counts["dev"], - "n_samples_test": self.counts["test"], - "batch_size": self.batch_size, - "ave_seq_len": ave_len, - "clipped": clipped, - } - ) - - def _calc_length_stats_single_encoder(self): - seq_lens = [] - for dataset in self.data["train"].datasets: - train_input_numpy = dataset[:][self.tensor_names.index("input_ids")].numpy() - seq_lens.extend(np.sum(train_input_numpy != self.processor.tokenizer.pad_token_id, axis=1)) - max_seq_len = dataset[:][self.tensor_names.index("input_ids")].shape[1] - clipped = np.mean(np.array(seq_lens) == max_seq_len) if seq_lens else 0 - ave_len = np.mean(seq_lens) if seq_lens else 0 - return clipped, ave_len, seq_lens, max_seq_len - - def _calc_length_stats_biencoder(self): - seq_lens = [[], []] - for dataset in self.data["train"].datasets: - query_input_numpy = dataset[:][self.tensor_names.index("query_input_ids")].numpy() - num_passages = dataset[:][self.tensor_names.index("passage_input_ids")].shape[1] - bs = dataset[:][self.tensor_names.index("passage_input_ids")].shape[0] - passage_input_numpy = ( - dataset[:][self.tensor_names.index("passage_input_ids")].numpy().reshape((bs, -1), order="C") - ) - qlen = np.sum(query_input_numpy != self.processor.query_tokenizer.pad_token_id, axis=1) - plen = np.sum(passage_input_numpy != self.processor.passage_tokenizer.pad_token_id, axis=1) / num_passages - seq_lens[0].extend(qlen) - seq_lens[1].extend(plen) - q_max_seq_len = dataset[:][self.tensor_names.index("query_input_ids")].shape[1] - p_max_seq_len = dataset[:][self.tensor_names.index("passage_input_ids")].shape[2] - clipped_q = np.mean(np.array(seq_lens[0]) == q_max_seq_len) if seq_lens[0] else 0 - ave_len_q = np.mean(seq_lens[0]) if seq_lens[0] else 0 - clipped_p = np.mean(np.array(seq_lens[1]) == p_max_seq_len) if seq_lens[1] else 0 - ave_len_p = np.mean(seq_lens[1]) if seq_lens[1] else 0 - clipped = [clipped_q, clipped_p] - ave_len = [ave_len_q, ave_len_p] - max_seq_len = [q_max_seq_len, p_max_seq_len] - return clipped, ave_len, seq_lens, max_seq_len - - def get_data_loader(self, dataset_name: str): - """ - Returns data loader for specified split of dataset. - - :param dataset_name: Split of dataset. Either 'train' or 'dev' or 'test'. - """ - return self.loaders[dataset_name] - - def n_samples(self, dataset_name: str): - """ - Returns the number of samples in a given dataset. - - :param dataset_name: Split of dataset. Choose from 'train', 'dev' or 'test'. - """ - return self.counts[dataset_name] - - -class DataSiloForCrossVal: - """ - Perform cross validation or nested cross validation. - - For performing cross validation or nested cross validation, we really want to combine all the - instances from all the sets or just some of the sets, then create a different data silo - instance for each fold or nested fold. - Calling DataSiloForCrossVal.make() creates a list of DataSiloForCrossVal instances - one for each fold. - """ - - def __init__( - self, - origsilo: DataSilo, - trainset: Union[List, Dataset], - devset: Union[List, Dataset], - testset: Union[List, Dataset], - ): - self.tensor_names = origsilo.tensor_names - self.data = {"train": trainset, "dev": devset, "test": testset} - self.processor = origsilo.processor - self.batch_size = origsilo.batch_size - # should not be necessary, xval makes no sense with huge data - # sampler_train = DistributedSampler(self.data["train"]) - sampler_train = RandomSampler(trainset) # type: ignore [arg-type] - - self.data_loader_train = NamedDataLoader( - dataset=trainset, sampler=sampler_train, batch_size=self.batch_size, tensor_names=self.tensor_names # type: ignore [arg-type] - ) - self.data_loader_dev = NamedDataLoader( - dataset=devset, # type: ignore [arg-type] - sampler=SequentialSampler(devset), # type: ignore [arg-type] - batch_size=self.batch_size, - tensor_names=self.tensor_names, - ) - self.data_loader_test = NamedDataLoader( - dataset=testset, # type: ignore [arg-type] - sampler=SequentialSampler(testset), # type: ignore [arg-type] - batch_size=self.batch_size, - tensor_names=self.tensor_names, - ) - self.loaders = {"train": self.data_loader_train, "dev": self.data_loader_dev, "test": self.data_loader_test} - - def get_data_loader(self, which): - return self.loaders[which] - - @classmethod - def make( - cls, - datasilo: DataSilo, - sets: Optional[List[str]] = None, - n_splits: int = 5, - shuffle: bool = True, - random_state: Optional[int] = None, - stratified: bool = True, - n_neg_answers_per_question: int = 1, - n_inner_splits: Optional[int] = None, - ): - """ - Create number of folds data-silo-like objects which can be used for training from the - original data silo passed on. - - :param datasilo: The data silo that contains the original data. - :param sets: Which sets to use to create the xval folds (strings). By default, "train", "dev", and "test" are used. - :param n_splits: number of folds to create - :param shuffle: shuffle each class' samples before splitting - :param random_state: random state for shuffling - :param stratified: If class stratification should be done. - It is never done with question answering. - :param n_neg_answers_per_question: number of negative answers per question to include for training - """ - if sets is None: - sets = ["train", "dev", "test"] - if "question_answering" in datasilo.processor.tasks and n_inner_splits is None: # type: ignore - return cls._make_question_answering( - datasilo, sets, n_splits, shuffle, random_state, n_neg_answers_per_question - ) - - else: - raise RuntimeError("Cross validation can not be done under these conditions!") - - @classmethod - def _make_question_answering( - cls, - datasilo: DataSilo, - sets: Optional[List[str]] = None, - n_splits: int = 5, - shuffle: bool = True, - random_state: Optional[int] = None, - n_neg_answers_per_question: int = 1, - ): - """ - Create number of folds data-silo-like objects which can be used for training from the - original data silo passed on. This function takes into account the characteristics of the - data for question-answering- - - :param datasilo: The data silo that contains the original data. - :param sets: Which sets to use to create the xval folds (strings). By default, "train", "dev", and "test" are used. - :param n_splits: Number of folds to create. - :param shuffle: Shuffle each class' samples before splitting. - :param random_state: Random state for shuffling. - :param n_neg_answers_per_question: Number of negative answers per question to include for training. - """ - if sets is None: - sets = ["train", "dev", "test"] - assert "id" in datasilo.tensor_names, f"Expected tensor 'id' in tensor names, found {datasilo.tensor_names}" # type: ignore - assert "labels" in datasilo.tensor_names, f"Expected tensor 'labels' in tensor names, found {datasilo.tensor_names}" # type: ignore - - id_index = datasilo.tensor_names.index("id") # type: ignore - label_index = datasilo.tensor_names.index("labels") # type:ignore - - sets_to_concat = [] - for setname in sets: - if datasilo.data[setname]: - sets_to_concat.extend(datasilo.data[setname]) - all_data = ConcatDataset(sets_to_concat) # type: Dataset - - documents = [] - keyfunc = lambda x: x[id_index][0] # pylint: disable=unnecessary-lambda-assignment - all_data = sorted(all_data.datasets, key=keyfunc) # type: ignore - for _, document in groupby(all_data, key=keyfunc): # type: ignore - documents.append(list(document)) - - xval_split = cls._split_for_qa( - documents=documents, id_index=id_index, n_splits=n_splits, shuffle=shuffle, random_state=random_state - ) - silos = [] - - for train_set, test_set in xval_split: - # Each training set is further divided into actual train and dev set - if datasilo.processor.dev_split > 0: - dev_split = datasilo.processor.dev_split - n_dev = int(np.ceil(dev_split * len(train_set))) - assert n_dev > 0, f"dev split of {dev_split} is not large enough to split away a development set" - n_actual_train = len(train_set) - n_dev - actual_train_set = train_set[:n_actual_train] - dev_set = train_set[n_actual_train:] - ds_dev = [sample for document in dev_set for sample in document] - else: - ds_dev = None # type: ignore - actual_train_set = train_set - - train_samples = [] - for doc in actual_train_set: - keyfunc = lambda x: x[id_index][1] # pylint: disable=unnecessary-lambda-assignment - doc = sorted(doc, key=keyfunc) - for _, question in groupby(doc, key=keyfunc): - # add all available answrs to train set - sample_list = list(question) - neg_answer_idx: List[int] = [] - for index, sample in enumerate(sample_list): - if sample[label_index][0][0] or sample[label_index][0][1]: - train_samples.append(sample) - else: - neg_answer_idx.append(index) - # add random n_neg_answers_per_question samples to train set - if len(neg_answer_idx) <= n_neg_answers_per_question: - train_samples.extend([sample_list[idx] for idx in neg_answer_idx]) - else: - neg_answer_idx = random.sample(neg_answer_idx, n_neg_answers_per_question) - train_samples.extend( - # For some reason pylint seems to be just wrong here. It's therefore silenced. - # Check if the issue persists in case of a future refactoring. - [sample_list[idx] for idx in neg_answer_idx] # pylint: disable=invalid-sequence-index - ) - - ds_train = train_samples - ds_test = [sample for document in test_set for sample in document] - silos.append(DataSiloForCrossVal(datasilo, ds_train, ds_dev, ds_test)) # type: ignore [arg-type] - return silos - - @staticmethod - def _split_for_qa( - documents: List, id_index: int, n_splits: int = 5, shuffle: bool = True, random_state: Optional[int] = None - ): - keyfunc = lambda x: x[id_index][1] # pylint: disable=unnecessary-lambda-assignment - if shuffle: - fixed_random = random.Random() - fixed_random.seed(random_state) - fixed_random.shuffle(documents) - - questions_per_doc = [] - for doc in documents: - # group samples in current doc by question id - doc = sorted(doc, key=keyfunc) - questions = list(groupby(doc, key=keyfunc)) - questions_per_doc.append(len(questions)) - - # split documents into n_splits splits with approximately same number of questions per split - questions_per_doc = np.array(questions_per_doc) # type: ignore [assignment] - accumulated_questions_per_doc = questions_per_doc.cumsum() # type: ignore - questions_per_fold = accumulated_questions_per_doc[-1] // n_splits - accumulated_questions_per_fold = np.array(range(1, n_splits)) * questions_per_fold - if accumulated_questions_per_fold[0] < accumulated_questions_per_doc[0]: - accumulated_questions_per_fold[0] = accumulated_questions_per_doc[0] + 1 - indices_to_split_at = np.searchsorted( - accumulated_questions_per_doc, accumulated_questions_per_fold, side="right" - ) - splits = np.split(documents, indices_to_split_at) - - for split in splits: - assert len(split) > 0 - - for idx, split in enumerate(splits): - current_test_set = split - current_train_set = np.hstack(np.delete(splits, idx, axis=0)) # type: ignore [call-overload] - - yield current_train_set, current_test_set - - -def get_dict_checksum(payload_dict): - """ - Get MD5 checksum for a dict. - """ - checksum = hashlib.md5(json.dumps(payload_dict, sort_keys=True).encode("utf-8")).hexdigest() - return checksum - - -class DistillationDataSilo(DataSilo): - """ - This data silo does a forward pass on the full data set on a teacher model for model distillation. - As its done in preprocessing, it does not need to be repeated in each epoch and can be cached. - """ - - def __init__( - self, - teacher_model: "FARMReader", - teacher_batch_size: int, - device: torch.device, - processor: Processor, - batch_size: int, - eval_batch_size: Optional[int] = None, - distributed: bool = False, - automatic_loading: bool = True, - max_processes: int = 128, - caching: bool = False, - cache_path: Path = Path("cache/data_silo"), - ): - self.teacher = teacher_model - self.teacher_batch_size = teacher_batch_size - self.device = device - max_processes = 1 # fix as long as multithreading is not working with teacher attribute - super().__init__( - max_processes=max_processes, - processor=processor, - batch_size=batch_size, - eval_batch_size=eval_batch_size, - distributed=distributed, - automatic_loading=automatic_loading, - caching=caching, - cache_path=cache_path, - ) - - def _run_teacher(self, batch: dict) -> List[torch.Tensor]: - """ - Run the teacher model on the given batch. - """ - params = { - "input_ids": batch["input_ids"], - "segment_ids": batch["segment_ids"], - "padding_mask": batch["padding_mask"], - } - if "output_hidden_states" in batch.keys(): - params["output_hidden_states"] = batch["output_hidden_states"] - if "output_attentions" in batch.keys(): - params["output_attentions"] = batch["output_attentions"] - return self.teacher.inferencer.model(**params) - - def _pass_batches( - self, - batch: List[List[torch.Tensor]], - corresponding_chunks: List[int], - teacher_outputs: List[List[Tuple[torch.Tensor, ...]]], - tensor_names: List[str], - ): - with torch.inference_mode(): - batch_transposed = zip(*batch) # transpose dimensions (from batch, features, ... to features, batch, ...) - batch_transposed_list = [torch.stack(b) for b in batch_transposed] # create tensors for each feature - batch_dict = { - key: tensor.to(self.device) for key, tensor in zip(tensor_names, batch_transposed_list) - } # create input dict - y = self._run_teacher(batch=batch_dict) # run teacher model - y = [y.cpu() for y in y] - self.output_len = len(y) - - # grouping by chunk - for i, data in zip(corresponding_chunks, zip(*y)): # transpose back - teacher_outputs[i].append(data) - return - - def _teacher_output_names(self) -> List[str]: - return ["teacher_output_" + str(i) for i in range(self.output_len)] - - def _get_dataset(self, filename: Optional[Union[str, Path]], dicts: Optional[List[Dict]] = None): - concat_datasets, tensor_names = super()._get_dataset(filename, dicts) - - batch = [] - corresponding_chunks = ( - [] - ) # to be able to associate elements of batches with chunks (elements could be from multiple chunks) - - teacher_outputs: List[List[Tuple[torch.Tensor, ...]]] = [] # list of teacher outputs group in list by chunk - - # creating batches from chunks - for i, dataset in enumerate(tqdm(concat_datasets.datasets, desc="Doing forward pass on teacher model")): - teacher_outputs.append([]) - for x in zip(*dataset.tensors): # loop through chunks - batch.append(x) - corresponding_chunks.append(i) - if len(batch) == self.teacher_batch_size: - self._pass_batches( - batch, corresponding_chunks, teacher_outputs, tensor_names # type: ignore [arg-type] - ) # doing forward pass on teacher model - batch = [] - corresponding_chunks = [] - if batch: - self._pass_batches(batch, corresponding_chunks, teacher_outputs, tensor_names) # type: ignore [arg-type] - - # appending teacher outputs to original dataset - for dataset, teacher_output in zip(concat_datasets.datasets, teacher_outputs): - dataset.tensors += tuple(torch.stack(tensors) for tensors in zip(*teacher_output)) - tensor_names += self._teacher_output_names() - concat_datasets = ConcatDataset(concat_datasets.datasets) # making sure metrics are updated - return concat_datasets, tensor_names - - def _get_checksum(self): - """ - Get checksum based on a dict to ensure validity of cached DataSilo - """ - # keys in the dict identifies uniqueness for a given DataSilo. - payload_dict = { - "train_filename": str(Path(self.processor.train_filename).absolute()), - "data_dir": str(self.processor.data_dir.absolute()), - "max_seq_len": self.processor.max_seq_len, - "dev_split": self.processor.dev_split, - "tasks": self.processor.tasks, - "teacher_name_or_path": self.teacher.model_name_or_path, - "data_silo_type": self.__class__.__name__, - } - checksum = get_dict_checksum(payload_dict) - return checksum diff --git a/haystack/modeling/data_handler/dataloader.py b/haystack/modeling/data_handler/dataloader.py deleted file mode 100644 index 52e95bc6d8..0000000000 --- a/haystack/modeling/data_handler/dataloader.py +++ /dev/null @@ -1,98 +0,0 @@ -from typing import Optional, List - -from math import ceil - -import torch -import torch.nn.functional as F -from torch.utils.data import DataLoader, Dataset, Sampler - -from haystack.errors import ModelingError - - -class NamedDataLoader(DataLoader): - def __init__( - self, - dataset: Dataset, - batch_size: int, - sampler: Optional[Sampler] = None, - tensor_names: Optional[List[str]] = None, - num_workers: int = 0, - pin_memory: bool = False, - ): - """ - A modified version of the PyTorch DataLoader that returns a dictionary where the key is - the name of the tensor and the value is the tensor itself. - - :param dataset: The dataset that will be wrapped by this NamedDataLoader - :param sampler: The sampler used by the NamedDataLoader to choose which samples to include in the batch - :param batch_size: The size of the batch to be returned by the NamedDataLoader - :param tensor_names: The names of the tensor, in the order that the dataset returns them in. - :param num_workers: number of workers to use for the DataLoader - :param pin_memory: argument for Data Loader to use page-locked memory for faster transfer of data to GPU - """ - - def collate_fn(batch): - """ - A custom collate function that formats the batch as a dictionary where the key is - the name of the tensor and the value is the tensor itself - """ - if type(dataset).__name__ == "_StreamingDataSet": - _tensor_names = dataset.tensor_names - else: - _tensor_names = tensor_names - - if isinstance(batch[0], list): - batch = batch[0] - - if len(batch[0]) != len(_tensor_names): - raise ModelingError( - f"Dataset contains {len(batch[0])} tensors while there are {len(_tensor_names)} tensor names supplied: {_tensor_names}" - ) - - max_num_labels = self._compute_max_number_of_labels(batch=batch, tensor_names=_tensor_names) - - ret = {name: [] for name in tensor_names} - for example in batch: - for name, tensor in zip(_tensor_names, example): - # each example may have a different number of answers/labels, - # so we need to pad the corresponding tensors to the max number of labels - if name == "labels" and tensor.ndim > 0: - num_labels = tensor.size(0) - if num_labels < max_num_labels: - padding = (0, 0, 0, max_num_labels - num_labels) - tensor = F.pad(tensor, padding, value=-1) - ret[name].append(tensor) - - for key in ret: - ret[key] = torch.stack(ret[key]) - - return ret - - super().__init__( - dataset=dataset, - sampler=sampler, - batch_size=batch_size, - collate_fn=collate_fn, - pin_memory=pin_memory, - num_workers=num_workers, - ) - - def __len__(self): - if type(self.dataset).__name__ == "_StreamingDataSet": - num_samples = len(self.dataset) - num_batches = ceil(num_samples / self.dataset.batch_size) - return num_batches - else: - return super().__len__() - - def _compute_max_number_of_labels(self, batch, tensor_names) -> int: - """ - Compute the maximum number of labels in a batch. - Each example may have a different number of labels, depending on the number of answers. - """ - max_num_labels = 0 - for example in batch: - for name, tensor in zip(tensor_names, example): - if name == "labels" and tensor.ndim > 0: - max_num_labels = max(max_num_labels, tensor.size(0)) - return max_num_labels diff --git a/haystack/modeling/data_handler/dataset.py b/haystack/modeling/data_handler/dataset.py deleted file mode 100644 index 3a8df06283..0000000000 --- a/haystack/modeling/data_handler/dataset.py +++ /dev/null @@ -1,103 +0,0 @@ -import logging -import numbers -from typing import Optional, List - -import numpy as np -import torch -from torch.utils.data import ConcatDataset, TensorDataset -from transformers import BatchEncoding - -from haystack.modeling.utils import flatten_list - -logger = logging.getLogger(__name__) - - -def flatten_rename( - encoded_batch: BatchEncoding, keys: Optional[List[str]] = None, renamed_keys: Optional[List[str]] = None -): - if encoded_batch is None: - return [] - if not keys: - keys = list(encoded_batch.keys()) - if not renamed_keys: - renamed_keys = keys - assert len(keys) == len( - renamed_keys - ), f"keys and renamed_keys have different size {len(keys)} != {len(renamed_keys)}" - assert any(key in encoded_batch for key in keys), f"one of the keys {keys} is not in batch {encoded_batch.keys()}" - features_flat = [] - for item in range(len(encoded_batch[keys[0]])): - feat_dict = dict(zip(renamed_keys, [encoded_batch[k][item] for k in keys])) - features_flat.append(feat_dict) - return features_flat - - -def convert_features_to_dataset(features): - """ - Converts a list of feature dictionaries (one for each sample) into a PyTorch Dataset. - - :param features: A list of dictionaries. Each dictionary corresponds to one sample. Its keys are the - names of the type of feature and the keys are the features themselves. - :Return: a Pytorch dataset and a list of tensor names. - """ - # features can be an empty list in cases where down sampling occurs - if len(features) == 0: - return None, None - tensor_names = list(features[0].keys()) - all_tensors = [] - for t_name in tensor_names: - try: - # Checking whether a non-integer will be silently converted to torch.long - check = features[0][t_name] - if isinstance(check, numbers.Number): - base = check - # extract a base variable from a nested lists or tuples - elif isinstance(check, list): - base = list(flatten_list(check))[0] - # extract a base variable from numpy arrays - else: - base = check.ravel()[0] - if not np.issubdtype(type(base), np.integer): - logger.warning( - "Problem during conversion to torch tensors:\n" - "A non-integer value for feature '%s' with a value of: " - "'%s' will be converted to a torch tensor of dtype long.", - t_name, - base, - ) - except: - logger.debug( - "Could not determine type for feature '%s'. Converting now to a tensor of default type long.", t_name - ) - - # Convert all remaining python objects to torch long tensors - cur_tensor = torch.as_tensor(np.array([sample[t_name] for sample in features]), dtype=torch.long) - - all_tensors.append(cur_tensor) - - dataset = TensorDataset(*all_tensors) - return dataset, tensor_names - - -class ConcatTensorDataset(ConcatDataset): - r"""ConcatDataset of only TensorDatasets which supports getting slices. - - This dataset allows the use of slices, e.g. ds[2:4] if all concatenated - datasets are either TensorDatasets or Subset or other ConcatTensorDataset instances - which eventually contain only TensorDataset instances. If no slicing is needed, - this class works exactly like torch.utils.data.ConcatDataset and can concatenate arbitrary - (not just TensorDataset) datasets. - - Args: - datasets (sequence): List of datasets to be concatenated - """ - - def __getitem__(self, idx): - if isinstance(idx, slice): - rows = [super(ConcatTensorDataset, self).__getitem__(i) for i in range(self.__len__())[idx]] - return tuple(map(torch.stack, zip(*rows))) - elif isinstance(idx, (list, np.ndarray)): - rows = [super(ConcatTensorDataset, self).__getitem__(i) for i in idx] - return tuple(map(torch.stack, zip(*rows))) - else: - return super(ConcatTensorDataset, self).__getitem__(idx) diff --git a/haystack/modeling/data_handler/input_features.py b/haystack/modeling/data_handler/input_features.py deleted file mode 100644 index 8ab1b8a4a2..0000000000 --- a/haystack/modeling/data_handler/input_features.py +++ /dev/null @@ -1,114 +0,0 @@ -""" -Contains functions that turn readable clear text input into dictionaries of features -""" -import logging -from numpy import pad - -logger = logging.getLogger(__name__) - - -def sample_to_features_text(sample, tasks, max_seq_len, tokenizer): - """ - Generates a dictionary of features for a given input sample that is to be consumed by a text classification model. - - :param sample: Sample object that contains human readable text and label fields from a single text classification data sample - :type sample: Sample - :param tasks: A dictionary where the keys are the names of the tasks and the values are the details of the task (e.g. label_list, metric, tensor name) - :type tasks: dict - :param max_seq_len: Sequences are truncated after this many tokens - :type max_seq_len: int - :param tokenizer: A tokenizer object that can turn string sentences into a list of tokens - :return: A list with one dictionary containing the keys "input_ids", "padding_mask" and "segment_ids" (also "label_ids" if not - in inference mode). The values are lists containing those features. - :rtype: list - """ - - if tokenizer.is_fast: - text = sample.clear_text["text"] - # Here, we tokenize the sample for the second time to get all relevant ids - # This should change once we git rid of FARM's tokenize_with_metadata() - inputs = tokenizer( - text, - return_token_type_ids=True, - truncation=True, - truncation_strategy="longest_first", - max_length=max_seq_len, - return_special_tokens_mask=True, - ) - - if (len(inputs["input_ids"]) - inputs["special_tokens_mask"].count(1)) != len(sample.tokenized["tokens"]): - logger.error( - "FastTokenizer encoded sample %s to %s tokens, which differs " - "from number of tokens produced in tokenize_with_metadata(). \n" - "Further processing is likely to be wrong.", - sample.clear_text["text"], - len(inputs["input_ids"]) - inputs["special_tokens_mask"].count(1), - ) - else: - # TODO It might be cleaner to adjust the data structure in sample.tokenized - tokens_a = sample.tokenized["tokens"] - tokens_b = sample.tokenized.get("tokens_b", None) - - inputs = tokenizer( - tokens_a, - tokens_b, - add_special_tokens=True, - truncation=False, # truncation_strategy is deprecated - return_token_type_ids=True, - is_split_into_words=False, - ) - - input_ids, segment_ids = inputs["input_ids"], inputs["token_type_ids"] - - # The mask has 1 for real tokens and 0 for padding tokens. Only real - # tokens are attended to. - padding_mask = [1] * len(input_ids) - - # Padding up to the sequence length. - # Normal case: adding multiple 0 to the right - # Special cases: - # a) xlnet pads on the left and uses "4" for padding token_type_ids - if tokenizer.__class__.__name__ == "XLNetTokenizer": - pad_on_left = True - segment_ids = pad(segment_ids, max_seq_len, 4, pad_on_left=pad_on_left) - else: - pad_on_left = False - segment_ids = pad(segment_ids, max_seq_len, 0, pad_on_left=pad_on_left) - - input_ids = pad(input_ids, max_seq_len, tokenizer.pad_token_id, pad_on_left=pad_on_left) - padding_mask = pad(padding_mask, max_seq_len, 0, pad_on_left=pad_on_left) - - assert len(input_ids) == max_seq_len - assert len(padding_mask) == max_seq_len - assert len(segment_ids) == max_seq_len - - feat_dict = {"input_ids": input_ids, "padding_mask": padding_mask, "segment_ids": segment_ids} - - # Add Labels for different tasks - for task_name, task in tasks.items(): - try: - label_name = task["label_name"] - label_raw = sample.clear_text[label_name] - label_list = task["label_list"] - if task["task_type"] == "classification": - # id of label - try: - label_ids = [label_list.index(label_raw)] - except ValueError: - raise ValueError(f"[Task: {task_name}] Observed label {label_raw} not in defined label_list") - elif task["task_type"] == "multilabel_classification": - # multi-hot-format - label_ids = [0] * len(label_list) - for l in label_raw.split(","): - if l != "": - label_ids[label_list.index(l)] = 1 - elif task["task_type"] == "regression": - label_ids = [float(label_raw)] - else: - raise ValueError(task["task_type"]) - except KeyError: - # For inference mode we don't expect labels - label_ids = None - if label_ids is not None: - feat_dict[task["label_tensor_name"]] = label_ids - return [feat_dict] diff --git a/haystack/modeling/data_handler/inputs.py b/haystack/modeling/data_handler/inputs.py deleted file mode 100644 index b9e472fd6a..0000000000 --- a/haystack/modeling/data_handler/inputs.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Optional, List, Union - - -class Question: - def __init__(self, text: str, uid: Optional[str] = None): - self.text = text - self.uid = uid - - def to_dict(self): - ret = {"question": self.text, "id": self.uid, "answers": []} - return ret - - -class QAInput: - def __init__(self, doc_text: str, questions: Union[List[Question], Question]): - self.doc_text = doc_text - if type(questions) == Question: - self.questions = [questions] - else: - self.questions = questions # type: ignore - - def to_dict(self): - questions = [q.to_dict() for q in self.questions] - ret = {"qas": questions, "context": self.doc_text} - return ret diff --git a/haystack/modeling/data_handler/processor.py b/haystack/modeling/data_handler/processor.py deleted file mode 100644 index f4c1707c72..0000000000 --- a/haystack/modeling/data_handler/processor.py +++ /dev/null @@ -1,2326 +0,0 @@ -from typing import Optional, Dict, List, Union, Any, Iterable, Type, IO, Tuple - -import os -import json -import uuid -import inspect -import logging -import random -import tarfile -import tempfile -from pathlib import Path -from inspect import signature -from abc import ABC, abstractmethod - -import numpy as np -import requests -from tqdm import tqdm -from torch.utils.data import TensorDataset -import transformers -from transformers import PreTrainedTokenizer, AutoTokenizer - -from haystack.errors import HaystackError -from haystack.modeling.model.feature_extraction import ( - tokenize_batch_question_answering, - tokenize_with_metadata, - truncate_sequences, -) -from haystack.modeling.data_handler.dataset import convert_features_to_dataset -from haystack.modeling.data_handler.samples import ( - Sample, - SampleBasket, - get_passage_offsets, - offset_to_token_idx_vecorized, -) -from haystack.modeling.data_handler.input_features import sample_to_features_text -from haystack.utils.experiment_tracking import Tracker as tracker - -DOWNSTREAM_TASK_MAP = { - "squad20": "https://s3.eu-central-1.amazonaws.com/deepset.ai-farm-downstream/squad20.tar.gz", - "covidqa": "https://s3.eu-central-1.amazonaws.com/deepset.ai-farm-downstream/covidqa.tar.gz", -} -logger = logging.getLogger(__name__) - - -class Processor(ABC): - """ - Base class for low level data processors to convert input text to PyTorch Datasets. - """ - - subclasses: dict = {} - - def __init__( - self, - tokenizer, - max_seq_len: int, - train_filename: Optional[Union[Path, str]], - dev_filename: Optional[Union[Path, str]], - test_filename: Optional[Union[Path, str]], - dev_split: float, - data_dir: Optional[Union[Path, str]], - tasks: Optional[Dict] = None, - proxies: Optional[Dict] = None, - multithreading_rust: Optional[bool] = True, - ): - """ - :param tokenizer: Used to split a sentence (str) into tokens. - :param max_seq_len: Samples are truncated after this many tokens. - :param train_filename: The name of the file containing training data. - :param dev_filename: The name of the file containing the dev data. If None and 0.0 < dev_split < 1.0 the dev set - will be a slice of the train set. - :param test_filename: The name of the file containing test data. - :param dev_split: The proportion of the train set that will be sliced. Only works if `dev_filename` is set to `None`. - :param data_dir: The directory in which the train, test and perhaps dev files can be found. - :param tasks: Tasks for which the processor shall extract labels from the input data. - Usually this includes a single, default task, e.g. text classification. - In a multitask setting this includes multiple tasks, e.g. 2x text classification. - The task name will be used to connect with the related PredictionHead. - :param proxies: proxy configuration to allow downloads of remote datasets. - Format as in "requests" library: https://2.python-requests.org//en/latest/user/advanced/#proxies - :param multithreading_rust: Whether to allow multithreading in Rust, e.g. for FastTokenizers. - Note: Enabling multithreading in Rust AND multiprocessing in python might cause - deadlocks. - """ - if tasks is None: - tasks = {} - if not multithreading_rust: - os.environ["RAYON_RS_NUM_CPUS"] = "1" - - self.tokenizer = tokenizer - self.max_seq_len = max_seq_len - self.tasks = tasks - self.proxies = proxies - - # data sets - self.train_filename = train_filename - self.dev_filename = dev_filename - self.test_filename = test_filename - self.dev_split = dev_split - if data_dir: - self.data_dir = Path(data_dir) - else: - self.data_dir = None # type: ignore - - self._log_params() - self.problematic_sample_ids: set = set() - - def __init_subclass__(cls, **kwargs): - """This automatically keeps track of all available subclasses. - Enables generic load() and load_from_dir() for all specific Processor implementation. - """ - super().__init_subclass__(**kwargs) - cls.subclasses[cls.__name__] = cls - - @classmethod - def load( - cls, - processor_name: str, - data_dir: str, # TODO revert ignore - tokenizer, # type: ignore - max_seq_len: int, - train_filename: str, - dev_filename: Optional[str], - test_filename: str, - dev_split: float, - **kwargs, - ): - """ - Loads the class of processor specified by processor name. - - :param processor_name: The class of processor to be loaded. - :param data_dir: Directory where data files are located. - :param tokenizer: A tokenizer object - :param max_seq_len: Sequences longer than this will be truncated. - :param train_filename: The name of the file containing training data. - :param dev_filename: The name of the file containing the dev data. - If None and 0.0 < dev_split < 1.0 the dev set - will be a slice of the train set. - :param test_filename: The name of the file containing test data. - :param dev_split: The proportion of the train set that will be sliced. - Only works if dev_filename is set to None - :param kwargs: placeholder for passing generic parameters - :return: An instance of the specified processor. - """ - - sig = signature(cls.subclasses[processor_name]) - unused_args = {k: v for k, v in kwargs.items() if k not in sig.parameters} - logger.debug( - "Got more parameters than needed for loading %s: %s. Those won't be used!", processor_name, unused_args - ) - processor = cls.subclasses[processor_name]( - data_dir=data_dir, - tokenizer=tokenizer, - max_seq_len=max_seq_len, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - dev_split=dev_split, - **kwargs, - ) - - return processor - - @classmethod - def load_from_dir(cls, load_dir: str): - """ - Infers the specific type of Processor from a config file (e.g. SquadProcessor) and loads an instance of it. - - :param load_dir: directory that contains a 'processor_config.json' - :return: An instance of a Processor Subclass (e.g. SquadProcessor) - """ - # read config - processor_config_file = Path(load_dir) / "processor_config.json" - with open(processor_config_file) as f: - config = json.load(f) - config["inference"] = True - # init tokenizer - if "lower_case" in config: - logger.warning( - "Loading tokenizer from deprecated config. " - "If you used `custom_vocab` or `never_split_chars`, this won't work anymore." - ) - tokenizer = AutoTokenizer.from_pretrained( - load_dir, tokenizer_class=config["tokenizer"], do_lower_case=config["lower_case"] - ) - else: - tokenizer = AutoTokenizer.from_pretrained(load_dir, tokenizer_class=config["tokenizer"]) - - # we have to delete the tokenizer string from config, because we pass it as Object - del config["tokenizer"] - - processor = cls.load(tokenizer=tokenizer, processor_name=config["processor"], **config) - - for task_name, task in config["tasks"].items(): - processor.add_task( - name=task_name, - metric=task["metric"], - label_list=task["label_list"], - label_column_name=task["label_column_name"], - text_column_name=task.get("text_column_name", None), - task_type=task["task_type"], - ) - - if processor is None: - raise Exception - - return processor - - @classmethod - def convert_from_transformers( - cls, - tokenizer_name_or_path, - task_type, - max_seq_len, - doc_stride, - revision=None, - tokenizer_class=None, - tokenizer_args=None, - use_fast=True, - max_query_length=64, - **kwargs, - ): - tokenizer_args = tokenizer_args or {} - tokenizer = AutoTokenizer.from_pretrained( - tokenizer_name_or_path, - tokenizer_class=tokenizer_class, - use_fast=use_fast, - revision=revision, - **tokenizer_args, - **kwargs, - ) - - # TODO infer task_type automatically from config (if possible) - if task_type == "question_answering": - processor = SquadProcessor( - tokenizer=tokenizer, - max_seq_len=max_seq_len, - label_list=["start_token", "end_token"], - metric="squad", - data_dir="data", - doc_stride=doc_stride, - max_query_length=max_query_length, - ) - elif task_type == "embeddings": - processor = InferenceProcessor(tokenizer=tokenizer, max_seq_len=max_seq_len) - - else: - raise ValueError( - f"`task_type` {task_type} is not supported yet. " - f"Valid options for arg `task_type`: 'question_answering', " - f"'embeddings', " - ) - - return processor - - def save(self, save_dir: str): - """ - Saves the vocabulary to file and also creates a json file containing all the - information needed to load the same processor. - - :param save_dir: Directory where the files are to be saved - :return: None - """ - os.makedirs(save_dir, exist_ok=True) - config = self.generate_config() - # save tokenizer incl. attributes - config["tokenizer"] = self.tokenizer.__class__.__name__ - - # Because the fast tokenizers expect a str and not Path - # always convert Path to str here. - self.tokenizer.save_pretrained(str(save_dir)) - - # save processor - config["processor"] = self.__class__.__name__ - output_config_file = Path(save_dir) / "processor_config.json" - with open(output_config_file, "w") as file: - json.dump(config, file) - - def generate_config(self): - """ - Generates config file from Class and instance attributes (only for sensible config parameters). - """ - config = {} - # self.__dict__ doesn't give parent class attributes - for key, value in inspect.getmembers(self): - if _is_json(value) and key[0] != "_": - if issubclass(type(value), Path): - value = str(value) - config[key] = value - return config - - # TODO potentially remove tasks from code - multitask learning is not supported anyways - def add_task( - self, name, metric, label_list, label_column_name=None, label_name=None, task_type=None, text_column_name=None - ): - if type(label_list) is not list: - raise ValueError(f"Argument `label_list` must be of type list. Got: f{type(label_list)}") - - if label_name is None: - label_name = f"{name}_label" - label_tensor_name = label_name + "_ids" - self.tasks[name] = { - "label_list": label_list, - "metric": metric, - "label_tensor_name": label_tensor_name, - "label_name": label_name, - "label_column_name": label_column_name, - "text_column_name": text_column_name, - "task_type": task_type, - } - - @abstractmethod - def file_to_dicts(self, file: str) -> List[dict]: - raise NotImplementedError() - - @abstractmethod - def dataset_from_dicts( - self, dicts: List[Dict], indices: Optional[List[int]] = None, return_baskets: bool = False, debug: bool = False - ): - raise NotImplementedError() - - @abstractmethod - def _create_dataset(self, baskets: List[SampleBasket]): - raise NotImplementedError - - @staticmethod - def log_problematic(problematic_sample_ids): - if problematic_sample_ids: - n_problematic = len(problematic_sample_ids) - problematic_id_str = ", ".join([str(i) for i in problematic_sample_ids]) - logger.error( - "Unable to convert %s samples to features. Their ids are : %s", n_problematic, problematic_id_str - ) - - @staticmethod - def _check_sample_features(basket: SampleBasket): - """ - Check if all samples in the basket has computed its features. - - :param basket: the basket containing the samples - - :return: True if all the samples in the basket has computed its features, False otherwise - """ - return basket.samples and not any(sample.features is None for sample in basket.samples) - - def _log_samples(self, n_samples: int, baskets: List[SampleBasket]): - logger.debug("*** Show %s random examples ***", n_samples) - if len(baskets) == 0: - logger.debug("*** No samples to show because there are no baskets ***") - return - for _ in range(n_samples): - random_basket = random.choice(baskets) - random_sample = random.choice(random_basket.samples) # type: ignore - logger.debug(random_sample) - - def _log_params(self): - params = {"processor": self.__class__.__name__, "tokenizer": self.tokenizer.__class__.__name__} - names = ["max_seq_len", "dev_split"] - for name in names: - value = getattr(self, name) - params.update({name: str(value)}) - tracker.track_params(params) - - -class SquadProcessor(Processor): - """ - Convert QA data (in SQuAD Format) - """ - - def __init__( - self, - tokenizer, # type: ignore - max_seq_len: int, - data_dir: Optional[Union[Path, str]], - label_list: Optional[List[str]] = None, - metric="squad", # type: ignore - train_filename: Optional[Union[Path, str]] = Path("train-v2.0.json"), - dev_filename: Optional[Union[Path, str]] = Path("dev-v2.0.json"), - test_filename: Optional[Union[Path, str]] = None, - dev_split: float = 0, - doc_stride: int = 128, - max_query_length: int = 64, - proxies: Optional[dict] = None, - max_answers: Optional[int] = None, - **kwargs, - ): - """ - :param tokenizer: Used to split a sentence (str) into tokens. - :param max_seq_len: Samples are truncated after this many tokens. - :param data_dir: The directory in which the train and dev files can be found. - If not available the dataset will be loaded automatically - if the last directory has the same name as a predefined dataset. - These predefined datasets are defined as the keys in the dict at - `haystack.basics.data_handler.utils.DOWNSTREAM_TASK_MAP `_. - :param label_list: list of labels to predict (strings). For most cases this should be: ["start_token", "end_token"] - :param metric: name of metric that shall be used for evaluation, can be "squad" or "top_n_accuracy" - :param train_filename: The name of the file containing training data. - :param dev_filename: The name of the file containing the dev data. If None and 0.0 < dev_split < 1.0 the dev set - will be a slice of the train set. - :param test_filename: None - :param dev_split: The proportion of the train set that will be sliced. Only works if `dev_filename` is set to `None`. - :param doc_stride: When the document containing the answer is too long it gets split into part, strided by doc_stride - :param max_query_length: Maximum length of the question (in number of subword tokens) - :param proxies: proxy configuration to allow downloads of remote datasets. - Format as in "requests" library: https://2.python-requests.org//en/latest/user/advanced/#proxies - :param max_answers: Number of answers to be converted. QA sets can contain multi-way annotations, which are converted to arrays of max_answer length. - Adjusts to maximum number of answers in the first processed datasets if not set. - Truncates or pads to max_answer length if set. - :param kwargs: placeholder for passing generic parameters - """ - self.ph_output_type = "per_token_squad" - - # validate max_seq_len - assert max_seq_len <= tokenizer.model_max_length, ( - "max_seq_len cannot be greater than the maximum sequence length handled by the model: " - f"got max_seq_len={max_seq_len}, while the model maximum length is {tokenizer.model_max_length}. " - "Please adjust max_seq_len accordingly or use another model " - ) - - assert doc_stride < (max_seq_len - max_query_length), ( - "doc_stride ({}) is longer than max_seq_len ({}) minus space reserved for query tokens ({}). \nThis means that there will be gaps " - "as the passage windows slide, causing the model to skip over parts of the document.\n" - "Please set a lower value for doc_stride (Suggestions: doc_stride=128, max_seq_len=384)\n " - "Or decrease max_query_length".format(doc_stride, max_seq_len, max_query_length) - ) - - self.doc_stride = doc_stride - self.max_query_length = max_query_length - self.max_answers = max_answers - super(SquadProcessor, self).__init__( - tokenizer=tokenizer, - max_seq_len=max_seq_len, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - dev_split=dev_split, - data_dir=data_dir, - tasks={}, - proxies=proxies, - ) - self._initialize_special_tokens_count() - if metric and label_list: - self.add_task("question_answering", metric, label_list) - else: - logger.info( - "Initialized processor without tasks. Supply `metric` and `label_list` to the constructor for " - "using the default task or add a custom task later via processor.add_task()" - ) - - def dataset_from_dicts( - self, dicts: List[Dict], indices: Optional[List[int]] = None, return_baskets: bool = False, debug: bool = False - ): - """ - Convert input dictionaries into a pytorch dataset for Question Answering. - For this we have an internal representation called "baskets". - Each basket is a question-document pair. - Each stage adds or transforms specific information to our baskets. - - :param dicts: dict, input dictionary with SQuAD style information present - :param indices: list, indices used during multiprocessing so that IDs assigned to our baskets is unique - :param return_baskets: boolean, whether to return the baskets or not (baskets are needed during inference) - """ - if indices is None: - indices = [] - # Convert to standard format - pre_baskets = [self.convert_qa_input_dict(x) for x in dicts] # TODO move to input object conversion - - # Tokenize documents and questions - baskets = tokenize_batch_question_answering(pre_baskets, self.tokenizer, indices) - - # Split documents into smaller passages to fit max_seq_len - baskets = self._split_docs_into_passages(baskets) - - # Determine max_answers if not set - max_answers = ( - self.max_answers - if self.max_answers is not None - else max(*(len(basket.raw["answers"]) for basket in baskets), 1) - ) - - # Convert answers from string to token space, skip this step for inference - if not return_baskets: - baskets = self._convert_answers(baskets, max_answers) - - # Convert internal representation (nested baskets + samples with mixed types) to pytorch features (arrays of numbers) - baskets = self._passages_to_pytorch_features(baskets, return_baskets, max_answers) - - # Convert features into pytorch dataset, this step also removes potential errors during preprocessing - dataset, tensor_names, baskets = self._create_dataset(baskets) - - # Logging - if indices and 0 in indices: - self._log_samples(n_samples=1, baskets=baskets) - - # During inference we need to keep the information contained in baskets. - if return_baskets: - return dataset, tensor_names, self.problematic_sample_ids, baskets - else: - return dataset, tensor_names, self.problematic_sample_ids - - def file_to_dicts(self, file: str) -> List[dict]: - nested_dicts = _read_squad_file(filename=file) - dicts = [y for x in nested_dicts for y in x["paragraphs"]] - return dicts - - # TODO use Input Objects instead of this function, remove Natural Questions (NQ) related code - def convert_qa_input_dict(self, infer_dict: dict) -> Dict[str, Any]: - """Input dictionaries in QA can either have ["context", "qas"] (internal format) as keys or - ["text", "questions"] (api format). This function converts the latter into the former. It also converts the - is_impossible field to answer_type so that NQ and SQuAD dicts have the same format. - """ - # validate again max_seq_len - assert self.max_seq_len <= self.tokenizer.model_max_length, ( - "max_seq_len cannot be greater than the maximum sequence length handled by the model: " - f"got max_seq_len={self.max_seq_len}, while the model maximum length is {self.tokenizer.model_max_length}. " - "Please adjust max_seq_len accordingly or use another model " - ) - - # check again for doc stride vs max_seq_len when. Parameters can be changed for already initialized models (e.g. in haystack) - assert self.doc_stride < (self.max_seq_len - self.max_query_length), ( - "doc_stride ({}) is longer than max_seq_len ({}) minus space reserved for query tokens ({}). \nThis means that there will be gaps " - "as the passage windows slide, causing the model to skip over parts of the document.\n" - "Please set a lower value for doc_stride (Suggestions: doc_stride=128, max_seq_len=384)\n " - "Or decrease max_query_length".format(self.doc_stride, self.max_seq_len, self.max_query_length) - ) - - try: - # Check if infer_dict is already in internal json format - if "context" in infer_dict and "qas" in infer_dict: - return infer_dict - # converts dicts from inference mode to data structure used in Haystack - questions = infer_dict["questions"] - text = infer_dict["text"] - uid = infer_dict.get("id", None) - qas = [{"question": q, "id": uid, "answers": [], "answer_type": None} for i, q in enumerate(questions)] - converted = {"qas": qas, "context": text} - return converted - except KeyError: - raise Exception("Input does not have the expected format") - - def _initialize_special_tokens_count(self): - vec = self.tokenizer.build_inputs_with_special_tokens(token_ids_0=["a"], token_ids_1=["b"]) - self.sp_toks_start = vec.index("a") - self.sp_toks_mid = vec.index("b") - self.sp_toks_start - 1 - self.sp_toks_end = len(vec) - vec.index("b") - 1 - - def _split_docs_into_passages(self, baskets: List[SampleBasket]): - """ - Because of the sequence length limitation of Language Models, the documents need to be divided into smaller - parts that we call passages. - """ - n_special_tokens = self.tokenizer.num_special_tokens_to_add(pair=True) - for basket in baskets: - samples = [] - ########## perform some basic checking - # TODO, eventually move checking into input validation functions - # ignore samples with empty context - if basket.raw["document_text"] == "": - logger.warning("Ignoring sample with empty context") - continue - ########## end checking - - # Calculate the number of tokens that can be reserved for the passage. This is calculated by considering - # the max_seq_len, the number of tokens in the question and the number of special tokens that will be added - # when the question and passage are joined (e.g. [CLS] and [SEP]) - passage_len_t = ( - self.max_seq_len - len(basket.raw["question_tokens"][: self.max_query_length]) - n_special_tokens - ) - - # passage_spans is a list of dictionaries where each defines the start and end of each passage - # on both token and character level - try: - passage_spans = get_passage_offsets( - basket.raw["document_offsets"], self.doc_stride, passage_len_t, basket.raw["document_text"] - ) - except Exception as e: - logger.warning( - "Could not divide document into passages. Document: %s\nWith error: %s", - basket.raw["document_text"][:200], - e, - ) - passage_spans = [] - - for passage_span in passage_spans: - # Unpack each variable in the dictionary. The "_t" and "_c" indicate - # whether the index is on the token or character level - passage_start_t = passage_span["passage_start_t"] - passage_end_t = passage_span["passage_end_t"] - passage_start_c = passage_span["passage_start_c"] - passage_end_c = passage_span["passage_end_c"] - - passage_start_of_word = basket.raw["document_start_of_word"][passage_start_t:passage_end_t] - passage_tokens = basket.raw["document_tokens"][passage_start_t:passage_end_t] - passage_text = basket.raw["document_text"][passage_start_c:passage_end_c] - - clear_text = { - "passage_text": passage_text, - "question_text": basket.raw["question_text"], - "passage_id": passage_span["passage_id"], - } - tokenized = { - "passage_start_t": passage_start_t, - "passage_start_c": passage_start_c, - "passage_tokens": passage_tokens, - "passage_start_of_word": passage_start_of_word, - "question_tokens": basket.raw["question_tokens"][: self.max_query_length], - "question_offsets": basket.raw["question_offsets"][: self.max_query_length], - "question_start_of_word": basket.raw["question_start_of_word"][: self.max_query_length], - } - # The sample ID consists of internal_id and a passage numbering - sample_id = f"{basket.id_internal}-{passage_span['passage_id']}" - samples.append(Sample(id=sample_id, clear_text=clear_text, tokenized=tokenized)) - - basket.samples = samples - - return baskets - - def _convert_answers(self, baskets: List[SampleBasket], max_answers: int): - """ - Converts answers that are pure strings into the token based representation with start and end token offset. - Can handle multiple answers per question document pair as is common for development/text sets - """ - for basket in baskets: - error_in_answer = False - for sample in basket.samples: # type: ignore - # Dealing with potentially multiple answers (e.g. Squad dev set) - # Initializing a numpy array of shape (max_answers, 2), filled with -1 for missing values - label_idxs = np.full((max_answers, 2), fill_value=-1) - - if error_in_answer or (len(basket.raw["answers"]) == 0): - # If there are no answers we set - label_idxs[0, :] = 0 - else: - # For all other cases we use start and end token indices, that are relative to the passage - for i, answer in enumerate(basket.raw["answers"]): - if i >= max_answers: - logger.warning( - "Found a sample with more answers (%d) than " - "max_answers (%d). These will be ignored.", - len(basket.raw["answers"]), - max_answers, - ) - break - # Calculate start and end relative to document - answer_len_c = len(answer["text"]) - answer_start_c = answer["answer_start"] - answer_end_c = answer_start_c + answer_len_c - 1 - - # Convert character offsets to token offsets on document level - answer_start_t = offset_to_token_idx_vecorized(basket.raw["document_offsets"], answer_start_c) - answer_end_t = offset_to_token_idx_vecorized(basket.raw["document_offsets"], answer_end_c) - - # Adjust token offsets to be relative to the passage - answer_start_t -= sample.tokenized["passage_start_t"] # type: ignore - answer_end_t -= sample.tokenized["passage_start_t"] # type: ignore - - # Initialize some basic variables - question_len_t = len(sample.tokenized["question_tokens"]) # type: ignore - passage_len_t = len(sample.tokenized["passage_tokens"]) # type: ignore - - # Check that start and end are contained within this passage - # answer_end_t is 0 if the first token is the answer - # answer_end_t is passage_len_t if the last token is the answer - if passage_len_t > answer_start_t >= 0 and passage_len_t >= answer_end_t >= 0: - # Then adjust the start and end offsets by adding question and special token - label_idxs[i][0] = self.sp_toks_start + question_len_t + self.sp_toks_mid + answer_start_t - label_idxs[i][1] = self.sp_toks_start + question_len_t + self.sp_toks_mid + answer_end_t - # If the start or end of the span answer is outside the passage, treat passage as no_answer - else: - label_idxs[i][0] = 0 - label_idxs[i][1] = 0 - - ########## answer checking ############################## - # TODO, move this checking into input validation functions and delete wrong examples there - # Cases where the answer is not within the current passage will be turned into no answers by the featurization fn - if answer_start_t < 0 or answer_end_t >= passage_len_t: - pass - else: - doc_text = basket.raw["document_text"] - answer_indices = doc_text[answer_start_c : answer_end_c + 1] - answer_text = answer["text"] - # check if answer string can be found in context - if answer_text not in doc_text: - logger.warning( - "Answer '%s' not contained in context.\n" - "Example will not be converted for training/evaluation.", - answer["text"], - ) - error_in_answer = True - label_idxs[i][0] = -100 # TODO remove this hack also from featurization - label_idxs[i][1] = -100 - break # Break loop around answers, so the error message is not shown multiple times - if answer_indices.strip() != answer_text.strip(): - logger.warning( - "Answer using start/end indices is '%s' while gold label text is '%s'.\n" - "Example will not be converted for training/evaluation.", - answer_indices, - answer_text, - ) - error_in_answer = True - label_idxs[i][0] = -100 # TODO remove this hack also from featurization - label_idxs[i][1] = -100 - break # Break loop around answers, so the error message is not shown multiple times - ########## end of checking #################### - - sample.tokenized["labels"] = label_idxs # type: ignore - - return baskets - - def _passages_to_pytorch_features(self, baskets: List[SampleBasket], return_baskets: bool, max_answers: int): - """ - Convert internal representation (nested baskets + samples with mixed types) to python features (arrays of numbers). - We first join question and passages into one large vector. - Then we add vectors for: - input_ids (token ids) - - segment_ids (does a token belong to question or document) - - padding_mask - - span_mask (valid answer tokens) - - start_of_word - """ - for basket in baskets: - # Add features to samples - for sample in basket.samples: # type: ignore - # Initialize some basic variables - if sample.tokenized is not None: - question_tokens = sample.tokenized["question_tokens"] - question_start_of_word = sample.tokenized["question_start_of_word"] - question_len_t = len(question_tokens) - passage_start_t = sample.tokenized["passage_start_t"] - passage_tokens = sample.tokenized["passage_tokens"] - passage_start_of_word = sample.tokenized["passage_start_of_word"] - passage_len_t = len(passage_tokens) - sample_id = [int(x) for x in sample.id.split("-")] - - # - Combines question_tokens and passage_tokens into a single vector called input_ids - # - input_ids also contains special tokens (e.g. CLS or SEP tokens). - # - It will have length = question_len_t + passage_len_t + n_special_tokens. This may be less than - # max_seq_len but never greater since truncation was already performed when the document was chunked into passages - question_input_ids = sample.tokenized["question_tokens"] - passage_input_ids = sample.tokenized["passage_tokens"] - - input_ids = self.tokenizer.build_inputs_with_special_tokens( - token_ids_0=question_input_ids, token_ids_1=passage_input_ids - ) - - segment_ids = self.tokenizer.create_token_type_ids_from_sequences( - token_ids_0=question_input_ids, token_ids_1=passage_input_ids - ) - # To make the start index of passage tokens the start manually - seq_2_start_t = self.sp_toks_start + question_len_t + self.sp_toks_mid - - start_of_word = ( - [0] * self.sp_toks_start - + question_start_of_word - + [0] * self.sp_toks_mid - + passage_start_of_word - + [0] * self.sp_toks_end - ) - - # The mask has 1 for real tokens and 0 for padding tokens. Only real - # tokens are attended to. - padding_mask = [1] * len(input_ids) - - # The span_mask has 1 for tokens that are valid start or end tokens for QA spans. - # 0s are assigned to question tokens, mid special tokens, end special tokens, and padding - # Note that start special tokens are assigned 1 since they can be chosen for a no_answer prediction - span_mask = [1] * self.sp_toks_start - span_mask += [0] * question_len_t - span_mask += [0] * self.sp_toks_mid - span_mask += [1] * passage_len_t - span_mask += [0] * self.sp_toks_end - - # Pad up to the sequence length. For certain models, the pad token id is not 0 (e.g. Roberta where it is 1) - pad_idx = self.tokenizer.pad_token_id - padding = [pad_idx] * (self.max_seq_len - len(input_ids)) - zero_padding = [0] * (self.max_seq_len - len(input_ids)) - - input_ids += padding - padding_mask += zero_padding - segment_ids += zero_padding - start_of_word += zero_padding - span_mask += zero_padding - - # TODO possibly remove these checks after input validation is in place - len_check = ( - len(input_ids) == len(padding_mask) == len(segment_ids) == len(start_of_word) == len(span_mask) - ) - id_check = len(sample_id) == 3 - label_check = return_baskets or len(sample.tokenized.get("labels", [])) == max_answers # type: ignore - # labels are set to -100 when answer cannot be found - label_check2 = return_baskets or np.all(sample.tokenized["labels"] > -99) # type: ignore - if len_check and id_check and label_check and label_check2: - # - The first of the labels will be used in train, and the full array will be used in eval. - # - start_of_word and spec_tok_mask are not actually needed by model.forward() but are needed for - # model.formatted_preds() during inference for creating answer strings - # - passage_start_t is index of passage's first token relative to document - feature_dict = { - "input_ids": input_ids, - "padding_mask": padding_mask, - "segment_ids": segment_ids, - "passage_start_t": passage_start_t, - "start_of_word": start_of_word, - "labels": sample.tokenized.get("labels", []), # type: ignore - "id": sample_id, - "seq_2_start_t": seq_2_start_t, - "span_mask": span_mask, - } - # other processor's features can be lists - sample.features = [feature_dict] # type: ignore - else: - self.problematic_sample_ids.add(sample.id) - sample.features = None - return baskets - - def _create_dataset(self, baskets: List[SampleBasket]): - """ - Convert python features into pytorch dataset. - Also removes potential errors during preprocessing. - Flattens nested basket structure to create a flat list of features - """ - features_flat: List[dict] = [] - basket_to_remove = [] - for basket in baskets: - if self._check_sample_features(basket): - for sample in basket.samples: # type: ignore - features_flat.extend(sample.features) # type: ignore - else: - # remove the entire basket - basket_to_remove.append(basket) - if len(basket_to_remove) > 0: - for basket in basket_to_remove: - # if basket_to_remove is not empty remove the related baskets - baskets.remove(basket) - - dataset, tensor_names = convert_features_to_dataset(features=features_flat) - return dataset, tensor_names, baskets - - -class TextSimilarityProcessor(Processor): - """ - Used to handle the Dense Passage Retrieval (DPR) datasets that come in json format, example: biencoder-nq-train.json, biencoder-nq-dev.json, trivia-train.json, trivia-dev.json - - Datasets can be downloaded from the official DPR github repository (https://github.com/facebookresearch/DPR) - dataset format: list of dictionaries with keys: 'dataset', 'question', 'answers', 'positive_ctxs', 'negative_ctxs', 'hard_negative_ctxs' - Each sample is a dictionary of format: - {"dataset": str, - "question": str, - "answers": list of str - "positive_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str} - "negative_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str} - "hard_negative_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str} - } - - """ - - def __init__( - self, - query_tokenizer, # type: ignore - passage_tokenizer, # type: ignore - max_seq_len_query: int, - max_seq_len_passage: int, - data_dir: str = "", - metric=None, # type: ignore - train_filename: str = "train.json", - dev_filename: Optional[str] = None, - test_filename: Optional[str] = "test.json", - dev_split: float = 0.1, - proxies: Optional[dict] = None, - max_samples: Optional[int] = None, - embed_title: bool = True, - num_positives: int = 1, - num_hard_negatives: int = 1, - shuffle_negatives: bool = True, - shuffle_positives: bool = False, - label_list: Optional[List[str]] = None, - **kwargs, - ): - """ - :param query_tokenizer: Used to split a question (str) into tokens - :param passage_tokenizer: Used to split a passage (str) into tokens. - :param max_seq_len_query: Query samples are truncated after this many tokens. - :param max_seq_len_passage: Context/Passage Samples are truncated after this many tokens. - :param data_dir: The directory in which the train and dev files can be found. - If not available the dataset will be loaded automatically - if the last directory has the same name as a predefined dataset. - These predefined datasets are defined as the keys in the dict at - `haystack.basics.data_handler.utils.DOWNSTREAM_TASK_MAP `_. - :param metric: name of metric that shall be used for evaluation, e.g. "acc" or "f1_macro". - Alternatively you can also supply a custom function, that takes preds and labels as args and returns a numerical value. - For using multiple metrics supply them as a list, e.g ["acc", my_custom_metric_fn]. - :param train_filename: The name of the file containing training data. - :param dev_filename: The name of the file containing the dev data. If None and 0.0 < dev_split < 1.0 the dev set - will be a slice of the train set. - :param test_filename: None - :param dev_split: The proportion of the train set that will sliced. Only works if dev_filename is set to None - :param proxies: proxy configuration to allow downloads of remote datasets. - Format as in "requests" library: https://2.python-requests.org//en/latest/user/advanced/#proxies - :param max_samples: maximum number of samples to use - :param embed_title: Whether to embed title in passages during tensorization (bool), - :param num_hard_negatives: maximum number to hard negative context passages in a sample - :param num_positives: maximum number to positive context passages in a sample - :param shuffle_negatives: Whether to shuffle all the hard_negative passages before selecting the num_hard_negative number of passages - :param shuffle_positives: Whether to shuffle all the positive passages before selecting the num_positive number of passages - :param label_list: list of labels to predict. Usually ["hard_negative", "positive"] - :param kwargs: placeholder for passing generic parameters - """ - # TODO If an arg is misspelt, e.g. metrics, it will be swallowed silently by kwargs - - # Custom processor attributes - self.max_samples = max_samples - self.query_tokenizer = query_tokenizer - self.passage_tokenizer = passage_tokenizer - self.embed_title = embed_title - self.num_hard_negatives = num_hard_negatives - self.num_positives = num_positives - self.shuffle_negatives = shuffle_negatives - self.shuffle_positives = shuffle_positives - self.max_seq_len_query = max_seq_len_query - self.max_seq_len_passage = max_seq_len_passage - - super(TextSimilarityProcessor, self).__init__( - tokenizer=None, # type: ignore - max_seq_len=0, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - dev_split=dev_split, - data_dir=data_dir, - tasks={}, - proxies=proxies, - ) - if metric: - self.add_task( - name="text_similarity", - metric=metric, - label_list=label_list, - label_name="label", - task_type="text_similarity", - ) - else: - logger.info( - "Initialized processor without tasks. Supply `metric` and `label_list` to the constructor for " - "using the default task or add a custom task later via processor.add_task()" - ) - - @classmethod - def load_from_dir(cls, load_dir: str): - """ - Overwriting method from parent class to **always** load the TextSimilarityProcessor instead of the specific class stored in the config. - - :param load_dir: directory that contains a 'processor_config.json' - :return: An instance of an TextSimilarityProcessor - """ - # read config - processor_config_file = Path(load_dir) / "processor_config.json" - with open(processor_config_file) as f: - config = json.load(f) - # init tokenizers - query_tokenizer_class: Type[PreTrainedTokenizer] = getattr(transformers, config["query_tokenizer"]) - query_tokenizer = query_tokenizer_class.from_pretrained( - pretrained_model_name_or_path=load_dir, subfolder="query" - ) - passage_tokenizer_class: Type[PreTrainedTokenizer] = getattr(transformers, config["passage_tokenizer"]) - passage_tokenizer = passage_tokenizer_class.from_pretrained( - pretrained_model_name_or_path=load_dir, subfolder="passage" - ) - - # we have to delete the tokenizer string from config, because we pass it as Object - del config["query_tokenizer"] - del config["passage_tokenizer"] - - processor = cls.load( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - processor_name="TextSimilarityProcessor", - **config, - ) - for task_name, task in config["tasks"].items(): - processor.add_task(name=task_name, metric=task["metric"], label_list=task["label_list"]) - - if processor is None: - raise Exception - - return processor - - def save(self, save_dir: Union[str, Path]): - """ - Saves the vocabulary to file and also creates a json file containing all the - information needed to load the same processor. - - :param save_dir: Directory where the files are to be saved - :return: None - """ - if isinstance(save_dir, str): - save_dir = Path(save_dir) - os.makedirs(save_dir, exist_ok=True) - config = self.generate_config() - # save tokenizer incl. attributes - config["query_tokenizer"] = self.query_tokenizer.__class__.__name__ - config["passage_tokenizer"] = self.passage_tokenizer.__class__.__name__ - - # Because the fast tokenizers expect a str and not Path - # always convert Path to str here. - self.query_tokenizer.save_pretrained(str(save_dir / "query")) - self.passage_tokenizer.save_pretrained(str(save_dir / "passage")) - - # save processor - config["processor"] = self.__class__.__name__ - output_config_file = Path(save_dir) / "processor_config.json" - with open(output_config_file, "w") as file: - json.dump(config, file) - - def dataset_from_dicts( - self, dicts: List[Dict], indices: Optional[List[int]] = None, return_baskets: bool = False, debug: bool = False - ): - """ - Convert input dictionaries into a pytorch dataset for TextSimilarity (e.g. DPR). - For conversion we have an internal representation called "baskets". - Each basket is one query and related text passages (positive passages fitting to the query and negative - passages that do not fit the query) - Each stage adds or transforms specific information to our baskets. - - :param dicts: input dictionary with DPR-style content - {"query": str, - "passages": List[ - {'title': str, - 'text': str, - 'label': 'hard_negative', - 'external_id': str}, - .... - ] - } - :param indices: indices used during multiprocessing so that IDs assigned to our baskets is unique - :param return_baskets: whether to return the baskets or not (baskets are needed during inference) - :return: dataset, tensor_names, problematic_ids, [baskets] - """ - if indices is None: - indices = [] - # Take the dict and insert into our basket structure, this stages also adds an internal IDs - baskets = self._fill_baskets(dicts, indices) - - # Separate conversion of query - baskets = self._convert_queries(baskets=baskets) - - # and context passages. When converting the context the label is also assigned. - baskets = self._convert_contexts(baskets=baskets) - - # Convert features into pytorch dataset, this step also removes and logs potential errors during preprocessing - dataset, tensor_names, problematic_ids, baskets = self._create_dataset(baskets) - - if problematic_ids: - logger.error( - "There were %s errors during preprocessing at positions: %s", len(problematic_ids), problematic_ids - ) - - if return_baskets: - return dataset, tensor_names, problematic_ids, baskets - else: - return dataset, tensor_names, problematic_ids - - def file_to_dicts(self, file: str) -> List[dict]: - """ - Converts a Dense Passage Retrieval (DPR) data file in json format to a list of dictionaries. - - :param file: filename of DPR data in json format - Each sample is a dictionary of format: - {"dataset": str, - "question": str, - "answers": list of str - "positive_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str} - "negative_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str} - "hard_negative_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str} - } - - - Returns: - list of dictionaries: List[dict] - each dictionary: - {"query": str, - "passages": [{"text": document_text, "title": xxx, "label": "positive", "external_id": abb123}, - {"text": document_text, "title": xxx, "label": "hard_negative", "external_id": abb134}, - ...]} - """ - dicts = _read_dpr_json( - file, - max_samples=self.max_samples, - num_hard_negatives=self.num_hard_negatives, - num_positives=self.num_positives, - shuffle_negatives=self.shuffle_negatives, - shuffle_positives=self.shuffle_positives, - ) - - # shuffle dicts to make sure that similar positive passages do not end up in one batch - dicts = random.sample(dicts, len(dicts)) - return dicts - - def _fill_baskets(self, dicts: List[dict], indices: Optional[List[int]]): - baskets = [] - if not indices: - indices = list(range(len(dicts))) - for d, id_internal in zip(dicts, indices): - basket = SampleBasket(id_external=None, id_internal=id_internal, raw=d) - baskets.append(basket) - return baskets - - def _convert_queries(self, baskets: List[SampleBasket]): - for basket in baskets: - clear_text = {} - tokenized = {} - features = [{}] # type: ignore - # extract query, positive context passages and titles, hard-negative passages and titles - if "query" in basket.raw: - try: - query = self._normalize_question(basket.raw["query"]) - - # featurize the query - query_inputs = self.query_tokenizer( - query, - max_length=self.max_seq_len_query, - add_special_tokens=True, - truncation=True, - truncation_strategy="longest_first", - padding="max_length", - return_token_type_ids=True, - ) - - # tokenize query - tokenized_query = self.query_tokenizer.convert_ids_to_tokens(query_inputs["input_ids"]) - - if len(tokenized_query) == 0: - logger.warning( - "The query could not be tokenized, likely because it contains a character that the query tokenizer does not recognize" - ) - return None - - clear_text["query_text"] = query - tokenized["query_tokens"] = tokenized_query - features[0]["query_input_ids"] = query_inputs["input_ids"] - features[0]["query_segment_ids"] = query_inputs["token_type_ids"] - features[0]["query_attention_mask"] = query_inputs["attention_mask"] - except Exception: - features = None # type: ignore - - sample = Sample(id="", clear_text=clear_text, tokenized=tokenized, features=features) # type: ignore - basket.samples = [sample] - return baskets - - def _convert_contexts(self, baskets: List[SampleBasket]): - for basket in baskets: - if "passages" in basket.raw: - try: - positive_context = list(filter(lambda x: x["label"] == "positive", basket.raw["passages"])) - if self.shuffle_positives: - random.shuffle(positive_context) - positive_context = positive_context[: self.num_positives] - hard_negative_context = list( - filter(lambda x: x["label"] == "hard_negative", basket.raw["passages"]) - ) - if self.shuffle_negatives: - random.shuffle(hard_negative_context) - hard_negative_context = hard_negative_context[: self.num_hard_negatives] - - positive_ctx_titles = [passage.get("title", None) for passage in positive_context] - positive_ctx_texts = [passage["text"] for passage in positive_context] - hard_negative_ctx_titles = [passage.get("title", None) for passage in hard_negative_context] - hard_negative_ctx_texts = [passage["text"] for passage in hard_negative_context] - - # all context passages and labels: 1 for positive context and 0 for hard-negative context - ctx_label = [1] * self.num_positives + [0] * self.num_hard_negatives - # featurize context passages - if self.embed_title: - # concatenate title with positive context passages + negative context passages - all_ctx = self._combine_title_context( - positive_ctx_titles, positive_ctx_texts - ) + self._combine_title_context(hard_negative_ctx_titles, hard_negative_ctx_texts) - else: - all_ctx = positive_ctx_texts + hard_negative_ctx_texts - - # assign empty string tuples if hard_negative passages less than num_hard_negatives - all_ctx += [("", "")] * ((self.num_positives + self.num_hard_negatives) - len(all_ctx)) - - ctx_inputs = self.passage_tokenizer( - all_ctx, - add_special_tokens=True, - truncation=True, - padding="max_length", - max_length=self.max_seq_len_passage, - return_token_type_ids=True, - ) - - ctx_segment_ids = [[0] * len(ctx_inputs["token_type_ids"][0])] * len(ctx_inputs["token_type_ids"]) - - # get tokens in string format - tokenized_passage = [ - self.passage_tokenizer.convert_ids_to_tokens(ctx) for ctx in ctx_inputs["input_ids"] - ] - - # for DPR we only have one sample containing query and corresponding (multiple) context features - sample = basket.samples[0] # type: ignore - sample.clear_text["passages"] = positive_context + hard_negative_context - sample.tokenized["passages_tokens"] = tokenized_passage # type: ignore - sample.features[0]["passage_input_ids"] = ctx_inputs["input_ids"] # type: ignore - sample.features[0]["passage_segment_ids"] = ctx_segment_ids # type: ignore - sample.features[0]["passage_attention_mask"] = ctx_inputs["attention_mask"] # type: ignore - sample.features[0]["label_ids"] = ctx_label # type: ignore - except Exception: - basket.samples[0].features = None # type: ignore - - return baskets - - def _create_dataset(self, baskets: List[SampleBasket]): - """ - Convert python features into pytorch dataset. - Also removes potential errors during preprocessing. - Flattens nested basket structure to create a flat list of features - """ - features_flat: List[dict] = [] - basket_to_remove = [] - problematic_ids: set = set() - for basket in baskets: - if self._check_sample_features(basket): - for sample in basket.samples: # type: ignore - features_flat.extend(sample.features) # type: ignore - else: - # remove the entire basket - basket_to_remove.append(basket) - if len(basket_to_remove) > 0: - for basket in basket_to_remove: - # if basket_to_remove is not empty remove the related baskets - problematic_ids.add(basket.id_internal) - baskets.remove(basket) - - dataset, tensor_names = convert_features_to_dataset(features=features_flat) - return dataset, tensor_names, problematic_ids, baskets - - @staticmethod - def _normalize_question(question: str) -> str: - """Removes '?' from queries/questions""" - if question[-1] == "?": - question = question[:-1] - return question - - @staticmethod - def _combine_title_context(titles: List[str], texts: List[str]): - res = [] - for title, ctx in zip(titles, texts): - if title is None: - title = "" - logger.warning( - "Couldn't find title although `embed_title` is set to True for DPR. Using title='' now. Related passage text: '%s' ", - ctx, - ) - res.append((title, ctx)) - return res - - -class TableTextSimilarityProcessor(Processor): - """ - Used to handle the Multimodal Retrieval datasets consisting of text passages and tables - that come in json format. - - """ - - def __init__( - self, - query_tokenizer, # type: ignore - passage_tokenizer, # type: ignore - table_tokenizer, # type: ignore - max_seq_len_query: int, - max_seq_len_passage: int, - max_seq_len_table: int, - data_dir: str = "", - metric: Optional[str] = None, - train_filename: Optional[Union[Path, str]] = "train.json", - dev_filename: Optional[Union[Path, str]] = None, - test_filename: Optional[Union[Path, str]] = "test.json", - dev_split: float = 0.1, - proxies: Optional[Dict] = None, - max_samples: Optional[int] = None, - embed_meta_fields: Optional[List[str]] = None, - num_positives: int = 1, - num_hard_negatives: int = 1, - shuffle_negatives: bool = True, - shuffle_positives: bool = False, - label_list: Optional[List[str]] = None, - **kwargs, - ): - """ - :param query_tokenizer: Used to split a question (str) into tokens - :param passage_tokenizer: Used to split a text passage (str) into tokens. - :param table_tokenizer: Used to split a table into tokens - :param max_seq_len_query: Query samples are truncated after this many tokens. - :param max_seq_len_passage: Context/Passage Samples are truncated after this many tokens. - :param max_seq_len_table: Table samples are truncated after this many tokens. - :param data_dir: The directory in which the train and dev files can be found. - If not available the dataset will be loaded automatically - if the last directory has the same name as a predefined dataset. - These predefined datasets are defined as the keys in the dict DOWNSTREAM_TASK_MAP - :param metric: Name of metric that shall be used for evaluation, e.g. "acc" or "f1_macro". - Alternatively you can also supply a custom function, that takes preds and labels as args and returns a numerical value. - For using multiple metrics supply them as a list, e.g ["acc", my_custom_metric_fn]. - :param train_filename: The name of the file containing training data. - :param dev_filename: The name of the file containing the dev data. If None and 0.0 < dev_split < 1.0 the dev set - will be a slice of the train set. - :param test_filename: The name of the file containing the test data. - :param dev_split: The proportion of the train set that will sliced. Only works if dev_filename is set to None. - :param proxies: Proxy configuration to allow downloads of remote datasets. - Format as in "requests" library: https://2.python-requests.org//en/latest/user/advanced/#proxies - :param max_samples: maximum number of samples to use. - :param embed_meta_fields: List of meta fields to embed in text passages and tables during tensorization. By default, "page_title", "section_title", and "caption" are used. - :param num_hard_negatives: Maximum number of hard negative context passages in a sample. - :param num_positives: Maximum number of positive context passages in a sample. - :param shuffle_negatives: Whether to shuffle all the hard_negative passages before selecting the - num_hard_negative number of passages. - :param shuffle_positives: Whether to shuffle all the positive passages before selecting the - num_positive number of passages. - :param label_list: List of labels to predict. Usually ["hard_negative", "positive"]. - :param kwargs: Placeholder for passing generic parameters - """ - # TODO If an arg is misspelt, e.g. metrics, it will be swallowed silently by kwargs - - if embed_meta_fields is None: - embed_meta_fields = ["page_title", "section_title", "caption"] - # Custom processor attributes - self.max_samples = max_samples - self.query_tokenizer = query_tokenizer - self.passage_tokenizer = passage_tokenizer - self.table_tokenizer = table_tokenizer - self.embed_meta_fields = embed_meta_fields - self.num_hard_negatives = num_hard_negatives - self.num_positives = num_positives - self.shuffle_negatives = shuffle_negatives - self.shuffle_positives = shuffle_positives - self.max_seq_len_query = max_seq_len_query - self.max_seq_len_passage = max_seq_len_passage - self.max_seq_len_table = max_seq_len_table - - super(TableTextSimilarityProcessor, self).__init__( - tokenizer=self.query_tokenizer, - max_seq_len=0, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - dev_split=dev_split, - data_dir=data_dir, - tasks={}, - proxies=proxies, - ) - if metric: - self.add_task( - name="text_similarity", - metric=metric, - label_list=label_list, - label_name="label", - task_type="text_similarity", - ) - else: - logger.info( - "Initialized processor without tasks. Supply `metric` and `label_list` to the constructor for " - "using the default task or add a custom task later via processor.add_task()" - ) - - @classmethod - def load_from_dir(cls, load_dir: str): - """ - Overwriting method from parent class to **always** load the TableTextSimilarityProcessor - instead of the specific class stored in the config. - - :param load_dir: Directory that contains a 'processor_config.json' - :return: An instance of an TableTextSimilarityProcessor. - """ - # read config - processor_config_file = Path(load_dir) / "processor_config.json" - with open(processor_config_file) as f: - config = json.load(f) - # init tokenizer - query_tokenizer = AutoTokenizer.from_pretrained( - load_dir, tokenizer_class=config["query_tokenizer"], subfolder="query" - ) - passage_tokenizer = AutoTokenizer.from_pretrained( - load_dir, tokenizer_class=config["passage_tokenizer"], subfolder="passage" - ) - table_tokenizer = AutoTokenizer.from_pretrained( - load_dir, tokenizer_class=config["table_tokenizer"], subfolder="table" - ) - - # we have to delete the tokenizer string from config, because we pass it as Object - del config["query_tokenizer"] - del config["passage_tokenizer"] - del config["table_tokenizer"] - - processor = cls.load( - query_tokenizer=query_tokenizer, - passage_tokenizer=passage_tokenizer, - table_tokenizer=table_tokenizer, - processor_name="TableTextSimilarityProcessor", - **config, - ) - for task_name, task in config["tasks"].items(): - processor.add_task(name=task_name, metric=task["metric"], label_list=task["label_list"]) - - if processor is None: - raise Exception - - return processor - - def save(self, save_dir: Union[str, Path]): - """ - Saves the vocabulary to file and also creates a json file containing all the - information needed to load the same processor. - - :param save_dir: Directory where the files are to be saved. - """ - if isinstance(save_dir, str): - save_dir = Path(save_dir) - os.makedirs(save_dir, exist_ok=True) - config = self.generate_config() - # save tokenizer incl. attributes - config["query_tokenizer"] = self.query_tokenizer.__class__.__name__ - config["passage_tokenizer"] = self.passage_tokenizer.__class__.__name__ - config["table_tokenizer"] = self.table_tokenizer.__class__.__name__ - - # Because the fast tokenizers expect a str and not Path - # always convert Path to str here. - self.query_tokenizer.save_pretrained(str(save_dir / "query")) - self.passage_tokenizer.save_pretrained(str(save_dir / "passage")) - self.table_tokenizer.save_pretrained(str(save_dir / "table")) - - # save processor - config["processor"] = self.__class__.__name__ - output_config_file = Path(save_dir) / "processor_config.json" - with open(output_config_file, "w") as file: - json.dump(config, file) - - def file_to_dicts(self, file: str) -> List[Dict]: - """ - Converts a Multimodal Retrieval data file in json format to a list of dictionaries. - - :param file: filename of DPR data in json format - Each sample is a dictionary of format: - {"question": str, - "answers": list of str - "positive_ctxs": list of dictionaries of format - {'title': str, 'text': str, 'passage_id': str, 'type': 'text', 'source': str} - or - {'page_title': str, 'section_title': str, 'caption': str, 'columns': list of str, - 'rows': list of list of str, 'type': 'table', 'source': str} - "hard_negative_ctxs": list of dictionaries of format - {'title': str, 'text': str, 'passage_id': str, 'type': 'text', 'source': str} - or - {'page_title': str, 'section_title': str, 'caption': str, 'columns': list of str, - 'rows': list of list of str, 'type': 'table', 'source': str} - } - - - Returns: - List of dictionaries: List[dict] - each dictionary: - {"query": str, - "passages": [ - {"title": str, "text": str, "label": "positive" / "hard_negative", "type": "text", "external_id": id} - or - {"page_title": str, "section_title": str, "caption": str, "columns": list of str, - "rows": list of list of str, "label": "positive" / "hard_negative", "type": "table", "external_id": id} - ...]} - """ - dicts = self._read_multimodal_dpr_json(file, max_samples=self.max_samples) - return dicts - - def _read_multimodal_dpr_json(self, file: str, max_samples: Optional[int] = None) -> List[Dict]: - """ - Reads a Multimodal Retrieval data file in json format and returns a list of dictionaries. - - :param file: filename of MMR data in json format - - Returns: - list of dictionaries: List[dict] - each dictionary: { - "query": str -> query_text - "passages": List[dictionaries] -> [ - {"text": str, "title": str, "label": "positive" / "hard_negative, "external_id": id}, - or - {"page_title": str, "section_title": str, "caption": str, "columns": list of str, - "rows": list of lists of str, "label": "positive" / "hard_negative", "type": "table", "external_id": id} - ...] - } - """ - with open(file) as f: - dicts = json.load(f) - if max_samples: - dicts = random.sample(dicts, min(max_samples, len(dicts))) - # convert DPR dictionary to standard dictionary - query_json_keys = ["question", "questions", "query"] - positive_context_json_keys = ["positive_contexts", "positive_ctxs", "positive_context", "positive_ctx"] - hard_negative_json_keys = [ - "hard_negative_contexts", - "hard_negative_ctxs", - "hard_negative_context", - "hard_negative_ctx", - ] - standard_dicts = [] - for dict in dicts: - sample = {} - docs = [] - for key, val in dict.items(): - if key in query_json_keys: - sample["query"] = val - elif key in positive_context_json_keys + hard_negative_json_keys: - for doc in val: - if doc["type"] == "table": - docs.append( - { - "meta": [ - doc[meta_field] for meta_field in self.embed_meta_fields if meta_field in doc - ], - "columns": doc.get("columns"), - "rows": doc.get("rows"), - "label": "positive" if key in positive_context_json_keys else "hard_negative", - "type": "table", - } - ) - elif doc["type"] == "text": - docs.append( - { - "meta": [ - doc[meta_field] for meta_field in self.embed_meta_fields if meta_field in doc - ], - "text": doc["text"], - "label": "positive" if key in positive_context_json_keys else "hard_negative", - "type": "text", - } - ) - - sample["passages"] = docs - standard_dicts.append(sample) - return standard_dicts - - def dataset_from_dicts( - self, dicts: List[Dict], indices: Optional[List[int]] = None, return_baskets: bool = False, debug: bool = False - ): - """ - Convert input dictionaries into a pytorch dataset for TextSimilarity. - For conversion we have an internal representation called "baskets". - Each basket is one query and related text passages (positive passages fitting to the query and negative - passages that do not fit the query) - Each stage adds or transforms specific information to our baskets. - - :param dicts: List of dicts, input dictionary with DPR-style content - {"query": str, - "passages": List[ - {'title': str, - 'text': str, - 'label': 'hard_negative', - 'external_id': str}, - .... - ] - } - :param indices: list, indices used during multiprocessing so that IDs assigned to our baskets is unique - :param return_baskets: boolean, whether to return the baskets or not (baskets are needed during inference) - """ - if indices is None: - indices = [] - # Take the dict and insert into our basket structure, this stages also adds an internal IDs - baskets = self._fill_baskets(dicts, indices) - - # Separate conversion of query - baskets = self._convert_queries(baskets=baskets) - - # and context passages and tables. When converting the context the label is also assigned. - baskets = self._convert_contexts(baskets=baskets) - - # Convert features into pytorch dataset, this step also removes and logs potential errors during preprocessing - dataset, tensor_names, problematic_ids, baskets = self._create_dataset(baskets) - - if problematic_ids: - logger.error( - "There were %s errors during preprocessing at positions: %s", len(problematic_ids), problematic_ids - ) - - if return_baskets: - return dataset, tensor_names, problematic_ids, baskets - else: - return dataset, tensor_names, problematic_ids - - def _fill_baskets(self, dicts: List[Dict], indices: Optional[Iterable[int]]): - baskets = [] - if not indices: - indices = range(len(dicts)) - for d, id_internal in zip(dicts, indices): - basket = SampleBasket(id_external=None, id_internal=id_internal, raw=d) - baskets.append(basket) - return baskets - - def _convert_queries(self, baskets: List[SampleBasket]): - for basket in baskets: - clear_text = {} - tokenized = {} - features: List[Dict] = [{}] - # extract query, positive context passages and titles, hard-negative passages and titles - if "query" in basket.raw: - try: - query = self._normalize_question(basket.raw["query"]) - - # featurize the query - query_inputs = self.query_tokenizer( - query, - max_length=self.max_seq_len_query, - add_special_tokens=True, - truncation=True, - truncation_strategy="longest_first", - padding="max_length", - return_token_type_ids=True, - ) - - # tokenize query - tokenized_query = self.query_tokenizer.convert_ids_to_tokens(query_inputs["input_ids"]) - - if len(tokenized_query) == 0: - logger.warning( - "The query could not be tokenized, likely because it contains a character that the query tokenizer does not recognize" - ) - return None - - clear_text["query_text"] = query - tokenized["query_tokens"] = tokenized_query - features[0]["query_input_ids"] = query_inputs["input_ids"] - features[0]["query_segment_ids"] = query_inputs["token_type_ids"] - features[0]["query_attention_mask"] = query_inputs["attention_mask"] - except Exception: - features = None # type: ignore - - sample = Sample(id="", clear_text=clear_text, tokenized=tokenized, features=features) # type: ignore - basket.samples = [sample] - return baskets - - def _convert_contexts(self, baskets: List[SampleBasket]): - # Converts both text passages and tables. - - for basket in baskets: - if "passages" in basket.raw: - try: - positive_context = list(filter(lambda x: x["label"] == "positive", basket.raw["passages"])) - if self.shuffle_positives: - random.shuffle(positive_context) - positive_context = positive_context[: self.num_positives] - hard_negative_context = list( - filter(lambda x: x["label"] == "hard_negative", basket.raw["passages"]) - ) - if self.shuffle_negatives: - random.shuffle(hard_negative_context) - hard_negative_context = hard_negative_context[: self.num_hard_negatives] - - positive_ctx_meta = [] - positive_ctx_texts = [] - hard_negative_ctx_meta = [] - hard_negative_ctx_texts = [] - is_table = [] - - for pos_ctx in positive_context: - if pos_ctx["type"] == "text": - positive_ctx_meta.append(" ".join(pos_ctx.get("meta"))) - positive_ctx_texts.append(pos_ctx["text"]) - is_table.append(0) - elif pos_ctx["type"] == "table": - positive_ctx_meta.append(" ".join(pos_ctx.get("meta"))) - linearized_rows = [cell for row in pos_ctx["rows"] for cell in row] - linearized_table = " ".join(pos_ctx["columns"]) + " " + " ".join(linearized_rows) - positive_ctx_texts.append(linearized_table) - is_table.append(1) - - for hn_ctx in hard_negative_context: - if hn_ctx["type"] == "text": - hard_negative_ctx_meta.append(" ".join(hn_ctx.get("meta"))) - hard_negative_ctx_texts.append(hn_ctx["text"]) - is_table.append(0) - elif hn_ctx["type"] == "table": - hard_negative_ctx_meta.append(" ".join(hn_ctx.get("meta"))) - linearized_rows = [cell for row in hn_ctx["rows"] for cell in row] - linearized_table = " ".join(hn_ctx["columns"]) + " " + " ".join(linearized_rows) - hard_negative_ctx_texts.append(linearized_table) - is_table.append(1) - - # all context passages and labels: 1 for positive context and 0 for hard-negative context - ctx_label = [1] * self.num_positives + [0] * self.num_hard_negatives - # featurize context passages - if self.embed_meta_fields: - # concatenate title with positive context passages + negative context passages - all_ctx = self._combine_meta_context( - positive_ctx_meta, positive_ctx_texts - ) + self._combine_meta_context(hard_negative_ctx_meta, hard_negative_ctx_texts) - else: - all_ctx = positive_ctx_texts + hard_negative_ctx_texts - - # assign empty string tuples if hard_negative passages less than num_hard_negatives - all_ctx += [("", "")] * ((self.num_positives + self.num_hard_negatives) - len(all_ctx)) - - inputs = self.passage_tokenizer( - all_ctx, - add_special_tokens=True, - truncation=True, - padding="max_length", - max_length=self.max_seq_len_passage, - return_token_type_ids=True, - ) - - input_ids = inputs["input_ids"] - passage_segment_ids = inputs["token_type_ids"] - attention_mask = inputs["attention_mask"] - - # get tokens in string format - tokenized = [self.passage_tokenizer.convert_ids_to_tokens(ctx) for ctx in input_ids] - - # for DPR we only have one sample containing query and corresponding (multiple) context features - sample = basket.samples[0] # type: ignore - sample.clear_text["passages"] = positive_context + hard_negative_context # type: ignore - sample.tokenized["passages_tokens"] = tokenized # type: ignore - sample.features[0]["passage_input_ids"] = input_ids # type: ignore - sample.features[0]["passage_segment_ids"] = passage_segment_ids # type: ignore - sample.features[0]["table_segment_ids"] = passage_segment_ids # type: ignore - sample.features[0]["passage_attention_mask"] = attention_mask # type: ignore - sample.features[0]["label_ids"] = ctx_label # type: ignore - sample.features[0]["is_table"] = is_table # type: ignore - except Exception: - basket.samples[0].features = None # type: ignore - - return baskets - - def _create_dataset(self, baskets: List[SampleBasket]): - """ - Convert python features into pytorch dataset. - Also removes potential errors during preprocessing. - Flattens nested basket structure to create a flat list of features - """ - features_flat: List = [] - basket_to_remove = [] - problematic_ids = set() - for basket in baskets: - if self._check_sample_features(basket): - for sample in basket.samples: # type: ignore - features_flat.extend(sample.features) # type: ignore - else: - # remove the entire basket - basket_to_remove.append(basket) - if len(basket_to_remove) > 0: - for basket in basket_to_remove: - # if basket_to_remove is not empty remove the related baskets - problematic_ids.add(basket.id_internal) - baskets.remove(basket) - - dataset, tensor_names = convert_features_to_dataset(features=features_flat) - return dataset, tensor_names, problematic_ids, baskets - - @staticmethod - def _normalize_question(question: str) -> str: - """Removes '?' from queries/questions""" - if question[-1] == "?": - question = question[:-1] - return question - - @staticmethod - def _combine_meta_context(meta_fields: List[str], texts: List[str]): - res = [] - for meta, ctx in zip(meta_fields, texts): - if meta is None: - meta = "" - res.append((meta, ctx)) - return res - - -class TextClassificationProcessor(Processor): - """ - Used to handle the text classification datasets that come in tabular format (CSV, TSV, etc.) - """ - - def __init__( - self, - tokenizer, - max_seq_len, - data_dir, - label_list=None, - metric=None, - train_filename="train.tsv", - dev_filename=None, - test_filename="test.tsv", - dev_split=0.1, - dev_stratification=False, - delimiter="\t", - quote_char="'", - skiprows=None, - label_column_name="label", - multilabel=False, - header=0, - proxies=None, - max_samples=None, - text_column_name="text", - **kwargs, - ): - """ - :param tokenizer: Used to split a sentence (str) into tokens. - :param max_seq_len: Samples are truncated after this many tokens. - :type max_seq_len: int - :param data_dir: The directory in which the train and dev files can be found. - If not available the dataset will be loaded automatically - if the last directory has the same name as a predefined dataset. - These predefined datasets are defined as the keys in the dict at - `farm.data_handler.utils.DOWNSTREAM_TASK_MAP `_. - :type data_dir: str - :param label_list: list of labels to predict (strings). For most cases this should be: ["start_token", "end_token"] - :type label_list: list - :param metric: name of metric that shall be used for evaluation, e.g. "acc" or "f1_macro". - Alternatively you can also supply a custom function, that takes preds and labels as args and returns a numerical value. - For using multiple metrics supply them as a list, e.g ["acc", my_custom_metric_fn]. - :type metric: str, function, or list - :param train_filename: The name of the file containing training data. - :type train_filename: str - :param dev_filename: The name of the file containing the dev data. If None and 0.0 < dev_split < 1.0 the dev set - will be a slice of the train set. - :type dev_filename: str or None - :param test_filename: None - :type test_filename: str - :param dev_split: The proportion of the train set that will sliced. Only works if dev_filename is set to None - :type dev_split: float - :param dev_stratification: if True, create a class-stratified split for the dev set. - :type dev_stratification: bool - :param delimiter: Separator used in the input tsv / csv file - :type delimiter: str - :param quote_char: Character used for quoting strings in the input tsv/ csv file - :type quote_char: str - :param skiprows: number of rows to skip in the tsvs (e.g. for multirow headers) - :type skiprows: int - :param label_column_name: name of the column in the input csv/tsv that shall be used as training labels - :type label_column_name: str - :param multilabel: set to True for multilabel classification - :type multilabel: bool - :param header: which line to use as a header in the input csv/tsv - :type header: int - :param proxies: proxy configuration to allow downloads of remote datasets. - Format as in "requests" library: https://2.python-requests.org//en/latest/user/advanced/#proxies - :type proxies: dict - :param text_column_name: name of the column in the input csv/tsv that shall be used as training text - :type text_column_name: str - :param kwargs: placeholder for passing generic parameters - :type kwargs: object - """ - # TODO If an arg is misspelt, e.g. metrics, it will be swallowed silently by kwargs - - # Custom processor attributes - self.delimiter = delimiter - self.quote_char = quote_char - self.skiprows = skiprows - self.header = header - self.max_samples = max_samples - self.dev_stratification = dev_stratification - logger.debug("Currently no support in Processor for returning problematic ids") - - super(TextClassificationProcessor, self).__init__( - tokenizer=tokenizer, - max_seq_len=max_seq_len, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - dev_split=dev_split, - data_dir=data_dir, - tasks={}, - proxies=proxies, - ) - if metric and label_list: - if multilabel: - task_type = "multilabel_classification" - else: - task_type = "classification" - self.add_task( - name="text_classification", - metric=metric, - label_list=label_list, - label_column_name=label_column_name, - text_column_name=text_column_name, - task_type=task_type, - ) - else: - logger.info( - "Initialized processor without tasks. Supply `metric` and `label_list` to the constructor for " - "using the default task or add a custom task later via processor.add_task()" - ) - - def file_to_dicts(self, file: str) -> List[Dict]: - raise NotImplementedError - - def dataset_from_dicts( - self, dicts: List[Dict], indices: Optional[List[int]] = None, return_baskets: bool = False, debug: bool = False - ): - if indices is None: - indices = [] - baskets = [] - # Tokenize in batches - texts = [x["text"] for x in dicts] - tokenized_batch = self.tokenizer( - texts, - return_offsets_mapping=True, - return_special_tokens_mask=True, - return_token_type_ids=True, - return_attention_mask=True, - truncation=True, - max_length=self.max_seq_len, - padding="max_length", - ) - input_ids_batch = tokenized_batch["input_ids"] - segment_ids_batch = tokenized_batch["token_type_ids"] - padding_masks_batch = tokenized_batch["attention_mask"] - tokens_batch = [x.tokens for x in tokenized_batch.encodings] - - # From here we operate on a per sample basis - for dictionary, input_ids, segment_ids, padding_mask, tokens in zip( - dicts, input_ids_batch, segment_ids_batch, padding_masks_batch, tokens_batch - ): - tokenized = {} - if debug: - tokenized["tokens"] = tokens - - feat_dict = {"input_ids": input_ids, "padding_mask": padding_mask, "segment_ids": segment_ids} - - # Create labels - # i.e. not inference - if not return_baskets: - label_dict = self.convert_labels(dictionary) - feat_dict.update(label_dict) - - # Add Basket to baskets - curr_sample = Sample(id="", clear_text=dictionary, tokenized=tokenized, features=[feat_dict]) - curr_basket = SampleBasket(id_internal=None, raw=dictionary, id_external=None, samples=[curr_sample]) - baskets.append(curr_basket) - - if indices and 0 not in indices: - pass - else: - self._log_samples(n_samples=1, baskets=baskets) - - # TODO populate problematic ids - problematic_ids: set = set() - dataset, tensornames = self._create_dataset(baskets) - if return_baskets: - return dataset, tensornames, problematic_ids, baskets - else: - return dataset, tensornames, problematic_ids - - def convert_labels(self, dictionary: Dict): - ret: Dict = {} - # Add labels for different tasks - for task in self.tasks.values(): - label_name = task["label_name"] - label_raw = dictionary[label_name] - label_list = task["label_list"] - if task["task_type"] == "classification": - # id of label - label_ids = [label_list.index(label_raw)] - elif task["task_type"] == "multilabel_classification": - # multi-hot-format - label_ids = [0] * len(label_list) - for l in label_raw.split(","): - if l != "": - label_ids[label_list.index(l)] = 1 - ret[task["label_tensor_name"]] = label_ids - return ret - - def _create_dataset(self, baskets: List[SampleBasket]): - features_flat: List = [] - basket_to_remove = [] - for basket in baskets: - if self._check_sample_features(basket): - if not isinstance(basket.samples, Iterable): - raise HaystackError("basket.samples must contain a list of samples.") - for sample in basket.samples: - if sample.features is None: - raise HaystackError("sample.features must not be None.") - features_flat.extend(sample.features) - else: - # remove the entire basket - basket_to_remove.append(basket) - dataset, tensor_names = convert_features_to_dataset(features=features_flat) - return dataset, tensor_names - - -class InferenceProcessor(TextClassificationProcessor): - """ - Generic processor used at inference time: - - fast - - no labels - - pure encoding of text into pytorch dataset - - Doesn't read from file, but only consumes dictionaries (e.g. coming from API requests) - """ - - def __init__(self, tokenizer, max_seq_len, **kwargs): - super(InferenceProcessor, self).__init__( - tokenizer=tokenizer, - max_seq_len=max_seq_len, - train_filename=None, - dev_filename=None, - test_filename=None, - dev_split=None, - data_dir=None, - tasks={}, - ) - - @classmethod - def load_from_dir(cls, load_dir: str): - """ - Overwriting method from parent class to **always** load the InferenceProcessor instead of the specific class stored in the config. - - :param load_dir: str, directory that contains a 'processor_config.json' - :return: An instance of an InferenceProcessor - """ - # read config - processor_config_file = Path(load_dir) / "processor_config.json" - with open(processor_config_file) as f: - config = json.load(f) - # init tokenizer - tokenizer = AutoTokenizer.from_pretrained(load_dir, tokenizer_class=config["tokenizer"]) - # we have to delete the tokenizer string from config, because we pass it as Object - del config["tokenizer"] - - processor = cls.load(tokenizer=tokenizer, processor_name="InferenceProcessor", **config) - for task_name, task in config["tasks"].items(): - processor.add_task(name=task_name, metric=task["metric"], label_list=task["label_list"]) - - if processor is None: - raise Exception - - return processor - - def file_to_dicts(self, file: str) -> List[Dict]: - raise NotImplementedError - - def convert_labels(self, dictionary: Dict): - # For inference we do not need labels - ret: Dict = {} - return ret - - # Private method to keep s3e pooling and embedding extraction working - def _dict_to_samples(self, dictionary: Dict, **kwargs) -> Sample: - # this tokenization also stores offsets - tokenized = tokenize_with_metadata(dictionary["text"], self.tokenizer) - # truncate tokens, offsets and start_of_word to max_seq_len that can be handled by the model - truncated_tokens = {} - for seq_name, tokens in tokenized.items(): - truncated_tokens[seq_name], _, _ = truncate_sequences( - seq_a=tokens, seq_b=None, tokenizer=self.tokenizer, max_seq_len=self.max_seq_len - ) - return Sample(id="", clear_text=dictionary, tokenized=truncated_tokens) - - # Private method to keep s3e pooling and embedding extraction working - def _sample_to_features(self, sample: Sample) -> Dict: - features = sample_to_features_text( - sample=sample, tasks=self.tasks, max_seq_len=self.max_seq_len, tokenizer=self.tokenizer - ) - return features - - -class UnlabeledTextProcessor(Processor): - """ - Processor to be used for distilling a teacher model into a student model from scratch. Can only be used with distil_intermediate_layers_from. - """ - - def __init__( - self, - tokenizer, - max_seq_len: int, - train_filename: Optional[Union[Path, str]] = None, - dev_filename: Optional[Union[Path, str]] = None, - test_filename: Optional[Union[Path, str]] = None, - dev_split: float = 0, - data_dir: Optional[Union[Path, str]] = None, - tasks: Optional[Dict] = None, - proxies: Optional[Dict] = None, - multithreading_rust: Optional[bool] = True, - ): - if tasks is None: - tasks = {} - super().__init__( - tokenizer, - max_seq_len, - train_filename, - dev_filename, - test_filename, - dev_split, - data_dir, - tasks, - proxies, - multithreading_rust, - ) - self.add_task("question_answering", "squad", ["start_token", "end_token"]) - - def file_to_dicts(self, file: str) -> List[dict]: - dicts = [] - with open(file, "r") as f: - for line in f: - dicts.append({"text": line}) - return dicts - - def dataset_from_dicts( - self, dicts: List[Dict], indices: Optional[List[int]] = None, return_baskets: bool = False, debug: bool = False - ): - if indices is None: - indices = [] - if return_baskets: - raise NotImplementedError("return_baskets is not supported by UnlabeledTextProcessor") - texts = [dict_["text"] for dict_ in dicts] - tokens = self.tokenizer( - texts, - add_special_tokens=True, - return_tensors="pt", - padding="max_length", - truncation=True, - max_length=self.max_seq_len, - ) - names = list(tokens) - inputs = [tokens[key] for key in tokens] - if "padding_mask" not in names: - index = names.index("attention_mask") - names[index] = "padding_mask" - if "segment_ids" not in names: - index = names.index("token_type_ids") - names[index] = "segment_ids" - - dataset = TensorDataset(*inputs) - return dataset, names, [] - - def _create_dataset(self, baskets: List[SampleBasket]): - raise NotImplementedError("_create_dataset is not supported by UnlabeledTextProcessor") - - -# helper fcts -def write_squad_predictions(predictions, out_filename, predictions_filename=None): - predictions_json = {} - for x in predictions: - for p in x["predictions"]: - if p["answers"][0]["answer"] is not None: - predictions_json[p["question_id"]] = p["answers"][0]["answer"] - else: - predictions_json[ - p["question_id"] - ] = "" # convert No answer = None to format understood by the SQuAD eval script - - if predictions_filename: - dev_labels = {} - temp = json.load(open(predictions_filename, "r")) - for d in temp["data"]: - for p in d["paragraphs"]: - for q in p["qas"]: - if q.get("is_impossible", False): - dev_labels[q["id"]] = "is_impossible" - else: - dev_labels[q["id"]] = q["answers"][0]["text"] - not_included = dev_labels.keys() - predictions_json.keys() - if len(not_included) > 0: - logger.info("There were missing predictions for question ids: %s", list(not_included)) - for x in not_included: - predictions_json[x] = "" - - # os.makedirs("model_output", exist_ok=True) - # filepath = Path("model_output") / out_filename - json.dump(predictions_json, open(out_filename, "w")) - logger.info("Written Squad predictions to: %s", out_filename) - - -def _read_dpr_json( - file: str, - max_samples: Optional[int] = None, - proxies: Optional[Any] = None, - num_hard_negatives: int = 1, - num_positives: int = 1, - shuffle_negatives: bool = True, - shuffle_positives: bool = False, -): - """ - Reads a Dense Passage Retrieval (DPR) data file in json format and returns a list of dictionaries. - - :param file: filename of DPR data in json format - - Returns: - list of dictionaries: List[dict] - each dictionary: { - "query": str -> query_text - "passages": List[dictionaries] -> [{"text": document_text, "title": xxx, "label": "positive", "external_id": abb123}, - {"text": document_text, "title": xxx, "label": "hard_negative", "external_id": abb134}, - ...] - } - example: - ["query": 'who sings does he love me with reba' - "passages" : [{'title': 'Does He Love You', - 'text': 'Does He Love You "Does He Love You" is a song written by Sandy Knox and Billy Stritch, and recorded as a duet by American country music artists Reba McEntire and Linda Davis. It was released in August 1993 as the first single from Reba\'s album "Greatest Hits Volume Two". It is one of country music\'s several songs about a love triangle. "Does He Love You" was written in 1982 by Billy Stritch. He recorded it with a trio in which he performed at the time, because he wanted a song that could be sung by the other two members', - 'label': 'positive', - 'external_id': '11828866'}, - {'title': 'When the Nightingale Sings', - 'text': "When the Nightingale Sings When The Nightingale Sings is a Middle English poem, author unknown, recorded in the British Library's Harley 2253 manuscript, verse 25. It is a love poem, extolling the beauty and lost love of an unknown maiden. When þe nyhtegale singes þe wodes waxen grene.
Lef ant gras ant blosme springes in aueryl y wene,
Ant love is to myn herte gon wiþ one spere so kene
Nyht ant day my blod hit drynkes myn herte deþ me tene. Ich have loved al þis er þat y may love namore,
Ich have siked moni syk lemmon for", - 'label': 'hard_negative', - 'external_id': '10891637'}] - ] - - """ - # get remote dataset if needed - if not os.path.exists(file): - logger.info("Couldn't find %s locally. Trying to download ...", file) - _download_extract_downstream_data(file, proxies=proxies) - - if Path(file).suffix.lower() == ".jsonl": - dicts = [] - with open(file, encoding="utf-8") as f: - for line in f: - dicts.append(json.loads(line)) - else: - with open(file, encoding="utf-8") as f: - dicts = json.load(f) - - if max_samples: - dicts = random.sample(dicts, min(max_samples, len(dicts))) - - # convert DPR dictionary to standard dictionary - query_json_keys = ["question", "questions", "query"] - positive_context_json_keys = ["positive_contexts", "positive_ctxs", "positive_context", "positive_ctx"] - hard_negative_json_keys = [ - "hard_negative_contexts", - "hard_negative_ctxs", - "hard_negative_context", - "hard_negative_ctx", - ] - standard_dicts = [] - for dict in dicts: - sample = {} - passages = [] - for key, val in dict.items(): - if key in query_json_keys: - sample["query"] = val - elif key in positive_context_json_keys: - if shuffle_positives: - random.shuffle(val) - for passage in val[:num_positives]: - passages.append( - { - "title": passage["title"], - "text": passage["text"], - "label": "positive", - "external_id": passage.get("passage_id", uuid.uuid4().hex.upper()[0:8]), - } - ) - elif key in hard_negative_json_keys: - if shuffle_negatives: - random.shuffle(val) - for passage in val[:num_hard_negatives]: - passages.append( - { - "title": passage["title"], - "text": passage["text"], - "label": "hard_negative", - "external_id": passage.get("passage_id", uuid.uuid4().hex.upper()[0:8]), - } - ) - sample["passages"] = passages - standard_dicts.append(sample) - return standard_dicts - - -def _read_squad_file(filename: str, proxies=None): - """Read a SQuAD json file""" - if not os.path.exists(filename): - logger.info("Couldn't find %s locally. Trying to download ...", filename) - _download_extract_downstream_data(filename, proxies) - with open(filename, "r", encoding="utf-8") as reader: - input_data = json.load(reader)["data"] - return input_data - - -def http_get( - url: str, - temp_file: IO[bytes], - proxies: Optional[Dict[str, str]] = None, - timeout: Union[float, Tuple[float, float]] = 10.0, -): - """ - Runs a HTTP GET requests and saves response content to file. - :param url: URL address - :param temp_file: file-like object open in binary mode - :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. - :param timeout: How many seconds to wait for the server to send data before giving up, - as a float, or a :ref:`(connect timeout, read timeout) ` tuple. - Defaults to 10 seconds. - """ - req = requests.get(url, stream=True, proxies=proxies, timeout=timeout) - content_length = req.headers.get("Content-Length") - total = int(content_length) if content_length is not None else None - progress = tqdm(unit="B", total=total) - for chunk in req.iter_content(chunk_size=1024): - if chunk: # filter out keep-alive new chunks - progress.update(len(chunk)) - temp_file.write(chunk) - progress.close() - - -def _download_extract_downstream_data(input_file: str, proxies=None): - # download archive to temp dir and extract to correct position - full_path = Path(os.path.realpath(input_file)) - directory = full_path.parent - taskname = directory.stem - datadir = directory.parent - logger.info("downloading and extracting file %s to dir %s", taskname, datadir) - if taskname not in DOWNSTREAM_TASK_MAP: - logger.error("Cannot download %s. Unknown data source.", taskname) - else: - if os.name == "nt": # make use of NamedTemporaryFile compatible with Windows - delete_tmp_file = False - else: - delete_tmp_file = True - with tempfile.NamedTemporaryFile(delete=delete_tmp_file) as temp_file: - http_get(DOWNSTREAM_TASK_MAP[taskname], temp_file, proxies=proxies) - temp_file.flush() - temp_file.seek(0) # making tempfile accessible - tfile = tarfile.open(temp_file.name) - tfile.extractall(datadir) - # temp_file gets deleted here - - -def _is_json(x): - if issubclass(type(x), Path): - return True - try: - json.dumps(x) - return True - except: - return False diff --git a/haystack/modeling/data_handler/samples.py b/haystack/modeling/data_handler/samples.py deleted file mode 100644 index 0fd7402539..0000000000 --- a/haystack/modeling/data_handler/samples.py +++ /dev/null @@ -1,195 +0,0 @@ -from typing import Any, Union, Optional, List, Dict - -import logging -import numpy as np -from haystack.modeling.visual import SAMPLE - - -logger = logging.getLogger(__name__) - - -class Sample: - """A single training/test sample. This should contain the input and the label. Is initialized with - the human readable clear_text. Over the course of data preprocessing, this object is populated - with tokenized and featurized versions of the data.""" - - def __init__( - self, - id: str, - clear_text: dict, - tokenized: Optional[dict] = None, - features: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - ): - """ - :param id: The unique id of the sample - :param clear_text: A dictionary containing various human readable fields (e.g. text, label). - :param tokenized: A dictionary containing the tokenized version of clear text plus helpful meta data: offsets (start position of each token in the original text) and start_of_word (boolean if a token is the first one of a word). - :param features: A dictionary containing features in a vectorized format needed by the model to process this sample. - """ - self.id = id - self.clear_text = clear_text - self.features = features - self.tokenized = tokenized - - def __str__(self): - if self.clear_text: - clear_text_str = "\n \t".join([k + ": " + str(v) for k, v in self.clear_text.items()]) - if len(clear_text_str) > 3000: - clear_text_str = ( - clear_text_str[:3_000] + f"\nTHE REST IS TOO LONG TO DISPLAY. " - f"Remaining chars :{len(clear_text_str)-3_000}" - ) - else: - clear_text_str = "None" - - if self.features: - if isinstance(self.features, list): - features = self.features[0] - else: - features = self.features - feature_str = "\n \t".join([k + ": " + str(v) for k, v in features.items()]) - else: - feature_str = "None" - - if self.tokenized: - tokenized_str = "\n \t".join([k + ": " + str(v) for k, v in self.tokenized.items()]) - if len(tokenized_str) > 3000: - tokenized_str = ( - tokenized_str[:3_000] + f"\nTHE REST IS TOO LONG TO DISPLAY. " - f"Remaining chars: {len(tokenized_str)-3_000}" - ) - else: - tokenized_str = "None" - s = ( - f"\n{SAMPLE}\n" - f"ID: {self.id}\n" - f"Clear Text: \n \t{clear_text_str}\n" - f"Tokenized: \n \t{tokenized_str}\n" - f"Features: \n \t{feature_str}\n" - "_____________________________________________________" - ) - return s - - -class SampleBasket: - """An object that contains one source text and the one or more samples that will be processed. This - is needed for tasks like question answering where the source text can generate multiple input - label - pairs.""" - - def __init__( - self, - id_internal: Optional[Union[int, str]], - raw: dict, - id_external: Optional[str] = None, - samples: Optional[List[Sample]] = None, - ): - """ - :param id_internal: A unique identifying id. Used for identification within Haystack. - :param external_id: Used for identification outside of Haystack. E.g. if another framework wants to pass along its own id with the results. - :param raw: Contains the various data needed to form a sample. It is ideally in human readable form. - :param samples: An optional list of Samples used to populate the basket at initialization. - """ - self.id_internal = id_internal - self.id_external = id_external - self.raw = raw - self.samples = samples - - -def process_answers(answers, doc_offsets, passage_start_c, passage_start_t): - """TODO Write Comment""" - answers_clear = [] - answers_tokenized = [] - for answer in answers: - # This section calculates start and end relative to document - answer_text = answer["text"] - answer_len_c = len(answer_text) - if "offset" in answer: - answer_start_c = answer["offset"] - else: - answer_start_c = answer["answer_start"] - answer_end_c = answer_start_c + answer_len_c - 1 - answer_start_t = offset_to_token_idx_vecorized(doc_offsets, answer_start_c) - answer_end_t = offset_to_token_idx_vecorized(doc_offsets, answer_end_c) - - # TODO: Perform check that answer can be recovered from document? - # This section converts start and end so that they are relative to the passage - # TODO: Is this actually necessary on character level? - answer_start_c -= passage_start_c - answer_end_c -= passage_start_c - answer_start_t -= passage_start_t - answer_end_t -= passage_start_t - - curr_answer_clear = {"text": answer_text, "start_c": answer_start_c, "end_c": answer_end_c} - curr_answer_tokenized = { - "start_t": answer_start_t, - "end_t": answer_end_t, - "answer_type": answer.get("answer_type", "span"), - } - - answers_clear.append(curr_answer_clear) - answers_tokenized.append(curr_answer_tokenized) - return answers_clear, answers_tokenized - - -def get_passage_offsets(doc_offsets, doc_stride, passage_len_t, doc_text): - """ - Get spans (start and end offsets) for passages by applying a sliding window function. - The sliding window moves in steps of doc_stride. - Returns a list of dictionaries which each describe the start, end and id of a passage - that is formed when chunking a document using a sliding window approach.""" - - passage_spans = [] - passage_id = 0 - doc_len_t = len(doc_offsets) - while True: - passage_start_t = passage_id * doc_stride - passage_end_t = passage_start_t + passage_len_t - passage_start_c = doc_offsets[passage_start_t] - - # If passage_end_t points to the last token in the passage, define passage_end_c as the length of the document - if passage_end_t >= doc_len_t - 1: - passage_end_c = len(doc_text) - - # Get document text up to the first token that is outside the passage. Strip of whitespace. - # Use the length of this text as the passage_end_c - else: - end_ch_idx = doc_offsets[passage_end_t + 1] - raw_passage_text = doc_text[:end_ch_idx] - passage_end_c = len(raw_passage_text.strip()) - - passage_span = { - "passage_start_t": passage_start_t, - "passage_end_t": passage_end_t, - "passage_start_c": passage_start_c, - "passage_end_c": passage_end_c, - "passage_id": passage_id, - } - passage_spans.append(passage_span) - passage_id += 1 - # If the end idx is greater than or equal to the length of the passage - if passage_end_t >= doc_len_t: - break - return passage_spans - - -def offset_to_token_idx(token_offsets, ch_idx) -> Optional[int]: - """Returns the idx of the token at the given character idx""" - n_tokens = len(token_offsets) - for i in range(n_tokens): - if (i + 1 == n_tokens) or (token_offsets[i] <= ch_idx < token_offsets[i + 1]): - return i - return None - - -def offset_to_token_idx_vecorized(token_offsets, ch_idx): - """Returns the idx of the token at the given character idx""" - # case ch_idx is at end of tokens - if ch_idx >= np.max(token_offsets): - # idx must be including - idx = np.argmax(token_offsets) - # looking for the first occurrence of token_offsets larger than ch_idx and taking one position to the left. - # This is needed to overcome n special_tokens at start of sequence - # and failsafe matching (the character start might not always coincide with a token offset, e.g. when starting at whitespace) - else: - idx = np.argmax(token_offsets > ch_idx) - 1 - return idx diff --git a/haystack/modeling/evaluation/__init__.py b/haystack/modeling/evaluation/__init__.py deleted file mode 100644 index 54adafbe1b..0000000000 --- a/haystack/modeling/evaluation/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.modeling.evaluation.eval import Evaluator diff --git a/haystack/modeling/evaluation/eval.py b/haystack/modeling/evaluation/eval.py deleted file mode 100644 index a349403861..0000000000 --- a/haystack/modeling/evaluation/eval.py +++ /dev/null @@ -1,221 +0,0 @@ -from typing import Dict, List, Optional, Any - -import logging -import numbers -import torch -from torch.nn import DataParallel -import numpy as np -from tqdm import tqdm - -from haystack.modeling.evaluation.metrics import compute_metrics, compute_report_metrics -from haystack.modeling.model.adaptive_model import AdaptiveModel -from haystack.modeling.model.biadaptive_model import BiAdaptiveModel -from haystack.modeling.model.optimization import WrappedDataParallel -from haystack.utils.experiment_tracking import Tracker as tracker -from haystack.telemetry import send_event -from haystack.modeling.visual import BUSH_SEP - - -logger = logging.getLogger(__name__) - - -class Evaluator: - """ - Handles evaluation of a given model over a specified dataset. - """ - - def __init__(self, data_loader: torch.utils.data.DataLoader, tasks, device: torch.device, report: bool = True): - """ - :param data_loader: The PyTorch DataLoader that will return batches of data from the evaluation dataset - :param tesks: - :param device: The device on which the tensors should be processed. Choose from torch.device("cpu") and torch.device("cuda"). - :param report: Whether an eval report should be generated (e.g. classification report per class). - """ - self.data_loader = data_loader - self.tasks = tasks - self.device = device - self.report = report - - def eval( - self, - model: AdaptiveModel, - return_preds_and_labels: bool = False, - calibrate_conf_scores: bool = False, - use_confidence_scores_for_ranking: bool = True, - use_no_answer_legacy_confidence: bool = False, - ) -> List[Dict]: - """ - Performs evaluation on a given model. - - :param model: The model on which to perform evaluation - :param return_preds_and_labels: Whether to add preds and labels in the returned dicts of the - :param calibrate_conf_scores: Whether to calibrate the temperature for scaling of the confidence scores. - :param use_confidence_scores_for_ranking: Whether to sort answers by confidence score (normalized between 0 and 1)(default) or by standard score (unbounded). - :param use_no_answer_legacy_confidence: Whether to use the legacy confidence definition for no_answer: difference - between the best overall answer confidence and the no_answer gap confidence. - Otherwise, we use the no_answer score normalized to a range of [0,1] by - an expit function (default). - :return: all_results: A list of dictionaries, one for each prediction head. Each dictionary contains the metrics - and reports generated during evaluation. - """ - send_event( - event_name="Evaluation", event_properties={"class": self.__class__.__name__, "function_name": "eval"} - ) - model.prediction_heads[0].use_confidence_scores_for_ranking = use_confidence_scores_for_ranking - model.prediction_heads[0].use_no_answer_legacy_confidence = use_no_answer_legacy_confidence - model.eval() - - # init empty lists per prediction head - loss_all: List = [0 for _ in model.prediction_heads] - preds_all: List = [[] for _ in model.prediction_heads] - label_all: List = [[] for _ in model.prediction_heads] - ids_all: List = [[] for _ in model.prediction_heads] - passage_start_t_all: List = [[] for _ in model.prediction_heads] - logits_all: List = [[] for _ in model.prediction_heads] - - for batch in tqdm(self.data_loader, desc="Evaluating", mininterval=10): - batch = {key: batch[key].to(self.device) for key in batch} - - if isinstance(model, (DataParallel, WrappedDataParallel)): - module = model.module - else: - module = model - - with torch.inference_mode(): - if isinstance(module, AdaptiveModel): - logits = model.forward( - input_ids=batch.get("input_ids", None), - segment_ids=batch.get("segment_ids", None), - padding_mask=batch.get("padding_mask", None), - output_hidden_states=batch.get("output_hidden_states", False), - output_attentions=batch.get("output_attentions", False), - ) - elif isinstance(module, BiAdaptiveModel): - logits = model.forward( # type: ignore [call-arg] # type: ignore [call-arg] - query_input_ids=batch.get("query_input_ids", None), - query_segment_ids=batch.get("query_segment_ids", None), - query_attention_mask=batch.get("query_attention_mask", None), - passage_input_ids=batch.get("passage_input_ids", None), - passage_segment_ids=batch.get("passage_segment_ids", None), - passage_attention_mask=batch.get("passage_attention_mask", None), - ) - else: - logits = model.forward(**batch) - - losses_per_head = model.logits_to_loss_per_head(logits=logits, **batch) - preds = model.logits_to_preds(logits=logits, **batch) - labels = model.prepare_labels(**batch) - - # stack results of all batches per prediction head - for head_num, head in enumerate(model.prediction_heads): - loss_all[head_num] += np.sum(_to_numpy(losses_per_head[head_num])) - preds_all[head_num] += list(_to_numpy(preds[head_num])) - label_all[head_num] += list(_to_numpy(labels[head_num])) - if head.model_type == "span_classification": - ids_all[head_num] += list(_to_numpy(batch["id"])) - passage_start_t_all[head_num] += list(_to_numpy(batch["passage_start_t"])) - if calibrate_conf_scores: - logits_all[head_num] += list(_to_numpy(logits)) - - # Evaluate per prediction head - all_results = [] - for head_num, head in enumerate(model.prediction_heads): - if head.model_type == "span_classification" and calibrate_conf_scores: - temperature_previous = head.temperature_for_confidence.item() - logger.info("temperature used for confidence scores before calibration: %s", temperature_previous) - head.calibrate_conf(logits_all[head_num], label_all[head_num]) - temperature_current = head.temperature_for_confidence.item() - logger.info("temperature used for confidence scores after calibration: %s", temperature_current) - temperature_change = (abs(temperature_current - temperature_previous) / temperature_previous) * 100.0 - if temperature_change > 50: - logger.warning( - "temperature used for calibration of confidence scores changed by more than %s percent", - temperature_change, - ) - if hasattr(head, "aggregate_preds"): - # Needed to convert NQ ids from np arrays to strings - ids_all_str = [x.astype(str) for x in ids_all[head_num]] - ids_all_list = [list(x) for x in ids_all_str] - head_ids = ["-".join(x) for x in ids_all_list] - preds_all[head_num], label_all[head_num] = head.aggregate_preds( - preds=preds_all[head_num], - labels=label_all[head_num], - passage_start_t=passage_start_t_all[head_num], - ids=head_ids, - ) - result = {"loss": loss_all[head_num] / len(self.data_loader.dataset), "task_name": head.task_name} # type: ignore [arg-type] - result.update(compute_metrics(metric=head.metric, preds=preds_all[head_num], labels=label_all[head_num])) - # Select type of report depending on prediction head output type - if self.report: - try: - result["report"] = compute_report_metrics(head, preds_all[head_num], label_all[head_num]) - except: - logger.error( - "Couldn't create eval report for head %s with following preds and labels:" - "\n Preds: %s \n Labels: %s", - head_num, - preds_all[head_num], - label_all[head_num], - ) - result["report"] = "Error" - - if return_preds_and_labels: - result["preds"] = preds_all[head_num] - result["labels"] = label_all[head_num] - - all_results.append(result) - - return all_results - - @staticmethod - def log_results( - results: List[Any], - dataset_name: str, - steps: int, - logging: bool = True, - print: bool = True, - num_fold: Optional[int] = None, - ): - # Print a header - header = "\n\n" - header += BUSH_SEP + "\n" - header += "***************************************************\n" - if num_fold: - header += ( - f"***** EVALUATION | FOLD: {num_fold} | {dataset_name.upper()} SET | AFTER {steps} BATCHES *****\n" - ) - else: - header += f"***** EVALUATION | {dataset_name.upper()} SET | AFTER {steps} BATCHES *****\n" - header += "***************************************************\n" - header += BUSH_SEP + "\n" - logger.info(header) - - for head in results: - logger.info("\n _________ %s _________", head["task_name"]) - for metric_name, metric_val in head.items(): - # log with experiment tracking framework (e.g. Mlflow) - if ( - logging - and not metric_name in ["preds", "labels"] - and not metric_name.startswith("_") - and isinstance(metric_val, numbers.Number) - ): - tracker.track_metrics( - metrics={f"{dataset_name}_{metric_name}_{head['task_name']}": metric_val}, step=steps - ) - # print via standard python logger - if print: - if metric_name == "report": - if isinstance(metric_val, str) and len(metric_val) > 8000: - metric_val = metric_val[:7500] + "\n ............................. \n" + metric_val[-500:] - logger.info("%s: \n %s", metric_name, metric_val) - else: - if not metric_name in ["preds", "labels"] and not metric_name.startswith("_"): - logger.info("%s: %s", metric_name, metric_val) - - -def _to_numpy(container): - try: - return container.cpu().numpy() - except AttributeError: - return container diff --git a/haystack/modeling/evaluation/metrics.py b/haystack/modeling/evaluation/metrics.py deleted file mode 100644 index 1c13f18085..0000000000 --- a/haystack/modeling/evaluation/metrics.py +++ /dev/null @@ -1,486 +0,0 @@ -import logging -from functools import reduce -from typing import Callable, Dict, List, Optional, Tuple, Union - -import numpy as np -from sentence_transformers import CrossEncoder, SentenceTransformer -from transformers import AutoConfig - -from haystack.modeling.model.prediction_head import PredictionHead -from haystack.modeling.utils import flatten_list -from haystack.lazy_imports import LazyImport - -logger = logging.getLogger(__name__) - -with LazyImport("Run 'pip install farm-haystack[metrics]'") as metrics_import: - from scipy.stats import pearsonr, spearmanr - from sklearn.metrics import classification_report, f1_score, matthews_corrcoef, mean_squared_error, r2_score - from sklearn.metrics.pairwise import cosine_similarity - from seqeval.metrics import classification_report as token_classification_report - - -registered_metrics = {} -registered_reports = {} - - -def register_metrics(name: str, implementation: Callable): - registered_metrics[name] = implementation - - -def register_report(name: str, implementation: Callable): - """ - Register a custom reporting function to be used during eval. - - This can be useful: - - if you want to overwrite a report for an existing output type of prediction head (e.g. "per_token") - - if you have a new type of prediction head and want to add a custom report for it - - :param name: This must match the `ph_output_type` attribute of the PredictionHead for which the report should be used. - (e.g. TokenPredictionHead => `per_token`, YourCustomHead => `some_new_type`). - :param implementation: Function to be executed. It must take lists of `y_true` and `y_pred` as input and return a - printable object (e.g. string or dict). - See sklearns.metrics.classification_report for an example. - :type implementation: function - """ - registered_reports[name] = implementation - - -def simple_accuracy(preds, labels): - # works also with nested lists of different lengths (needed for masked LM task) - if type(preds) == type(labels) == list: - preds = np.array(list(flatten_list(preds))) - labels = np.array(list(flatten_list(labels))) - assert type(preds) == type(labels) == np.ndarray - correct = preds == labels - return {"acc": correct.mean()} - - -def acc_and_f1(preds, labels): - metrics_import.check() - acc = simple_accuracy(preds, labels) - f1 = f1_score(y_true=labels, y_pred=preds) - return {"acc": acc["acc"], "f1": f1, "acc_and_f1": (acc["acc"] + f1) / 2} - - -def f1_macro(preds, labels): - metrics_import.check() - return {"f1_macro": f1_score(y_true=labels, y_pred=preds, average="macro")} - - -def pearson_and_spearman(preds, labels): - metrics_import.check() - pearson_corr = pearsonr(preds, labels)[0] - spearman_corr = spearmanr(preds, labels)[0] - return {"pearson": pearson_corr, "spearman": spearman_corr, "corr": (pearson_corr + spearman_corr) / 2} - - -def compute_metrics(metric: str, preds, labels): - """ - Calculate the named metric values for the list of predictions vs list of labels. - - :param metric: The name of a predefined metric; a function that takes a prediction list and a label - list and returns a dict from metric names to values, or recursively a list of metrics. - Predefined metrics are: mcc, acc, acc_f1, pear_spear, seq_f1, f1_macro, squad, mse, r2, - top_n_accuracy, text_similarity_metric. - :param preds: list of predictions - :param labels: list of target labels - :return: a dictionary mapping metric names to values. - """ - FUNCTION_FOR_METRIC = { - "mcc": lambda preds, labels: {"mcc": matthews_corrcoef(labels, preds)}, - "acc": simple_accuracy, - "acc_f1": acc_and_f1, - "pear_spear": pearson_and_spearman, - "f1_macro": f1_macro, - "squad": squad, - "mse": lambda preds, labels: {"mse": mean_squared_error(preds, labels)}, - "r2": lambda preds, labels: {"r2": r2_score(preds, labels)}, - "top_n_accuracy": lambda preds, labels: {"top_n_accuracy": top_n_accuracy(preds, labels)}, - "text_similarity_metric": text_similarity_metric, - } - assert len(preds) == len(labels) - if metric in FUNCTION_FOR_METRIC.keys(): - if metric in ["mcc", "mse", "r2"]: - metrics_import.check() - return FUNCTION_FOR_METRIC[metric](preds, labels) - elif isinstance(metric, list): - ret = {} - for m in metric: - ret.update(compute_metrics(m, preds, labels)) - return ret - elif metric in registered_metrics: - metric_func = registered_metrics[metric] - return metric_func(preds, labels) - else: - raise KeyError(metric) - - -def compute_report_metrics(head: PredictionHead, preds, labels): - if head.ph_output_type in registered_reports: - report_fn = registered_reports[head.ph_output_type] # type: ignore [index] - elif head.ph_output_type == "per_token": - metrics_import.check() - report_fn = token_classification_report - elif head.ph_output_type == "per_sequence": - metrics_import.check() - report_fn = classification_report - elif head.ph_output_type == "per_token_squad": - report_fn = lambda *args, **kwargs: "Not Implemented" # pylint: disable=unnecessary-lambda-assignment - elif head.ph_output_type == "per_sequence_continuous": - report_fn = r2_score - else: - raise AttributeError( - f"No report function for head.ph_output_type '{head.ph_output_type}'. " - f"You can register a custom one via register_report(name='{head.ph_output_type}', implementation=" - ) - - # CHANGE PARAMETERS, not all report_fn accept digits - if head.ph_output_type in ["per_sequence"]: - # supply labels as all possible combination because if ground truth labels do not cover - # all values in label_list (maybe dev set is small), the report will break - if head.model_type == "text_similarity": - labels = reduce(lambda x, y: x + list(y.astype("long")), labels, []) - preds = reduce(lambda x, y: x + [0] * y[0] + [1] + [0] * (len(y) - y[0] - 1), preds, []) # type: ignore - all_possible_labels = list(range(len(head.label_list))) # type: ignore [arg-type] - else: - all_possible_labels = head.label_list # type: ignore [assignment] - return report_fn(labels, preds, digits=4, labels=all_possible_labels, target_names=head.label_list) - else: - return report_fn(labels, preds) - - -def squad_EM(preds, labels): - """ - Count how often the pair of first predicted start and end index exactly matches one of the labels - """ - n_docs = len(preds) - n_correct = 0 - for pred, label in zip(preds, labels): - qa_candidate = pred[0][0] - pred_start = qa_candidate.offset_answer_start - pred_end = qa_candidate.offset_answer_end - curr_labels = label - if (pred_start, pred_end) in curr_labels: - n_correct += 1 - return n_correct / n_docs if n_docs else 0 - - -def top_n_EM(preds, labels): - """ - Count how often the pair of predicted start and end index exactly matches one of the labels - """ - n_docs = len(preds) - n_correct = 0 - for pred, label in zip(preds, labels): - qa_candidates = pred[0] - for qa_candidate in qa_candidates: - pred_start = qa_candidate.offset_answer_start - pred_end = qa_candidate.offset_answer_end - curr_labels = label - if (pred_start, pred_end) in curr_labels: - n_correct += 1 - break - return n_correct / n_docs if n_docs else 0 - - -def squad_EM_start(preds, labels): - """ - Count how often the predicted start index exactly matches the start index given by one of the labels - """ - n_docs = len(preds) - n_correct = 0 - for pred, label in zip(preds, labels): - qa_candidate = pred[0][0] - pred_start = qa_candidate.offset_answer_start - curr_labels = label - curr_labels_start = [curr_label[0] for curr_label in curr_labels] - if pred_start in curr_labels_start: - n_correct += 1 - return n_correct / n_docs if n_docs else 0 - - -def squad_f1(preds, labels): - """Calculates the f1 score (token overlap) of the first prediction""" - f1_scores = [] - n_docs = len(preds) - for i in range(n_docs): - best_pred = preds[i][0] - best_f1 = max(squad_f1_single(best_pred, label) for label in labels[i]) - f1_scores.append(best_f1) - return np.mean(f1_scores) - - -def top_n_f1(preds, labels): - f1_scores = [] - for pred, label in zip(preds, labels): - pred_candidates = pred[0] - best_f1 = max( - squad_f1_single([pred_candidate], label_candidate) - for label_candidate in label - for pred_candidate in pred_candidates - ) - f1_scores.append(best_f1) - return np.mean(f1_scores) - - -def squad_f1_single(pred, label, pred_idx: int = 0): - label_start, label_end = label - span = pred[pred_idx] - pred_start = span.offset_answer_start - pred_end = span.offset_answer_end - - if (pred_start + pred_end == 0) or (label_start + label_end == 0): - if pred_start == label_start: - return 1.0 - else: - return 0.0 - pred_span = list(range(pred_start, pred_end + 1)) - label_span = list(range(label_start, label_end + 1)) - n_overlap = len([x for x in pred_span if x in label_span]) - if n_overlap == 0: - return 0.0 - precision = n_overlap / len(pred_span) - recall = n_overlap / len(label_span) - f1 = (2 * precision * recall) / (precision + recall) - return f1 - - -def confidence(preds): - conf = 0 - for pred in preds: - conf += pred[0][0].confidence - return conf / len(preds) if len(preds) else 0 - - -def metrics_per_bin(preds, labels, num_bins: int = 10): - pred_bins = [[] for _ in range(num_bins)] # type: List - label_bins = [[] for _ in range(num_bins)] # type: List - count_per_bin = [0] * num_bins - for pred, label in zip(preds, labels): - current_score = pred[0][0].confidence - if current_score >= 1.0: - current_score = 0.9999 - pred_bins[int(current_score * num_bins)].append(pred) - label_bins[int(current_score * num_bins)].append(label) - count_per_bin[int(current_score * num_bins)] += 1 - - em_per_bin = [0] * num_bins - confidence_per_bin = [0] * num_bins - for i in range(num_bins): - em_per_bin[i] = squad_EM_start(preds=pred_bins[i], labels=label_bins[i]) - confidence_per_bin[i] = confidence(preds=pred_bins[i]) - return em_per_bin, confidence_per_bin, count_per_bin - - -def squad_base(preds, labels): - em = squad_EM(preds=preds, labels=labels) - f1 = squad_f1(preds=preds, labels=labels) - top_acc = top_n_accuracy(preds=preds, labels=labels) - return {"EM": em, "f1": f1, "top_n_accuracy": top_acc} - - -def squad(preds, labels): - """ - This method calculates squad evaluation metrics a) overall, b) for questions with text answer and c) for questions with no answer - """ - # TODO change check for no_answer questions from using (start,end)==(-1,-1) to is_impossible flag in QAInput. This needs to be done for labels though. Not for predictions. - overall_results = squad_base(preds, labels) - - preds_answer = [pred for (pred, label) in zip(preds, labels) if (-1, -1) not in label] - labels_answer = [label for label in labels if (-1, -1) not in label] - answer_results = squad_base(preds_answer, labels_answer) - top_n_em_answer = top_n_EM(preds_answer, labels_answer) - top_n_f1_answer = top_n_f1(preds_answer, labels_answer) - - preds_no_answer = [pred for (pred, label) in zip(preds, labels) if (-1, -1) in label] - labels_no_answer = [label for label in labels if (-1, -1) in label] - no_answer_results = squad_base(preds_no_answer, labels_no_answer) - - return { - "EM": overall_results["EM"], # this is top_1 only - "f1": overall_results["f1"], # this is top_1 only - "top_n_accuracy": overall_results["top_n_accuracy"], - "EM_text_answer": answer_results["EM"], # this is top_1 only - "f1_text_answer": answer_results["f1"], # this is top_1 only - "top_n_accuracy_text_answer": answer_results["top_n_accuracy"], - "top_n_EM_text_answer": top_n_em_answer, - "top_n_f1_text_answer": top_n_f1_answer, - "Total_text_answer": len(preds_answer), - "EM_no_answer": no_answer_results["EM"], # this is top_1 only - "f1_no_answer": no_answer_results["f1"], # this is top_1 only - "top_n_accuracy_no_answer": no_answer_results["top_n_accuracy"], - "Total_no_answer": len(preds_no_answer), - } - - -def top_n_accuracy(preds, labels): - """ - This method calculates the percentage of documents for which the model makes top n accurate predictions. - The definition of top n accurate a top n accurate prediction is as follows: - For any given question document pair, there can be multiple predictions from the model and multiple labels. - If any of those predictions overlap at all with any of the labels, those predictions are considered to be top n accurate. - """ - answer_in_top_n = [] - n_questions = len(preds) - for i in range(n_questions): - f1_score = 0 - current_preds = preds[i][0] - for idx in range(len(current_preds)): - f1_score = max(squad_f1_single(current_preds, label, pred_idx=idx) for label in labels[i]) - if f1_score: - break - if f1_score: - answer_in_top_n.append(1) - else: - answer_in_top_n.append(0) - return np.mean(answer_in_top_n) - - -def text_similarity_acc_and_f1(preds, labels): - """ - Returns accuracy and F1 scores for top-1(highest) ranked sequence(context/passage) for each sample/query - - :param preds: list of numpy arrays of dimension n1 x n2 containing n2 predicted ranks for n1 sequences/queries - :type preds: List of numpy array containing similarity scores for each sequence in batch - :param labels: list of arrays of dimension n1 x n2 where each array contains n2 labels(0/1) indicating whether the sequence/passage is a positive(1) passage or hard_negative(0) passage - :type labels: List of list containing values(0/1) - - :return: predicted ranks of passages for each query - """ - top_1_pred = reduce(lambda x, y: x + [0] * y[0] + [1] + [0] * (len(y) - y[0] - 1), preds, []) - labels = reduce(lambda x, y: x + list(y.astype("long")), labels, []) - res = acc_and_f1(top_1_pred, labels) - return res - - -def text_similarity_avg_ranks(preds, labels) -> float: - """ - Calculates average predicted rank of positive sequence(context/passage) for each sample/query - - :param preds: list of numpy arrays of dimension n1 x n2 containing n2 predicted ranks for n1 sequences/queries - :type preds: List of numpy array containing similarity scores for each sequence in batch - :param labels: list of arrays of dimension n1 x n2 where each array contains n2 labels(0/1) indicating whether the sequence/passage is a positive(1) passage or hard_negative(0) passage - :type labels: List of list containing values(0/1) - - :return: average predicted ranks of positive sequence/passage for each sample/query - """ - positive_idx_per_question = list(reduce(lambda x, y: x + list((y == 1).nonzero()[0]), labels, [])) # type: ignore - rank = 0 - for i, idx in enumerate(positive_idx_per_question): - # aggregate the rank of the known gold passage in the sorted results for each question - gold_idx = (preds[i] == idx).nonzero()[0] - rank += gold_idx.item() - return float(rank / len(preds)) - - -def text_similarity_metric(preds, labels) -> Dict[str, float]: - """ - Returns accuracy, F1 scores and average rank scores for text similarity task - - :param preds: list of numpy arrays of dimension n1 x n2 containing n2 predicted ranks for n1 sequences/queries - :type preds: List of numpy array containing similarity scores for each sequence in batch - :param labels: list of arrays of dimension n1 x n2 where each array contains n2 labels(0/1) indicating whether the sequence/passage is a positive(1) passage or hard_negative(0) passage - :type labels: List of list containing values(0/1) - - :return: metrics(accuracy, F1, average rank) for text similarity task - """ - scores = text_similarity_acc_and_f1(preds, labels) - scores["average_rank"] = text_similarity_avg_ranks(preds, labels) - return scores - - -def semantic_answer_similarity( - predictions: List[List[str]], - gold_labels: List[List[str]], - sas_model_name_or_path: str = "sentence-transformers/paraphrase-multilingual-mpnet-base-v2", - batch_size: int = 32, - use_gpu: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, -) -> Tuple[List[float], List[float], List[List[float]]]: - """ - Computes Transformer-based similarity of predicted answer to gold labels to derive a more meaningful metric than EM or F1. - Returns per QA pair a) the similarity of the most likely prediction (top 1) to all available gold labels - b) the highest similarity of all predictions to gold labels - c) a matrix consisting of the similarities of all the predictions compared to all gold labels - - :param predictions: Predicted answers as list of multiple preds per question - :param gold_labels: Labels as list of multiple possible answers per question - :param sas_model_name_or_path: SentenceTransformers semantic textual similarity model, should be path or string - pointing to downloadable models. - :param batch_size: Number of prediction label pairs to encode at once. - :param use_gpu: Whether to use a GPU or the CPU for calculating semantic answer similarity. - Falls back to CPU if no GPU is available. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :return: top_1_sas, top_k_sas, pred_label_matrix - """ - metrics_import.check() - assert len(predictions) == len(gold_labels) - - config = AutoConfig.from_pretrained(sas_model_name_or_path, use_auth_token=use_auth_token) - cross_encoder_used = False - if config.architectures is not None: - cross_encoder_used = any(arch.endswith("ForSequenceClassification") for arch in config.architectures) - - device = None if use_gpu else "cpu" - - # Compute similarities - top_1_sas = [] - top_k_sas = [] - pred_label_matrix = [] - lengths: List[Tuple[int, int]] = [] - - # Based on Modelstring we can load either Bi-Encoders or Cross Encoders. - # Similarity computation changes for both approaches - if cross_encoder_used: - model = CrossEncoder( - sas_model_name_or_path, - device=device, - tokenizer_args={"use_auth_token": use_auth_token}, - automodel_args={"use_auth_token": use_auth_token}, - ) - grid = [] - for preds, labels in zip(predictions, gold_labels): - for p in preds: - for l in labels: - grid.append((p, l)) - lengths.append((len(preds), len(labels))) - scores = model.predict(grid, batch_size=batch_size) - - current_position = 0 - for len_p, len_l in lengths: - scores_window = scores[current_position : current_position + len_p * len_l] - # Per predicted doc there are len_l entries comparing it to all len_l labels. - # So to only consider the first doc we have to take the first len_l entries - top_1_sas.append(np.max(scores_window[:len_l])) - top_k_sas.append(np.max(scores_window)) - pred_label_matrix.append(scores_window.reshape(len_p, len_l).tolist()) - current_position += len_p * len_l - else: - # For Bi-encoders we can flatten predictions and labels into one list - model = SentenceTransformer(sas_model_name_or_path, device=device, use_auth_token=use_auth_token) - all_texts: List[str] = [] - for p, l in zip(predictions, gold_labels): # type: ignore - # TODO potentially exclude (near) exact matches from computations - all_texts.extend(p) - all_texts.extend(l) - lengths.append((len(p), len(l))) - # then compute embeddings - embeddings = model.encode(all_texts, batch_size=batch_size) - - # then select which embeddings will be used for similarity computations - current_position = 0 - for len_p, len_l in lengths: - pred_embeddings = embeddings[current_position : current_position + len_p, :] - current_position += len_p - label_embeddings = embeddings[current_position : current_position + len_l, :] - current_position += len_l - sims = cosine_similarity(pred_embeddings, label_embeddings) - top_1_sas.append(np.max(sims[0, :])) - top_k_sas.append(np.max(sims)) - pred_label_matrix.append(sims.tolist()) - - return top_1_sas, top_k_sas, pred_label_matrix diff --git a/haystack/modeling/evaluation/squad.py b/haystack/modeling/evaluation/squad.py deleted file mode 100644 index a882a4f2f5..0000000000 --- a/haystack/modeling/evaluation/squad.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -This is a copy of the official evaluation script for SQuAD version 2.0. -Modified by XLNet authors to update `find_best_threshold` scripts for SQuAD V2.0 - -In addition to basic functionality, we also compute additional statistics and -plot precision-recall curves if an additional na_prob.json file is provided. -This file is expected to map question ID's to the model's predicted probability -that a question is unanswerable. -""" -import collections -import re -import string - - -def normalize_answer(s: str): - """ - Lower text and remove punctuation, articles and extra whitespace. - """ - - def remove_articles(text): - regex = re.compile(r"\b(a|an|the)\b", re.UNICODE) - return re.sub(regex, " ", text) - - def white_space_fix(text): - return " ".join(text.split()) - - def remove_punc(text): - exclude = set(string.punctuation) - return "".join(ch for ch in text if ch not in exclude) - - def lower(text): - return text.lower() - - return white_space_fix(remove_articles(remove_punc(lower(s)))) - - -def get_tokens(s: str): - if not s: - return [] - return normalize_answer(s).split() - - -def compute_exact(a_gold: str, a_pred: str): - return int(normalize_answer(a_gold) == normalize_answer(a_pred)) - - -def compute_f1(a_gold: str, a_pred: str): - gold_toks = get_tokens(a_gold) - pred_toks = get_tokens(a_pred) - common: collections.Counter = collections.Counter(gold_toks) & collections.Counter(pred_toks) - num_same = sum(common.values()) - if len(gold_toks) == 0 or len(pred_toks) == 0: - # If either is no-answer, then F1 is 1 if they agree, 0 otherwise - return int(gold_toks == pred_toks) - if num_same == 0: - return 0 - precision = 1.0 * num_same / len(pred_toks) - recall = 1.0 * num_same / len(gold_toks) - f1 = (2 * precision * recall) / (precision + recall) - return f1 diff --git a/haystack/modeling/infer.py b/haystack/modeling/infer.py deleted file mode 100644 index 8d2d256829..0000000000 --- a/haystack/modeling/infer.py +++ /dev/null @@ -1,520 +0,0 @@ -import contextlib -import logging -import os -from typing import Any, Dict, List, Optional, Set, Union - -import torch -from torch.utils.data import Dataset -from torch.utils.data.sampler import SequentialSampler -from tqdm import tqdm - -from haystack.modeling.data_handler.dataloader import NamedDataLoader -from haystack.modeling.data_handler.inputs import QAInput -from haystack.modeling.data_handler.processor import InferenceProcessor, Processor -from haystack.modeling.data_handler.samples import SampleBasket -from haystack.modeling.model.adaptive_model import AdaptiveModel, BaseAdaptiveModel -from haystack.modeling.model.predictions import QAPred -from haystack.modeling.utils import initialize_device_settings, set_all_seeds - -logger = logging.getLogger(__name__) - - -class Inferencer: - """ - Loads a saved AdaptiveModel/ONNXAdaptiveModel from disk and runs it in inference mode. Can be used for a - model with prediction head (down-stream predictions) and without (using LM as embedder). - """ - - def __init__( - self, - model: AdaptiveModel, - processor: Processor, - task_type: Optional[str], - batch_size: int = 4, - gpu: bool = False, - name: Optional[str] = None, - return_class_probs: bool = False, - extraction_strategy: Optional[str] = None, - extraction_layer: Optional[int] = None, - num_processes: Optional[int] = None, - disable_tqdm: bool = False, - devices: Optional[List[Union[str, torch.device]]] = None, - ): - """ - Initializes Inferencer from an AdaptiveModel and a Processor instance. - - :param model: AdaptiveModel to run in inference mode - :param processor: A dataset specific Processor object which will turn input (file or dict) into a Pytorch Dataset. - :param task_type: Type of task the model should be used for. Currently supporting: "question_answering" - :param batch_size: Number of samples computed once per batch - :param gpu: If GPU shall be used - :param name: Name for the current Inferencer model, displayed in the REST API - :param return_class_probs: either return probability distribution over all labels or the prob of the associated label - :param extraction_strategy: Strategy to extract vectors. Choices: 'cls_token' (sentence vector), 'reduce_mean' - (sentence vector), reduce_max (sentence vector), 'per_token' (individual token vectors), - 's3e' (sentence vector via S3E pooling, see https://arxiv.org/abs/2002.09620) - :param extraction_layer: number of layer from which the embeddings shall be extracted. Default: -1 (very last layer). - :param num_processes: the number of processes for `multiprocessing.Pool`. - Set to value of 1 (or 0) to disable multiprocessing. - Set to None to let Inferencer use all CPU cores minus one. - If you want to debug the Language Model, you might need to disable multiprocessing! - **Warning!** If you use multiprocessing you have to close the - `multiprocessing.Pool` again! To do so call - :func:`~farm.infer.Inferencer.close_multiprocessing_pool` after you are - done using this class. The garbage collector will not do this for you! - .. deprecated:: 1.10 - This parameter has no effect; it will be removed as Inferencer multiprocessing - has been deprecated. - :param disable_tqdm: Whether to disable tqdm logging (can get very verbose in multiprocessing) - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :return: An instance of the Inferencer. - - """ - # Init device and distributed settings - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - self.processor = processor - self.model = model - self.model.eval() - self.batch_size = batch_size - self.language = self.model.get_language() - self.task_type = task_type - self.disable_tqdm = disable_tqdm - self.problematic_sample_ids: Set[List[int]] = set() # type ignore - - if task_type == "embeddings": - if not extraction_layer or not extraction_strategy: - logger.warning( - "Using task_type='embeddings', but couldn't find one of the args `extraction_layer` and `extraction_strategy`. " - "Since FARM 0.4.2, you set both when initializing the Inferencer and then call inferencer.inference_from_dicts() instead of inferencer.extract_vectors()" - ) - self.model.prediction_heads = torch.nn.ModuleList([]) - self.model.language_model.extraction_layer = extraction_layer # type: ignore [assignment] - self.model.language_model.extraction_strategy = extraction_strategy # type: ignore [assignment] - - # TODO add support for multiple prediction heads - - self.name = name if name is not None else f"anonymous-{self.task_type}" - self.return_class_probs = return_class_probs - - model.connect_heads_with_processor(processor.tasks, require_labels=False) - set_all_seeds(42) - - @classmethod - def load( - cls, - model_name_or_path: str, - revision: Optional[str] = None, - batch_size: int = 4, - gpu: bool = False, - task_type: Optional[str] = None, - return_class_probs: bool = False, - strict: bool = True, - max_seq_len: int = 256, - doc_stride: int = 128, - extraction_strategy: Optional[str] = None, - extraction_layer: Optional[int] = None, - num_processes: Optional[int] = None, - disable_tqdm: bool = False, - tokenizer_class: Optional[str] = None, - use_fast: bool = True, - tokenizer_args: Optional[Dict] = None, - multithreading_rust: bool = True, - use_auth_token: Optional[Union[bool, str]] = None, - devices: Optional[List[Union[str, torch.device]]] = None, - max_query_length: int = 64, - **kwargs, - ): - """ - Load an Inferencer incl. all relevant components (model, tokenizer, processor ...) either by - - 1. specifying a public name from transformers' model hub (https://huggingface.co/models) - 2. or pointing to a local directory it is saved in. - - :param model_name_or_path: Local directory or public name of the model to load. - :param revision: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param batch_size: Number of samples computed once per batch - :param gpu: If GPU shall be used - :param task_type: Type of task the model should be used for. Currently supporting: "question_answering" - :param return_class_probs: either return probability distribution over all labels or the prob of the associated label - :param strict: whether to strictly enforce that the keys loaded from saved model match the ones in - the PredictionHead (see torch.nn.module.load_state_dict()). - Set to `False` for backwards compatibility with PHs saved with older version of FARM. - :param max_seq_len: maximum length of one text sample - :param doc_stride: Only QA: When input text is longer than max_seq_len it gets split into parts, strided by doc_stride - :param extraction_strategy: Strategy to extract vectors. Choices: 'cls_token' (sentence vector), 'reduce_mean' - (sentence vector), reduce_max (sentence vector), 'per_token' (individual token vectors) - :param extraction_layer: number of layer from which the embeddings shall be extracted. Default: -1 (very last layer). - :param num_processes: the number of processes for `multiprocessing.Pool`. Set to value of 0 to disable - multiprocessing. Set to None to let Inferencer use all CPU cores minus one. If you want to - debug the Language Model, you might need to disable multiprocessing! - **Warning!** If you use multiprocessing you have to close the - `multiprocessing.Pool` again! To do so call - :func:`~farm.infer.Inferencer.close_multiprocessing_pool` after you are - done using this class. The garbage collector will not do this for you! - .. deprecated:: 1.10 - This parameter has no effect; it will be removed as Inferencer multiprocessing - has been deprecated. - :param disable_tqdm: Whether to disable tqdm logging (can get very verbose in multiprocessing) - :param tokenizer_class: (Optional) Name of the tokenizer class to load (e.g. `BertTokenizer`) - :param use_fast: (Optional, True by default) Indicate if FARM should try to load the fast version of the tokenizer (True) or - use the Python one (False). - :param tokenizer_args: (Optional) Will be passed to the Tokenizer ``__init__`` method. - See https://huggingface.co/transformers/main_classes/tokenizer.html and detailed tokenizer documentation - on `Hugging Face Transformers `_. - :param multithreading_rust: Whether to allow multithreading in Rust, e.g. for FastTokenizers. - Note: Enabling multithreading in Rust AND multiprocessing in python might cause - deadlocks. - :param devices: List of devices to perform inference on. (Currently, only the first device in the list is used.) - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param max_query_length: Only QA: Maximum length of the question in number of tokens. - :return: An instance of the Inferencer. - """ - if tokenizer_args is None: - tokenizer_args = {} - - devices, _ = initialize_device_settings(devices=devices, use_cuda=gpu, multi_gpu=False) # type: ignore [assignment] - if devices and len(devices) > 1: - logger.warning("Multiple devices are not supported in Inferencer, using the first device %s.", devices[0]) # type: ignore [index] - - name = os.path.basename(model_name_or_path) - - # a) non-hf models (i.e. FARM, ONNX) from local dir - farm_model_bin = os.path.join(model_name_or_path, "language_model.bin") - onnx_model = os.path.join(model_name_or_path, "model.onnx") - if os.path.isfile(farm_model_bin) or os.path.isfile(onnx_model): - model = BaseAdaptiveModel.load(load_dir=model_name_or_path, device=devices[0], strict=strict) # type: ignore [index] - if task_type == "embeddings": - processor = InferenceProcessor.load_from_dir(model_name_or_path) - else: - processor = Processor.load_from_dir(model_name_or_path) - - # b) transformers models from hub or from local - else: - if not task_type: - raise ValueError( - "Please specify the 'task_type' of the model you want to load from transformers. " - "Valid options for arg `task_type`:" - "'question_answering'" - ) - - model = AdaptiveModel.convert_from_transformers( - model_name_or_path, - revision=revision, - device=devices[0], # type: ignore - task_type=task_type, - use_auth_token=use_auth_token, - **kwargs, - ) - processor = Processor.convert_from_transformers( - model_name_or_path, - revision=revision, - task_type=task_type, - max_seq_len=max_seq_len, - doc_stride=doc_stride, - tokenizer_class=tokenizer_class, - tokenizer_args=tokenizer_args, - use_fast=use_fast, - use_auth_token=use_auth_token, - max_query_length=max_query_length, - **kwargs, - ) - - # override processor attributes loaded from config or HF with inferencer params - processor.max_seq_len = max_seq_len - processor.multithreading_rust = multithreading_rust - if hasattr(processor, "doc_stride"): - assert doc_stride < max_seq_len, ( - "doc_stride is longer than max_seq_len. This means that there will be gaps " - "as the passage windows slide, causing the model to skip over parts of the document. " - "Please set a lower value for doc_stride (Suggestions: doc_stride=128, max_seq_len=384) " - ) - processor.doc_stride = doc_stride - if hasattr(processor, "max_query_length"): - processor.max_query_length = max_query_length - - return cls( - model, - processor, - task_type=task_type, - batch_size=batch_size, - gpu=gpu, - name=name, - return_class_probs=return_class_probs, - extraction_strategy=extraction_strategy, - extraction_layer=extraction_layer, - num_processes=num_processes, - disable_tqdm=disable_tqdm, - devices=devices, - ) - - def save(self, path: str): - self.model.save(path) - self.processor.save(path) - - def inference_from_file(self, file: str, multiprocessing_chunksize: Optional[int] = None, return_json: bool = True): - """ - Run down-stream inference on samples created from an input file. - The file should be in the same format as the ones used during training - (e.g. squad style for QA, tsv for doc classification ...) as the same Processor will be used for conversion. - - :param file: path of the input file for Inference - :param multiprocessing_chunksize: number of dicts to put together in one chunk and feed to one process - .. deprecated:: 1.10 - This parameter has no effect; it will be removed as Inferencer multiprocessing - has been deprecated. - :return: list of predictions - """ - dicts = self.processor.file_to_dicts(file) - preds_all = self.inference_from_dicts( - dicts, return_json=return_json, multiprocessing_chunksize=multiprocessing_chunksize - ) - return list(preds_all) - - def inference_from_dicts( - self, dicts: List[Dict], return_json: bool = True, multiprocessing_chunksize: Optional[int] = None - ) -> List: - """ - Runs down-stream inference on samples created from input dictionaries. - - * QA (FARM style): [{"questions": ["What is X?"], "text": "Some context containing the answer"}] - - :param dicts: Samples to run inference on provided as a list(or a generator object) of dicts. - One dict per sample. - :param return_json: Whether the output should be in a json appropriate format. If False, it returns the prediction - object where applicable, else it returns PredObj.to_json() - :param multiprocessing_chunksize: number of dicts to put together in one chunk and feed to one process - (only relevant if you do multiprocessing) - .. deprecated:: 1.10 - This parameter has no effect; it will be removed as Inferencer multiprocessing - has been deprecated. - :return: list of predictions - """ - # whether to aggregate predictions across different samples (e.g. for QA on long texts) - # TODO remove or adjust after implementing input objects properly - # if set(dicts[0].keys()) == {"qas", "context"}: - # warnings.warn("QA Input dictionaries with [qas, context] as keys will be deprecated in the future", - # DeprecationWarning) - aggregate_preds = False - if len(self.model.prediction_heads) > 0: - aggregate_preds = hasattr(self.model.prediction_heads[0], "aggregate_preds") - - predictions: Any = self._inference_without_multiprocessing(dicts, return_json, aggregate_preds) - return predictions - - def _inference_without_multiprocessing(self, dicts: List[Dict], return_json: bool, aggregate_preds: bool) -> List: - """ - Implementation of inference from dicts without using Python multiprocessing. Useful for debugging or in API - framework where spawning new processes could be expensive. - - :param dicts: Samples to run inference on provided as a list of dicts. One dict per sample. - :param return_json: Whether the output should be in a json appropriate format. If False, it returns the prediction - object where applicable, else it returns PredObj.to_json() - :param aggregate_preds: whether to aggregate predictions across different samples (e.g. for QA on long texts) - :return: list of predictions - """ - indices = list(range(len(dicts))) - dataset, tensor_names, problematic_ids, baskets = self.processor.dataset_from_dicts( - dicts, indices=indices, return_baskets=True - ) - self.problematic_sample_ids = problematic_ids - - # TODO change format of formatted_preds in QA (list of dicts) - if aggregate_preds: - preds_all = self._get_predictions_and_aggregate(dataset, tensor_names, baskets) - else: - preds_all = self._get_predictions(dataset, tensor_names, baskets) - - if return_json: - # TODO this try catch should be removed when all tasks return prediction objects - with contextlib.suppress(AttributeError): - preds_all = [x.to_json() for x in preds_all] - - return preds_all - - def _get_predictions(self, dataset: Dataset, tensor_names: List, baskets): - """ - Feed a preprocessed dataset to the model and get the actual predictions (forward pass + formatting). - - :param dataset: PyTorch Dataset with samples you want to predict - :param tensor_names: Names of the tensors in the dataset - :param baskets: For each item in the dataset, we need additional information to create formatted preds. - Baskets contain all relevant infos for that. - Example: QA - input string to convert the predicted answer from indices back to string space - :return: list of predictions - """ - samples = [s for b in baskets for s in b.samples] - - data_loader = NamedDataLoader( - dataset=dataset, sampler=SequentialSampler(dataset), batch_size=self.batch_size, tensor_names=tensor_names # type: ignore [arg-type] - ) # type ignore - preds_all = [] - for i, batch in enumerate( - tqdm(data_loader, desc="Inferencing Samples", unit=" Batches", disable=self.disable_tqdm) - ): - batch = {key: batch[key].to(self.devices[0]) for key in batch} - batch_samples = samples[i * self.batch_size : (i + 1) * self.batch_size] - - # get logits - with torch.inference_mode(): - logits = self.model.forward(**batch) - preds = self.model.formatted_preds( - logits=logits, samples=batch_samples, padding_mask=batch.get("padding_mask", None) - ) - preds_all += preds - return preds_all - - def _get_predictions_and_aggregate(self, dataset: Dataset, tensor_names: List, baskets: List[SampleBasket]): - """ - Feed a preprocessed dataset to the model and get the actual predictions (forward pass + logits_to_preds + formatted_preds). - - Difference to _get_predictions(): - - Additional aggregation step across predictions of individual samples - (e.g. For QA on long texts, we extract answers from multiple passages and then aggregate them on the "document level") - - :param dataset: PyTorch Dataset with samples you want to predict - :param tensor_names: Names of the tensors in the dataset - :param baskets: For each item in the dataset, we need additional information to create formatted preds. - Baskets contain all relevant infos for that. - Example: QA - input string to convert the predicted answer from indices back to string space - :return: list of predictions - """ - data_loader = NamedDataLoader( - dataset=dataset, sampler=SequentialSampler(dataset), batch_size=self.batch_size, tensor_names=tensor_names # type: ignore [arg-type] - ) # type ignore - # TODO Sometimes this is the preds of one head, sometimes of two. We need a more advanced stacking operation - # TODO so that preds of the right shape are passed in to formatted_preds - unaggregated_preds_all = [] - - for batch in tqdm(data_loader, desc="Inferencing Samples", unit=" Batches", disable=self.disable_tqdm): - batch = {key: batch[key].to(self.devices[0]) for key in batch} - - # get logits - with torch.inference_mode(): - # Aggregation works on preds, not logits. We want as much processing happening in one batch + on GPU - # So we transform logits to preds here as well - logits = self.model.forward( - input_ids=batch["input_ids"], - segment_ids=batch["segment_ids"], - padding_mask=batch["padding_mask"], - output_hidden_states=batch.get("output_hidden_states", False), - output_attentions=batch.get("output_attentions", False), - ) - # preds = self.model.logits_to_preds(logits, **batch)[0] (This must somehow be useful for SQuAD) - preds = self.model.logits_to_preds(logits, **batch) - unaggregated_preds_all.append(preds) - - # In some use cases we want to aggregate the individual predictions. - # This is mostly useful, if the input text is longer than the max_seq_len that the model can process. - # In QA we can use this to get answers from long input texts by first getting predictions for smaller passages - # and then aggregating them here. - - # At this point unaggregated preds has shape [n_batches][n_heads][n_samples] - - # can assume that we have only complete docs i.e. all the samples of one doc are in the current chunk - logits = [None] - preds_all = self.model.formatted_preds( - logits=logits, # For QA we collected preds per batch and do not want to pass logits - preds=unaggregated_preds_all, - baskets=baskets, - ) # type ignore - return preds_all - - def extract_vectors( - self, dicts: List[Dict], extraction_strategy: Optional[str] = "cls_token", extraction_layer: Optional[int] = -1 - ): - """ - Converts a text into vector(s) using the language model only (no prediction head involved). - - Example: - basic_texts = [{"text": "Some text we want to embed"}, {"text": "And a second one"}] - result = inferencer.extract_vectors(dicts=basic_texts) - - :param dicts: Samples to run inference on provided as a list of dicts. One dict per sample. - :param extraction_strategy: Strategy to extract vectors. Choices: 'cls_token' (sentence vector), 'reduce_mean' - (sentence vector), reduce_max (sentence vector), 'per_token' (individual token vectors) - :param extraction_layer: number of layer from which the embeddings shall be extracted. Default: -1 (very last layer). - :return: dict of predictions - """ - logger.warning("Deprecated! Please use Inferencer.inference_from_dicts() instead.") - self.model.prediction_heads = torch.nn.ModuleList([]) - self.model.language_model.extraction_layer = extraction_layer # type: ignore [assignment] - self.model.language_model.extraction_strategy = extraction_strategy # type: ignore [assignment] - - return self.inference_from_dicts(dicts) - - -class QAInferencer(Inferencer): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # FIXME - if self.task_type != "question_answering": - logger.warning( - "QAInferencer always has task_type='question_answering' even if another value is provided " - "to Inferencer.load() or QAInferencer()" - ) - self.task_type = "question_answering" - - def inference_from_dicts( - self, dicts: List[dict], return_json: bool = True, multiprocessing_chunksize: Optional[int] = None - ) -> List[QAPred]: - """ - :param multiprocessing_chunksize: number of dicts to put together in one chunk and feed to one process - (only relevant if you do multiprocessing) - .. deprecated:: 1.10 - This parameter has no effect; it will be removed as Inferencer multiprocessing - has been deprecated. - """ - return Inferencer.inference_from_dicts( - self, dicts, return_json=return_json, multiprocessing_chunksize=multiprocessing_chunksize - ) - - def inference_from_file( - self, file: str, multiprocessing_chunksize: Optional[int] = None, return_json=True - ) -> List[QAPred]: - """ - :param multiprocessing_chunksize: number of dicts to put together in one chunk and feed to one process - (only relevant if you do multiprocessing) - .. deprecated:: 1.10 - This parameter has no effect; it will be removed as Inferencer multiprocessing - has been deprecated. - """ - return Inferencer.inference_from_file( - self, file, return_json=return_json, multiprocessing_chunksize=multiprocessing_chunksize - ) - - def inference_from_objects( - self, objects: List[QAInput], return_json: bool = True, multiprocessing_chunksize: Optional[int] = None - ) -> List[QAPred]: - """ - :param multiprocessing_chunksize: number of dicts to put together in one chunk and feed to one process - (only relevant if you do multiprocessing) - .. deprecated:: 1.10 - This parameter has no effect; it will be removed as Inferencer multiprocessing - has been deprecated. - """ - # Return no predictions if there are no inputs - if not objects: - return [] - - dicts = [o.to_dict() for o in objects] - # TODO investigate this deprecation warning. Timo: I thought we were about to implement Input Objects, - # then we can and should use inference from (input) objects! - # logger.warning("QAInferencer.inference_from_objects() will soon be deprecated. Use QAInferencer.inference_from_dicts() instead") - return self.inference_from_dicts( - dicts, return_json=return_json, multiprocessing_chunksize=multiprocessing_chunksize - ) diff --git a/haystack/modeling/model/__init__.py b/haystack/modeling/model/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/haystack/modeling/model/adaptive_model.py b/haystack/modeling/model/adaptive_model.py deleted file mode 100644 index 87d84a1cda..0000000000 --- a/haystack/modeling/model/adaptive_model.py +++ /dev/null @@ -1,830 +0,0 @@ -import copy -import json -import logging -import multiprocessing -import os -from pathlib import Path -from typing import Iterable, Dict, Union, List, Optional, Callable - -import numpy -import torch -from torch import nn -from transformers import AutoConfig, AutoModelForQuestionAnswering -from transformers.convert_graph_to_onnx import convert, quantize as quantize_model - -from haystack.modeling.data_handler.processor import Processor -from haystack.modeling.model.language_model import ( - get_language_model, - LanguageModel, - _get_model_type, - capitalize_model_type, -) -from haystack.modeling.model.prediction_head import PredictionHead, QuestionAnsweringHead -from haystack.utils.experiment_tracking import Tracker as tracker - - -logger = logging.getLogger(__name__) - - -class BaseAdaptiveModel: - """ - Base Class for implementing AdaptiveModel with frameworks like PyTorch and ONNX. - """ - - language_model: LanguageModel - subclasses = {} # type: Dict - - def __init_subclass__(cls, **kwargs): - """ - This automatically keeps track of all available subclasses. - Enables generic load() for all specific AdaptiveModel implementation. - """ - super().__init_subclass__(**kwargs) - cls.subclasses[cls.__name__] = cls - - def __init__(self, prediction_heads: Union[List[PredictionHead], nn.ModuleList]): - self.prediction_heads = prediction_heads - - @classmethod - def load(cls, **kwargs): - """ - Load corresponding AdaptiveModel Class(AdaptiveModel/ONNXAdaptiveModel) based on the - files in the load_dir. - - :param kwargs: Arguments to pass for loading the model. - :return: Instance of a model. - """ - if (Path(kwargs["load_dir"]) / "model.onnx").is_file(): - model = cls.subclasses["ONNXAdaptiveModel"].load(**kwargs) - else: - model = cls.subclasses["AdaptiveModel"].load(**kwargs) - return model - - def logits_to_preds(self, logits: torch.Tensor, **kwargs): - """ - Get predictions from all prediction heads. - - :param logits: Logits that can vary in shape and type, depending on task. - :return: A list of all predictions from all prediction heads. - """ - all_preds = [] - # collect preds from all heads - for head, logits_for_head in zip(self.prediction_heads, logits): - preds = head.logits_to_preds(logits=logits_for_head, **kwargs) - all_preds.append(preds) - return all_preds - - def formatted_preds(self, logits: torch.Tensor, **kwargs): - """ - Format predictions for inference. - - :param logits: Model logits. - :return: Predictions in the right format. - """ - n_heads = len(self.prediction_heads) - - if n_heads == 0: - # just return LM output (e.g. useful for extracting embeddings at inference time) - preds_final = self.language_model.formatted_preds(logits=logits, **kwargs) - - elif n_heads == 1: - preds_final = [] - # This try catch is to deal with the fact that sometimes we collect preds before passing it to - # formatted_preds (see Inferencer._get_predictions_and_aggregate()) and sometimes we don't - # (see Inferencer._get_predictions()) - try: - preds = kwargs["preds"] - temp = [y[0] for y in preds] - preds_flat = [item for sublist in temp for item in sublist] - kwargs["preds"] = preds_flat - except KeyError: - kwargs["preds"] = None - head = self.prediction_heads[0] - logits_for_head = logits[0] - preds = head.formatted_preds(logits=logits_for_head, **kwargs) # type: ignore [operator] - # TODO This is very messy - we need better definition of what the output should look like - if type(preds) == list: - preds_final += preds - elif type(preds) == dict and "predictions" in preds: - preds_final.append(preds) - - return preds_final - - def connect_heads_with_processor(self, tasks: Dict, require_labels: bool = True): - """ - Populates prediction head with information coming from tasks. - - :param tasks: A dictionary where the keys are the names of the tasks and - the values are the details of the task (e.g. label_list, metric, - tensor name). - :param require_labels: If True, an error will be thrown when a task is - not supplied with labels. - :return: None - """ - for head in self.prediction_heads: - head.label_tensor_name = tasks[head.task_name]["label_tensor_name"] - label_list = tasks[head.task_name]["label_list"] - if not label_list and require_labels: - raise Exception(f"The task '{head.task_name}' is missing a valid set of labels") - label_list = tasks[head.task_name]["label_list"] - head.label_list = label_list - head.metric = tasks[head.task_name]["metric"] - - @classmethod - def _get_prediction_head_files(cls, load_dir: Union[str, Path], strict: bool = True): - load_dir = Path(load_dir) - files = os.listdir(load_dir) - model_files = [load_dir / f for f in files if ".bin" in f and "prediction_head" in f] - config_files = [load_dir / f for f in files if "config.json" in f and "prediction_head" in f] - # sort them to get correct order in case of multiple prediction heads - model_files.sort() - config_files.sort() - - if strict: - error_str = ( - f"There is a mismatch in number of model files ({len(model_files)}) and config files ({len(config_files)})." - "This might be because the Language Model Prediction Head " - "does not currently support saving and loading" - ) - assert len(model_files) == len(config_files), error_str - logger.info("Found files for loading %s prediction heads", len(model_files)) - - return model_files, config_files - - -def loss_per_head_sum(loss_per_head: Iterable, global_step: Optional[int] = None, batch: Optional[Dict] = None): - """ - Sums up the loss of each prediction head. - - :param loss_per_head: List of losses. - """ - return sum(loss_per_head) - - -class AdaptiveModel(nn.Module, BaseAdaptiveModel): - """ - PyTorch implementation containing all the modelling needed for your NLP task. Combines a language - model and a prediction head. Allows for gradient flow back to the language model component. - """ - - def __init__( - self, - language_model: LanguageModel, - prediction_heads: List[PredictionHead], - embeds_dropout_prob: float, - lm_output_types: Union[str, List[str]], - device: torch.device, - loss_aggregation_fn: Optional[Callable] = None, - ): - """ - :param language_model: Any model that turns token ids into vector representations. - :param prediction_heads: A list of models that take embeddings and return logits for a given task. - :param embeds_dropout_prob: The probability that a value in the embeddings returned by the - language model will be zeroed. - :param lm_output_types: How to extract the embeddings from the final layer of the language model. When set - to "per_token", one embedding will be extracted per input token. If set to - "per_sequence", a single embedding will be extracted to represent the full - input sequence. Can either be a single string, or a list of strings, - one for each prediction head. - :param device: The device on which this model will operate. Either torch.device("cpu") or torch.device("cuda"). - :param loss_aggregation_fn: Function to aggregate the loss of multiple prediction heads. - Input: loss_per_head (list of tensors), global_step (int), batch (dict) - Output: aggregated loss (tensor) - Default is a simple sum: - `lambda loss_per_head, global_step=None, batch=None: sum(tensors)` - However, you can pass more complex functions that depend on the - current step (e.g. for round-robin style multitask learning) or the actual - content of the batch (e.g. certain labels) - Note: The loss at this stage is per sample, i.e one tensor of - shape (batchsize) per prediction head. - """ - super(AdaptiveModel, self).__init__() # type: ignore - self.device = device - self.language_model = language_model.to(device) - self.lm_output_dims = language_model.output_dims - self.prediction_heads = nn.ModuleList([ph.to(device) for ph in prediction_heads]) - self.fit_heads_to_lm() - self.dropout = nn.Dropout(embeds_dropout_prob) - self.lm_output_types = [lm_output_types] if isinstance(lm_output_types, str) else lm_output_types - self.log_params() - # default loss aggregation function is a simple sum (without using any of the optional params) - if not loss_aggregation_fn: - loss_aggregation_fn = loss_per_head_sum - self.loss_aggregation_fn = loss_aggregation_fn - - def fit_heads_to_lm(self): - """ - This iterates over each prediction head and ensures that its input - dimensionality matches the output dimensionality of the language model. - If it doesn't, it is resized so it does fit. - """ - for ph in self.prediction_heads: - ph.resize_input(self.lm_output_dims) - ph.to(self.device) - - def bypass_ph(self): - """ - Replaces methods in the prediction heads with dummy functions. - Used for benchmarking where we want to isolate the LanguageModel run time - from the PredictionHead run time. - """ - # TODO convert inner functions into lambdas - - def fake_forward(x): - """ - Slices lm vector outputs of shape (batch_size, max_seq_len, dims) --> (batch_size, max_seq_len, 2) - """ - return x.narrow(2, 0, 2) - - def fake_logits_to_preds(logits, **kwargs): - batch_size = logits.shape[0] - return [None, None] * batch_size - - def fake_formatted_preds(**kwargs): - return None - - for ph in self.prediction_heads: - ph.forward = fake_forward - ph.logits_to_preds = fake_logits_to_preds - ph.formatted_preds = fake_formatted_preds - - def save(self, save_dir: Union[str, Path]): - """ - Saves the language model and prediction heads. This will generate a config file - and model weights for each. - - :param save_dir: Path to save the AdaptiveModel to. - """ - os.makedirs(save_dir, exist_ok=True) - self.language_model.save(save_dir) - for i, ph in enumerate(self.prediction_heads): - ph.save(save_dir, i) - # Need to save config and pipeline - - @classmethod - def load( # type: ignore - cls, - load_dir: Union[str, Path], - device: Union[str, torch.device], - strict: bool = True, - processor: Optional[Processor] = None, - ): - """ - Loads an AdaptiveModel from a directory. The directory must contain: - - * language_model.bin - * language_model_config.json - * prediction_head_X.bin multiple PH possible - * prediction_head_X_config.json - * processor_config.json config for transforming input - * vocab.txt vocab file for language model, turning text to Wordpiece Tokens - - :param load_dir: Location where the AdaptiveModel is stored. - :param device: Specifies the device to which you want to send the model, either torch.device("cpu") or torch.device("cuda"). - :param strict: Whether to strictly enforce that the keys loaded from saved model match the ones in - the PredictionHead (see torch.nn.module.load_state_dict()). - :param processor: Processor to populate prediction head with information coming from tasks. - """ - device = torch.device(device) - language_model = get_language_model(load_dir) - - # Prediction heads - _, ph_config_files = cls._get_prediction_head_files(load_dir) - prediction_heads = [] - ph_output_type = [] - for config_file in ph_config_files: - head = PredictionHead.load(config_file, strict=strict) - prediction_heads.append(head) - ph_output_type.append(head.ph_output_type) - - model = cls(language_model, prediction_heads, 0.1, ph_output_type, device) - if processor: - model.connect_heads_with_processor(processor.tasks) - - return model - - @classmethod - def convert_from_transformers( - cls, - model_name_or_path, - device: Union[str, torch.device], - revision: Optional[str] = None, - task_type: str = "question_answering", - processor: Optional[Processor] = None, - use_auth_token: Optional[Union[bool, str]] = None, - **kwargs, - ) -> "AdaptiveModel": - """ - Load a (downstream) model from huggingface's transformers format. Use cases: - - continue training in Haystack (e.g. take a squad QA model and fine-tune on your own data) - - compare models without switching frameworks - - use model directly for inference - - :param model_name_or_path: local path of a saved model or name of a public one. - Exemplary public names: - - distilbert-base-uncased-distilled-squad - - deepset/bert-large-uncased-whole-word-masking-squad2 - - See https://huggingface.co/models for full list - :param device: torch.device("cpu") or torch.device("cuda") - :param revision: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - Right now accepts only 'question_answering'. - :param processor: populates prediction head with information coming from tasks. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :return: AdaptiveModel - """ - - lm = get_language_model( - model_name_or_path, revision=revision, use_auth_token=use_auth_token, model_kwargs=kwargs - ) - if task_type is None: - # Infer task type from config - architecture = lm.model.config.architectures[0] - if "QuestionAnswering" in architecture: - task_type = "question_answering" - else: - logger.error( - "Could not infer task type from model config. Please provide task type manually. " - "('question_answering' or 'embeddings')" - ) - - if task_type == "question_answering": - ph = QuestionAnsweringHead.load( - model_name_or_path, revision=revision, use_auth_token=use_auth_token, **kwargs - ) - adaptive_model = cls( - language_model=lm, - prediction_heads=[ph], - embeds_dropout_prob=0.1, - lm_output_types="per_token", - device=device, # type: ignore [arg-type] - ) - elif task_type == "embeddings": - adaptive_model = cls( - language_model=lm, - prediction_heads=[], - embeds_dropout_prob=0.1, - lm_output_types=["per_token", "per_sequence"], - device=device, # type: ignore [arg-type] - ) - - if processor: - adaptive_model.connect_heads_with_processor(processor.tasks) - - return adaptive_model - - def convert_to_transformers(self): - """ - Convert an adaptive model to huggingface's transformers format. Returns a list containing one model for each - prediction head. - - :return: List of huggingface transformers models. - """ - converted_models = [] - - # convert model for each prediction head - for prediction_head in self.prediction_heads: - if len(prediction_head.layer_dims) != 2: - logger.error( - "Currently conversion only works for PredictionHeads that are a single layer Feed Forward NN with dimensions [LM_output_dim, number_classes].\n" - " Your PredictionHead has %s dimensions.", - str(prediction_head.layer_dims), - ) - continue - if prediction_head.model_type == "span_classification": - transformers_model = self._convert_to_transformers_qa(prediction_head) - converted_models.append(transformers_model) - else: - logger.error( - "Haystack -> Transformers conversion is not supported yet for prediction heads of type %s", - prediction_head.model_type, - ) - - return converted_models - - def _convert_to_transformers_qa(self, prediction_head): - # TODO add more infos to config - - # remove pooling layer - self.language_model.model.pooler = None - # init model - transformers_model = AutoModelForQuestionAnswering.from_config(self.language_model.model.config) - # transfer weights for language model + prediction head - setattr(transformers_model, transformers_model.base_model_prefix, self.language_model.model) - transformers_model.qa_outputs.load_state_dict(prediction_head.feed_forward.feed_forward[0].state_dict()) - - return transformers_model - - def logits_to_loss_per_head(self, logits: torch.Tensor, **kwargs): - """ - Collect losses from each prediction head. - - :param logits: Logits, can vary in shape and type, depending on task. - :return: The per sample per prediciton head loss whose first two dimensions - have length n_pred_heads, batch_size. - """ - all_losses = [] - for head, logits_for_one_head in zip(self.prediction_heads, logits): - # check if PredictionHead connected to Processor - assert hasattr(head, "label_tensor_name"), ( - f"Label_tensor_names are missing inside the {head.task_name} Prediction Head. Did you connect the model" - " with the processor through either 'model.connect_heads_with_processor(processor.tasks)'" - " or by passing the processor to the Adaptive Model?" - ) - all_losses.append(head.logits_to_loss(logits=logits_for_one_head, **kwargs)) - return all_losses - - def logits_to_loss(self, logits: torch.Tensor, global_step: Optional[int] = None, **kwargs): - """ - Get losses from all prediction heads & reduce to single loss *per sample*. - - :param logits: Logits, can vary in shape and type, depending on task. - :param global_step: Number of current training step. - :param kwargs: Placeholder for passing generic parameters. - Note: Contains the batch (as dict of tensors), when called from Trainer.train(). - :return: torch.tensor that is the per sample loss (len: batch_size) - """ - all_losses = self.logits_to_loss_per_head(logits, **kwargs) - # This aggregates the loss per sample across multiple prediction heads - # Default is sum(), but you can configure any fn that takes [Tensor, Tensor ...] and returns [Tensor] - loss = self.loss_aggregation_fn(all_losses, global_step=global_step, batch=kwargs) - return loss - - def prepare_labels(self, **kwargs): - """ - Label conversion to original label space, per prediction head. - - :param label_maps: dictionary for mapping ids to label strings - :type label_maps: dict[int:str] - :return: labels in the right format - """ - all_labels = [] - # for head, label_map_one_head in zip(self.prediction_heads): - # labels = head.prepare_labels(label_map=label_map_one_head, **kwargs) - # all_labels.append(labels) - for head in self.prediction_heads: - labels = head.prepare_labels(**kwargs) - all_labels.append(labels) - return all_labels - - def forward( - self, - input_ids: torch.Tensor, - segment_ids: torch.Tensor, - padding_mask: torch.Tensor, - output_hidden_states: bool = False, - output_attentions: bool = False, - ): - """ - Push data through the whole model and returns logits. The data will - propagate through the language model and each of the attached prediction heads. - - :param input_ids: The IDs of each token in the input sequence. It's a tensor of shape [batch_size, max_seq_len]. - :param segment_ids: The ID of the segment. For example, in next sentence prediction, the tokens in the - first sentence are marked with 0 and the tokens in the second sentence are marked with 1. - It is a tensor of shape [batch_size, max_seq_len]. - :param padding_mask: A mask that assigns 1 to valid input tokens and 0 to padding tokens - of shape [batch_size, max_seq_len]. - :param output_hidden_states: Whether to output hidden states - :param output_attentions: Whether to output attentions - :return: All logits as torch.tensor or multiple tensors. - """ - # Run forward pass of language model - output_tuple = self.language_model.forward( - input_ids=input_ids, - segment_ids=segment_ids, - attention_mask=padding_mask, - output_hidden_states=output_hidden_states, - output_attentions=output_attentions, - ) - if output_hidden_states and output_attentions: - sequence_output, pooled_output, hidden_states, attentions = output_tuple - elif output_hidden_states: - sequence_output, pooled_output, hidden_states = output_tuple - elif output_attentions: - sequence_output, pooled_output, attentions = output_tuple - else: - sequence_output, pooled_output = output_tuple - # Run forward pass of (multiple) prediction heads using the output from above - all_logits = [] - if len(self.prediction_heads) > 0: - for head, lm_out in zip(self.prediction_heads, self.lm_output_types): - # Choose relevant vectors from LM as output and perform dropout - if lm_out == "per_token": - output = self.dropout(sequence_output) - elif lm_out == "per_sequence" or lm_out == "per_sequence_continuous": - output = self.dropout(pooled_output) - elif ( - lm_out == "per_token_squad" - ): # we need a per_token_squad because of variable metric computation later on... - output = self.dropout(sequence_output) - else: - raise ValueError("Unknown extraction strategy from language model: {}".format(lm_out)) - - # Do the actual forward pass of a single head - all_logits.append(head(output)) - else: - # just return LM output (e.g. useful for extracting embeddings at inference time) - all_logits.append((sequence_output, pooled_output)) - - if output_hidden_states and output_attentions: - return all_logits, hidden_states, attentions - if output_hidden_states: - return all_logits, hidden_states - if output_attentions: - return all_logits, attentions - return all_logits - - def forward_lm(self, **kwargs): - """ - Forward pass for the language model. - - :return: Tuple containing list of embeddings for each token and - embedding for whole sequence. - """ - # Check if we have to extract from a special layer of the LM (default = last layer) - try: - extraction_layer = self.language_model.extraction_layer - except: - extraction_layer = -1 - - # Run forward pass of language model - if extraction_layer == -1: - sequence_output, pooled_output = self.language_model( - **kwargs, return_dict=False, output_all_encoded_layers=False - ) - else: - # get output from an earlier layer - self.language_model.enable_hidden_states_output() - sequence_output, pooled_output, all_hidden_states = self.language_model(**kwargs, return_dict=False) - sequence_output = all_hidden_states[extraction_layer] - pooled_output = None # not available in earlier layers - self.language_model.disable_hidden_states_output() - return sequence_output, pooled_output - - def log_params(self): - """ - Logs parameters to generic logger MlLogger - """ - params = { - "lm_type": self.language_model.__class__.__name__, - "lm_name": self.language_model.name, - "prediction_heads": ",".join([head.__class__.__name__ for head in self.prediction_heads]), - "lm_output_types": ",".join(self.lm_output_types), - } - try: - tracker.track_params(params) - except Exception as e: - logger.warning("ML logging didn't work: %s", e) - - def verify_vocab_size(self, vocab_size: int): - """ - Verifies that the model fits to the tokenizer vocabulary. - They could diverge in case of custom vocabulary added via tokenizer.add_tokens() - """ - model_vocab_len = self.language_model.model.resize_token_embeddings(new_num_tokens=None).num_embeddings # type: ignore [union-attr,operator] - - msg = ( - f"Vocab size of tokenizer {vocab_size} doesn't match with model {model_vocab_len}. " - "If you added a custom vocabulary to the tokenizer, " - "make sure to supply 'n_added_tokens' to get_language_model() and BertStyleLM.load()" - ) - assert vocab_size == model_vocab_len, msg - - for head in self.prediction_heads: - if head.model_type == "language_modelling": - ph_decoder_len = head.decoder.weight.shape[0] # type: ignore [union-attr,index] - assert vocab_size == ph_decoder_len, msg - - def get_language(self): - return self.language_model.language - - @classmethod - def convert_to_onnx( - cls, - model_name: str, - output_path: Path, - task_type: str, - convert_to_float16: bool = False, - quantize: bool = False, - opset_version: int = 11, - use_auth_token: Optional[Union[str, bool]] = None, - ): - """ - Convert a PyTorch model from transformers hub to an ONNX Model. - - :param model_name: Transformers model name. - :param output_path: Output Path to write the converted model to. - :param task_type: Type of task for the model. Available options: "question_answering" - :param convert_to_float16: By default, the model uses float32 precision. With half precision of float16, inference - should be faster on Nvidia GPUs with Tensor core like T4 or V100. On older GPUs, float32 - might be more performant. - :param quantize: Convert floating point number to integers - :param opset_version: ONNX opset version. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :return: None. - """ - model_type = capitalize_model_type(_get_model_type(model_name)) # type: ignore - if model_type not in ["Bert", "Roberta", "XLMRoberta"]: - raise Exception("The current ONNX conversion only support 'BERT', 'RoBERTa', and 'XLMRoberta' models.") - - task_type_to_pipeline_map = {"question_answering": "question-answering"} - - convert( - pipeline_name=task_type_to_pipeline_map[task_type], - framework="pt", - model=model_name, - output=output_path / "model.onnx", - opset=opset_version, - use_external_format=model_type == "XLMRoberta", - use_auth_token=use_auth_token, - ) - - # save processor & model config files that are needed when loading the model with the Haystack.basics Inferencer - processor = Processor.convert_from_transformers( - tokenizer_name_or_path=model_name, - task_type=task_type, - max_seq_len=256, - doc_stride=128, - use_fast=True, - use_auth_token=use_auth_token, - ) - processor.save(output_path) - model = AdaptiveModel.convert_from_transformers( - model_name, device=torch.device("cpu"), task_type=task_type, use_auth_token=use_auth_token - ) - model.save(output_path) - os.remove(output_path / "language_model.bin") # remove the actual PyTorch model(only configs are required) - - onnx_model_config = { - "task_type": task_type, - "onnx_opset_version": opset_version, - "language_model_class": model_type, - "language": model.language_model.language, - } - with open(output_path / "onnx_model_config.json", "w") as f: - json.dump(onnx_model_config, f) - - if convert_to_float16: - from onnxruntime_tools import optimizer - - config = AutoConfig.from_pretrained(model_name, use_auth_token=use_auth_token) - optimized_model = optimizer.optimize_model( - input=str(output_path / "model.onnx"), - model_type="bert", - num_heads=config.num_hidden_layers, - hidden_size=config.hidden_size, - ) - optimized_model.convert_model_float32_to_float16() - optimized_model.save_model_to_file("model.onnx") - - if quantize: - quantize_model(output_path / "model.onnx") - - -class ONNXAdaptiveModel(BaseAdaptiveModel): - """ - Implementation of ONNX Runtime for Inference of ONNX Models. - - Existing PyTorch based Haystack.basics AdaptiveModel can be converted to ONNX format using AdaptiveModel.convert_to_onnx(). - The conversion is currently only implemented for Question Answering Models. - - For inference, this class is compatible with the Haystack.basics Inferencer. - """ - - # TODO validate usefulness - def __init__( - self, - onnx_session, # TODO - language_model_class: str, - language: str, - prediction_heads: List[PredictionHead], - device: torch.device, - ): - """ - :param onnx_session: ? # TODO - :param language_model_class: Class of LanguageModel - :param language: Language the model is trained for. - :param prediction_heads: A list of models that take embeddings and return logits for a given task. - :param device: The device on which this model will operate. Either torch.device("cpu") or torch.device("cuda"). - """ - import onnxruntime - - super().__init__(prediction_heads) - - if str(device) == "cuda" and onnxruntime.get_device() != "GPU": - raise Exception( - f"Device {device} not available for Inference. For CPU, run pip install onnxruntime and" - f"for GPU run pip install onnxruntime-gpu" - ) - self.onnx_session = onnx_session - self.language_model_class = language_model_class - self.language = language - self.prediction_heads = prediction_heads - self.device = device - - @classmethod - def load(cls, load_dir: Union[str, Path], device: Union[str, torch.device], **kwargs): # type: ignore - """ - Loads an ONNXAdaptiveModel from a directory. - - :param load_dir: Location where the ONNXAdaptiveModel is stored. - :param device: The device on which this model will operate. Either torch.device("cpu") or torch.device("cuda"). - """ - device = torch.device(device) - load_dir = Path(load_dir) - import onnxruntime - - sess_options = onnxruntime.SessionOptions() - # Set graph optimization level to ORT_ENABLE_EXTENDED to enable bert optimization. - sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_EXTENDED - # Use OpenMP optimizations. Only useful for CPU, has little impact for GPUs. - sess_options.intra_op_num_threads = multiprocessing.cpu_count() - - providers = kwargs.get( - "providers", ["CPUExecutionProvider"] if device.type == "cpu" else ["CUDAExecutionProvider"] - ) - onnx_session = onnxruntime.InferenceSession(str(load_dir / "model.onnx"), sess_options, providers=providers) - - # Prediction heads - _, ph_config_files = cls._get_prediction_head_files(load_dir, strict=False) - prediction_heads = [] - ph_output_type = [] - for config_file in ph_config_files: - # ONNX Model doesn't need have a separate neural network for PredictionHead. It only uses the - # instance methods of PredictionHead class, so, we load with the load_weights param as False. - head = PredictionHead.load(config_file, load_weights=False) - prediction_heads.append(head) - ph_output_type.append(head.ph_output_type) - - with open(load_dir / "onnx_model_config.json") as f: - model_config = json.load(f) - language_model_class = model_config["language_model_class"] - language = model_config["language"] - - return cls(onnx_session, language_model_class, language, prediction_heads, device) - - def forward(self, **kwargs): - """ - Perform forward pass on the model and return the logits. - - :param kwargs: All arguments that need to be passed on to the model. - :return: All logits as torch.tensor or multiple tensors. - """ - with torch.inference_mode(): - if self.language_model_class == "Bert": - input_to_onnx = { - "input_ids": numpy.ascontiguousarray(kwargs["input_ids"].cpu().numpy()), - "attention_mask": numpy.ascontiguousarray(kwargs["padding_mask"].cpu().numpy()), - "token_type_ids": numpy.ascontiguousarray(kwargs["segment_ids"].cpu().numpy()), - } - elif self.language_model_class in ["Roberta", "XLMRoberta"]: - input_to_onnx = { - "input_ids": numpy.ascontiguousarray(kwargs["input_ids"].cpu().numpy()), - "attention_mask": numpy.ascontiguousarray(kwargs["padding_mask"].cpu().numpy()), - } - res = self.onnx_session.run(None, input_to_onnx) - res = numpy.stack(res).transpose(1, 2, 0) - logits = [torch.Tensor(res).to(self.device)] - - return logits - - def eval(self): - """ - Stub to make ONNXAdaptiveModel compatible with the PyTorch AdaptiveModel. - """ - return True - - def get_language(self): - """ - Get the language(s) the model was trained for. - :return: str - """ - return self.language - - -class ONNXWrapper(AdaptiveModel): - """ - Wrapper Class for converting PyTorch models to ONNX. - - As of torch v1.4.0, torch.onnx.export only support passing positional arguments - to the forward pass of the model. However, the AdaptiveModel's forward takes keyword arguments. - This class circumvents the issue by converting positional arguments to keyword arguments. - """ - - @classmethod - def load_from_adaptive_model(cls, adaptive_model: AdaptiveModel): - model = copy.deepcopy(adaptive_model) - model.__class__ = ONNXWrapper - return model - - def forward(self, *batch): - return super().forward(input_ids=batch[0], padding_mask=batch[1], segment_ids=batch[2]) diff --git a/haystack/modeling/model/biadaptive_model.py b/haystack/modeling/model/biadaptive_model.py deleted file mode 100644 index 3e717484d0..0000000000 --- a/haystack/modeling/model/biadaptive_model.py +++ /dev/null @@ -1,530 +0,0 @@ -from typing import List, Optional, Callable, Union, Dict - -import os -import logging -from pathlib import Path - -import torch -from torch import nn -from transformers import DPRContextEncoder, DPRQuestionEncoder, AutoModel - -from haystack.modeling.data_handler.processor import Processor -from haystack.modeling.model.language_model import get_language_model, LanguageModel -from haystack.modeling.model.prediction_head import PredictionHead, TextSimilarityHead -from haystack.utils.experiment_tracking import Tracker as tracker - - -logger = logging.getLogger(__name__) - - -def loss_per_head_sum( - loss_per_head: List[torch.Tensor], global_step: Optional[int] = None, batch: Optional[Dict] = None -): - """ - Sums up the loss of each prediction head. - - :param loss_per_head: List of losses. - """ - return sum(loss_per_head) - - -class BiAdaptiveModel(nn.Module): - """ - PyTorch implementation containing all the modelling needed for your NLP task. - Combines 2 language models for representation of 2 sequences and a prediction head. - Allows for gradient flow back to the 2 language model components. - """ - - def __init__( - self, - language_model1: LanguageModel, - language_model2: LanguageModel, - prediction_heads: List[PredictionHead], - embeds_dropout_prob: float = 0.1, - device: Optional[torch.device] = None, - lm1_output_types: Optional[Union[str, List[str]]] = None, - lm2_output_types: Optional[Union[str, List[str]]] = None, - loss_aggregation_fn: Optional[Callable] = None, - ): - """ - :param language_model1: Any model that turns token ids into vector representations. - :param language_model2: Any model that turns token ids into vector representations. - :param prediction_heads: A list of models that take 2 sequence embeddings and return logits for a given task. - :param embeds_dropout_prob: The probability that a value in the embeddings returned by any of the 2 - language models will be zeroed. - :param lm1_output_types: How to extract the embeddings from the final layer of the first language model. When set - to "per_token", one embedding will be extracted per input token. If set to - "per_sequence" (default), a single embedding will be extracted to represent the full - input sequence. Can either be a single string, or a list of strings, - one for each prediction head. - :param lm2_output_types: How to extract the embeddings from the final layer of the second language model. When set - to "per_token", one embedding will be extracted per input token. If set to - "per_sequence" (default), a single embedding will be extracted to represent the full - input sequence. Can either be a single string, or a list of strings, - one for each prediction head. - :param device: The device on which this model will operate. Either torch.device("cpu") or torch.device("cuda"). - :param loss_aggregation_fn: Function to aggregate the loss of multiple prediction heads. - Input: loss_per_head (list of tensors), global_step (int), batch (dict) - Output: aggregated loss (tensor) - Default is a simple sum: - `lambda loss_per_head, global_step=None, batch=None: sum(tensors)` - However, you can pass more complex functions that depend on the - current step (e.g. for round-robin style multitask learning) or the actual - content of the batch (e.g. certain labels) - Note: The loss at this stage is per sample, i.e one tensor of - shape (batchsize) per prediction head. - """ - if not device: - device = torch.device("cuda") - - if lm1_output_types is None: - lm1_output_types = ["per_sequence"] - if lm2_output_types is None: - lm2_output_types = ["per_sequence"] - super(BiAdaptiveModel, self).__init__() - - self.device = device - self.language_model1 = language_model1.to(device) - self.lm1_output_dims = language_model1.output_dims - self.language_model2 = language_model2.to(device) - self.lm2_output_dims = language_model2.output_dims - self.dropout1 = nn.Dropout(embeds_dropout_prob) - self.dropout2 = nn.Dropout(embeds_dropout_prob) - self.prediction_heads = nn.ModuleList([ph.to(device) for ph in prediction_heads]) - self.lm1_output_types = [lm1_output_types] if isinstance(lm1_output_types, str) else lm1_output_types - self.lm2_output_types = [lm2_output_types] if isinstance(lm2_output_types, str) else lm2_output_types - self.log_params() - # default loss aggregation function is a simple sum (without using any of the optional params) - if not loss_aggregation_fn: - loss_aggregation_fn = loss_per_head_sum - self.loss_aggregation_fn = loss_aggregation_fn - - def save(self, save_dir: Union[str, Path], lm1_name: str = "lm1", lm2_name: str = "lm2"): - """ - Saves the 2 language model weights and respective config_files in directories lm1 and lm2 within save_dir. - - :param save_dir: Path | str to save the BiAdaptiveModel to. - """ - os.makedirs(save_dir, exist_ok=True) - for name, model in zip([lm1_name, lm2_name], [self.language_model1, self.language_model2]): - model_save_dir = Path.joinpath(Path(save_dir), Path(name)) - os.makedirs(model_save_dir, exist_ok=True) - model.save(model_save_dir) - - for i, ph in enumerate(self.prediction_heads): - logger.info("prediction_head saving") - ph.save(save_dir, i) - - @classmethod - def load( - cls, - load_dir: Path, - device: torch.device, - strict: bool = False, - lm1_name: str = "lm1", - lm2_name: str = "lm2", - processor: Optional[Processor] = None, - ): - """ - Loads a BiAdaptiveModel from a directory. The directory must contain: - - * directory "lm1_name" with following files: - -> language_model.bin - -> language_model_config.json - * directory "lm2_name" with following files: - -> language_model.bin - -> language_model_config.json - * prediction_head_X.bin multiple PH possible - * prediction_head_X_config.json - * processor_config.json config for transforming input - * vocab.txt vocab file for language model, turning text to Wordpiece Token - * special_tokens_map.json - - :param load_dir: Location where adaptive model is stored. - :param device: To which device we want to sent the model, either torch.device("cpu") or torch.device("cuda"). - :param lm1_name: The name to assign to the first loaded language model (for encoding queries). - :param lm2_name: The name to assign to the second loaded language model (for encoding context/passages). - :param strict: Whether to strictly enforce that the keys loaded from saved model match the ones in - the PredictionHead (see torch.nn.module.load_state_dict()). - :param processor: Processor to populate prediction head with information coming from tasks. - """ - # Language Model - if lm1_name: - language_model1 = get_language_model(os.path.join(load_dir, lm1_name)) - else: - language_model1 = get_language_model(load_dir) - if lm2_name: - language_model2 = get_language_model(os.path.join(load_dir, lm2_name)) - else: - language_model2 = get_language_model(load_dir) - - # Prediction heads - ph_config_files = cls._get_prediction_head_files(load_dir) - prediction_heads = [] - ph_output_type = [] - for config_file in ph_config_files: - head = PredictionHead.load(config_file, strict=strict, load_weights=False) - prediction_heads.append(head) - ph_output_type.append(head.ph_output_type) - - model = cls(language_model1, language_model2, prediction_heads, 0.1, device) - if processor: - model.connect_heads_with_processor(processor.tasks) # type: ignore - - return model - - def logits_to_loss_per_head(self, logits: torch.Tensor, **kwargs): - """ - Collect losses from each prediction head. - - :param logits: Logits, can vary in shape and type, depending on task. - :return: The per sample per prediciton head loss whose first two dimensions have length n_pred_heads, batch_size. - """ - all_losses = [] - for head, logits_for_one_head in zip(self.prediction_heads, logits): - # check if PredictionHead connected to Processor - assert hasattr(head, "label_tensor_name"), ( - f"Label_tensor_names are missing inside the {head.task_name} Prediction Head. Did you connect the model" - " with the processor through either 'model.connect_heads_with_processor(processor.tasks)'" - " or by passing the processor to the Adaptive Model?" - ) - all_losses.append(head.logits_to_loss(logits=logits_for_one_head, **kwargs)) - return all_losses - - def logits_to_loss(self, logits: torch.Tensor, global_step: Optional[int] = None, **kwargs): - """ - Get losses from all prediction heads & reduce to single loss *per sample*. - - :param logits: Logits, can vary in shape and type, depending on task. - :param global_step: Number of current training step. - :param kwargs: Placeholder for passing generic parameters. - Note: Contains the batch (as dict of tensors), when called from Trainer.train(). - :return: torch.Tensor that is the per sample loss (len: batch_size). - """ - all_losses = self.logits_to_loss_per_head(logits, **kwargs) - # This aggregates the loss per sample across multiple prediction heads - # Default is sum(), but you can configure any fn that takes [Tensor, Tensor ...] and returns [Tensor] - loss = self.loss_aggregation_fn(all_losses, global_step=global_step, batch=kwargs) - return loss - - def logits_to_preds(self, logits: torch.Tensor, **kwargs): - """ - Get predictions from all prediction heads. - - :param logits: Logits, can vary in shape and type, depending on task. - :return: A list of all predictions from all prediction heads. - """ - all_preds = [] - # collect preds from all heads - for head, logits_for_head in zip(self.prediction_heads, logits): - preds = head.logits_to_preds(logits=logits_for_head, **kwargs) - all_preds.append(preds) - return all_preds - - def formatted_preds(self, logits: torch.Tensor, **kwargs): - """ - Format predictions to strings for inference output - - :param logits: Model logits. - :param kwargs: Placeholder for passing generic parameters - :return: Predictions in the right format. - """ - n_heads = len(self.prediction_heads) - - if n_heads == 1: - preds_final = [] - # This try catch is to deal with the fact that sometimes we collect preds before passing it to - # formatted_preds (see Inferencer._get_predictions_and_aggregate()) and sometimes we don't - # (see Inferencer._get_predictions()) - try: - preds = kwargs["preds"] - temp = [y[0] for y in preds] - preds_flat = [item for sublist in temp for item in sublist] - kwargs["preds"] = preds_flat - except KeyError: - kwargs["preds"] = None - head = self.prediction_heads[0] - logits_for_head = logits[0] - preds = head.formatted_preds(logits=logits_for_head, **kwargs) - # TODO This is very messy - we need better definition of what the output should look like - if type(preds) == list: - preds_final += preds - elif type(preds) == dict and "predictions" in preds: - preds_final.append(preds) - return preds_final - - def prepare_labels(self, **kwargs): - """ - Label conversion to original label space, per prediction head. - - :return: Labels in the right format. - """ - all_labels = [] - # for head, label_map_one_head in zip(self.prediction_heads): - # labels = head.prepare_labels(label_map=label_map_one_head, **kwargs) - # all_labels.append(labels) - for head in self.prediction_heads: - labels = head.prepare_labels(**kwargs) - all_labels.append(labels) - return all_labels - - def forward( - self, - query_input_ids: Optional[torch.Tensor] = None, - query_segment_ids: Optional[torch.Tensor] = None, - query_attention_mask: Optional[torch.Tensor] = None, - passage_input_ids: Optional[torch.Tensor] = None, - passage_segment_ids: Optional[torch.Tensor] = None, - passage_attention_mask: Optional[torch.Tensor] = None, - ): - """ - Push data through the whole model and returns logits. The data will propagate through - the first language model and second language model based on the tensor names and both the - encodings through each of the attached prediction heads. - - :param kwargs: Holds all arguments that need to be passed to both the language models and prediction head(s). - :return: All logits as torch.tensor or multiple tensors. - """ - - # Run forward pass of both language models - pooled_output = self.forward_lm( - query_input_ids=query_input_ids, - query_segment_ids=query_segment_ids, - query_attention_mask=query_attention_mask, - passage_input_ids=passage_input_ids, - passage_segment_ids=passage_segment_ids, - passage_attention_mask=passage_attention_mask, - ) - - # Run forward pass of (multiple) prediction heads using the output from above - all_logits = [] - if len(self.prediction_heads) > 0: - for head, lm1_out, lm2_out in zip(self.prediction_heads, self.lm1_output_types, self.lm2_output_types): - # Choose relevant vectors from LM as output and perform dropout - if pooled_output[0] is not None: - if lm1_out == "per_sequence" or lm1_out == "per_sequence_continuous": - output1 = self.dropout1(pooled_output[0]) - else: - raise ValueError( - "Unknown extraction strategy from BiAdaptive language_model1: {}".format(lm1_out) - ) - else: - output1 = None - - if pooled_output[1] is not None: - if lm2_out == "per_sequence" or lm2_out == "per_sequence_continuous": - output2 = self.dropout2(pooled_output[1]) - else: - raise ValueError( - "Unknown extraction strategy from BiAdaptive language_model2: {}".format(lm2_out) - ) - else: - output2 = None - - embedding1, embedding2 = head(output1, output2) - all_logits.append((embedding1, embedding2)) - else: - # just return LM output (e.g. useful for extracting embeddings at inference time) - all_logits.append((pooled_output)) - - return all_logits - - def forward_lm( - self, - query_input_ids: Optional[torch.Tensor] = None, - query_segment_ids: Optional[torch.Tensor] = None, - query_attention_mask: Optional[torch.Tensor] = None, - passage_input_ids: Optional[torch.Tensor] = None, - passage_segment_ids: Optional[torch.Tensor] = None, - passage_attention_mask: Optional[torch.Tensor] = None, - ): - """ - Forward pass for the BiAdaptive model. - - :param kwargs: Holds all arguments that need to be passed to the language models. - :return: 2 tensors of pooled_output from the 2 language models. - """ - pooled_output = [None, None] - - if query_input_ids is not None and query_segment_ids is not None and query_attention_mask is not None: - pooled_output1, _ = self.language_model1( - input_ids=query_input_ids, segment_ids=query_segment_ids, attention_mask=query_attention_mask - ) - pooled_output[0] = pooled_output1 - - if passage_input_ids is not None and passage_segment_ids is not None and passage_attention_mask is not None: - max_seq_len = passage_input_ids.shape[-1] - passage_input_ids = passage_input_ids.view(-1, max_seq_len) - passage_attention_mask = passage_attention_mask.view(-1, max_seq_len) - passage_segment_ids = passage_segment_ids.view(-1, max_seq_len) - - pooled_output2, _ = self.language_model2( - input_ids=passage_input_ids, segment_ids=passage_segment_ids, attention_mask=passage_attention_mask - ) - pooled_output[1] = pooled_output2 - - return tuple(pooled_output) - - def log_params(self): - """ - Logs parameters to generic logger MlLogger - """ - params = { - "lm1_type": self.language_model1.__class__.__name__, - "lm1_name": self.language_model1.name, - "lm1_output_types": ",".join(self.lm1_output_types), - "lm2_type": self.language_model2.__class__.__name__, - "lm2_name": self.language_model2.name, - "lm2_output_types": ",".join(self.lm2_output_types), - "prediction_heads": ",".join([head.__class__.__name__ for head in self.prediction_heads]), - } - try: - tracker.track_params(params) - except Exception as e: - logger.warning("ML logging didn't work: %s", e) - - def verify_vocab_size(self, vocab_size1: int, vocab_size2: int): - """ - Verifies that the model fits to the tokenizer vocabulary. - They could diverge in case of custom vocabulary added via tokenizer.add_tokens() - """ - - model1_vocab_len = self.language_model1.model.resize_token_embeddings(new_num_tokens=None).num_embeddings # type: ignore [union-attr,operator] - - msg = ( - f"Vocab size of tokenizer {vocab_size1} doesn't match with model {model1_vocab_len}. " - "If you added a custom vocabulary to the tokenizer, " - "make sure to supply 'n_added_tokens' to get_language_model() and BertStyleLM.load()" - ) - assert vocab_size1 == model1_vocab_len, msg - - model2_vocab_len = self.language_model2.model.resize_token_embeddings(new_num_tokens=None).num_embeddings # type: ignore [union-attr,operator] - - msg = ( - f"Vocab size of tokenizer {vocab_size1} doesn't match with model {model2_vocab_len}. " - "If you added a custom vocabulary to the tokenizer, " - "make sure to supply 'n_added_tokens' to get_language_model() and BertStyleLM.load()" - ) - assert vocab_size2 == model2_vocab_len, msg - - def connect_heads_with_processor(self, tasks: Dict, require_labels: bool = True): - """ - Populates prediction head with information coming from tasks. - - :param tasks: A dictionary where the keys are the names of the tasks and the values are the details of the task (e.g. label_list, metric, tensor name) - :param require_labels: If True, an error will be thrown when a task is not supplied with labels) - :return: - """ - - for head in self.prediction_heads: - head.label_tensor_name = tasks[head.task_name]["label_tensor_name"] - label_list = tasks[head.task_name]["label_list"] - if not label_list and require_labels: - raise Exception(f"The task '{head.task_name}' is missing a valid set of labels") - label_list = tasks[head.task_name]["label_list"] - head.label_list = label_list - head.metric = tasks[head.task_name]["metric"] - - def get_language(self): - return self.language_model1.language, self.language_model2.language - - @classmethod - def _get_prediction_head_files(cls, load_dir: Union[str, Path]): - load_dir = Path(load_dir) - files = os.listdir(load_dir) - config_files = [load_dir / f for f in files if "config.json" in f and "prediction_head" in f] - # sort them to get correct order in case of multiple prediction heads - config_files.sort() - return config_files - - def convert_to_transformers(self): - if len(self.prediction_heads) != 1: - raise ValueError( - f"Currently conversion only works for models with a SINGLE prediction head. " - f"Your model has {len(self.prediction_heads)}" - ) - - if self.prediction_heads[0].model_type == "text_similarity": - # init model - if "dpr" in self.language_model1.model.config.model_type: - transformers_model1 = DPRQuestionEncoder(config=self.language_model1.model.config) - else: - transformers_model1 = AutoModel.from_config(config=self.language_model1.model.config) - if "dpr" in self.language_model2.model.config.model_type: - transformers_model2 = DPRContextEncoder(config=self.language_model2.model.config) - else: - transformers_model2 = AutoModel.from_config(config=self.language_model2.model.config) - - # transfer weights for language model + prediction head - setattr(transformers_model1, transformers_model1.base_model_prefix, self.language_model1.model) - setattr(transformers_model2, transformers_model2.base_model_prefix, self.language_model2.model) - logger.warning("No prediction head weights are required for DPR") - - else: - raise NotImplementedError( - f"Haystack -> Transformers conversion is not supported yet for" - f" prediction heads of type {self.prediction_heads[0].model_type}" - ) - pass - - return transformers_model1, transformers_model2 - - @classmethod - def convert_from_transformers( - cls, - model_name_or_path1: Union[str, Path], - model_name_or_path2: Union[str, Path], - device: torch.device, - task_type: str = "text_similarity", - processor: Optional[Processor] = None, - similarity_function: str = "dot_product", - use_auth_token: Optional[Union[str, bool]] = None, - ): - """ - Load a (downstream) model from huggingface's transformers format. Use cases: - - continue training in Haystack (e.g. take a squad QA model and fine-tune on your own data) - - compare models without switching frameworks - - use model directly for inference - - :param model_name_or_path1: local path of a saved model or name of a public one for Question Encoder - Exemplary public names: - - facebook/dpr-question_encoder-single-nq-base - - deepset/bert-large-uncased-whole-word-masking-squad2 - :param model_name_or_path2: local path of a saved model or name of a public one for Context/Passage Encoder - Exemplary public names: - - facebook/dpr-ctx_encoder-single-nq-base - - deepset/bert-large-uncased-whole-word-masking-squad2 - :param device: On which hardware the conversion is going to run on. Either torch.device("cpu") or torch.device("cuda") - :param task_type: 'text_similarity' More tasks coming soon ... - :param processor: populates prediction head with information coming from tasks - :type processor: Processor - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :return: AdaptiveModel - """ - lm1 = get_language_model(pretrained_model_name_or_path=model_name_or_path1, use_auth_token=use_auth_token) - lm2 = get_language_model(pretrained_model_name_or_path=model_name_or_path2, use_auth_token=use_auth_token) - prediction_head = TextSimilarityHead(similarity_function=similarity_function) - # TODO Infer type of head automatically from config - if task_type == "text_similarity": - bi_adaptive_model = cls( - language_model1=lm1, - language_model2=lm2, - prediction_heads=[prediction_head], - embeds_dropout_prob=0.1, - lm1_output_types=["per_sequence"], - lm2_output_types=["per_sequence"], - device=device, - ) - else: - raise NotImplementedError( - f"Huggingface's transformer models of type {task_type} are not supported yet for BiAdaptive Models" - ) - - if processor: - bi_adaptive_model.connect_heads_with_processor(processor.tasks) # type: ignore - - return bi_adaptive_model diff --git a/haystack/modeling/model/feature_extraction.py b/haystack/modeling/model/feature_extraction.py deleted file mode 100644 index 6b7508a84a..0000000000 --- a/haystack/modeling/model/feature_extraction.py +++ /dev/null @@ -1,399 +0,0 @@ -# coding=utf-8 -# Copyright 2018 deepset team. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import Dict, Any, Union, Tuple, Optional, List - -import re -import os -import json -import logging -from pathlib import Path - -import numpy as np -from haystack.errors import ModelingError -from haystack.modeling.data_handler.samples import SampleBasket -from haystack.lazy_imports import LazyImport - -logger = logging.getLogger(__name__) - -#: Special characters used by the different tokenizers to indicate start of word / whitespace -SPECIAL_TOKENIZER_CHARS = r"^(##|Ġ|▁)" - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as transformers_import: - import transformers - from transformers import PreTrainedTokenizer, RobertaTokenizer, AutoConfig, AutoFeatureExtractor, AutoTokenizer - - # NOTE: These two constants are internals of HF. Keep in mind that they might be renamed or removed at any time. - from transformers.models.auto.feature_extraction_auto import FEATURE_EXTRACTOR_MAPPING_NAMES - from transformers.models.auto.tokenization_auto import TOKENIZER_MAPPING_NAMES - - FEATURE_EXTRACTORS = { - **{key: AutoTokenizer for key in TOKENIZER_MAPPING_NAMES.keys()}, - **{key: AutoFeatureExtractor for key in FEATURE_EXTRACTOR_MAPPING_NAMES.keys()}, - } - - DEFAULT_EXTRACTION_PARAMS = { - AutoTokenizer: { - "max_length": 256, - "add_special_tokens": True, - "truncation": True, - "truncation_strategy": "longest_first", - "padding": "max_length", - "return_token_type_ids": True, - }, - AutoFeatureExtractor: {"return_tensors": "pt"}, - } - - -class FeatureExtractor: - def __init__( - self, - pretrained_model_name_or_path: Union[str, Path], - revision: Optional[str] = None, - use_fast: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - **kwargs, - ): - """ - Enables loading of different feature extractors, including tokenizers, with a uniform interface. - - Use `FeatureExtractor.extract_features()` to convert your input queries, documents, images, and tables - into vectors that you can pass to the language model. - - :param pretrained_model_name_or_path: The path of the saved pretrained model or its name (for example, `bert-base-uncased`) - :param revision: The version of the model to use from the Hugging Face model hub. It can be tag name, branch name, or commit hash. - :param use_fast: Indicate if Haystack should try to load the fast version of the tokenizer (True) or use the Python one (False). Defaults to True. - :param use_auth_token: The API token used to download private models from Hugging Face. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) is used. - For more information, see - [Hugging Face documentation](https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained) - :param kwargs: Other kwargs you want to pass on to `PretrainedTokenizer.from_pretrained()` - """ - transformers_import.check() - - model_name_or_path = str(pretrained_model_name_or_path) - model_type = None - - config_file = Path(pretrained_model_name_or_path) / "tokenizer_config.json" - if os.path.exists(config_file): - # it's a local directory - with open(config_file) as f: - config = json.load(f) - feature_extractor_classname = config["tokenizer_class"] - logger.debug("⛏️ Selected feature extractor: %s (from %s)", feature_extractor_classname, config_file) - # Use FastTokenizers as much as possible - try: - feature_extractor_class = getattr(transformers, feature_extractor_classname + "Fast") - logger.debug( - "Fast version of this tokenizer exists. Loaded class: %s", - feature_extractor_class.__class__.__name__, - ) - except AttributeError: - logger.debug("Fast version could not be loaded. Falling back to base version.") - feature_extractor_class = getattr(transformers, feature_extractor_classname) - - else: - # it's a HF Hub identifier - config = AutoConfig.from_pretrained( - pretrained_model_name_or_path=model_name_or_path, use_auth_token=use_auth_token, revision=revision - ) - model_type = config.model_type - try: - feature_extractor_class = FEATURE_EXTRACTORS[model_type] - except KeyError as e: - raise ModelingError( - f"'{pretrained_model_name_or_path}' has no known feature extractor. " - "Haystack can assign tokenizers to the following model types: " - # Using chr(10) instead of \n due to f-string limitation - # https://peps.python.org/pep-0498/#specification: "Backslashes may not appear anywhere within expressions" - f"\n- {f'{chr(10)}- '.join(FEATURE_EXTRACTORS.keys())}" - ) from e - logger.debug( - "⛏️ Selected feature extractor: %s (for model type '%s')", feature_extractor_class.__name__, model_type - ) - - self.default_params = DEFAULT_EXTRACTION_PARAMS.get(feature_extractor_class, {}) - - self.feature_extractor = feature_extractor_class.from_pretrained( - pretrained_model_name_or_path=model_name_or_path, - revision=revision, - use_fast=use_fast, - use_auth_token=use_auth_token, - **kwargs, - ) - - def __call__(self, **kwargs): - params = {**self.default_params, **(kwargs or {})} - return self.feature_extractor(**params) - - -def tokenize_batch_question_answering( - pre_baskets: List[Dict[str, Any]], tokenizer: PreTrainedTokenizer, indices: List[Any] -) -> List[SampleBasket]: - """ - Tokenizes text data for question answering tasks. Tokenization means splitting words into subwords, depending on the - tokenizer's vocabulary. - - - We first tokenize all documents in batch mode. (When using FastTokenizers Rust multithreading can be enabled by TODO add how to enable rust mt) - - Then we tokenize each question individually - - We construct dicts with question and corresponding document text + tokens + offsets + ids - - :param pre_baskets: input dicts with QA info #TODO change to input objects - :param tokenizer: tokenizer to be used - :param indices: indices used during multiprocessing so that IDs assigned to our baskets are unique - :return: baskets, list containing question and corresponding document information - """ - if not len(indices) == len(pre_baskets): - raise ValueError("indices and pre_baskets must have the same length") - - if not tokenizer.is_fast: - raise ModelingError( - "Processing QA data is only supported with fast tokenizers for now." - "Please load Tokenizers with 'use_fast=True' option." - ) - - baskets = [] - # # Tokenize texts in batch mode - texts = [d["context"] for d in pre_baskets] - tokenized_docs_batch = tokenizer( - text=texts, - return_offsets_mapping=True, - return_special_tokens_mask=True, - add_special_tokens=False, - verbose=False, - ) - - # Extract relevant data - tokenids_batch = tokenized_docs_batch["input_ids"] - offsets_batch = [] - for o in tokenized_docs_batch["offset_mapping"]: - offsets_batch.append(np.asarray([x[0] for x in o], dtype=np.int32)) - start_of_words_batch = [] - for e in tokenized_docs_batch.encodings: - start_of_words_batch.append(_get_start_of_word_QA(e.word_ids)) - - for i_doc, d in enumerate(pre_baskets): - document_text = d["context"] - # # Tokenize questions one by one - for i_q, q in enumerate(d["qas"]): - question_text = q["question"] - tokenized_q = tokenizer( - question_text, return_offsets_mapping=True, return_special_tokens_mask=True, add_special_tokens=False - ) - - # Extract relevant data - question_tokenids = tokenized_q["input_ids"] - question_offsets = [x[0] for x in tokenized_q["offset_mapping"]] - question_sow = _get_start_of_word_QA(tokenized_q.encodings[0].word_ids) - - external_id = q["id"] - # The internal_id depends on unique ids created for each process before forking - internal_id = f"{indices[i_doc]}-{i_q}" - raw = { - "document_text": document_text, - "document_tokens": tokenids_batch[i_doc], - "document_offsets": offsets_batch[i_doc], - "document_start_of_word": start_of_words_batch[i_doc], - "question_text": question_text, - "question_tokens": question_tokenids, - "question_offsets": question_offsets, - "question_start_of_word": question_sow, - "answers": q["answers"], - } - # TODO add only during debug mode (need to create debug mode) - raw["document_tokens_strings"] = tokenized_docs_batch.encodings[i_doc].tokens - raw["question_tokens_strings"] = tokenized_q.encodings[0].tokens - - baskets.append(SampleBasket(raw=raw, id_internal=internal_id, id_external=external_id, samples=None)) - return baskets - - -def _get_start_of_word_QA(word_ids): - return [1] + list(np.ediff1d(np.asarray(word_ids, dtype=np.int32))) - - -def truncate_sequences( - seq_a: list, - seq_b: Optional[list], - tokenizer: AutoTokenizer, - max_seq_len: int, - truncation_strategy: str = "longest_first", - with_special_tokens: bool = True, - stride: int = 0, -) -> Tuple[List[Any], Optional[List[Any]], List[Any]]: - """ - Reduces a single sequence or a pair of sequences to a maximum sequence length. - The sequences can contain tokens or any other elements (offsets, masks ...). - If `with_special_tokens` is enabled, it'll remove some additional tokens to have exactly - enough space for later adding special tokens (CLS, SEP etc.) - - Supported truncation strategies: - - - longest_first: (default) Iteratively reduce the inputs sequence until the input is under - max_length starting from the longest one at each token (when there is a pair of input sequences). - Overflowing tokens only contains overflow from the first sequence. - - only_first: Only truncate the first sequence. raise an error if the first sequence is - shorter or equal to than num_tokens_to_remove. - - only_second: Only truncate the second sequence - - do_not_truncate: Does not truncate (raise an error if the input sequence is longer than max_length) - - :param seq_a: First sequence of tokens/offsets/... - :param seq_b: Optional second sequence of tokens/offsets/... - :param tokenizer: Tokenizer (e.g. from get_tokenizer)) - :param max_seq_len: - :param truncation_strategy: how the sequence(s) should be truncated down. - Default: "longest_first" (see above for other options). - :param with_special_tokens: If true, it'll remove some additional tokens to have exactly enough space - for later adding special tokens (CLS, SEP etc.) - :param stride: optional stride of the window during truncation - :return: truncated seq_a, truncated seq_b, overflowing tokens - """ - pair = seq_b is not None - len_a = len(seq_a) - len_b = len(seq_b) if seq_b is not None else 0 - num_special_tokens = tokenizer.num_special_tokens_to_add(pair=pair) if with_special_tokens else 0 - total_len = len_a + len_b + num_special_tokens - overflowing_tokens = [] - - if max_seq_len and total_len > max_seq_len: - seq_a, seq_b, overflowing_tokens = tokenizer.truncate_sequences( - seq_a, - pair_ids=seq_b, - num_tokens_to_remove=total_len - max_seq_len, - truncation_strategy=truncation_strategy, - stride=stride, - ) - return (seq_a, seq_b, overflowing_tokens) - - -# -# FIXME this is a relic from FARM. If there's the occasion, remove it! -# -def tokenize_with_metadata(text: str, tokenizer: PreTrainedTokenizer) -> Dict[str, Any]: - """ - Performing tokenization while storing some important metadata for each token: - - * offsets: (int) Character index where the token begins in the original text - * start_of_word: (bool) If the token is the start of a word. Particularly helpful for NER and QA tasks. - - We do this by first doing whitespace tokenization and then applying the model specific tokenizer to each "word". - - .. note:: We don't assume to preserve exact whitespaces in the tokens! - This means: tabs, new lines, multiple whitespace etc will all resolve to a single " ". - This doesn't make a difference for BERT + XLNet but it does for RoBERTa. - For RoBERTa it has the positive effect of a shorter sequence length, but some information about whitespace - type is lost which might be helpful for certain NLP tasks ( e.g tab for tables). - - :param text: Text to tokenize - :param tokenizer: Tokenizer (e.g. from get_tokenizer)) - :return: Dictionary with "tokens", "offsets" and "start_of_word" - """ - # normalize all other whitespace characters to " " - # Note: using text.split() directly would destroy the offset, - # since \n\n\n would be treated similarly as a single \n - text = re.sub(r"\s", " ", text) - - words: Union[List[str], np.ndarray] = [] - word_offsets: Union[List[int], np.ndarray] = [] - start_of_word: List[Union[int, bool]] = [] - - # Fast Tokenizers return offsets, so we don't need to calculate them ourselves - if tokenizer.is_fast: - # tokenized = tokenizer(text, return_offsets_mapping=True, return_special_tokens_mask=True) - tokenized = tokenizer(text, return_offsets_mapping=True, return_special_tokens_mask=True) - - tokens = tokenized["input_ids"] - offsets = np.array([x[0] for x in tokenized["offset_mapping"]]) - # offsets2 = [x[0] for x in tokenized2["offset_mapping"]] - words = np.array(tokenized.encodings[0].words) - - # TODO check for validity for all tokenizer and special token types - words[0] = -1 - words[-1] = words[-2] - words += 1 - start_of_word = [0] + list(np.ediff1d(words)) - return {"tokens": tokens, "offsets": offsets, "start_of_word": start_of_word} - - # split text into "words" (here: simple whitespace tokenizer). - words = text.split(" ") - cumulated = 0 - for word in words: - word_offsets.append(cumulated) # type: ignore [union-attr] - cumulated += len(word) + 1 # 1 because we so far have whitespace tokenizer - - # split "words" into "subword tokens" - tokens, offsets, start_of_word = _words_to_tokens(words, word_offsets, tokenizer) # type: ignore - return {"tokens": tokens, "offsets": offsets, "start_of_word": start_of_word} - - -# Note: only used by tokenize_with_metadata() -def _words_to_tokens( - words: List[str], word_offsets: List[int], tokenizer: PreTrainedTokenizer -) -> Tuple[List[str], List[int], List[bool]]: - """ - Tokenize "words" into subword tokens while keeping track of offsets and if a token is the start of a word. - :param words: list of words. - :param word_offsets: Character indices where each word begins in the original text - :param tokenizer: Tokenizer (e.g. from get_tokenizer)) - :return: Tuple of (tokens, offsets, start_of_word) - """ - tokens: List[str] = [] - token_offsets: List[int] = [] - start_of_word: List[bool] = [] - index = 0 - for index, (word, word_offset) in enumerate(zip(words, word_offsets)): - if index % 500000 == 0: - logger.info(index) - # Get (subword) tokens of single word. - - # empty / pure whitespace - if len(word) == 0: - continue - # For the first word of a text: we just call the regular tokenize function. - # For later words: we need to call it with add_prefix_space=True to get the same results with roberta / gpt2 tokenizer - # see discussion here. https://github.com/huggingface/transformers/issues/1196 - if len(tokens) == 0: - tokens_word = tokenizer.tokenize(word) - else: - if type(tokenizer) == RobertaTokenizer: - tokens_word = tokenizer.tokenize(word, add_prefix_space=True) - else: - tokens_word = tokenizer.tokenize(word) - # Sometimes the tokenizer returns no tokens - if len(tokens_word) == 0: - continue - tokens += tokens_word - - # get global offset for each token in word + save marker for first tokens of a word - first_token = True - for token in tokens_word: - token_offsets.append(word_offset) - # Depending on the tokenizer type special chars are added to distinguish tokens with preceding - # whitespace (=> "start of a word"). We need to get rid of these to calculate the original length of the token - original_token = re.sub(SPECIAL_TOKENIZER_CHARS, "", token) - # Don't use length of unk token for offset calculation - if original_token == tokenizer.special_tokens_map["unk_token"]: - word_offset += 1 - else: - word_offset += len(original_token) - if first_token: - start_of_word.append(True) - first_token = False - else: - start_of_word.append(False) - - return tokens, token_offsets, start_of_word diff --git a/haystack/modeling/model/language_model.py b/haystack/modeling/model/language_model.py deleted file mode 100644 index e1f4028eba..0000000000 --- a/haystack/modeling/model/language_model.py +++ /dev/null @@ -1,974 +0,0 @@ -# coding=utf-8 -# Copyright 2018 The Google AI Language Team Authors, The HuggingFace Inc. Team and deepset Team. -# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Acknowledgements: Many of the modeling parts here come from the great transformers repository: https://github.com/huggingface/transformers. -Thanks for the great work! -""" - -from typing import Type, Optional, Dict, Any, Union, List - -import re -import json -import logging -import os -from abc import ABC, abstractmethod -from pathlib import Path -import numpy as np -import torch -from torch import nn -import transformers -from transformers import PretrainedConfig, PreTrainedModel -from transformers import AutoModel, AutoConfig -from transformers.modeling_utils import SequenceSummary - -from haystack.errors import ModelingError -from haystack.modeling.utils import silence_transformers_logs - - -logger = logging.getLogger(__name__) - - -LANGUAGE_HINTS = ( - ("german", "german"), - ("english", "english"), - ("chinese", "chinese"), - ("indian", "indian"), - ("french", "french"), - ("camembert", "french"), - ("polish", "polish"), - ("spanish", "spanish"), - ("umberto", "italian"), - ("multilingual", "multilingual"), -) - -#: Names of the attributes in various model configs which refer to the number of dimensions in the output vectors -OUTPUT_DIM_NAMES = ["dim", "hidden_size", "d_model"] - - -# TODO analyse if LMs can be completely used through HF transformers -class LanguageModel(nn.Module, ABC): - """ - The parent class for any kind of model that can embed language into a semantic vector space. - These models read in tokenized sentences and return vectors that capture the meaning of sentences or of tokens. - """ - - def __init__(self, model_type: str): - super().__init__() - self._output_dims = None - self.name = model_type - - @property - def encoder(self): - return self.model.encoder - - @abstractmethod - def forward( - self, - input_ids: torch.Tensor, - attention_mask: torch.Tensor, - segment_ids: Optional[torch.Tensor], # DistilBERT does not use them, see DistilBERTLanguageModel - output_hidden_states: Optional[bool] = None, - output_attentions: Optional[bool] = None, - return_dict: bool = False, - ): - raise NotImplementedError - - @property - def output_hidden_states(self): - """ - Controls whether the model outputs the hidden states or not - """ - self.encoder.config.output_hidden_states = True - - @output_hidden_states.setter - def output_hidden_states(self, value: bool): - """ - Sets the model to output the hidden states or not - """ - self.encoder.config.output_hidden_states = value - - @property - def output_dims(self): - """ - The output dimension of this language model - """ - if self._output_dims: - return self._output_dims - - try: - for odn in OUTPUT_DIM_NAMES: - value = getattr(self.model.config, odn, None) - if value: - self._output_dims = value - return value - except AttributeError: - raise ModelingError("Can't get the output dimension before loading the model.") - - raise ModelingError("Could not infer the output dimensions of the language model.") - - def save_config(self, save_dir: Union[Path, str]): - """ - Save the configuration of the language model in Haystack format. - """ - save_filename = Path(save_dir) / "language_model_config.json" - setattr(self.model.config, "name", self.name) # type: ignore [union-attr] - setattr(self.model.config, "language", self.language) # type: ignore [union-attr] - - string = self.model.config.to_json_string() # type: ignore [union-attr,operator] - with open(save_filename, "w") as file: - file.write(string) - - def save(self, save_dir: Union[str, Path], state_dict: Optional[Dict[Any, Any]] = None): - """ - Save the model `state_dict` and its configuration file so that it can be loaded again. - - :param save_dir: The directory in which the model should be saved. - :param state_dict: A dictionary containing the whole state of the module, including names of layers. By default, the unchanged state dictionary of the module is used. - """ - # Save Weights - save_name = Path(save_dir) / "language_model.bin" - model_to_save = self.model.module if hasattr(self.model, "module") else self.model # Only save the model itself - - if not state_dict: - state_dict = model_to_save.state_dict() # type: ignore [union-attr] - torch.save(state_dict, save_name) - self.save_config(save_dir) - - def formatted_preds( - self, logits, samples, ignore_first_token: bool = True, padding_mask: Optional[torch.Tensor] = None - ) -> List[Dict[str, Any]]: - """ - Extracting vectors from a language model (for example, for extracting sentence embeddings). - You can use different pooling strategies and layers by specifying them in the object attributes - `extraction_layer` and `extraction_strategy`. You should set both these attributes using the Inferencer: - Example: Inferencer(extraction_strategy='cls_token', extraction_layer=-1) - - :param logits: Tuple of (sequence_output, pooled_output) from the language model. - Sequence_output: one vector per token, pooled_output: one vector for whole sequence. - :param samples: For each item in logits, we need additional meta information to format the prediction (for example, input text). - This is created by the Processor and passed in here from the Inferencer. - :param ignore_first_token: When set to `True`, includes the first token for pooling operations (for example, reduce_mean). - Many models use a special token, like [CLS], that you don't want to include in your average of token embeddings. - :param padding_mask: Mask for the padding tokens. These aren't included in the pooling operations to prevent a bias by the number of padding tokens. - :param input_ids: IDs of the tokens in the vocabulary. - :param kwargs: kwargs - :return: A list of dictionaries containing predictions, for example: [{"context": "some text", "vec": [-0.01, 0.5 ...]}]. - """ - if not hasattr(self, "extraction_layer") or not hasattr(self, "extraction_strategy"): - raise ModelingError( - "`extraction_layer` or `extraction_strategy` not specified for LM. " - "Make sure to set both, e.g. via Inferencer(extraction_strategy='cls_token', extraction_layer=-1)`" - ) - - # unpack the tuple from LM forward pass - sequence_output = logits[0][0] - pooled_output = logits[0][1] - - # aggregate vectors - if self.extraction_strategy == "pooled": - if self.extraction_layer != -1: - raise ModelingError( - f"Pooled output only works for the last layer, but got extraction_layer={self.extraction_layer}. " - "Please set `extraction_layer=-1`" - ) - vecs = pooled_output.cpu().numpy() - - elif self.extraction_strategy == "per_token": - vecs = sequence_output.cpu().numpy() - - elif self.extraction_strategy in ("reduce_mean", "reduce_max"): - vecs = self._pool_tokens( - sequence_output, padding_mask, self.extraction_strategy, ignore_first_token=ignore_first_token # type: ignore [arg-type] # type: ignore [arg-type] - ) - elif self.extraction_strategy == "cls_token": - vecs = sequence_output[:, 0, :].cpu().numpy() - else: - raise NotImplementedError( - f"This extraction strategy ({self.extraction_strategy}) is not supported by Haystack." - ) - - preds = [] - for vec, sample in zip(vecs, samples): - pred = {} - pred["context"] = sample.clear_text["text"] - pred["vec"] = vec - preds.append(pred) - return preds - - def _pool_tokens( - self, sequence_output: torch.Tensor, padding_mask: torch.Tensor, strategy: str, ignore_first_token: bool - ): - token_vecs = sequence_output.cpu().numpy() - # we only take the aggregated value of non-padding tokens - padding_mask = padding_mask.cpu().numpy() - ignore_mask_2d = padding_mask == 0 - # sometimes we want to exclude the CLS token as well from our aggregation operation - if ignore_first_token: - ignore_mask_2d[:, 0] = True - ignore_mask_3d = np.zeros(token_vecs.shape, dtype=bool) - ignore_mask_3d[:, :, :] = ignore_mask_2d[:, :, np.newaxis] - if strategy == "reduce_max": - pooled_vecs = np.ma.array(data=token_vecs, mask=ignore_mask_3d).max(axis=1).data - if strategy == "reduce_mean": - pooled_vecs = np.ma.array(data=token_vecs, mask=ignore_mask_3d).mean(axis=1).data - - return pooled_vecs - - -class HFLanguageModel(LanguageModel): - """ - A model that wraps Hugging Face's implementation - (https://github.com/huggingface/transformers) to fit the LanguageModel class. - """ - - @silence_transformers_logs - def __init__( - self, - pretrained_model_name_or_path: Union[Path, str], - model_type: str, - language: Optional[str] = None, - n_added_tokens: int = 0, - use_auth_token: Optional[Union[str, bool]] = None, - model_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - Load a pretrained model by supplying one of the following: - - * The name of a remote model on s3 (for example, "bert-base-cased"). - * A local path of a model trained using transformers (for example, "some_dir/huggingface_model"). - * A local path of a model trained using Haystack (for example, "some_dir/haystack_model"). - - You can also use `get_language_model()` for a uniform interface across different model types. - - :param pretrained_model_name_or_path: The path of the saved pretrained model or the name of the model. - :param model_type: the HuggingFace class name prefix (for example 'Bert', 'Roberta', etc...) - :param language: the model's language ('multilingual' is also accepted) - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - super().__init__(model_type=model_type) - - config_class: PretrainedConfig = getattr(transformers, model_type + "Config", None) - model_class: PreTrainedModel = getattr(transformers, model_type + "Model", None) - - haystack_lm_config = Path(pretrained_model_name_or_path) / "language_model_config.json" - if os.path.exists(haystack_lm_config): - # Haystack style - haystack_lm_model = Path(pretrained_model_name_or_path) / "language_model.bin" - model_config = config_class.from_pretrained(haystack_lm_config, use_auth_token=use_auth_token) - self.model = model_class.from_pretrained( - haystack_lm_model, config=model_config, use_auth_token=use_auth_token, **(model_kwargs or {}) - ) - self.language = self.model.config.language - else: - # Pytorch-transformer Style - self.model = model_class.from_pretrained( - str(pretrained_model_name_or_path), use_auth_token=use_auth_token, **(model_kwargs or {}) - ) - self.language = language or _guess_language(str(pretrained_model_name_or_path)) - - # resize embeddings in case of custom vocab - if n_added_tokens != 0: - # TODO verify for other models than BERT - model_emb_size = self.model.resize_token_embeddings(new_num_tokens=None).num_embeddings - vocab_size = model_emb_size + n_added_tokens - logger.info( - "Resizing embedding layer of LM from %s to %s to cope with custom vocab.", model_emb_size, vocab_size - ) - self.model.resize_token_embeddings(vocab_size) - # verify - model_emb_size = self.model.resize_token_embeddings(new_num_tokens=None).num_embeddings - assert vocab_size == model_emb_size - - def forward( # type: ignore [override] - self, - input_ids: torch.Tensor, - attention_mask: torch.Tensor, - segment_ids: torch.Tensor, - output_hidden_states: Optional[bool] = None, - output_attentions: Optional[bool] = None, - return_dict: bool = False, - ): - """ - Perform the forward pass of the model. - - :param input_ids: The IDs of each token in the input sequence. It's a tensor of shape [batch_size, max_seq_len]. - :param segment_ids: The ID of the segment. For example, in next sentence prediction, the tokens in the - first sentence are marked with 0 and the tokens in the second sentence are marked with 1. - It is a tensor of shape [batch_size, max_seq_len]. - :param attention_mask: A mask that assigns 1 to valid input tokens and 0 to padding tokens - of shape [batch_size, max_seq_len]. Different models call this parameter differently (padding/attention mask). - :param output_hidden_states: When set to `True`, outputs hidden states in addition to the embeddings. - :param output_attentions: When set to `True`, outputs attentions in addition to the embeddings. - :return: Embeddings for each token in the input sequence. Can also return hidden states and attentions if specified using the arguments `output_hidden_states` and `output_attentions`. - """ - if hasattr(self, "encoder"): # Not all models have an encoder - if output_hidden_states is None: - output_hidden_states = self.model.encoder.config.output_hidden_states - if output_attentions is None: - output_attentions = self.model.encoder.config.output_attentions - - params = {} - if input_ids is not None: - params["input_ids"] = input_ids - if segment_ids is not None: - # Some models don't take this (see DistilBERT) - params["token_type_ids"] = segment_ids - if attention_mask is not None: - params["attention_mask"] = attention_mask - if output_hidden_states: - params["output_hidden_states"] = output_hidden_states # type: ignore [assignment] - if output_attentions: - params["output_attentions"] = output_attentions # type: ignore [assignment] - - return self.model(**params, return_dict=return_dict) - - -class HFLanguageModelWithPooler(HFLanguageModel): - """ - A model that wraps Hugging Face's implementation - (https://github.com/huggingface/transformers) to fit the LanguageModel class, - with an extra pooler. - - NOTE: - - Unlike the other BERT variants, these don't output the `pooled_output`. An additional pooler is initialized. - """ - - def __init__( - self, - pretrained_model_name_or_path: Union[Path, str], - model_type: str, - language: Optional[str] = None, - n_added_tokens: int = 0, - use_auth_token: Optional[Union[str, bool]] = None, - model_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - Load a pretrained model by supplying one of the following: - - * The name of a remote model on s3 (for example, "distilbert-base-german-cased") - * A local path of a model trained using transformers (for example, "some_dir/huggingface_model") - * A local path of a model trained using Haystack (for example, "some_dir/haystack_model") - - :param pretrained_model_name_or_path: The path of the saved pretrained model or its name. - :param model_type: the HuggingFace class name prefix (for example 'DebertaV2', 'Electra', etc...) - :param language: the model's language ('multilingual' is also accepted) - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - super().__init__( - pretrained_model_name_or_path=pretrained_model_name_or_path, - model_type=model_type, - language=language, - n_added_tokens=n_added_tokens, - use_auth_token=use_auth_token, - model_kwargs=model_kwargs, - ) - config = self.model.config - - # These models do not provide a pooled_output by default. Therefore, we need to initialize an extra pooler. - # The pooler takes the first hidden representation & feeds it to a dense layer of (hidden_dim x hidden_dim). - # We don't want a dropout in the end of the pooler, since we do that already in the adaptive model before we - # feed everything to the prediction head - sequence_summary_config = POOLER_PARAMETERS.get(self.name.lower(), {}) - for key, value in sequence_summary_config.items(): - setattr(config, key, value) - - self.pooler = SequenceSummary(config) - self.pooler.apply(self.model._init_weights) - - def forward( - self, - input_ids: torch.Tensor, - attention_mask: torch.Tensor, - segment_ids: Optional[torch.Tensor], - output_hidden_states: Optional[bool] = None, - output_attentions: Optional[bool] = None, - return_dict: bool = False, - ): - """ - Perform the forward pass of the model. - - :param input_ids: The IDs of each token in the input sequence. It's a tensor of shape [batch_size, max_seq_len]. - :param segment_ids: The ID of the segment. For example, in next sentence prediction, the tokens in the - first sentence are marked with 0 and the tokens in the second sentence are marked with 1. - It is a tensor of shape [batch_size, max_seq_len]. Optional, some models don't need it (DistilBERT for example) - :param padding_mask/attention_mask: A mask that assigns 1 to valid input tokens and 0 to padding tokens - of shape [batch_size, max_seq_len]. Different models call this parameter differently (padding/attention mask). - :param output_hidden_states: When set to `True`, outputs hidden states in addition to the embeddings. - :param output_attentions: When set to `True`, outputs attentions in addition to the embeddings. - :return: Embeddings for each token in the input sequence. - """ - output_tuple = super().forward( - input_ids=input_ids, - segment_ids=segment_ids, # type: ignore [arg-type] - attention_mask=attention_mask, - output_hidden_states=output_hidden_states, - output_attentions=output_attentions, - return_dict=return_dict, - ) - pooled_output = self.pooler(output_tuple[0]) - return (output_tuple[0], pooled_output) + output_tuple[1:] - - -class HFLanguageModelNoSegmentIds(HFLanguageModelWithPooler): - """ - A model that wraps Hugging Face's implementation of a model that does not need segment ids. - (https://github.com/huggingface/transformers) to fit the LanguageModel class. - - These are for now kept in a separate subclass to show a proper warning. - """ - - def forward( - self, - input_ids: torch.Tensor, - attention_mask: torch.Tensor, - segment_ids: Optional[torch.Tensor] = None, - output_hidden_states: Optional[bool] = None, - output_attentions: Optional[bool] = None, - return_dict: bool = False, - ): - """ - Perform the forward pass of the model. - - :param input_ids: The IDs of each token in the input sequence. It's a tensor of shape [batch_size, max_seq_len]. - :param attention_mask: A mask that assigns 1 to valid input tokens and 0 to padding tokens - of shape [batch_size, max_seq_len]. Different models call this parameter differently (padding/attention mask). - :param segment_ids: Unused. See DistilBERT documentation. - :param output_hidden_states: When set to `True`, outputs hidden states in addition to the embeddings. - :param output_attentions: When set to `True`, outputs attentions in addition to the embeddings. - :return: Embeddings for each token in the input sequence. Can also return hidden states and attentions if - specified using the arguments `output_hidden_states` and `output_attentions`. - """ - if segment_ids is not None: - logger.warning("'segment_ids' is not None, but %s does not use them. They will be ignored.", self.name) - - return super().forward( - input_ids=input_ids, - segment_ids=None, - attention_mask=attention_mask, - output_hidden_states=output_hidden_states, - output_attentions=output_attentions, - return_dict=return_dict, - ) - - -class DPREncoder(LanguageModel): - """ - A DPREncoder model that wraps Hugging Face's implementation. - """ - - @silence_transformers_logs - def __init__( - self, - pretrained_model_name_or_path: Union[Path, str], - model_type: str, - language: Optional[str] = None, - n_added_tokens: int = 0, - use_auth_token: Optional[Union[str, bool]] = None, - model_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - Load a pretrained model by supplying one of the following: - * The name of a remote model on s3 (for example, "facebook/dpr-question_encoder-single-nq-base"). - * A local path of a model trained using transformers (for example, "some_dir/huggingface_model"). - * A local path of a model trained using Haystack (for example, "some_dir/haystack_model"). - - :param pretrained_model_name_or_path: The path of the base pretrained language model whose weights are used to initialize DPRQuestionEncoder. - :param model_type: the type of model (see `HUGGINGFACE_TO_HAYSTACK`) - :param language: the model's language. If not given, it will be inferred. Defaults to english. - :param n_added_tokens: unused for `DPREncoder` - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param model_kwargs: any kwarg to pass to the model at init - """ - super().__init__(model_type=model_type) - self.role = "question" if "question" in model_type.lower() else "context" - self._encoder = None - - model_classname = f"DPR{self.role.capitalize()}Encoder" - try: - model_class: Type[PreTrainedModel] = getattr(transformers, model_classname) - except AttributeError: - raise ModelingError(f"Model class of type '{model_classname}' not found.") - - haystack_lm_config = Path(pretrained_model_name_or_path) / "language_model_config.json" - if os.path.exists(haystack_lm_config): - self._init_model_haystack_style( - haystack_lm_config=haystack_lm_config, - model_name_or_path=pretrained_model_name_or_path, - model_class=model_class, - model_kwargs=model_kwargs or {}, - use_auth_token=use_auth_token, - ) - else: - self._init_model_transformers_style( - model_name_or_path=pretrained_model_name_or_path, - model_class=model_class, - model_kwargs=model_kwargs or {}, - use_auth_token=use_auth_token, - language=language, - ) - - def _init_model_haystack_style( - self, - haystack_lm_config: Path, - model_name_or_path: Union[str, Path], - model_class: Type[PreTrainedModel], - model_kwargs: Dict[str, Any], - use_auth_token: Optional[Union[str, bool]] = None, - ): - """ - Init a Haystack-style DPR model. - - :param haystack_lm_config: path to the language model config file - :param model_name_or_path: name or path of the model to load - :param model_class: The HuggingFace model class name - :param model_kwargs: any kwarg to pass to the model at init - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - original_model_config = AutoConfig.from_pretrained(haystack_lm_config) - haystack_lm_model = Path(model_name_or_path) / "language_model.bin" - - original_model_type = original_model_config.model_type - if original_model_type and "dpr" in original_model_type.lower(): - dpr_config = transformers.DPRConfig.from_pretrained(haystack_lm_config, use_auth_token=use_auth_token) - self.model = model_class.from_pretrained( - haystack_lm_model, config=dpr_config, use_auth_token=use_auth_token, **model_kwargs - ) - - else: - self.model = self._init_model_through_config( - model_config=original_model_config, model_class=model_class, model_kwargs=model_kwargs - ) - original_model_type = capitalize_model_type(original_model_type) - language_model_class = get_language_model_class(original_model_type) - if not language_model_class: - raise ValueError( - f"The type of model supplied ({model_name_or_path} , " - f"({original_model_type}) is not supported by Haystack. " - f"Supported model categories are: {', '.join(HUGGINGFACE_TO_HAYSTACK.keys())}" - ) - # Instantiate the class for this model - self.model.base_model.bert_model = language_model_class( - pretrained_model_name_or_path=model_name_or_path, - model_type=original_model_type, - use_auth_token=use_auth_token, - **model_kwargs, - ).model - - self.language = self.model.config.language - - def _init_model_transformers_style( - self, - model_name_or_path: Union[str, Path], - model_class: Type[PreTrainedModel], - model_kwargs: Dict[str, Any], - use_auth_token: Optional[Union[str, bool]] = None, - language: Optional[str] = None, - ): - """ - Init a Transformers-style DPR model. - - :param model_name_or_path: name or path of the model to load - :param model_class: The HuggingFace model class name - :param model_kwargs: any kwarg to pass to the model at init - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param language: the model's language. If not given, it will be inferred. Defaults to english. - """ - original_model_config = AutoConfig.from_pretrained(model_name_or_path, use_auth_token=use_auth_token) - if "dpr" in original_model_config.model_type.lower(): - # "pretrained dpr model": load existing pretrained DPRQuestionEncoder model - self.model = model_class.from_pretrained( - str(model_name_or_path), use_auth_token=use_auth_token, **model_kwargs - ) - else: - # "from scratch": load weights from different architecture (e.g. bert) into DPRQuestionEncoder - # but keep config values from original architecture - # TODO test for architectures other than BERT, e.g. Electra - self.model = self._init_model_through_config( - model_config=original_model_config, model_class=model_class, model_kwargs=model_kwargs - ) - self.model.base_model.bert_model = AutoModel.from_pretrained( - str(model_name_or_path), use_auth_token=use_auth_token, **vars(original_model_config) - ) - self.language = language or _guess_language(str(model_name_or_path)) - - def _init_model_through_config( - self, model_config: AutoConfig, model_class: Type[PreTrainedModel], model_kwargs: Optional[Dict[str, Any]] - ): - """ - Init a DPR model using a config object. - """ - if model_config.model_type.lower() != "bert": - logger.warning( - "Using a model of type '%s' which might be incompatible with DPR encoders. " - "Only Bert-based encoders are supported. They need input_ids, token_type_ids, attention_mask as input tensors.", - model_config.model_type, - ) - config_dict = vars(model_config) - if model_kwargs: - config_dict.update(model_kwargs) - return model_class(config=transformers.DPRConfig(**config_dict)) - - @property - def encoder(self): - if not self._encoder: - self._encoder = self.model.question_encoder if self.role == "question" else self.model.ctx_encoder - return self._encoder - - def save_config(self, save_dir: Union[Path, str]) -> None: - """ - Save the configuration of the language model in Haystack format. - - :param save_dir: the path to save the model at - """ - # For DPR models, transformers overwrites the model_type with the one set in DPRConfig - # Therefore, we copy the model_type from the model config to DPRConfig - setattr(transformers.DPRConfig, "model_type", self.model.config.model_type) - super().save_config(save_dir=save_dir) - - def save(self, save_dir: Union[str, Path], state_dict: Optional[Dict[Any, Any]] = None) -> None: - """ - Save the model `state_dict` and its configuration file so that it can be loaded again. - - :param save_dir: The directory in which the model should be saved. - :param state_dict: A dictionary containing the whole state of the module including names of layers. - By default, the unchanged state dictionary of the module is used. - """ - model_to_save = self.model.module if hasattr(self.model, "module") else self.model # Only save the model itself - - if "dpr" not in self.model.config.model_type.lower(): - prefix = "question" if self.role == "question" else "ctx" - - state_dict = model_to_save.state_dict() - if state_dict: - for key in list(state_dict.keys()): # list() here performs a copy and allows editing the dict - new_key = key - - if key.startswith(f"{prefix}_encoder.bert_model.model."): - new_key = key.split("_encoder.bert_model.model.", 1)[1] - - elif key.startswith(f"{prefix}_encoder.bert_model."): - new_key = key.split("_encoder.bert_model.", 1)[1] - - state_dict[new_key] = state_dict.pop(key) - - super().save(save_dir=save_dir, state_dict=state_dict) - - def forward( - self, - input_ids: torch.Tensor, - attention_mask: torch.Tensor, - segment_ids: Optional[torch.Tensor], - output_hidden_states: Optional[bool] = None, - output_attentions: Optional[bool] = None, - return_dict: bool = True, - ): - """ - Perform the forward pass of the DPR encoder model. - - :param input_ids: The IDs of each token in the input sequence. It's a tensor of shape [batch_size, number_of_hard_negative, max_seq_len]. - :param segment_ids: The ID of the segment. For example, in next sentence prediction, the tokens in the - first sentence are marked with 0 and the tokens in the second sentence are marked with 1. - It is a tensor of shape [batch_size, max_seq_len]. - :param attention_mask: A mask that assigns 1 to valid input tokens and 0 to padding tokens - of shape [batch_size, max_seq_len]. - :param output_hidden_states: whether to add the hidden states along with the pooled output - :param output_attentions: unused - :return: Embeddings for each token in the input sequence. - """ - output_hidden_states = ( - output_hidden_states if output_hidden_states is not None else self.encoder.config.output_hidden_states - ) - - model_output = self.model( - input_ids=input_ids, - token_type_ids=segment_ids, - attention_mask=attention_mask, - output_hidden_states=output_hidden_states, - output_attentions=False, - return_dict=return_dict, - ) - - if output_hidden_states: - return model_output.pooler_output, model_output.hidden_states - return model_output.pooler_output, None - - -#: Match the name of the HuggingFace Model class to the corresponding Haystack wrapper -HUGGINGFACE_TO_HAYSTACK: Dict[str, Union[Type[HFLanguageModel], Type[DPREncoder]]] = { - "Auto": HFLanguageModel, - "Albert": HFLanguageModel, - "Bert": HFLanguageModel, - "BigBird": HFLanguageModel, - "Camembert": HFLanguageModel, - "Codebert": HFLanguageModel, - "DebertaV2": HFLanguageModelWithPooler, - "DistilBert": HFLanguageModelNoSegmentIds, - "DPRContextEncoder": DPREncoder, - "DPRQuestionEncoder": DPREncoder, - "Electra": HFLanguageModelWithPooler, - "GloVe": HFLanguageModel, - "MiniLM": HFLanguageModel, - "Roberta": HFLanguageModel, - "Umberto": HFLanguageModel, - "Word2Vec": HFLanguageModel, - "WordEmbedding_LM": HFLanguageModel, - "XLMRoberta": HFLanguageModel, - "XLNet": HFLanguageModelWithPooler, -} -#: HF Capitalization pairs -HUGGINGFACE_CAPITALIZE = { - "xlm-roberta": "XLMRoberta", - "deberta-v2": "DebertaV2", - **{k.lower(): k for k in HUGGINGFACE_TO_HAYSTACK.keys()}, -} - -#: Regex to match variants of the HF class name, to enhance our mode type guessing abilities. -NAME_HINTS: Dict[str, str] = { - "xlm.*roberta": "XLMRoberta", - "roberta.*xml": "XLMRoberta", - "codebert.*mlm": "Roberta", - "mlm.*codebert": "Roberta", - "[dpr]?.*question.*encoder": "DPRQuestionEncoder", - "[dpr]?.*query.*encoder": "DPRQuestionEncoder", - "[dpr]?.*passage.*encoder": "DPRContextEncoder", - "[dpr]?.*context.*encoder": "DPRContextEncoder", - "[dpr]?.*ctx.*encoder": "DPRContextEncoder", - "deberta-v2": "DebertaV2", -} - -#: Parameters or the pooler of models that don't have their own pooler -POOLER_PARAMETERS: Dict[str, Dict[str, Any]] = { - "DistilBert": {"summary_last_dropout": 0, "summary_type": "first", "summary_activation": "tanh"}, - "XLNet": {"summary_last_dropout": 0}, - "Electra": { - "summary_last_dropout": 0, - "summary_type": "first", - "summary_activation": "gelu", - "summary_use_proj": False, - }, - "DebertaV2": { - "summary_last_dropout": 0, - "summary_type": "first", - "summary_activation": "tanh", - "summary_use_proj": False, - }, -} - - -def capitalize_model_type(model_type: str) -> str: - """ - Returns the proper capitalized version of the model type, that can be used to - retrieve the model class from transformers. - :param model_type: the model_type as found in the config file - :return: the capitalized version of the model type, or the original name of not found. - """ - return HUGGINGFACE_CAPITALIZE.get(model_type.lower(), model_type) - - -def is_supported_model(model_type: Optional[str]): - """ - Returns whether the model type is supported by Haystack - :param model_type: the model_type as found in the config file - :return: whether the model type is supported by the Haystack - """ - return model_type and model_type.lower() in HUGGINGFACE_CAPITALIZE - - -def get_language_model_class(model_type: str) -> Optional[Type[Union[HFLanguageModel, DPREncoder]]]: - """ - Returns the corresponding Haystack LanguageModel subclass. - :param model_type: the model_type , properly capitalized (see `capitalize_model_type()`) - :return: the wrapper class, or `None` if `model_type` was `None` or was not recognized. - Lower case model_type values will return `None` as well - """ - return HUGGINGFACE_TO_HAYSTACK.get(model_type) - - -def get_language_model( - pretrained_model_name_or_path: Union[Path, str], - language: Optional[str] = None, - n_added_tokens: int = 0, - use_auth_token: Optional[Union[str, bool]] = None, - revision: Optional[str] = None, - autoconfig_kwargs: Optional[Dict[str, Any]] = None, - model_kwargs: Optional[Dict[str, Any]] = None, -) -> LanguageModel: - """ - Load a pretrained language model by doing one of the following: - - 1. Specifying its name and downloading the model. - 2. Pointing to the directory the model is saved in. - - See all supported model variations at: https://huggingface.co/models. - - The appropriate language model class is inferred automatically from model configuration. - - :param pretrained_model_name_or_path: The path of the saved pretrained model or its name. - :param language: The language of the model (i.e english etc). - :param n_added_tokens: The number of added tokens to the model. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param revision: The version of the model to use from the Hugging Face model hub. This can be a tag name, - a branch name, or a commit hash. - :param autoconfig_kwargs: Additional keyword arguments to pass to the autoconfig function. - :param model_kwargs: Additional keyword arguments to pass to the lamguage model constructor. - """ - - if not pretrained_model_name_or_path or not isinstance(pretrained_model_name_or_path, (str, Path)): - raise ValueError(f"{pretrained_model_name_or_path} is not a valid pretrained_model_name_or_path parameter") - - config_file = Path(pretrained_model_name_or_path) / "language_model_config.json" - - model_type = None - config_file_exists = os.path.exists(config_file) - if config_file_exists: - # it's a local directory in Haystack format - with open(config_file) as f: - config = json.load(f) - model_type = config["name"] - - if not model_type: - model_type = _get_model_type( - pretrained_model_name_or_path, - use_auth_token=use_auth_token, - revision=revision, - autoconfig_kwargs=autoconfig_kwargs, - ) - - if not model_type: - logger.error( - "Model type not understood for '%s' (%s). " - "Either supply the local path for a saved model, " - "or the name of a model that can be downloaded from the Model Hub. " - "Ensure that the model class name can be inferred from the directory name " - "when loading a Transformers model.", - pretrained_model_name_or_path, - model_type if model_type else "model_type not set", - ) - logger.error("Using the AutoModel class for '%s'. This can cause crashes!", pretrained_model_name_or_path) - model_type = "Auto" - - # Find the class corresponding to this model type - model_type = capitalize_model_type(model_type) - language_model_class = get_language_model_class(model_type) - if not language_model_class: - raise ValueError( - f"The type of model supplied ({model_type}) is not supported by Haystack or was not correctly identified. " - f"Supported model types are: {', '.join(HUGGINGFACE_TO_HAYSTACK.keys())}" - ) - - logger.info( - " * LOADING MODEL: '%s' %s", pretrained_model_name_or_path, "(" + model_type + ")" if model_type else "" - ) - - # Instantiate the class for this model - language_model = language_model_class( - pretrained_model_name_or_path=pretrained_model_name_or_path, - model_type=model_type, - language=language, - n_added_tokens=n_added_tokens, - use_auth_token=use_auth_token, - model_kwargs=model_kwargs, - ) - logger.info( - "Loaded '%s' (%s model) from %s.", - pretrained_model_name_or_path, - model_type, - "local file system" if config_file_exists else "model hub", - ) - return language_model - - -def _get_model_type( - model_name_or_path: Union[str, Path], - use_auth_token: Optional[Union[str, bool]] = None, - revision: Optional[str] = None, - autoconfig_kwargs: Optional[Dict[str, Any]] = None, -) -> Optional[str]: - """ - Given a model name, try to use AutoConfig to understand which model type it is. - In case it's not successful, tries to infer the type from the name of the model. - """ - model_name_or_path = str(model_name_or_path) - - model_type: Optional[str] = None - # Use AutoConfig to understand the model class - try: - config = AutoConfig.from_pretrained( - pretrained_model_name_or_path=model_name_or_path, - use_auth_token=use_auth_token, - revision=revision, - **(autoconfig_kwargs or {}), - ) - model_type = config.model_type - # if unsupported model, try to infer from config.architectures - if not is_supported_model(model_type) and config.architectures: - model_type = config.architectures[0] if is_supported_model(config.architectures[0]) else None - - except Exception as e: - logger.error("AutoConfig failed to load on '%s': %s", model_name_or_path, e) - - if not model_type: - logger.warning("Could not infer the model type from its config. Looking for clues in the model name.") - - # Look for other patterns and variation that hints at the model type - for regex, model_name in NAME_HINTS.items(): - if re.match(f".*{regex}.*", model_name_or_path): - model_type = model_name - break - - if model_type and model_type.lower() == "roberta" and "mlm" in model_name_or_path.lower(): - logger.error( - "MLM part of codebert is currently not supported in Haystack: '%s' may crash later.", model_name_or_path - ) - - return model_type - - -def _guess_language(name: str) -> str: - """ - Looks for clues about the model language in the model name. - """ - languages = [lang for hint, lang in LANGUAGE_HINTS if hint.lower() in name.lower()] - if len(languages) > 0: - language = languages[0] - else: - language = "english" - logger.info("Auto-detected model language: %s", language) - return language diff --git a/haystack/modeling/model/multimodal/__init__.py b/haystack/modeling/model/multimodal/__init__.py deleted file mode 100644 index d66c19e0c3..0000000000 --- a/haystack/modeling/model/multimodal/__init__.py +++ /dev/null @@ -1,184 +0,0 @@ -from typing import Optional, Union, Dict, Any, Type, List - -import logging -from pathlib import Path -from transformers import AutoConfig -import torch -from huggingface_hub import hf_hub_download - -from haystack.modeling.model.multimodal.base import HaystackModel -from haystack.modeling.model.multimodal.sentence_transformers import HaystackSentenceTransformerModel - - -logger = logging.getLogger(__name__) - - -#: Match the name of the HuggingFace Model class to the corresponding Haystack wrapper -HUGGINGFACE_TO_HAYSTACK: Dict[str, Type[HaystackModel]] = { - "CLIP": HaystackSentenceTransformerModel, - "MPNet": HaystackSentenceTransformerModel, - "DPRContextEncoder": HaystackSentenceTransformerModel, - "DPRQuestionEncoder": HaystackSentenceTransformerModel, -} - - -#: HF Capitalization pairs. Contains alternative capitalizations. -HUGGINGFACE_CAPITALIZE = { - "big-bird": "BigBird", - "deberta-v2": "DebertaV2", - "xlm-roberta": "XLMRoberta", - **{k.lower(): k for k in HUGGINGFACE_TO_HAYSTACK.keys()}, -} - - -def get_model( - pretrained_model_name_or_path: Union[Path, str], - content_type: str, # change to ContentTypes starting Python3.8 - devices: Optional[List[torch.device]] = None, - autoconfig_kwargs: Optional[Dict[str, Any]] = None, - model_kwargs: Optional[Dict[str, Any]] = None, - feature_extractor_kwargs: Optional[Dict[str, Any]] = None, - pooler_kwargs: Optional[Dict[str, Any]] = None, -) -> HaystackModel: - """ - Load a pretrained language model by specifying its name and either downloading the model from the Hugging Face hub - (if it's given a model identifier from Hugging Face Hub) or loading it from disk (if it's given a local path). - - For all supported model variations, see [Models](https://huggingface.co/models). - The appropriate language model class is inferred automatically from the model's configuration or its name. - - :param pretrained_model_name_or_path: The path of the saved pretrained model or its name. - :param content_type: The type (text, image, ...) of content the model should handle. - :param autoconfig_kwargs: Additional keyword arguments to pass to AutoConfig, like the revision or the auth key. - :param model_kwargs: Additional keyword arguments to pass to the language model constructor. - Haystack applies some default parameters to some models. You can override them by specifying the - desired value in this parameter. See `DEFAULT_MODEL_PARAMS`. - :param feature_extractor_kwargs: A dictionary of parameters to pass to the feature extractor's initialization (revision, use_auth_key, etc...) - Haystack applies some default parameters to some models. You can override them by specifying the - desired value in this parameter. See `DEFAULT_MODEL_PARAMS`. - :param pooler_kwargs: A dictionary of parameters to pass to the pooler's initialization (summary_last_dropout, summary_activation, etc...) - Haystack applies some default parameters to some models. You can override them by specifying the - desired value in this parameter. See `POOLER_PARAMETERS`. - """ - autoconfig_kwargs = autoconfig_kwargs or {} - model_kwargs = model_kwargs or {} - feature_extractor_kwargs = feature_extractor_kwargs or {} - pooler_kwargs = pooler_kwargs or {} - - if not pretrained_model_name_or_path or not isinstance(pretrained_model_name_or_path, (str, Path)): - raise ValueError( - f"{pretrained_model_name_or_path} is not a valid 'pretrained_model_name_or_path' value. " - "Please provide a string or a Path object." - ) - model_name = str(pretrained_model_name_or_path) - model_type: Optional[str] = "" - model_wrapper_class: Type[HaystackModel] - - # Prepare the kwargs the model wrapper expects (see each wrapper's init for details) - wrapper_kwarg_groups = {} - wrapper_kwarg_groups["model_kwargs"] = model_kwargs - - # SentenceTransformers are much faster, so use them whenever possible - if _is_sentence_transformers_model( - pretrained_model_name_or_path, use_auth_token=autoconfig_kwargs.get("use_auth_token", False) - ): - model_wrapper_class = HaystackSentenceTransformerModel - try: - # Use AutoConfig to log some more info about the model class - config = AutoConfig.from_pretrained(pretrained_model_name_or_path=model_name, **autoconfig_kwargs) - model_type = config.model_type - except Exception as e: - logger.debug("Can't find model type for %s: %s", pretrained_model_name_or_path, e) - - if feature_extractor_kwargs is not None: - logger.debug( - "Can't forward feature_extractor_kwargs to a SentenceTransformers model. " - "These kwargs are being dropped. " - "Content of feature_extractor_kwargs: %s", - feature_extractor_kwargs, - ) - - else: - # Use AutoConfig to understand the model class - config = AutoConfig.from_pretrained(pretrained_model_name_or_path=model_name, **autoconfig_kwargs) - if not config.model_type: - logger.error( - "Model type not understood for '%s'. Please provide the name of " - "a model that can be downloaded from the Model Hub.\nUsing the AutoModel class. " - "THIS CAN CAUSE CRASHES and won't work for models that are not working with text.", - pretrained_model_name_or_path, - ) - model_type = None - else: - try: - model_type = HUGGINGFACE_CAPITALIZE[config.model_type.lower()] - except KeyError: - logger.error( - "Haystack doesn't support model '%s' (type '%s') " - "We'll use the AutoModel class for it. " - "THIS CAN CAUSE CRASHES and won't work for models that are not working with text. " - "Supported model types: %s", - pretrained_model_name_or_path, - config.model_type.lower(), - ", ".join(HUGGINGFACE_CAPITALIZE.keys()), - ) - model_type = None - - # Find the HF class corresponding to this model type - try: - model_wrapper_class = HUGGINGFACE_TO_HAYSTACK[model_type or "AutoModel"] - except KeyError as e: - raise ValueError( - f"The type of the given model (name/path: {pretrained_model_name_or_path}, detected type: {model_type or config.model_type}) " - "is not supported by Haystack or was not correctly identified. Please use supported models only. " - f"Supported model types: {', '.join(HUGGINGFACE_TO_HAYSTACK.keys())}" - ) from e - - if feature_extractor_kwargs: - wrapper_kwarg_groups["feature_extractor_kwargs"] = feature_extractor_kwargs - if pooler_kwargs: - wrapper_kwarg_groups["pooler_kwargs"] = pooler_kwargs - - # Instantiate the model's wrapper - model_wrapper = model_wrapper_class( - pretrained_model_name_or_path=pretrained_model_name_or_path, - model_type=model_type, - content_type=content_type, - **wrapper_kwarg_groups, - ) - model_wrapper.to(devices) - - return model_wrapper - - -def _is_sentence_transformers_model(pretrained_model_name_or_path: Union[Path, str], use_auth_token: Union[bool, str]): - # Check if sentence transformers config file is in local path - if ( - Path(pretrained_model_name_or_path).exists() - and (Path(pretrained_model_name_or_path) / "config_sentence_transformers.json").exists() - ): - return True - - # Check if sentence transformers config file is in model hub - try: - hf_hub_download( # type: ignore [call-arg] - repo_id=str(pretrained_model_name_or_path), - filename="config_sentence_transformers.json", - use_auth_token=use_auth_token, - ) - return True - - except Exception as e: - logger.debug("%s not found in model hub: an error occurred. Error: %s", pretrained_model_name_or_path, e) - - # Pattern matching the name as a last resort - if str(pretrained_model_name_or_path).startswith("sentence-transformers"): - logger.debug( - "The model name starts with 'sentence-transformers': assuming this is a Sentence Transformers model." - ) - return True - - logger.debug( - "The model name doesn't start with 'sentence-transformers': assuming this is NOT a Sentence Transformers model." - ) - return False diff --git a/haystack/modeling/model/multimodal/base.py b/haystack/modeling/model/multimodal/base.py deleted file mode 100644 index 99a0c4cab1..0000000000 --- a/haystack/modeling/model/multimodal/base.py +++ /dev/null @@ -1,58 +0,0 @@ -from typing import Any, List, Union, Optional - -import logging -from pathlib import Path -from abc import ABC, abstractmethod - -import torch - - -logger = logging.getLogger(__name__) - - -class HaystackModel(ABC): - """ - The interface on top of HaystackTransformer and HaystackSentenceTransformer. - """ - - def __init__( - self, pretrained_model_name_or_path: Union[str, Path], model_type: Optional[str], content_type: str - ): # replace the type of content_type with ContentTypes starting Python3.8 - """ - :param pretrained_model_name_or_path: The name of the model to load - :param model_type: the value of `model_type` from the model's `Config` class. - :param content_type: The type of data (such as "text", "image" and so on) the model should process. - See the values of `haystack.schema.ContentTypes`. - """ - logger.info( - " 🤖 Loading '%s' (%s of type '%s' for %s data)", - pretrained_model_name_or_path, - self.__class__.__name__, - model_type if model_type else "", - content_type, - ) - self.model_name_or_path = pretrained_model_name_or_path - self.model_type = model_type - self.content_type = content_type - - @abstractmethod - def encode(self, data: List[Any], **kwargs) -> torch.Tensor: - """ - Run the model on the input data to obtain output vectors. - """ - raise NotImplementedError("Abstract method, use a subclass.") - - @abstractmethod - def to(self, devices: Optional[List[torch.device]]) -> None: - """ - Send the model to the specified PyTorch device(s) - """ - raise NotImplementedError("Abstract method, use a subclass.") - - @property - @abstractmethod - def embedding_dim(self) -> int: - """ - The output embedding size. - """ - raise NotImplementedError("Abstract method, use a subclass.") diff --git a/haystack/modeling/model/multimodal/sentence_transformers.py b/haystack/modeling/model/multimodal/sentence_transformers.py deleted file mode 100644 index 1a21f2678d..0000000000 --- a/haystack/modeling/model/multimodal/sentence_transformers.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Optional, Dict, Any, List, Union - -import logging -from pathlib import Path - -import torch -from torch import nn -from sentence_transformers import SentenceTransformer - -from haystack.modeling.model.multimodal.base import HaystackModel -from haystack.schema import ContentTypes - - -logger = logging.getLogger(__name__) - - -class HaystackSentenceTransformerModel(HaystackModel): - """ - Parent class for `sentence-transformers` models. - - These models read raw data (text, image), internally extract features, and return vectors that capture the meaning - of the original data. - - Models inheriting from `HaystackSentenceTransformerModel` are designed to be used in parallel one with the other - in multimodal retrieval settings, for example image retrieval from a text query, mixed table/text retrieval, and so on. - """ - - def __init__( - self, - pretrained_model_name_or_path: Union[str, Path], - model_type: str, - content_type: ContentTypes, - model_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - :param pretrained_model_name_or_path: The name of the model to load. - :param model_type: the value of `model_type` from the model's `Config` class - :param content_type: The type of data (such as "text", "image", and so on) the model should process. - See the values of `haystack.schema.ContentTypes`. - :param model_kwargs: A dictionary of parameters to pass to the model's initialization. - (revision, use_auth_key, and so on) - Haystack applies some default parameters to some models. You can override them by specifying the - desired value in this parameter. See `DEFAULT_MODEL_PARAMS`. - """ - super().__init__( - pretrained_model_name_or_path=pretrained_model_name_or_path, - model_type=model_type, - content_type=content_type, - ) - try: - self.model = SentenceTransformer(pretrained_model_name_or_path, **(model_kwargs or {})) - except Exception: - logger.exception( - "Models of type '%s' like %s " - "are only supported through sentence-transformers. Make sure this " - "model is compatible with sentence-transformers or use an alternative, compatible " - "implementation of this model.", - model_type, - pretrained_model_name_or_path, - ) - - @property - def embedding_dim(self) -> int: - """ - Finds out the output embedding dim by running the model on a minimal amount of mock data. - """ - emedding_dim = self.model.get_sentence_embedding_dimension() - if not emedding_dim: - logger.warning( - "Can't find the output embedding dimensions for '%s'. Some checks will not run as intended.", - self.model_name_or_path, - ) - return emedding_dim - - def to(self, devices: Optional[List[torch.device]]) -> None: - """ - Send the model to the specified PyTorch devices. - """ - if devices: - if len(devices) > 1: - self.model = nn.DataParallel(self.model, device_ids=devices) - else: - self.model.to(devices[0]) - - def encode(self, data: List[Any], **kwargs) -> torch.Tensor: - """ - Generate the tensors representing the input data. - - Validates the inputs according to what the subclass declared in the `expected_inputs` property. - Then passes the vectors to the `_forward()` method and returns its output untouched. - """ - return self.model.encode(data, convert_to_tensor=True, **kwargs) diff --git a/haystack/modeling/model/optimization.py b/haystack/modeling/model/optimization.py deleted file mode 100644 index d3e55f7674..0000000000 --- a/haystack/modeling/model/optimization.py +++ /dev/null @@ -1,308 +0,0 @@ -# TODO analyse if this optimization is needed or whether we can use HF transformers code -from typing import Dict, Any, Optional - -import inspect -import logging -import sys -from importlib import import_module -import torch -from torch.nn import DataParallel -from torch.nn.parallel import DistributedDataParallel - -from haystack.modeling.model.adaptive_model import AdaptiveModel -from haystack.utils.experiment_tracking import Tracker as tracker - -logger = logging.getLogger(__name__) - - -class WrappedDataParallel(DataParallel): - """ - A way of adapting attributes of underlying class to parallel mode. See: - https://pytorch.org/tutorials/beginner/former_torchies/parallelism_tutorial.html#dataparallel - - Gets into recursion errors. Workaround see: - https://discuss.pytorch.org/t/access-att-of-model-wrapped-within-torch-nn-dataparallel-maximum-recursion-depth-exceeded/46975 - """ - - def __getattr__(self, name): - try: - return super().__getattr__(name) - except AttributeError: - return getattr(self.module, name) - - -class WrappedDDP(DistributedDataParallel): - """ - A way of adapting attributes of underlying class to distributed mode. Same as in WrappedDataParallel above. - Even when using distributed on a single computer with multiple GPUs, automatic mixed precision can speed up training - significantly. - Distributed code must be launched with "python -m torch.distributed.launch --nproc_per_node=1 run_script.py" - """ - - def __getattr__(self, name): - try: - return super().__getattr__(name) - except AttributeError: - return getattr(self.module, name) - - -def initialize_optimizer( - model: AdaptiveModel, - n_batches: int, - n_epochs: int, - device: torch.device, - learning_rate: float, - optimizer_opts: Optional[Dict[Any, Any]] = None, - schedule_opts: Optional[Dict[Any, Any]] = None, - distributed: bool = False, - grad_acc_steps: int = 1, - local_rank: int = -1, - use_amp: bool = False, -): - """ - Initializes an optimizer, a learning rate scheduler and converts the model if needed (e.g for mixed precision). - Per default, we use transformers' AdamW and a linear warmup schedule with warmup ratio 0.1. - You can easily switch optimizer and schedule via `optimizer_opts` and `schedule_opts`. - - :param model: model to optimize (e.g. trimming weights to fp16 / mixed precision) - :param n_batches: number of batches for training - :param n_epochs: number of epochs for training - :param device: Which hardware will be used by the optimizer. Either torch.device("cpu") or torch.device("cuda"). - :param learning_rate: Learning rate - :param optimizer_opts: Dictionary to customize the optimizer. Choose any optimizer available from torch.optim or - transformers.optimization by supplying the class name and the parameters for the constructor. - Examples: - 1) AdamW from Transformers (Default): - {"name": "AdamW", "correct_bias": False, "weight_decay": 0.01} - 2) SGD from pytorch: - {"name": "SGD", "momentum": 0.0} - :param schedule_opts: Dict to customize the learning rate schedule. - Choose any Schedule from Pytorch or Huggingface's Transformers by supplying the class name - and the parameters needed by the constructor. - If the dict does not contain ``num_training_steps`` it will be set by - calculating it from ``n_batches``, ``grad_acc_steps`` and ``n_epochs``. - Examples: - 1) Linear Warmup (Default): - {"name": "LinearWarmup", - "num_warmup_steps": 0.1 * num_training_steps, - "num_training_steps": num_training_steps} - 2) CosineWarmup: - {"name": "CosineWarmup", - "num_warmup_steps": 0.1 * num_training_steps, - "num_training_steps": num_training_steps} - 3) CyclicLR from pytorch: - {"name": "CyclicLR", "base_lr": 1e-5, "max_lr":1e-4, "step_size_up": 100} - :param distributed: Whether training on distributed machines - :param grad_acc_steps: Number of steps to accumulate gradients for. Helpful to mimic large batch_sizes on small machines. - :param local_rank: rank of the machine in a distributed setting - :param use_amp: This option is deprecated. Haystack supports only PyTorch automatic mixed precision (AMP). We no longer support the Apex library. This means this function doesn't use `use_amp` any longer - because it's not needed to initialize native Pytorch AMP. If you provide a value, you'll see a warning message. - - :return: model, optimizer, scheduler - """ - if isinstance(use_amp, str): - logger.warning( - "Haystack supports only PyTorch automatic mixed precision. We no longer support the Apex library.\n" - "This means that modeling.model.initialize_optimizer no longer uses use_amp since it is not needed\n" - "to initialize native PyTorch automatic mixed precision. For more information, see [Optimization](https://haystack.deepset.ai/guides/optimization).\n" - "In the future provide use_amp=True to use automatic mixed precision." - ) - - if (schedule_opts is not None) and (not isinstance(schedule_opts, dict)): - raise TypeError( - "Parameter schedule_opts must be None or " "an instance of dict but was {}!".format(type(schedule_opts)) - ) - - num_train_optimization_steps = int(n_batches / grad_acc_steps) * n_epochs - - # Use some defaults to simplify life of inexperienced users - if optimizer_opts is None: - optimizer_opts = {"name": "AdamW", "correct_bias": False, "weight_decay": 0.01} - optimizer_opts["lr"] = learning_rate - - if schedule_opts is None: - # Default schedule: Linear Warmup with 10% warmup - schedule_opts = { - "name": "LinearWarmup", - "num_warmup_steps": 0.1 * num_train_optimization_steps, - "num_training_steps": num_train_optimization_steps, - } - - # schedule_opts = {"name": "OneCycleLR", "max_lr":learning_rate, "pct_start": 0.1, - # "total_steps": num_train_optimization_steps } - elif "num_training_steps" not in schedule_opts: - schedule_opts["num_training_steps"] = num_train_optimization_steps - - # Log params - tracker.track_params({"num_train_optimization_steps": schedule_opts["num_training_steps"]}) - - # Get optimizer from pytorch or transformers - optimizer = _get_optim(model, optimizer_opts) - - # Adjust for parallel training - model, optimizer = optimize_model(model, device, local_rank, optimizer, distributed) - - # Get learning rate schedule - moved below to suppress warning - scheduler = get_scheduler(optimizer, schedule_opts) - - return model, optimizer, scheduler - - -def _get_optim(model, opts: Dict): - """ - Get the optimizer based on dictionary with options. Options are passed to the optimizer constructor. - - :param model: model to optimize - :param opts: config dictionary that will be passed to optimizer together with the params - (e.g. lr, weight_decay, correct_bias ...). no_decay' can be given - parameters containing any of those strings - will have weight_decay set to 0. - :return: created optimizer - """ - optimizer_name = opts.pop("name", None) - - # Logging - logger.info("Loading optimizer '%s': %s", optimizer_name, opts) - tracker.track_params(opts) - tracker.track_params({"optimizer_name": optimizer_name}) - - weight_decay = opts.pop("weight_decay", None) - no_decay = opts.pop("no_decay", None) - - if no_decay: - optimizable_parameters = [ - { - "params": [ - p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay) and p.requires_grad - ], - **opts, - }, - { - "params": [ - p for n, p in model.named_parameters() if any(nd in n for nd in no_decay) and p.requires_grad - ], - "weight_decay": 0.0, - **opts, - }, - ] - else: - optimizable_parameters = [{"params": [p for p in model.parameters() if p.requires_grad], **opts}] - - # default weight decay is not the same for all optimizers, so we can't use default value - # only explicitly add weight decay if it's given - if weight_decay is not None: - optimizable_parameters[0]["weight_decay"] = weight_decay # type: ignore - - # Import optimizer by checking in order: torch, transformers and local imports - try: - optim_constructor = getattr(import_module("torch.optim"), optimizer_name) - except AttributeError: - try: - optim_constructor = getattr(import_module("transformers.optimization"), optimizer_name) - except AttributeError: - try: - # Workaround to allow loading AdamW from transformers - # pytorch > 1.2 has now also a AdamW (but without the option to set bias_correction = False, - # which is done in the original BERT implementation) - optim_constructor = getattr(sys.modules[__name__], optimizer_name) - except (AttributeError, ImportError): - raise AttributeError( - f"We couldn't find optimizer '{optimizer_name}' in 'torch', 'transformers' or 'local imports'." - ) - - return optim_constructor(optimizable_parameters) - - -def get_scheduler(optimizer, opts): - """ - Get the scheduler based on dictionary with options. Options are passed to the scheduler constructor. - - :param optimizer: optimizer whose learning rate to control - :param opts: dictionary of args to be passed to constructor of schedule - :return: created scheduler - """ - schedule_name = opts.get("name") - try: - sched_constructor = getattr(import_module("torch.optim.lr_scheduler"), schedule_name) - except AttributeError: - try: - # The method names in transformers became quite long and unhandy. - # for convenience we offer usage of shorter alias (e.g. "LinearWarmup") - scheduler_translations = { - "LinearWarmup": "get_linear_schedule_with_warmup", - "ConstantWarmup": "get_constant_schedule_with_warmup", - "Constant": "get_constant_schedule", - "CosineWarmup": "get_cosine_schedule_with_warmup", - "CosineWarmupWithRestarts": "get_cosine_with_hard_restarts_schedule_with_warmup", - } - if schedule_name in scheduler_translations.keys(): - schedule_name = scheduler_translations[schedule_name] - # in contrast to torch, we actually get here a method and not a class - sched_constructor = getattr(import_module("transformers.optimization"), schedule_name) - except AttributeError: - raise AttributeError(f"Scheduler '{schedule_name}' not found in 'torch' or 'transformers'") - - logger.info("Using scheduler '%s'", schedule_name) - - # get supported args of constructor - allowed_args = inspect.signature(sched_constructor).parameters.keys() - - # convert from warmup proportion to steps if required - if "num_warmup_steps" in allowed_args and "num_warmup_steps" not in opts and "warmup_proportion" in opts: - opts["num_warmup_steps"] = int(opts["warmup_proportion"] * opts["num_training_steps"]) - tracker.track_params({"warmup_proportion": opts["warmup_proportion"]}) - - # only pass args that are supported by the constructor - constructor_opts = {k: v for k, v in opts.items() if k in allowed_args} - - # Logging - logger.info("Loading schedule '%s': '%s'", schedule_name, constructor_opts) - tracker.track_params(constructor_opts) - tracker.track_params({"schedule_name": schedule_name}) - - scheduler = sched_constructor(optimizer, **constructor_opts) - scheduler.opts = opts # save the opts with the scheduler to use in load/save - return scheduler - - -def optimize_model( - model: "AdaptiveModel", - device: torch.device, - local_rank: int, - optimizer: Optional[torch.optim.Optimizer] = None, - distributed: bool = False, - use_amp: bool = False, -): - """ - Wraps MultiGPU or distributed usage around a model - No support for ONNX models - - :param model: model to optimize (e.g. trimming weights to fp16 / mixed precision) - :param device: either torch.device("cpu") or torch.device("cuda"). Get the device from `initialize_device_settings()` - :param distributed: Whether training on distributed machines - :param local_rank: rank of the machine in a distributed setting - :param optimizer: torch optimizer - :param use_amp: This option is deprecated. Haystack supports only PyTorch automatic mixed precision (AMP). We no longer support the Apex library. This means this function no longer uses `use_amp` - because it's not needed to initialize native Pytorch AMP. If you provide a value, you'll see a warning message. - - :return: model, optimizer - """ - if isinstance(use_amp, str): - logger.warning( - "Haystack supports only PyTorch automatic mixed precision. We no longer support the Apex library.\n" - "This means that modeling.model.initialize_optimizer no longer uses use_amp since it's not needed\n" - "to initialize native PyTorch automatic mixed precision. For more information, see [Optimization](https://haystack.deepset.ai/guides/optimization).\n" - "In the future, set `use_amp=True` to use automatic mixed precision." - ) - - model = model.to(device) - - if distributed: - # for some models DistributedDataParallel might complain about parameters - # not contributing to loss. find_used_parameters remedies that. - model = WrappedDDP(model, device_ids=[local_rank], output_device=local_rank, find_unused_parameters=True) # type: ignore [assignment] - - elif torch.cuda.device_count() > 1 and device.type == "cuda": - model = WrappedDataParallel(model) if not isinstance(model, DataParallel) else WrappedDataParallel(model.module) # type: ignore [assignment] - logger.info("Multi-GPU Training via DataParallel") - - return model, optimizer diff --git a/haystack/modeling/model/prediction_head.py b/haystack/modeling/model/prediction_head.py deleted file mode 100644 index 45e2d72690..0000000000 --- a/haystack/modeling/model/prediction_head.py +++ /dev/null @@ -1,1129 +0,0 @@ -import json -import logging -import os -from pathlib import Path -from typing import List, Tuple, Optional, Union, Dict - -import numpy as np -import torch -from torch import nn -from torch import optim -from torch.nn import CrossEntropyLoss, NLLLoss -from transformers import AutoModelForQuestionAnswering - -from haystack.modeling.data_handler.samples import SampleBasket -from haystack.modeling.model.predictions import QACandidate, QAPred -from haystack.modeling.utils import try_get, all_gather_list -from haystack.utils.scipy_utils import expit - - -logger = logging.getLogger(__name__) - - -class PredictionHead(nn.Module): - """ - Takes word embeddings from a language model and generates logits for a given task. Can also convert logits - to loss and and logits to predictions. - """ - - subclasses = {} # type: Dict - - def __init_subclass__(cls, **kwargs): - """This automatically keeps track of all available subclasses. - Enables generic load() for all specific PredictionHead implementation. - """ - super().__init_subclass__(**kwargs) - cls.subclasses[cls.__name__] = cls - - @classmethod - def create(cls, prediction_head_name: str, layer_dims: List[int], class_weights=Optional[List[float]]): - """ - Create subclass of Prediction Head. - - :param prediction_head_name: Classname (exact string!) of prediction head we want to create - :param layer_dims: describing the feed forward block structure, e.g. [768,2] - :param class_weights: The loss weighting to be assigned to certain label classes during training. - Used to correct cases where there is a strong class imbalance. - :return: Prediction Head of class prediction_head_name - """ - # TODO make we want to make this more generic. - # 1. Class weights is not relevant for all heads. - # 2. Layer weights impose FF structure, maybe we want sth else later - # Solution: We could again use **kwargs - return cls.subclasses[prediction_head_name](layer_dims=layer_dims, class_weights=class_weights) - - def save_config(self, save_dir: Union[str, Path], head_num: int = 0): - """ - Saves the config as a json file. - - :param save_dir: Path to save config to - :param head_num: Which head to save - """ - # updating config in case the parameters have been changed - self.generate_config() - output_config_file = Path(save_dir) / f"prediction_head_{head_num}_config.json" - with open(output_config_file, "w") as file: - json.dump(self.config, file) - - def save(self, save_dir: Union[str, Path], head_num: int = 0): - """ - Saves the prediction head state dict. - - :param save_dir: path to save prediction head to - :param head_num: which head to save - """ - output_model_file = Path(save_dir) / f"prediction_head_{head_num}.bin" - torch.save(self.state_dict(), output_model_file) - self.save_config(save_dir, head_num) - - def generate_config(self): - """ - Generates config file from Class parameters (only for sensible config parameters). - """ - config = {} - for key, value in self.__dict__.items(): - if type(value) is np.ndarray: - value = value.tolist() - if _is_json(value) and key[0] != "_": - config[key] = value - if self.task_name == "text_similarity" and key == "similarity_function": - config["similarity_function"] = value - config["name"] = self.__class__.__name__ - config.pop("config", None) - self.config = config - - @classmethod - def load(cls, config_file: str, strict: bool = True, load_weights: bool = True): - """ - Loads a Prediction Head. Infers the class of prediction head from config_file. - - :param config_file: location where corresponding config is stored - :param strict: whether to strictly enforce that the keys loaded from saved model match the ones in - the PredictionHead (see torch.nn.module.load_state_dict()). - Set to `False` for backwards compatibility with PHs saved with older version of Haystack. - :param load_weights: whether to load weights of the prediction head - :return: PredictionHead - :rtype: PredictionHead[T] - """ - with open(config_file) as f: - config = json.load(f) - prediction_head = cls.subclasses[config["name"]](**config) - if load_weights: - model_file = cls._get_model_file(config_file=config_file) - logger.info("Loading prediction head from %s", model_file) - prediction_head.load_state_dict(torch.load(model_file, map_location=torch.device("cpu")), strict=strict) - return prediction_head - - def logits_to_loss(self, logits, labels): - """ - Implement this function in your special Prediction Head. - Should combine logits and labels with a loss fct to a per sample loss. - - :param logits: logits, can vary in shape and type, depending on task - :param labels: labels, can vary in shape and type, depending on task - :return: per sample loss as a torch.tensor of shape [batch_size] - """ - raise NotImplementedError() - - def logits_to_preds(self, logits, span_mask, start_of_word, seq_2_start_t, max_answer_length, **kwargs): - """ - Implement this function in your special Prediction Head. - Should combine turn logits into predictions. - - :param logits: logits, can vary in shape and type, depending on task - :return: predictions as a torch.tensor of shape [batch_size] - """ - raise NotImplementedError() - - def prepare_labels(self, **kwargs): - """ - Some prediction heads need additional label conversion. - - :param kwargs: placeholder for passing generic parameters - :return: labels in the right format - :rtype: object - """ - # TODO maybe just return **kwargs to not force people to implement this - raise NotImplementedError() - - def resize_input(self, input_dim): - """ - This function compares the output dimensionality of the language model against the input dimensionality - of the prediction head. If there is a mismatch, the prediction head will be resized to fit. - """ - # Note on pylint disable - # self.feed_forward's existence seems to be a condition for its own initialization - # within this class, which is clearly wrong. The only way this code could ever be called is - # thanks to subclasses initializing self.feed_forward somewhere else; however, this is a - # very implicit requirement for subclasses, and in general bad design. FIXME when possible. - if "feed_forward" not in dir(self): - return - else: - old_dims = self.feed_forward.layer_dims # pylint: disable=access-member-before-definition - if input_dim == old_dims[0]: - return - new_dims = [input_dim] + old_dims[1:] - logger.info( - "Resizing input dimensions of %s (%s) from %s to %s to match language model", - type(self).__name__, - self.task_name, - old_dims, - new_dims, - ) - self.feed_forward = FeedForwardBlock(new_dims) - self.layer_dims[0] = input_dim - self.feed_forward.layer_dims[0] = input_dim - - @classmethod - def _get_model_file(cls, config_file: Union[str, Path]): - if "config.json" in str(config_file) and "prediction_head" in str(config_file): - head_num = int("".join([char for char in os.path.basename(config_file) if char.isdigit()])) - model_file = Path(os.path.dirname(config_file)) / f"prediction_head_{head_num}.bin" - else: - raise ValueError(f"This doesn't seem to be a proper prediction_head config file: '{config_file}'") - return model_file - - def _set_name(self, name): - self.task_name = name - - -class FeedForwardBlock(nn.Module): - """ - A feed forward neural network of variable depth and width. - """ - - def __init__(self, layer_dims: List[int], **kwargs): - # Todo: Consider having just one input argument - super(FeedForwardBlock, self).__init__() - self.layer_dims = layer_dims - # If read from config the input will be string - n_layers = len(layer_dims) - 1 - layers_all = [] - # TODO: IS this needed? - self.output_size = layer_dims[-1] - - for i in range(n_layers): - size_in = layer_dims[i] - size_out = layer_dims[i + 1] - layer = nn.Linear(size_in, size_out) - layers_all.append(layer) - self.feed_forward = nn.Sequential(*layers_all) - - def forward(self, X: torch.Tensor): - logits = self.feed_forward(X) - return logits - - -class QuestionAnsweringHead(PredictionHead): - """ - A question answering head predicts the start and end of the answer on token level. - - In addition, it gives a score for the prediction so that multiple answers can be ranked. - There are three different kinds of scores available: - 1) (standard) score: the sum of the logits of the start and end index. This score is unbounded because the logits are unbounded. - It is the default for ranking answers. - 2) confidence score: also based on the logits of the start and end index but scales them to the interval 0 to 1 and incorporates no_answer. - It can be used for ranking by setting use_confidence_scores_for_ranking to True - 3) calibrated confidence score: same as 2) but divides the logits by a learned temperature_for_confidence parameter - so that the confidence scores are closer to the model's achieved accuracy. It can be used for ranking by setting - use_confidence_scores_for_ranking to True and temperature_for_confidence!=1.0. See examples/question_answering_confidence.py for more details. - """ - - def __init__( - self, - layer_dims: Optional[List[int]] = None, - task_name: str = "question_answering", - no_ans_boost: float = 0.0, - context_window_size: int = 100, - n_best: int = 5, - n_best_per_sample: Optional[int] = None, - duplicate_filtering: int = -1, - temperature_for_confidence: float = 1.0, - use_confidence_scores_for_ranking: bool = True, - use_no_answer_legacy_confidence: bool = False, - **kwargs, - ): - """ - :param layer_dims: dimensions of Feed Forward block, e.g. [768,2] used by default, for adjusting to BERT embedding. Output should be always 2 - :param kwargs: placeholder for passing generic parameters - :param no_ans_boost: How much the no_answer logit is boosted/increased. - The higher the value, the more likely a "no answer possible given the input text" is returned by the model - :param context_window_size: The size, in characters, of the window around the answer span that is used when displaying the context around the answer. - :param n_best: The number of positive answer spans for each document. - :param n_best_per_sample: num candidate answer spans to consider from each passage. Each passage also returns "no answer" info. - This is decoupled from n_best on document level, since predictions on passage level are very similar. - It should have a low value - :param duplicate_filtering: Answers are filtered based on their position. Both start and end position of the answers are considered. - The higher the value, answers that are more apart are filtered out. 0 corresponds to exact duplicates. -1 turns off duplicate removal. - :param temperature_for_confidence: The divisor that is used to scale logits to calibrate confidence scores - :param use_confidence_scores_for_ranking: Whether to sort answers by confidence score (normalized between 0 and 1)(default) or by standard score (unbounded). - :param use_no_answer_legacy_confidence: Whether to use the legacy confidence definition for no_answer: difference between the best overall answer confidence and the no_answer gap confidence. - Otherwise we use the no_answer score normalized to a range of [0,1] by an expit function (default). - """ - if layer_dims is None: - layer_dims = [768, 2] - super(QuestionAnsweringHead, self).__init__() - if len(kwargs) > 0: - logger.warning( - "Some unused parameters are passed to the QuestionAnsweringHead. Might not be a problem. Params: %s", - json.dumps(kwargs), - ) - self.layer_dims = layer_dims - assert self.layer_dims[-1] == 2 - self.feed_forward = FeedForwardBlock(self.layer_dims) - logger.debug("Prediction head initialized with size %s", self.layer_dims) - self.num_labels = self.layer_dims[-1] - self.ph_output_type = "per_token_squad" - self.model_type = "span_classification" # predicts start and end token of answer - self.task_name = task_name - self.no_ans_boost = no_ans_boost - self.context_window_size = context_window_size - self.n_best = n_best - if n_best_per_sample: - self.n_best_per_sample = n_best_per_sample - else: - # increasing n_best_per_sample to n_best ensures that there are n_best predictions in total - # otherwise this might not be the case for very short documents with only one "sample" - self.n_best_per_sample = n_best - self.duplicate_filtering = duplicate_filtering - self.generate_config() - self.temperature_for_confidence = nn.Parameter(torch.ones(1) * temperature_for_confidence) - self.use_confidence_scores_for_ranking = use_confidence_scores_for_ranking - self.use_no_answer_legacy_confidence = use_no_answer_legacy_confidence - - @classmethod - def load( # type: ignore - cls, - pretrained_model_name_or_path: Union[str, Path], - revision: Optional[str] = None, - use_auth_token: Optional[Union[str, bool]] = None, - **kwargs, - ): - """ - Load a prediction head from a saved Haystack or transformers model. `pretrained_model_name_or_path` - can be one of the following: - a) Local path to a Haystack prediction head config (e.g. my-bert/prediction_head_0_config.json) - b) Local path to a Transformers model (e.g. my-bert) - c) Name of a public model from https://huggingface.co/models (e.g. distilbert-base-uncased-distilled-squad) - - - :param pretrained_model_name_or_path: local path of a saved model or name of a publicly available model. - Exemplary public names: - - distilbert-base-uncased-distilled-squad - - bert-large-uncased-whole-word-masking-finetuned-squad - See https://huggingface.co/models for full list - :param revision: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - if ( - os.path.exists(pretrained_model_name_or_path) - and "config.json" in str(pretrained_model_name_or_path) - and "prediction_head" in str(pretrained_model_name_or_path) - ): - # a) Haystack style - super(QuestionAnsweringHead, cls).load(str(pretrained_model_name_or_path)) - else: - # b) transformers style - # load all weights from model - full_qa_model = AutoModelForQuestionAnswering.from_pretrained( - pretrained_model_name_or_path, revision=revision, use_auth_token=use_auth_token, **kwargs - ) - # init empty head - head = cls(layer_dims=[full_qa_model.config.hidden_size, 2], task_name="question_answering") - # transfer weights for head from full model - head.feed_forward.feed_forward[0].load_state_dict(full_qa_model.qa_outputs.state_dict()) - del full_qa_model - - return head - - def forward(self, X: torch.Tensor): - """ - One forward pass through the prediction head model, starting with language model output on token level. - """ - logits = self.feed_forward(X) - return self.temperature_scale(logits) - - def logits_to_loss(self, logits: torch.Tensor, labels: torch.Tensor, **kwargs): - """ - Combine predictions and labels to a per sample loss. - """ - # todo explain how we only use first answer for train - # labels.shape = [batch_size, n_max_answers, 2]. n_max_answers is by default 6 since this is the - # most that occurs in the SQuAD dev set. The 2 in the final dimension corresponds to [start, end] - start_position = labels[:, 0, 0] - end_position = labels[:, 0, 1] - - # logits is of shape [batch_size, max_seq_len, 2]. Like above, the final dimension corresponds to [start, end] - start_logits, end_logits = logits.split(1, dim=-1) - start_logits = start_logits.squeeze(-1) - end_logits = end_logits.squeeze(-1) - - # Squeeze final singleton dimensions - if len(start_position.size()) > 1: - start_position = start_position.squeeze(-1) - if len(end_position.size()) > 1: - end_position = end_position.squeeze(-1) - - ignored_index = start_logits.size(1) - start_position.clamp_(0, ignored_index) - end_position.clamp_(0, ignored_index) - - # Workaround for pytorch bug in version 1.10.0 with non-continguous tensors - # Fix expected in 1.10.1 based on https://github.com/pytorch/pytorch/pull/64954 - start_logits = start_logits.contiguous() - start_position = start_position.contiguous() - end_logits = end_logits.contiguous() - end_position = end_position.contiguous() - - loss_fct = CrossEntropyLoss(reduction="none") - start_loss = loss_fct(start_logits, start_position) - end_loss = loss_fct(end_logits, end_position) - per_sample_loss = (start_loss + end_loss) / 2 - return per_sample_loss - - def temperature_scale(self, logits: torch.Tensor): - return torch.div(logits, self.temperature_for_confidence) - - def calibrate_conf(self, logits, label_all): - """ - Learning a temperature parameter to apply temperature scaling to calibrate confidence scores - """ - logits = torch.cat(logits, dim=0) - - # To handle no_answer labels correctly (-1,-1), we set their start_position to 0. The logit at index 0 also refers to no_answer - # TODO some language models do not have the CLS token at position 0. For these models, we need to map start_position==-1 to the index of CLS token - start_position = [label[0][0] if label[0][0] >= 0 else 0 for label in label_all] - end_position = [label[0][1] if label[0][1] >= 0 else 0 for label in label_all] - - start_logits, end_logits = logits.split(1, dim=-1) - start_logits = start_logits.squeeze(-1) - end_logits = end_logits.squeeze(-1) - - start_position = torch.tensor(start_position) - if len(start_position.size()) > 1: - start_position = start_position.squeeze(-1) - end_position = torch.tensor(end_position) - if len(end_position.size()) > 1: - end_position = end_position.squeeze(-1) - - ignored_index = start_logits.size(1) - 1 - start_position.clamp_(0, ignored_index) - end_position.clamp_(0, ignored_index) - - nll_criterion = CrossEntropyLoss() - - optimizer = optim.LBFGS([self.temperature_for_confidence], lr=0.01, max_iter=50) - - def eval_start_end_logits(): - loss = nll_criterion( - self.temperature_scale(start_logits), start_position.to(device=start_logits.device) - ) + nll_criterion(self.temperature_scale(end_logits), end_position.to(device=end_logits.device)) - loss.backward() - return loss - - optimizer.step(eval_start_end_logits) - - def logits_to_preds( - self, - logits: torch.Tensor, - span_mask: torch.Tensor, - start_of_word: torch.Tensor, - seq_2_start_t: torch.Tensor, - max_answer_length: int = 1000, - **kwargs, - ): - """ - Get the predicted index of start and end token of the answer. Note that the output is at token level - and not word level. Note also that these logits correspond to the tokens of a sample - (i.e. special tokens, question tokens, passage_tokens) - """ - - # Will be populated with the top-n predictions of each sample in the batch - # shape = batch_size x ~top_n - # Note that ~top_n = n if no_answer is within the top_n predictions - # ~top_n = n+1 if no_answer is not within the top_n predictions - all_top_n = [] - - # logits is of shape [batch_size, max_seq_len, 2]. The final dimension corresponds to [start, end] - start_logits, end_logits = logits.split(1, dim=-1) - start_logits = start_logits.squeeze(-1) - end_logits = end_logits.squeeze(-1) - - # Calculate a few useful variables - batch_size = start_logits.size()[0] - max_seq_len = start_logits.shape[1] # target dim - - # get scores for all combinations of start and end logits => candidate answers - start_matrix = start_logits.unsqueeze(2).expand(-1, -1, max_seq_len) - end_matrix = end_logits.unsqueeze(1).expand(-1, max_seq_len, -1) - start_end_matrix = start_matrix + end_matrix - - # disqualify answers where end < start - # (set the lower triangular matrix to low value, excluding diagonal) - indices = torch.tril_indices(max_seq_len, max_seq_len, offset=-1, device=start_end_matrix.device) - start_end_matrix[:, indices[0][:], indices[1][:]] = -888 - - # disqualify answers where answer span is greater than max_answer_length - # (set the upper triangular matrix to low value, excluding diagonal) - indices_long_span = torch.triu_indices( - max_seq_len, max_seq_len, offset=max_answer_length, device=start_end_matrix.device - ) - start_end_matrix[:, indices_long_span[0][:], indices_long_span[1][:]] = -777 - - # disqualify answers where start=0, but end != 0 - start_end_matrix[:, 0, 1:] = -666 - - # Turn 1d span_mask vectors into 2d span_mask along 2 different axes - # span mask has: - # 0 for every position that is never a valid start or end index (question tokens, mid and end special tokens, padding) - # 1 everywhere else - span_mask_start = span_mask.unsqueeze(2).expand(-1, -1, max_seq_len) - span_mask_end = span_mask.unsqueeze(1).expand(-1, max_seq_len, -1) - span_mask_2d = span_mask_start + span_mask_end - # disqualify spans where either start or end is on an invalid token - invalid_indices = torch.nonzero((span_mask_2d != 2), as_tuple=True) - start_end_matrix[invalid_indices[0][:], invalid_indices[1][:], invalid_indices[2][:]] = -999 - - # Sort the candidate answers by their score. Sorting happens on the flattened matrix. - # flat_sorted_indices.shape: (batch_size, max_seq_len^2, 1) - flat_scores = start_end_matrix.view(batch_size, -1) - flat_sorted_indices_2d = flat_scores.sort(descending=True)[1] - flat_sorted_indices = flat_sorted_indices_2d.unsqueeze(2) - - # The returned indices are then converted back to the original dimensionality of the matrix. - # sorted_candidates.shape : (batch_size, max_seq_len^2, 2) - start_indices = torch.div(flat_sorted_indices, max_seq_len, rounding_mode="trunc") - end_indices = flat_sorted_indices % max_seq_len - sorted_candidates = torch.cat((start_indices, end_indices), dim=2) - - # Get the n_best candidate answers for each sample - sorted_candidates = sorted_candidates.cpu().numpy() - start_end_matrix = start_end_matrix.cpu().numpy() - for sample_idx in range(batch_size): - sample_top_n = self.get_top_candidates( - sorted_candidates[sample_idx], - start_end_matrix[sample_idx], - sample_idx, - start_matrix=start_matrix[sample_idx], - end_matrix=end_matrix[sample_idx], - ) - all_top_n.append(sample_top_n) - - return all_top_n - - def get_top_candidates(self, sorted_candidates, start_end_matrix, sample_idx: int, start_matrix, end_matrix): - """ - Returns top candidate answers as a list of Span objects. Operates on a matrix of summed start and end logits. - This matrix corresponds to a single sample (includes special tokens, question tokens, passage tokens). - This method always returns a list of len n_best + 1 (it is comprised of the n_best positive answers along with the one no_answer) - """ - # Initialize some variables - top_candidates: List[QACandidate] = [] - n_candidates = sorted_candidates.shape[0] - start_idx_candidates = set() - end_idx_candidates = set() - - start_matrix_softmax_start = torch.softmax(start_matrix[:, 0], dim=-1).cpu().numpy() - end_matrix_softmax_end = torch.softmax(end_matrix[0, :], dim=-1).cpu().numpy() - # Iterate over all candidates and break when we have all our n_best candidates - for candidate_idx in range(n_candidates): - # Retrieve candidate's indices - start_idx = sorted_candidates[candidate_idx, 0] - end_idx = sorted_candidates[candidate_idx, 1] - # Ignore no_answer scores which will be extracted later in this method - if start_idx == 0 and end_idx == 0: - continue - if self.duplicate_filtering > -1 and (start_idx in start_idx_candidates or end_idx in end_idx_candidates): - continue - score = start_end_matrix[start_idx, end_idx] - confidence = ( - (start_matrix_softmax_start[start_idx] + end_matrix_softmax_end[end_idx]) / 2 - if score > -500 - else np.exp(score / 10) # disqualify answers according to scores in logits_to_preds() - ) - top_candidates.append( - QACandidate( - offset_answer_start=start_idx, - offset_answer_end=end_idx, - score=score, - answer_type="span", - offset_unit="token", - aggregation_level="passage", - passage_id=str(sample_idx), - confidence=confidence, - ) - ) - if self.duplicate_filtering > -1: - for i in range(0, self.duplicate_filtering + 1): - start_idx_candidates.add(start_idx + i) - start_idx_candidates.add(start_idx - i) - end_idx_candidates.add(end_idx + i) - end_idx_candidates.add(end_idx - i) - - # Only check if we have enough candidates after adding new candidate to the list - if len(top_candidates) == self.n_best_per_sample: - break - - no_answer_score = start_end_matrix[0, 0] - no_answer_confidence = (start_matrix_softmax_start[0] + end_matrix_softmax_end[0]) / 2 - top_candidates.append( - QACandidate( - offset_answer_start=0, - offset_answer_end=0, - score=no_answer_score, - answer_type="no_answer", - offset_unit="token", - aggregation_level="passage", - passage_id=None, - confidence=no_answer_confidence, - ) - ) - - return top_candidates - - def formatted_preds( - self, preds: List[QACandidate], baskets: List[SampleBasket], logits: Optional[torch.Tensor] = None, **kwargs - ): - """ - Takes a list of passage level predictions, each corresponding to one sample, and converts them into document level - predictions. Leverages information in the SampleBaskets. Assumes that we are being passed predictions from - ALL samples in the one SampleBasket i.e. all passages of a document. Logits should be None, because we have - already converted the logits to predictions before calling formatted_preds. - (see Inferencer._get_predictions_and_aggregate()). - """ - # Unpack some useful variables - # passage_start_t is the token index of the passage relative to the document (usually a multiple of doc_stride) - # seq_2_start_t is the token index of the first token in passage relative to the input sequence (i.e. number of - # special tokens and question tokens that come before the passage tokens) - if logits or preds is None: - logger.error( - "QuestionAnsweringHead.formatted_preds() expects preds as input and logits to be None \ - but was passed something different" - ) - samples = [s for b in baskets for s in b.samples] # type: ignore - ids = [s.id for s in samples] - passage_start_t = [s.features[0]["passage_start_t"] for s in samples] # type: ignore - seq_2_start_t = [s.features[0]["seq_2_start_t"] for s in samples] # type: ignore - - # Aggregate passage level predictions to create document level predictions. - # This method assumes that all passages of each document are contained in preds - # i.e. that there are no incomplete documents. The output of this step - # are prediction spans - preds_d = self.aggregate_preds(preds, passage_start_t, ids, seq_2_start_t) - - # Separate top_preds list from the no_ans_gap float. - top_preds, no_ans_gaps = zip(*preds_d) - - # Takes document level prediction spans and returns string predictions - doc_preds = self.to_qa_preds(top_preds, no_ans_gaps, baskets) - - return doc_preds - - def to_qa_preds(self, top_preds, no_ans_gaps, baskets): - """ - Groups Span objects together in a QAPred object - """ - ret = [] - - # Iterate over each set of document level prediction - for pred_d, no_ans_gap, basket in zip(top_preds, no_ans_gaps, baskets): - # Unpack document offsets, clear text and id - token_offsets = basket.raw["document_offsets"] - pred_id = basket.id_external if basket.id_external else basket.id_internal - - # These options reflect the different input dicts that can be assigned to the basket - # before any kind of normalization or preprocessing can happen - question_names = ["question_text", "qas", "questions"] - doc_names = ["document_text", "context", "text"] - - document_text = try_get(doc_names, basket.raw) - question = self.get_question(question_names, basket.raw) - ground_truth = self.get_ground_truth(basket) - - curr_doc_pred = QAPred( - id=pred_id, - prediction=pred_d, - context=document_text, - question=question, - token_offsets=token_offsets, - context_window_size=self.context_window_size, - aggregation_level="document", - ground_truth_answer=ground_truth, - no_answer_gap=no_ans_gap, - ) - - ret.append(curr_doc_pred) - return ret - - @staticmethod - def get_ground_truth(basket: SampleBasket): - if "answers" in basket.raw: - return basket.raw["answers"] - elif "annotations" in basket.raw: - return basket.raw["annotations"] - else: - return None - - @staticmethod - def get_question(question_names: List[str], raw_dict: Dict): - # For NQ style dicts - qa_name = None - if "qas" in raw_dict: - qa_name = "qas" - elif "question" in raw_dict: - qa_name = "question" - if qa_name and type(raw_dict[qa_name][0]) == dict: - return raw_dict[qa_name][0]["question"] - return try_get(question_names, raw_dict) - - def aggregate_preds(self, preds, passage_start_t, ids, seq_2_start_t=None, labels=None): - """ - Aggregate passage level predictions to create document level predictions. - This method assumes that all passages of each document are contained in preds - i.e. that there are no incomplete documents. The output of this step - are prediction spans. No answer is represented by a (-1, -1) span on the document level - """ - # Initialize some variables - n_samples = len(preds) - all_basket_preds = {} - all_basket_labels = {} - - # Iterate over the preds of each sample - remove final number which is the sample id and not needed for aggregation - for sample_idx in range(n_samples): - basket_id = ids[sample_idx] - basket_id = basket_id.split("-")[:-1] - basket_id = "-".join(basket_id) - - # curr_passage_start_t is the token offset of the current passage - # It will always be a multiple of doc_stride - curr_passage_start_t = passage_start_t[sample_idx] - - # This is to account for the fact that all model input sequences start with some special tokens - # and also the question tokens before passage tokens. - if seq_2_start_t: - cur_seq_2_start_t = seq_2_start_t[sample_idx] - curr_passage_start_t -= cur_seq_2_start_t - - # Converts the passage level predictions+labels to document level predictions+labels. Note - # that on the passage level a no answer is (0,0) but at document level it is (-1,-1) since (0,0) - # would refer to the first token of the document - pred_d = self.pred_to_doc_idxs(preds[sample_idx], curr_passage_start_t) - if labels: - label_d = self.label_to_doc_idxs(labels[sample_idx], curr_passage_start_t) - - # Initialize the basket_id as a key in the all_basket_preds and all_basket_labels dictionaries - if basket_id not in all_basket_preds: - all_basket_preds[basket_id] = [] - all_basket_labels[basket_id] = [] - - # Add predictions and labels to dictionary grouped by their basket_ids - all_basket_preds[basket_id].append(pred_d) - if labels: - all_basket_labels[basket_id].append(label_d) - - # Pick n-best predictions and remove repeated labels - all_basket_preds = {k: self.reduce_preds(v) for k, v in all_basket_preds.items()} - if labels: - all_basket_labels = {k: self.reduce_labels(v) for k, v in all_basket_labels.items()} - - # Return aggregated predictions in order as a list of lists - keys = list(all_basket_preds) - aggregated_preds = [all_basket_preds[k] for k in keys] - if labels: - labels = [all_basket_labels[k] for k in keys] - return aggregated_preds, labels - else: - return aggregated_preds - - @staticmethod - def reduce_labels(labels): - """ - Removes repeat answers. Represents a no answer label as (-1,-1) - """ - positive_answers = [(start, end) for x in labels for start, end in x if not (start == -1 and end == -1)] - if not positive_answers: - return [(-1, -1)] - else: - return list(set(positive_answers)) - - def reduce_preds(self, preds): - """ - This function contains the logic for choosing the best answers from each passage. In the end, it - returns the n_best predictions on the document level. - """ - # Initialize variables - passage_no_answer = [] - passage_best_score = [] - passage_best_confidence = [] - no_answer_scores = [] - no_answer_confidences = [] - n_samples = len(preds) - - # Iterate over the top predictions for each sample - for sample_idx, sample_preds in enumerate(preds): - best_pred = sample_preds[0] - best_pred_score = best_pred.score - best_pred_confidence = best_pred.confidence - no_answer_score, no_answer_confidence = self.get_no_answer_score_and_confidence(sample_preds) - no_answer_score += self.no_ans_boost - # TODO we might want to apply some kind of a no_ans_boost to no_answer_confidence too - no_answer = no_answer_score > best_pred_score - passage_no_answer.append(no_answer) - no_answer_scores.append(no_answer_score) - no_answer_confidences.append(no_answer_confidence) - passage_best_score.append(best_pred_score) - passage_best_confidence.append(best_pred_confidence) - - # Get all predictions in flattened list and sort by score - pos_answers_flat = [] - for sample_idx, passage_preds in enumerate(preds): - for qa_candidate in passage_preds: - if not (qa_candidate.offset_answer_start == -1 and qa_candidate.offset_answer_end == -1): - pos_answers_flat.append( - QACandidate( - offset_answer_start=qa_candidate.offset_answer_start, - offset_answer_end=qa_candidate.offset_answer_end, - score=qa_candidate.score, - answer_type=qa_candidate.answer_type, - offset_unit="token", - aggregation_level="document", - passage_id=str(sample_idx), - n_passages_in_doc=n_samples, - confidence=qa_candidate.confidence, - ) - ) - - # TODO add switch for more variation in answers, e.g. if varied_ans then never return overlapping answers - pos_answer_dedup = self.deduplicate(pos_answers_flat) - - # This is how much no_ans_boost needs to change to turn a no_answer to a positive answer (or vice versa) - no_ans_gap = -min(nas - pbs for nas, pbs in zip(no_answer_scores, passage_best_score)) - no_ans_gap_confidence = -min(nas - pbs for nas, pbs in zip(no_answer_confidences, passage_best_confidence)) - - # "no answer" scores and positive answers scores are difficult to compare, because - # + a positive answer score is related to a specific text qa_candidate - # - a "no answer" score is related to all input texts - # Thus we compute the "no answer" score relative to the best possible answer and adjust it by - # the most significant difference between scores. - # Most significant difference: change top prediction from "no answer" to answer (or vice versa) - best_overall_positive_score = max(x.score for x in pos_answer_dedup) - best_overall_positive_confidence = max(x.confidence for x in pos_answer_dedup) - no_answer_pred = QACandidate( - offset_answer_start=-1, - offset_answer_end=-1, - score=best_overall_positive_score - no_ans_gap, - answer_type="no_answer", - offset_unit="token", - aggregation_level="document", - passage_id=None, - n_passages_in_doc=n_samples, - confidence=best_overall_positive_confidence - no_ans_gap_confidence - if self.use_no_answer_legacy_confidence - else float(expit(np.asarray(best_overall_positive_score - no_ans_gap) / 8)), - ) - - # Add no answer to positive answers, sort the order and return the n_best - n_preds = [no_answer_pred] + pos_answer_dedup - n_preds_sorted = sorted( - n_preds, key=lambda x: x.confidence if self.use_confidence_scores_for_ranking else x.score, reverse=True - ) - n_preds_reduced = n_preds_sorted[: self.n_best] - return n_preds_reduced, no_ans_gap - - @staticmethod - def deduplicate(flat_pos_answers): - # Remove duplicate spans that might be twice predicted in two different passages - seen = {} - for qa_answer in flat_pos_answers: - if (qa_answer.offset_answer_start, qa_answer.offset_answer_end) not in seen: - seen[(qa_answer.offset_answer_start, qa_answer.offset_answer_end)] = qa_answer - else: - seen_score = seen[(qa_answer.offset_answer_start, qa_answer.offset_answer_end)].score - if qa_answer.score > seen_score: - seen[(qa_answer.offset_answer_start, qa_answer.offset_answer_end)] = qa_answer - return list(seen.values()) - - @staticmethod - def get_no_answer_score_and_confidence(preds): - for qa_answer in preds: - start = qa_answer.offset_answer_start - end = qa_answer.offset_answer_end - score = qa_answer.score - confidence = qa_answer.confidence - if start == -1 and end == -1: - return score, confidence - raise Exception - - @staticmethod - def pred_to_doc_idxs(pred, passage_start_t): - """ - Converts the passage level predictions to document level predictions. Note that on the doc level we - don't have special tokens or question tokens. This means that a no answer - cannot be represented by a (0,0) qa_answer but will instead be represented by (-1, -1) - """ - new_pred = [] - for qa_answer in pred: - start = qa_answer.offset_answer_start - end = qa_answer.offset_answer_end - if start == 0: - start = -1 - else: - start += passage_start_t - if start < 0: - logger.error("Start token index < 0 (document level)") - if end == 0: - end = -1 - else: - end += passage_start_t - if end < 0: - logger.error("End token index < 0 (document level)") - qa_answer.to_doc_level(start, end) - new_pred.append(qa_answer) - return new_pred - - @staticmethod - def label_to_doc_idxs(label, passage_start_t): - """ - Converts the passage level labels to document level labels. Note that on the doc level we - don't have special tokens or question tokens. This means that a no answer - cannot be represented by a (0,0) span but will instead be represented by (-1, -1) - """ - new_label = [] - for start, end in label: - # If there is a valid label - if start > 0 or end > 0: - new_label.append((start + passage_start_t, end + passage_start_t)) - # If the label is a no answer, we represent this as a (-1, -1) span - # since there is no CLS token on the document level - if start == 0 and end == 0: - new_label.append((-1, -1)) - return new_label - - def prepare_labels(self, labels, start_of_word, **kwargs): - return labels - - -class TextSimilarityHead(PredictionHead): - """ - Trains a head on predicting the similarity of two texts like in Dense Passage Retrieval. - """ - - def __init__(self, similarity_function: str = "dot_product", global_loss_buffer_size: int = 150000, **kwargs): - """ - Init the TextSimilarityHead. - - :param similarity_function: Function to calculate similarity between queries and passage embeddings. - Choose either "dot_product" (Default) or "cosine". - :param global_loss_buffer_size: Buffer size for all_gather() in DDP. - Increase if errors like "encoded data exceeds max_size ..." come up - :param kwargs: - """ - super(TextSimilarityHead, self).__init__() - - self.similarity_function = similarity_function - self.loss_fct = NLLLoss(reduction="mean") - self.task_name = "text_similarity" - self.model_type = "text_similarity" - self.ph_output_type = "per_sequence" - self.global_loss_buffer_size = global_loss_buffer_size - self.generate_config() - - @classmethod - def dot_product_scores(cls, query_vectors: torch.Tensor, passage_vectors: torch.Tensor) -> torch.Tensor: - """ - Calculates dot product similarity scores for two 2-dimensional tensors - - :param query_vectors: tensor of query embeddings from BiAdaptive model - of dimension n1 x D, - where n1 is the number of queries/batch size and D is embedding size - :param passage_vectors: tensor of context/passage embeddings from BiAdaptive model - of dimension n2 x D, - where n2 is (batch_size * num_positives) + (batch_size * num_hard_negatives) - and D is embedding size - - :return: dot_product: similarity score of each query with each context/passage (dimension: n1xn2) - """ - # q_vector: n1 x D, ctx_vectors: n2 x D, result n1 x n2 - dot_product = torch.matmul(query_vectors, torch.transpose(passage_vectors, 0, 1)) - return dot_product - - @classmethod - def cosine_scores(cls, query_vectors: torch.Tensor, passage_vectors: torch.Tensor) -> torch.Tensor: - """ - Calculates cosine similarity scores for two 2-dimensional tensors - - :param query_vectors: tensor of query embeddings from BiAdaptive model - of dimension n1 x D, - where n1 is the number of queries/batch size and D is embedding size - :param passage_vectors: tensor of context/passage embeddings from BiAdaptive model - of dimension n2 x D, - where n2 is (batch_size * num_positives) + (batch_size * num_hard_negatives) - and D is embedding size - - :return: cosine similarity score of each query with each context/passage (dimension: n1xn2) - """ - # q_vector: n1 x D, ctx_vectors: n2 x D, result n1 x n2 - cosine_similarities = [] - passages_per_batch = passage_vectors.shape[0] - for query_vector in query_vectors: - query_vector_repeated = query_vector.repeat(passages_per_batch, 1) - current_cosine_similarities = nn.functional.cosine_similarity(query_vector_repeated, passage_vectors, dim=1) - cosine_similarities.append(current_cosine_similarities) - return torch.stack(cosine_similarities) - - def get_similarity_function(self): - """ - Returns the type of similarity function used to compare queries and passages/contexts - """ - if "dot_product" in self.similarity_function: - return TextSimilarityHead.dot_product_scores - elif "cosine" in self.similarity_function: - return TextSimilarityHead.cosine_scores - else: - raise AttributeError( - f"The similarity function can only be 'dot_product' or 'cosine', not '{self.similarity_function}'" - ) - - def forward(self, query_vectors: torch.Tensor, passage_vectors: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: - """ - Only packs the embeddings from both language models into a tuple. No further modification. - The similarity calculation is handled later to enable distributed training (DDP) - while keeping the support for in-batch negatives. - (Gather all embeddings from nodes => then do similarity scores + loss) - - :param query_vectors: Tensor of query embeddings from BiAdaptive model - of dimension n1 x D, - where n1 is the number of queries/batch size and D is embedding size - :param passage_vectors: Tensor of context/passage embeddings from BiAdaptive model - of dimension n2 x D, - where n2 is the number of queries/batch size and D is embedding size - """ - return query_vectors, passage_vectors - - def _embeddings_to_scores(self, query_vectors: torch.Tensor, passage_vectors: torch.Tensor) -> torch.Tensor: - """ - Calculates similarity scores between all given query_vectors and passage_vectors - - :param query_vectors: Tensor of queries encoded by the query encoder model - :param passage_vectors: Tensor of passages encoded by the passage encoder model - :return: Tensor of log softmax similarity scores of each query with each passage (dimension: n1xn2) - """ - sim_func = self.get_similarity_function() - scores = sim_func(query_vectors, passage_vectors) - - if len(query_vectors.size()) > 1: - q_num = query_vectors.size(0) - scores = scores.view(q_num, -1) - - softmax_scores = nn.functional.log_softmax(scores, dim=1) - return softmax_scores - - def logits_to_loss(self, logits: Tuple[torch.Tensor, torch.Tensor], label_ids, **kwargs): # type: ignore - """ - Computes the loss (Default: NLLLoss) by applying a similarity function (Default: dot product) to the input - tuple of (query_vectors, passage_vectors) and afterwards applying the loss function on similarity scores. - - :param logits: Tuple of Tensors (query_embedding, passage_embedding) as returned from forward() - - :return: negative log likelihood loss from similarity scores - """ - # Check if DDP is initialized - try: - if torch.distributed.is_available(): - rank = torch.distributed.get_rank() - else: - rank = -1 - except (AssertionError, RuntimeError): - rank = -1 - - # Prepare predicted scores - query_vectors, passage_vectors = logits - - # Prepare Labels - positive_idx_per_question = torch.nonzero((label_ids.view(-1) == 1), as_tuple=False) - - # Gather global embeddings from all distributed nodes (DDP) - if rank != -1: - q_vector_to_send = torch.empty_like(query_vectors).cpu().copy_(query_vectors).detach_() - p_vector_to_send = torch.empty_like(passage_vectors).cpu().copy_(passage_vectors).detach_() - - global_question_passage_vectors = all_gather_list( - [q_vector_to_send, p_vector_to_send, positive_idx_per_question], max_size=self.global_loss_buffer_size - ) - - global_query_vectors = [] - global_passage_vectors = [] - global_positive_idx_per_question = [] - total_passages = 0 - for i, item in enumerate(global_question_passage_vectors): - q_vector, p_vectors, positive_idx = item - - if i != rank: - global_query_vectors.append(q_vector.to(query_vectors.device)) - global_passage_vectors.append(p_vectors.to(passage_vectors.device)) - global_positive_idx_per_question.extend([v + total_passages for v in positive_idx]) - else: - global_query_vectors.append(query_vectors) - global_passage_vectors.append(passage_vectors) - global_positive_idx_per_question.extend([v + total_passages for v in positive_idx_per_question]) - total_passages += p_vectors.size(0) - - global_query_vectors = torch.cat(global_query_vectors, dim=0) # type: ignore - global_passage_vectors = torch.cat(global_passage_vectors, dim=0) # type: ignore - global_positive_idx_per_question = torch.LongTensor(global_positive_idx_per_question) # type: ignore - else: - global_query_vectors = query_vectors # type: ignore - global_passage_vectors = passage_vectors # type: ignore - global_positive_idx_per_question = positive_idx_per_question # type: ignore - - # Get similarity scores - softmax_scores = self._embeddings_to_scores(global_query_vectors, global_passage_vectors) # type: ignore - targets = global_positive_idx_per_question.squeeze(-1).to(softmax_scores.device) # type: ignore - - # Calculate loss - loss = self.loss_fct(softmax_scores, targets) - return loss - - def logits_to_preds(self, logits: Tuple[torch.Tensor, torch.Tensor], **kwargs) -> torch.Tensor: # type: ignore - """ - Returns predicted ranks(similarity) of passages/context for each query - - :param logits: tensor of log softmax similarity scores of each query with each context/passage (dimension: n1xn2) - - :return: predicted ranks of passages for each query - """ - query_vectors, passage_vectors = logits - softmax_scores = self._embeddings_to_scores(query_vectors, passage_vectors) - _, sorted_scores = torch.sort(softmax_scores, dim=1, descending=True) - return sorted_scores - - def prepare_labels(self, label_ids, **kwargs) -> torch.Tensor: # type: ignore - """ - Returns a tensor with passage labels(0:hard_negative/1:positive) for each query - - :return: passage labels(0:hard_negative/1:positive) for each query - """ - labels = torch.zeros(label_ids.size(0), label_ids.numel()) - - positive_indices = torch.nonzero(label_ids.view(-1) == 1, as_tuple=False) - - for i, indx in enumerate(positive_indices): - labels[i, indx.item()] = 1 - return labels - - def formatted_preds(self, logits: Tuple[torch.Tensor, torch.Tensor], **kwargs): - raise NotImplementedError("formatted_preds is not supported in TextSimilarityHead yet!") - - -def _is_json(x): - if issubclass(type(x), Path): - return True - try: - json.dumps(x) - return True - except: - return False diff --git a/haystack/modeling/model/predictions.py b/haystack/modeling/model/predictions.py deleted file mode 100644 index db74c4e590..0000000000 --- a/haystack/modeling/model/predictions.py +++ /dev/null @@ -1,335 +0,0 @@ -from typing import List, Any, Optional, Tuple, Union, Dict - -import logging -from abc import ABC - - -logger = logging.getLogger(__name__) - - -class Pred(ABC): - """ - Abstract base class for predictions of every task - """ - - def __init__(self, id: str, prediction: List[Any], context: str): - self.id = id - self.prediction = prediction - self.context = context - - def to_json(self): - raise NotImplementedError - - -class QACandidate: - """ - A single QA candidate answer. - """ - - def __init__( - self, - answer_type: str, - score: float, - offset_answer_start: int, - offset_answer_end: int, - offset_unit: str, - aggregation_level: str, - probability: Optional[float] = None, - n_passages_in_doc: Optional[int] = None, - passage_id: Optional[str] = None, - confidence: Optional[float] = None, - ): - """ - :param answer_type: The category that this answer falls into e.g. "no_answer", "yes", "no" or "span" - :param score: The score representing the model's confidence of this answer - :param offset_answer_start: The index of the start of the answer span (whether it is char or tok is stated in self.offset_unit) - :param offset_answer_end: The index of the start of the answer span (whether it is char or tok is stated in self.offset_unit) - :param offset_unit: States whether the offsets refer to character or token indices - :param aggregation_level: States whether this candidate and its indices are on a passage level (pre aggregation) or on a document level (post aggregation) - :param probability: The probability the model assigns to the answer - :param n_passages_in_doc: Number of passages that make up the document - :param passage_id: The id of the passage which contains this candidate answer - :param confidence: The (calibrated) confidence score representing the model's predicted accuracy of the index of the start of the answer span - """ - # self.answer_type can be "no_answer", "yes", "no" or "span" - self.answer_type = answer_type - self.score = score - self.probability = probability - - # If self.answer_type is "span", self.answer is a string answer (generated by self.span_to_string()) - # Otherwise, it is None - self.answer = None # type: Optional[str] - self.offset_answer_start = offset_answer_start - self.offset_answer_end = offset_answer_end - - # If self.answer_type is in ["yes", "no"] then self.answer_support is a text string - # If self.answer is a string answer span or self.answer_type is "no_answer", answer_support is None - self.answer_support = None # type: Optional[str] - self.offset_answer_support_start = None # type: Optional[int] - self.offset_answer_support_end = None # type: Optional[int] - - # self.context is the document or passage where the answer is found - self.context_window = None # type: Optional[str] - self.offset_context_window_start = None # type: Optional[int] - self.offset_context_window_end = None # type: Optional[int] - - # Offset unit is either "token" or "char" - # Aggregation level is either "doc" or "passage" - self.offset_unit = offset_unit - self.aggregation_level = aggregation_level - - self.n_passages_in_doc = n_passages_in_doc - self.passage_id = passage_id - self.confidence = confidence - - # This attribute is used by Haystack to store sample metadata - self.meta = None - - def set_context_window(self, context_window_size: int, clear_text: str): - window_str, start_ch, end_ch = self._create_context_window(context_window_size, clear_text) - self.context_window = window_str - self.offset_context_window_start = start_ch - self.offset_context_window_end = end_ch - - def set_answer_string(self, token_offsets: List[int], document_text: str): - pred_str, self.offset_answer_start, self.offset_answer_end = self._span_to_string(token_offsets, document_text) - self.offset_unit = "char" - self._add_answer(pred_str) - - def _add_answer(self, string: str): - """ - Set the answer string. This method will check that the answer given is valid given the start - and end indices that are stored in the object. - """ - if string == "": - self.answer = "no_answer" - if self.offset_answer_start != 0 or self.offset_answer_end != 0: - logger.error( - "Both start and end offsets should be 0: \n%s, %s with a no_answer. ", - self.offset_answer_start, - self.offset_answer_end, - ) - else: - self.answer = string - if self.offset_answer_end - self.offset_answer_start <= 0: - logger.error( - "End offset comes before start offset: \n(%s, %s) with a span answer. ", - self.offset_answer_start, - self.offset_answer_end, - ) - elif self.offset_answer_end <= 0: - logger.error( - "Invalid end offset: \n(%s, %s) with a span answer. ", - self.offset_answer_start, - self.offset_answer_end, - ) - - def _create_context_window(self, context_window_size: int, clear_text: str) -> Tuple[str, int, int]: - """ - Extract from the clear_text a window that contains the answer and (usually) some amount of text on either - side of the answer. Useful for cases where the answer and its surrounding context needs to be - displayed in a UI. If the self.context_window_size is smaller than the extracted answer, it will be - enlarged so that it can contain the answer - - :param context_window_size: The size of the context window to be generated. Note that the window size may be increased if the answer is longer. - :param clear_text: The text from which the answer is extracted - """ - if self.offset_answer_start == 0 and self.offset_answer_end == 0: - return "", 0, 0 - else: - # If the extracted answer is longer than the context_window_size, - # we will increase the context_window_size - len_ans = self.offset_answer_end - self.offset_answer_start - context_window_size = max(context_window_size, len_ans + 1) - - len_text = len(clear_text) - midpoint = int(len_ans / 2) + self.offset_answer_start - half_window = int(context_window_size / 2) - window_start_ch = midpoint - half_window - window_end_ch = midpoint + half_window - - # if we have part of the context window overlapping the start or end of the passage, - # we'll trim it and use the additional chars on the other side of the answer - overhang_start = max(0, -window_start_ch) - overhang_end = max(0, window_end_ch - len_text) - window_start_ch -= overhang_end - window_start_ch = max(0, window_start_ch) - window_end_ch += overhang_start - window_end_ch = min(len_text, window_end_ch) - window_str = clear_text[window_start_ch:window_end_ch] - return window_str, window_start_ch, window_end_ch - - def _span_to_string(self, token_offsets: List[int], clear_text: str) -> Tuple[str, int, int]: - """ - Generates a string answer span using self.offset_answer_start and self.offset_answer_end. If the candidate - is a no answer, an empty string is returned - - :param token_offsets: A list of ints which give the start character index of the corresponding token - :param clear_text: The text from which the answer span is to be extracted - :return: The string answer span, followed by the start and end character indices - """ - if self.offset_unit != "token": - logger.error( - "QACandidate needs to have self.offset_unit=token before calling _span_to_string() (id = %s)", - self.passage_id, - ) - - start_t = self.offset_answer_start - end_t = self.offset_answer_end - - # If it is a no_answer prediction - if start_t == -1 and end_t == -1: - return "", 0, 0 - - n_tokens = len(token_offsets) - - # We do this to point to the beginning of the first token after the span instead of - # the beginning of the last token in the span - end_t += 1 - - # Predictions sometimes land on the very final special token of the passage. But there are no - # special tokens on the document level. We will just interpret this as a span that stretches - # to the end of the document - end_t = min(end_t, n_tokens) - - start_ch = int(token_offsets[start_t]) - # i.e. pointing at the END of the last token - if end_t == n_tokens: - end_ch = len(clear_text) - else: - end_ch = token_offsets[end_t] - - final_text = clear_text[start_ch:end_ch] - - # if the final_text is more than whitespaces we trim it otherwise return a no_answer - # final_text can be an empty string if start_t points to the very final token of the passage - # final_text can be a whitespace if there is a whitespace token in the text, e.g., - # if the original text contained multiple consecutive whitespaces - cleaned_final_text = final_text.strip() - if not cleaned_final_text: - self.answer_type = "no_answer" - return "", 0, 0 - - # Adjust the offsets in case of whitespace at the beginning of the answer - left_offset = len(final_text) - len(final_text.lstrip()) - if left_offset: - start_ch = start_ch + left_offset - - end_ch = start_ch + len(cleaned_final_text) - - return cleaned_final_text, start_ch, end_ch - - def to_doc_level(self, start: int, end: int): - """ - Populate the start and end indices with document level indices. Changes aggregation level to 'document' - """ - self.offset_answer_start = start - self.offset_answer_end = end - self.aggregation_level = "document" - - def to_list(self) -> List[Optional[Union[str, int, float]]]: - return [self.answer, self.offset_answer_start, self.offset_answer_end, self.score, self.passage_id] - - -class QAPred(Pred): - """ - A set of QA predictions for a passage or a document. The candidates are stored in QAPred.prediction which is a - list of QACandidate objects. Also contains all attributes needed to convert the object into json format and also - to create a context window for a UI - """ - - def __init__( - self, - id: str, - prediction: List[QACandidate], - context: str, - question: str, - token_offsets: List[int], - context_window_size: int, - aggregation_level: str, - no_answer_gap: float, - ground_truth_answer: Optional[str] = None, - answer_types: Optional[List[str]] = None, - ): - """ - :param id: The id of the passage or document - :param prediction: A list of QACandidate objects for the given question and document - :param context: The text passage from which the answer can be extracted - :param question: The question being posed - :param token_offsets: A list of ints indicating the start char index of each token - :param context_window_size: The number of chars in the text window around the answer - :param aggregation_level: States whether this candidate and its indices are on a passage level (pre aggregation) or on a document level (post aggregation) - :param no_answer_gap: How much the QuestionAnsweringHead.no_ans_boost needs to change to turn a no_answer to a positive answer - :param ground_truth_answer: Ground truth answers - :param answer_types: List of answer_types supported by this task e.g. ["span", "yes_no", "no_answer"] - """ - if answer_types is None: - answer_types = [] - super().__init__(id, prediction, context) - self.question = question - self.token_offsets = token_offsets - self.context_window_size = context_window_size - self.aggregation_level = aggregation_level - self.answer_types = answer_types - self.ground_truth_answer = ground_truth_answer - self.no_answer_gap = no_answer_gap - self.n_passages = self.prediction[0].n_passages_in_doc - for qa_candidate in self.prediction: - qa_candidate.set_answer_string(token_offsets, self.context) - qa_candidate.set_context_window(self.context_window_size, self.context) - - def to_json(self, squad=False) -> Dict: - """ - Converts the information stored in the object into a json format. - - :param squad: If True, no_answers are represented by the empty string instead of "no_answer" - """ - answers = self._answers_to_json(self.id, squad) - ret = { - "task": "qa", - "predictions": [ - { - "question": self.question, - "id": self.id, - "ground_truth": self.ground_truth_answer, - "answers": answers, - "no_ans_gap": self.no_answer_gap, # Add no_ans_gap to current no_ans_boost for switching top prediction - } - ], - } - if squad: - del ret["predictions"][0]["id"] # type: ignore - ret["predictions"][0]["question_id"] = self.id # type: ignore - return ret - - def _answers_to_json(self, ext_id, squad=False) -> List[Dict]: - """ - Convert all answers into a json format. - - :param ext_id: ID of the question document pair. - :param squad: If True, no_answers are represented by the empty string instead of "no_answer". - """ - ret = [] - - # iterate over the top_n predictions of the one document - for qa_candidate in self.prediction: - if squad and qa_candidate.answer == "no_answer": - answer_string = "" - else: - answer_string = qa_candidate.answer - curr = { - "score": qa_candidate.score, - "probability": None, - "answer": answer_string, - "offset_answer_start": qa_candidate.offset_answer_start, - "offset_answer_end": qa_candidate.offset_answer_end, - "context": qa_candidate.context_window, - "offset_context_start": qa_candidate.offset_context_window_start, - "offset_context_end": qa_candidate.offset_context_window_end, - "document_id": ext_id, - } - ret.append(curr) - return ret - - def to_squad_eval(self) -> Dict: - return self.to_json(squad=True) diff --git a/haystack/modeling/model/triadaptive_model.py b/haystack/modeling/model/triadaptive_model.py deleted file mode 100644 index 5d831eee1a..0000000000 --- a/haystack/modeling/model/triadaptive_model.py +++ /dev/null @@ -1,478 +0,0 @@ -import logging -import os -from pathlib import Path -from typing import List, Optional, Callable, Union, Dict - -import torch -from torch import nn - -from haystack.modeling.data_handler.processor import Processor -from haystack.modeling.model.language_model import get_language_model, LanguageModel -from haystack.modeling.model.prediction_head import PredictionHead -from haystack.utils.experiment_tracking import Tracker as tracker - -logger = logging.getLogger(__name__) - - -def loss_per_head_sum( - loss_per_head: List[torch.Tensor], global_step: Optional[int] = None, batch: Optional[Dict] = None -): - """ - Input: loss_per_head (list of tensors), global_step (int), batch (dict) - Output: aggregated loss (tensor) - """ - return sum(loss_per_head) - - -class TriAdaptiveModel(nn.Module): - """PyTorch implementation containing all the modelling needed for - your NLP task. Combines 3 language models for representation of 3 - sequences and a prediction head. Allows for gradient flow back to - the 3 language model components. - - The TriAdaptiveModel is currently highly tailored to the use case of joint - retrieval of text passages and tables using one encoder as question encoder - (language_model1), one encoder as text passage encoder (language_model2), and - one encoder as table encoder (language_model3). - """ - - def __init__( - self, - language_model1: LanguageModel, - language_model2: LanguageModel, - language_model3: LanguageModel, - prediction_heads: List[PredictionHead], - embeds_dropout_prob: float = 0.1, - device: Optional[torch.device] = None, - lm1_output_types: Optional[Union[str, List[str]]] = None, - lm2_output_types: Optional[Union[str, List[str]]] = None, - lm3_output_types: Optional[Union[str, List[str]]] = None, - loss_aggregation_fn: Optional[Callable] = None, - ): - """ - :param language_model1: Any model that turns token ids into vector representations. - :param language_model2: Any model that turns token ids into vector representations. - :param language_model3: Any model that turns token ids into vector representations. - :param prediction_heads: A list of models that take 3 sequence embeddings and return logits for a given task. - :param embeds_dropout_prob: The probability that a value in the embeddings returned by any of the three - language model will be zeroed. - :param lm1_output_types: How to extract the embeddings from the final layer of the first language model. When set - to "per_token", one embedding will be extracted per input token. If set to - "per_sequence" (default), a single embedding will be extracted to represent the full - input sequence. Can either be a single string, or a list of strings, - one for each prediction head. - :param lm2_output_types: How to extract the embeddings from the final layer of the second language model. When set - to "per_token", one embedding will be extracted per input token. If set to - "per_sequence" (default), a single embedding will be extracted to represent the full - input sequence. Can either be a single string, or a list of strings, - one for each prediction head. - :param lm3_output_types: How to extract the embeddings from the final layer of the third language model. When set - to "per_token", one embedding will be extracted per input token. If set to - "per_sequence" (default), a single embedding will be extracted to represent the full - input sequence. Can either be a single string, or a list of strings, - one for each prediction head. - :param device: The device on which this model will operate. Either torch.device("cpu") or torch.device("cuda"). - :param loss_aggregation_fn: Function to aggregate the loss of multiple prediction heads. - Input: loss_per_head (list of tensors), global_step (int), batch (dict) - Output: aggregated loss (tensor) - Default is a simple sum: - `lambda loss_per_head, global_step=None, batch=None: sum(tensors)` - However, you can pass more complex functions that depend on the - current step (e.g. for round-robin style multitask learning) or the actual - content of the batch (e.g. certain labels) - Note: The loss at this stage is per sample, i.e one tensor of - shape (batchsize) per prediction head. - """ - if not device: - device = torch.device("cuda") - - if lm1_output_types is None: - lm1_output_types = ["per_sequence"] - if lm2_output_types is None: - lm2_output_types = ["per_sequence"] - if lm3_output_types is None: - lm3_output_types = ["per_sequence"] - super(TriAdaptiveModel, self).__init__() - self.device = device - self.language_model1 = language_model1.to(device) - self.lm1_output_dims = language_model1.output_dims - self.language_model2 = language_model2.to(device) - self.lm2_output_dims = language_model2.output_dims - self.language_model3 = language_model3.to(device) - self.lm3_output_dims = language_model3.output_dims - self.dropout1 = nn.Dropout(embeds_dropout_prob) - self.dropout2 = nn.Dropout(embeds_dropout_prob) - self.dropout3 = nn.Dropout(embeds_dropout_prob) - self.prediction_heads = nn.ModuleList([ph.to(device) for ph in prediction_heads]) - self.lm1_output_types = [lm1_output_types] if isinstance(lm1_output_types, str) else lm1_output_types - self.lm2_output_types = [lm2_output_types] if isinstance(lm2_output_types, str) else lm2_output_types - self.lm3_output_types = [lm3_output_types] if isinstance(lm3_output_types, str) else lm3_output_types - self.log_params() - # default loss aggregation function is a simple sum (without using any of the optional params) - if not loss_aggregation_fn: - loss_aggregation_fn = loss_per_head_sum - self.loss_aggregation_fn = loss_aggregation_fn - - def save(self, save_dir: Union[str, Path], lm1_name: str = "lm1", lm2_name: str = "lm2", lm3_name: str = "lm3"): - """ - Saves the 3 language model weights and respective config_files in directories lm1 and lm2 within save_dir. - - :param save_dir: Path | str to save the TriAdaptiveModel to. - """ - os.makedirs(save_dir, exist_ok=True) - for name, model in zip( - [lm1_name, lm2_name, lm3_name], [self.language_model1, self.language_model2, self.language_model3] - ): - model_save_dir = Path.joinpath(Path(save_dir), Path(name)) - os.makedirs(model_save_dir, exist_ok=True) - model.save(model_save_dir) - - for i, ph in enumerate(self.prediction_heads): - logger.info("prediction_head saving") - ph.save(save_dir, i) - - @classmethod - def load( - cls, - load_dir: Path, - device: torch.device, - strict: bool = False, - lm1_name: str = "lm1", - lm2_name: str = "lm2", - lm3_name: str = "lm3", - processor: Optional[Processor] = None, - ): - """ - Loads a TriAdaptiveModel from a directory. The directory must contain: - - * directory "lm1_name" with following files: - -> language_model.bin - -> language_model_config.json - * directory "lm2_name" with following files: - -> language_model.bin - -> language_model_config.json - * directory "lm3_name" with following files: - -> language_model.bin - -> language_model_config.json - * prediction_head_X.bin multiple PH possible - * prediction_head_X_config.json - * processor_config.json config for transforming input - * vocab.txt vocab file for language model, turning text to Wordpiece Token - * special_tokens_map.json - - :param load_dir: Location where the TriAdaptiveModel is stored. - :param device: To which device we want to sent the model, either torch.device("cpu") or torch.device("cuda"). - :param lm1_name: The name to assign to the first loaded language model (for encoding queries). - :param lm2_name: The name to assign to the second loaded language model (for encoding context/passages). - :param lm3_name: The name to assign to the second loaded language model (for encoding tables). - :param strict: Whether to strictly enforce that the keys loaded from saved model match the ones in - the PredictionHead (see torch.nn.module.load_state_dict()). - :param processor: Processor to populate prediction head with information coming from tasks. - """ - # Language Model - if lm1_name: - language_model1 = get_language_model(os.path.join(load_dir, lm1_name)) - else: - language_model1 = get_language_model(load_dir) - if lm2_name: - language_model2 = get_language_model(os.path.join(load_dir, lm2_name)) - else: - language_model2 = get_language_model(load_dir) - if lm3_name: - language_model3 = get_language_model(os.path.join(load_dir, lm3_name)) - else: - language_model3 = get_language_model(load_dir) - - # Prediction heads - ph_config_files = cls._get_prediction_head_files(load_dir) # type: ignore [attr-defined] - prediction_heads = [] - ph_output_type = [] - for config_file in ph_config_files: - head = PredictionHead.load(config_file, strict=strict, load_weights=False) - prediction_heads.append(head) - ph_output_type.append(head.ph_output_type) - - model = cls(language_model1, language_model2, language_model3, prediction_heads, 0.1, device) - if processor: - model.connect_heads_with_processor(processor.tasks) - - return model - - def logits_to_loss_per_head(self, logits: torch.Tensor, **kwargs): - """ - Collect losses from each prediction head. - - :param logits: Logits, can vary in shape and type, depending on task. - :return: The per sample per prediciton head loss whose first two dimensions have length n_pred_heads, batch_size. - """ - all_losses = [] - for head, logits_for_one_head in zip(self.prediction_heads, logits): - # check if PredictionHead connected to Processor - assert hasattr(head, "label_tensor_name"), ( - f"Label_tensor_names are missing inside the {head.task_name} Prediction Head. Did you connect the model" - " with the processor through either 'model.connect_heads_with_processor(processor.tasks)'" - " or by passing the processor to the Adaptive Model?" - ) - all_losses.append(head.logits_to_loss(logits=logits_for_one_head, **kwargs)) - return all_losses - - def logits_to_loss(self, logits: torch.Tensor, global_step: Optional[int] = None, **kwargs): - """ - Get losses from all prediction heads & reduce to single loss *per sample*. - - :param logits: logits, can vary in shape and type, depending on task. - :param global_step: number of current training step. - :param kwargs: Placeholder for passing generic parameters. - Note: Contains the batch (as dict of tensors), when called from Trainer.train(). - :return: loss: torch.Tensor that is the per sample loss (len: batch_size) - """ - all_losses = self.logits_to_loss_per_head(logits, **kwargs) - # This aggregates the loss per sample across multiple prediction heads - # Default is sum(), but you can configure any fn that takes [Tensor, Tensor ...] and returns [Tensor] - loss = self.loss_aggregation_fn(all_losses, global_step=global_step, batch=kwargs) - return loss - - def prepare_labels(self, **kwargs): - """ - Label conversion to original label space, per prediction head. - - :return: Labels in the right format. - """ - all_labels = [] - for head in self.prediction_heads: - labels = head.prepare_labels(**kwargs) - all_labels.append(labels) - return all_labels - - def forward(self, **kwargs): - """ - Push data through the whole model and returns logits. The data will propagate through - the first language model, second and third language model based on the tensor names and both the - encodings through each of the attached prediction heads. - - :param kwargs: Holds all arguments that need to be passed to both the language models and prediction head(s). - :return: All logits as torch.Tensor or multiple tensors. - """ - - # Run forward pass of the three language models - pooled_output = self.forward_lm(**kwargs) - - # Run forward pass of (multiple) prediction heads using the output from above - all_logits = [] - if len(self.prediction_heads) > 0: - for head, lm1_out, lm2_out in zip(self.prediction_heads, self.lm1_output_types, self.lm2_output_types): - # Choose relevant vectors from LM as output and perform dropout - if pooled_output[0] is not None: - if lm1_out == "per_sequence" or lm1_out == "per_sequence_continuous": - output1 = self.dropout1(pooled_output[0]) - else: - raise ValueError( - "Unknown extraction strategy from TriAdaptive language_model1: {}".format(lm1_out) - ) - else: - output1 = None - - if pooled_output[1] is not None: - if lm2_out == "per_sequence" or lm2_out == "per_sequence_continuous": - output2 = self.dropout2(pooled_output[1]) - else: - raise ValueError( - "Unknown extraction strategy from TriAdaptive language_model2: {}".format(lm2_out) - ) - else: - output2 = None - - embedding1, embedding2 = head(output1, output2) - all_logits.append((embedding1, embedding2)) - else: - # just return LM output (e.g. useful for extracting embeddings at inference time) - all_logits.append((pooled_output)) - - return all_logits - - def forward_lm(self, **kwargs): - """ - Forward pass for the TriAdaptive model. - - :param kwargs: Holds all arguments that need to be passed to the language models. - :return: Two tensors of pooled_output from the three language models - """ - pooled_output = [None, None] - # Forward pass for the queries - if "query_input_ids" in kwargs.keys(): - pooled_output1, _ = self.language_model1( - input_ids=kwargs.get("query_input_ids"), - segment_ids=kwargs.get("query_segment_ids"), - attention_mask=kwargs.get("query_attention_mask"), - output_hidden_states=False, - output_attentions=False, - ) - pooled_output[0] = pooled_output1 - - # Forward pass for text passages and tables - if "passage_input_ids" in kwargs.keys(): - table_mask = torch.flatten(kwargs["is_table"]) == 1 - - # Make input two-dimensional - max_seq_len = kwargs["passage_input_ids"].shape[-1] - passage_input_ids = kwargs["passage_input_ids"].view(-1, max_seq_len) - passage_attention_mask = kwargs["passage_attention_mask"].view(-1, max_seq_len) - passage_segment_ids = kwargs["passage_segment_ids"].view(-1, max_seq_len) - - # Current batch consists of only tables - if all(table_mask): - pooled_output2, _ = self.language_model3( - input_ids=passage_input_ids, - segment_ids=passage_segment_ids, - attention_mask=passage_attention_mask, - output_hidden_states=False, - output_attentions=False, - ) - pooled_output[1] = pooled_output2 - - # Current batch consists of tables and texts - elif any(table_mask): - table_segment_ids = kwargs["table_segment_ids"].view(-1, max_seq_len) - table_input_ids = passage_input_ids[table_mask] - table_segment_ids = table_segment_ids[table_mask] - table_attention_mask = passage_attention_mask[table_mask] - - pooled_output_tables, _ = self.language_model3( - input_ids=table_input_ids, - segment_ids=table_segment_ids, - attention_mask=table_attention_mask, - output_hidden_states=False, - output_attentions=False, - ) - - text_input_ids = passage_input_ids[~table_mask] - text_segment_ids = passage_segment_ids[~table_mask] - text_attention_mask = passage_attention_mask[~table_mask] - - pooled_output_text, _ = self.language_model2( - input_ids=text_input_ids, - segment_ids=text_segment_ids, - attention_mask=text_attention_mask, - output_hidden_states=False, - output_attentions=False, - ) - - last_table_idx = 0 - last_text_idx = 0 - combined_outputs = [] - for mask in table_mask: - if mask: - combined_outputs.append(pooled_output_tables[last_table_idx]) - last_table_idx += 1 - else: - combined_outputs.append(pooled_output_text[last_text_idx]) - last_text_idx += 1 - combined_outputs = torch.stack(combined_outputs) - - embedding_size = pooled_output_tables.shape[-1] - assert ( - pooled_output_tables.shape[-1] == pooled_output_text.shape[-1] - ), "Passage embedding model and table embedding model use different embedding sizes" - pooled_output_combined = combined_outputs.view(-1, embedding_size) - pooled_output[1] = pooled_output_combined - - # Current batch consists of only texts - else: - pooled_output2, _ = self.language_model2( - input_ids=passage_input_ids, - attention_mask=passage_attention_mask, - segment_ids=passage_segment_ids, - output_hidden_states=False, - output_attentions=False, - ) - pooled_output[1] = pooled_output2 - - return tuple(pooled_output) - - def log_params(self): - """ - Logs parameters to generic logger MlLogger - """ - params = { - "lm1_type": self.language_model1.__class__.__name__, - "lm1_name": self.language_model1.name, - "lm1_output_types": ",".join(self.lm1_output_types), - "lm2_type": self.language_model2.__class__.__name__, - "lm2_name": self.language_model2.name, - "lm2_output_types": ",".join(self.lm2_output_types), - "lm3_type": self.language_model3.__class__.__name__, - "lm3_name": self.language_model3.name, - "lm3_output_types": ",".join(self.lm3_output_types), - "prediction_heads": ",".join([head.__class__.__name__ for head in self.prediction_heads]), - } - try: - tracker.track_params(params) - except Exception as e: - logger.warning("ML logging didn't work: %s", e) - - def verify_vocab_size(self, vocab_size1: int, vocab_size2: int, vocab_size3: int): - """Verifies that the model fits to the tokenizer vocabulary. - They could diverge in case of custom vocabulary added via tokenizer.add_tokens()""" - - model1_vocab_len = self.language_model1.model.resize_token_embeddings(new_num_tokens=None).num_embeddings # type: ignore [union-attr,operator] - - msg = ( - f"Vocab size of tokenizer {vocab_size1} doesn't match with model {model1_vocab_len}. " - "If you added a custom vocabulary to the tokenizer, " - "make sure to supply 'n_added_tokens' to get_language_model() and BertStyleLM.load()" - ) - assert vocab_size1 == model1_vocab_len, msg - - model2_vocab_len = self.language_model2.model.resize_token_embeddings(new_num_tokens=None).num_embeddings # type: ignore [union-attr,operator] - - msg = ( - f"Vocab size of tokenizer {vocab_size1} doesn't match with model {model2_vocab_len}. " - "If you added a custom vocabulary to the tokenizer, " - "make sure to supply 'n_added_tokens' to get_language_model() and BertStyleLM.load()" - ) - assert vocab_size2 == model2_vocab_len, msg - - model3_vocab_len = self.language_model3.model.resize_token_embeddings(new_num_tokens=None).num_embeddings # type: ignore [union-attr,operator] - - msg = ( - f"Vocab size of tokenizer {vocab_size3} doesn't match with model {model3_vocab_len}. " - "If you added a custom vocabulary to the tokenizer, " - "make sure to supply 'n_added_tokens' to get_language_model() and BertStyleLM.load()" - ) - - assert vocab_size3 == model1_vocab_len, msg - - def get_language(self): - return self.language_model1.language, self.language_model2.language, self.language_model3.language - - def connect_heads_with_processor(self, tasks: Dict, require_labels: bool = True): - """ - Populates prediction head with information coming from tasks. - - :param tasks: A dictionary where the keys are the names of the tasks and the values are the details of the task - (e.g. label_list, metric, tensor name). - :param require_labels: If True, an error will be thrown when a task is not supplied with labels. - """ - - for head in self.prediction_heads: - head.label_tensor_name = tasks[head.task_name]["label_tensor_name"] - label_list = tasks[head.task_name]["label_list"] - if not label_list and require_labels: - raise Exception(f"The task '{head.task_name}' is missing a valid set of labels") - label_list = tasks[head.task_name]["label_list"] - head.label_list = label_list - head.metric = tasks[head.task_name]["metric"] - - def logits_to_preds(self, logits: torch.Tensor, **kwargs): - """ - Get predictions from all prediction heads. - - :param logits: Logits, can vary in shape and type, depending on task. - :return: A list of all predictions from all prediction heads. - """ - all_preds = [] - # collect preds from all heads - for head, logits_for_head in zip(self.prediction_heads, logits): - preds = head.logits_to_preds(logits=logits_for_head, **kwargs) - all_preds.append(preds) - return all_preds diff --git a/haystack/modeling/training/__init__.py b/haystack/modeling/training/__init__.py deleted file mode 100644 index 398fb326f9..0000000000 --- a/haystack/modeling/training/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.modeling.training.base import Trainer, DistillationTrainer, TinyBERTDistillationTrainer diff --git a/haystack/modeling/training/base.py b/haystack/modeling/training/base.py deleted file mode 100644 index 700f288cbf..0000000000 --- a/haystack/modeling/training/base.py +++ /dev/null @@ -1,952 +0,0 @@ -from typing import Optional, Union, List, Callable - -import sys -import shutil -import logging -from pathlib import Path - -import numpy -from tqdm import tqdm -import torch -from torch.optim.lr_scheduler import _LRScheduler -from torch.nn import MSELoss, Linear, Module, ModuleList, DataParallel -import torch.nn.functional as F -from torch.optim import Optimizer - -from haystack.modeling.data_handler.data_silo import DataSilo, DistillationDataSilo -from haystack.modeling.evaluation.eval import Evaluator -from haystack.modeling.model.adaptive_model import AdaptiveModel -from haystack.modeling.model.biadaptive_model import BiAdaptiveModel -from haystack.modeling.model.optimization import get_scheduler, WrappedDataParallel -from haystack.modeling.utils import GracefulKiller -from haystack.utils.experiment_tracking import Tracker as tracker -from haystack.utils.early_stopping import EarlyStopping -from haystack.telemetry import send_event - - -logger = logging.getLogger(__name__) - - -class Trainer: - """ - Handles the main model training procedure. This includes performing evaluation on the dev set at regular - intervals during training as well as evaluation on the test set at the end of training. - """ - - def __init__( - self, - model, - optimizer, - data_silo: DataSilo, - epochs: int, - n_gpu: int, - device: torch.device, - lr_schedule=None, - evaluate_every: int = 100, - eval_report: bool = True, - use_amp: bool = False, - grad_acc_steps: int = 1, - local_rank: int = -1, - early_stopping: Optional[EarlyStopping] = None, - log_learning_rate: bool = False, - log_loss_every: int = 10, - checkpoint_on_sigterm: bool = False, - checkpoint_every: Optional[int] = None, - checkpoint_root_dir: Optional[Path] = None, - checkpoints_to_keep: int = 3, - from_epoch: int = 0, - from_step: int = 0, - global_step: int = 0, - evaluator_test: bool = True, - disable_tqdm: bool = False, - max_grad_norm: float = 1.0, - ): - """ - :param optimizer: An optimizer object that determines the learning strategy to be used during training - :param data_silo: A DataSilo object that will contain the train, dev and test datasets as PyTorch DataLoaders - :param epochs: How many times the training procedure will loop through the train dataset - :param n_gpu: The number of gpus available for training and evaluation. - :param device: The device on which the train, dev and test tensors should be hosted. Choose from torch.device("cpu") and torch.device("cuda"). - :param lr_schedule: An optional scheduler object that can regulate the learning rate of the optimizer - :param evaluate_every: Perform dev set evaluation after this many steps of training. - :param eval_report: If evaluate_every is not 0, specifies if an eval report should be generated when evaluating - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param grad_acc_steps: Number of training steps for which the gradients should be accumulated. - Useful to achieve larger effective batch sizes that would not fit in GPU memory. - :param local_rank: Local rank of process when distributed training via DDP is used. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - :param log_learning_rate: Whether to log learning rate to experiment tracker (e.g. Mlflow) - :param log_loss_every: Log current train loss after this many train steps. - :param checkpoint_on_sigterm: save a checkpoint for the Trainer when a SIGTERM signal is sent. The checkpoint - can be used to resume training. It is useful in frameworks like AWS SageMaker with Spot instances where - a SIGTERM notifies to save the training state and subsequently the instance is terminated. - :param checkpoint_every: Save a training checkpoint after this many steps of training. - :param checkpoint_root_dir: The directory Path where all training checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoints_to_keep: The maximum number of training checkpoints to save. - :param from_epoch: the epoch number to start the training from. In the case when training resumes from a saved - checkpoint, it is used to fast-forward training to the last epoch in the checkpoint. - :param from_step: the step number to start the training from. In the case when training resumes from a saved - checkpoint, it is used to fast-forward training to the last step in the checkpoint. - :param global_step: the global step number across the training epochs. - :param evaluator_test: whether to perform evaluation on the test set - :param disable_tqdm: Disable tqdm progress bar (helps to reduce verbosity in some environments) - :param max_grad_norm: Max gradient norm for clipping, default 1.0, set to None to disable - """ - amp_mapping = {"O0": False, "O1": True, "O2": True, "O3": True} - self.model = model - self.data_silo = data_silo - self.epochs = int(epochs) - if isinstance(use_amp, str): - if use_amp in amp_mapping: - logger.warning( - "The Trainer only supports native PyTorch automatic mixed precision and no longer supports the Apex library.\n" - "Because you provided Apex optimization level %s, automatic mixed precision was set to %s.\n" - "In the future, set `use_amp=True` to turn on automatic mixed precision.", - use_amp, - amp_mapping[use_amp], - ) - use_amp = amp_mapping[use_amp] - else: - raise Exception( - f"use_amp value {use_amp} is not supported. Please provide use_amp=True to turn on automatic mixed precision." - ) - self.use_amp = use_amp - self.optimizer = optimizer - self.scaler = torch.cuda.amp.GradScaler(enabled=self.use_amp) - self.evaluate_every = evaluate_every - self.eval_report = eval_report - self.evaluator_test = evaluator_test - self.n_gpu = n_gpu - self.grad_acc_steps = grad_acc_steps - self.lr_schedule = lr_schedule - self.device = device - self.local_rank = local_rank - self.log_params() - self.early_stopping = early_stopping - self.log_learning_rate = log_learning_rate - self.log_loss_every = log_loss_every - self.disable_tqdm = disable_tqdm - self.max_grad_norm = max_grad_norm - self.test_result = None - - self.checkpoint_on_sigterm = checkpoint_on_sigterm - if checkpoint_on_sigterm: - self.sigterm_handler = GracefulKiller() # type: Optional[GracefulKiller] - else: - self.sigterm_handler = None - self.checkpoint_root_dir = checkpoint_root_dir - self.checkpoints_to_keep = checkpoints_to_keep - self.checkpoint_every = checkpoint_every - if self.checkpoint_every and not checkpoint_root_dir: - raise Exception("checkpoint_path needs to be supplied when using checkpoint_every.") - if checkpoint_on_sigterm and not checkpoint_root_dir: - raise Exception("checkpoint_path needs to be supplied when using checkpoint_on_sigterm.") - - self.from_epoch = from_epoch - self.from_step = from_step - self.global_step = global_step - - def train(self): - """ - Perform the training procedure. - - The training is visualized by a progress bar. It counts the epochs in a zero based manner. - For example, when you specify ``epochs=20`` it starts to count from 0 to 19. - - If trainer evaluates the model with a test set the result of the - evaluation is stored in ``test_result``. - - :return: Returns the model after training. When you do ``early_stopping`` - with a ``save_dir`` the best model is loaded and returned. - """ - send_event(event_name="Training", event_properties={"class": self.__class__.__name__, "function_name": "train"}) - # connect the prediction heads with the right output from processor - self.model.connect_heads_with_processor(self.data_silo.processor.tasks, require_labels=True) - # Check that the tokenizer(s) fits the language model(s) - if hasattr(self.model, "language_model3"): - self.model.verify_vocab_size( - vocab_size1=len(self.data_silo.processor.query_tokenizer), - vocab_size2=len(self.data_silo.processor.passage_tokenizer), - vocab_size3=len(self.data_silo.processor.table_tokenizer), - ) - elif hasattr(self.model, "language_model2"): - self.model.verify_vocab_size( - vocab_size1=len(self.data_silo.processor.query_tokenizer), - vocab_size2=len(self.data_silo.processor.passage_tokenizer), - ) - elif ( - self.model.language_model.name != "DebertaV2" - ): # DebertaV2 has mismatched vocab size on purpose (see https://github.com/huggingface/transformers/issues/12428) - self.model.verify_vocab_size(vocab_size=len(self.data_silo.processor.tokenizer)) - self.model.train() - - do_stopping = False - evalnr = 0 - loss = 0 - resume_from_step = self.from_step - - for epoch in range(self.from_epoch, self.epochs): - early_break = False - self.from_epoch = epoch - train_data_loader = self.data_silo.get_data_loader("train") - progress_bar = tqdm(train_data_loader, disable=self.local_rank not in [0, -1] or self.disable_tqdm) - for step, batch in enumerate(progress_bar): - # when resuming training from a checkpoint, we want to fast forward to the step of the checkpoint - if resume_from_step and step <= resume_from_step: - if step % 10000 == 0: - logger.info("Skipping %s out of %s steps ...", step, resume_from_step) - if resume_from_step == step: - logger.info("Finished skipping %s steps ...", resume_from_step) - resume_from_step = None - else: - continue - - progress_bar.set_description(f"Train epoch {epoch}/{self.epochs-1} (Cur. train loss: {loss:.4f})") - - # Only for distributed training: we need to ensure that all ranks still have a batch left for training - if self.local_rank != -1 and not self._all_ranks_have_data(has_data=True, step=step): - early_break = True - break - - # Move batch of samples to device - batch = {key: batch[key].to(self.device) for key in batch} - loss = self.compute_loss(batch, step) - - # Perform evaluation - if ( - self.evaluate_every != 0 - and self.global_step % self.evaluate_every == 0 - and self.global_step != 0 - and self.local_rank in [0, -1] - ): - dev_data_loader = self.data_silo.get_data_loader("dev") - if dev_data_loader is not None: - evaluator_dev = Evaluator( - data_loader=dev_data_loader, - tasks=self.data_silo.processor.tasks, - device=self.device, - report=self.eval_report, - ) - evalnr += 1 - result = evaluator_dev.eval(self.model) - evaluator_dev.log_results(result, "Dev", self.global_step) - if self.early_stopping: - do_stopping, save_model, eval_value = self.early_stopping.check_stopping(result) - if save_model: - logger.info( - "Saving current best model to %s, eval=%s", self.early_stopping.save_dir, eval_value - ) - self.model.save(self.early_stopping.save_dir) - self.data_silo.processor.save(self.early_stopping.save_dir) - if do_stopping: - # log the stopping - logger.info("STOPPING EARLY AT EPOCH %s, STEP %s, EVALUATION %s", epoch, step, evalnr) - if do_stopping: - break - - self.global_step += 1 - self.from_step = step + 1 - - # save the current state as a checkpoint before exiting if a SIGTERM signal is received - if self.sigterm_handler and self.sigterm_handler.kill_now: - logger.info("Received a SIGTERM signal. Saving the current train state as a checkpoint ...") - if self.local_rank in [0, -1]: - self._save() - torch.distributed.destroy_process_group() - sys.exit(0) - - # save a checkpoint and continue train - if self.checkpoint_every and step % self.checkpoint_every == 0: - if self.local_rank in [0, -1]: - self._save() - # Let other ranks wait until rank 0 has finished saving - if self.local_rank != -1: - torch.distributed.barrier() - - if do_stopping: - break - - # Only for distributed training: we need to ensure that all ranks still have a batch left for training - if self.local_rank != -1 and not early_break: - self._all_ranks_have_data(has_data=False) - - # With early stopping we want to restore the best model - if self.early_stopping and self.early_stopping.save_dir: - logger.info("Restoring best model so far from %s", self.early_stopping.save_dir) - self.model = self.model.load(self.early_stopping.save_dir, self.device) - self.model.connect_heads_with_processor(self.data_silo.processor.tasks, require_labels=True) - - # Eval on test set - if self.evaluator_test and self.local_rank in [0, -1]: - test_data_loader = self.data_silo.get_data_loader("test") - if test_data_loader is not None: - evaluator_test = Evaluator( - data_loader=test_data_loader, tasks=self.data_silo.processor.tasks, device=self.device - ) - self.test_result = evaluator_test.eval(self.model) - evaluator_test.log_results(self.test_result, "Test", self.global_step) - self.model.eval() - return self.model - - def compute_loss(self, batch: dict, step: int) -> torch.Tensor: - # Forward & backward pass through model - if isinstance(self.model, (DataParallel, WrappedDataParallel)): - module = self.model.module - else: - module = self.model - - with torch.cuda.amp.autocast(enabled=self.use_amp): - if isinstance(module, AdaptiveModel): - logits = self.model.forward( - input_ids=batch["input_ids"], segment_ids=None, padding_mask=batch["padding_mask"] - ) - - elif isinstance(module, BiAdaptiveModel): - logits = self.model.forward( - query_input_ids=batch["query_input_ids"], - query_segment_ids=batch["query_segment_ids"], - query_attention_mask=batch["query_attention_mask"], - passage_input_ids=batch["passage_input_ids"], - passage_segment_ids=batch["passage_segment_ids"], - passage_attention_mask=batch["passage_attention_mask"], - ) - - else: - logits = self.model.forward(**batch) - - per_sample_loss = self.model.logits_to_loss(logits=logits, global_step=self.global_step, **batch) - loss = self.adjust_loss(per_sample_loss) - return self.backward_propagate(loss, step) - - def backward_propagate(self, loss: torch.Tensor, step: int): - if self.global_step % self.log_loss_every == 0 and self.local_rank in [-1, 0] and self.local_rank in [-1, 0]: - tracker.track_metrics({"Train_loss_total": float(loss.detach().cpu().numpy())}, step=self.global_step) - if self.log_learning_rate: - tracker.track_metrics({"learning_rate": self.lr_schedule.get_last_lr()[0]}, step=self.global_step) - - self.scaler.scale(loss).backward() - - if step % self.grad_acc_steps == 0: - if self.max_grad_norm is not None: - self.scaler.unscale_(self.optimizer) - torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.max_grad_norm) - self.scaler.step(self.optimizer) - self.scaler.update() - self.optimizer.zero_grad() - if self.lr_schedule: - self.lr_schedule.step() - return loss - - def adjust_loss(self, loss: torch.Tensor): - loss = loss.mean() - if self.grad_acc_steps > 1: - loss = loss / self.grad_acc_steps - return loss - - def log_params(self): - params = {"epochs": self.epochs, "n_gpu": self.n_gpu, "device": self.device, "use_amp": self.use_amp} - tracker.track_params(params) - - @classmethod - def create_or_load_checkpoint( - cls, - data_silo: DataSilo, - checkpoint_root_dir: Path, - model, - optimizer, - local_rank: int = -1, - resume_from_checkpoint: str = "latest", - **kwargs, - ): - """ - Try loading a saved Trainer checkpoint. If no checkpoint found, it creates a new instance of Trainer. - - :param data_silo: A DataSilo object that will contain the train, dev and test datasets as PyTorch DataLoaders - :param checkpoint_root_dir: Path of the directory where all train checkpoints are saved. Each individual - checkpoint is stored in a sub-directory under it. - :param resume_from_checkpoint: the checkpoint name to start training from, e.g., "epoch_1_step_4532". It - defaults to "latest", using the checkpoint with the highest train steps. - """ - checkpoint_to_load = None - if checkpoint_root_dir and checkpoint_root_dir.exists(): - if resume_from_checkpoint == "latest": - saved_checkpoints = cls._get_checkpoints(checkpoint_root_dir) - if saved_checkpoints: - checkpoint_to_load = saved_checkpoints[0] # latest checkpoint - else: - checkpoint_to_load = None - else: - checkpoint_to_load = checkpoint_root_dir / resume_from_checkpoint - - if checkpoint_to_load: - # TODO load empty model class from config instead of passing here? - trainer = cls._load_checkpoint( - path=checkpoint_to_load, data_silo=data_silo, model=model, optimizer=optimizer, local_rank=local_rank - ) - logger.info("Resuming training from the train checkpoint at %s ...", checkpoint_to_load) - else: - logger.info("No train checkpoints found. Starting a new training ...") - trainer = cls( - data_silo=data_silo, - model=model, - optimizer=optimizer, - local_rank=local_rank, - checkpoint_root_dir=checkpoint_root_dir, - **kwargs, - ) - return trainer - - @classmethod - def _load_checkpoint(cls, path: Path, data_silo: DataSilo, model, optimizer, local_rank: int = -1): - """ - Load the train checkpoint at given path. - - :param path: The checkpoint path is subdirectory under checkpoint_root_dir. The individual checkpoint dirs have - a default naming convention of "epoch_{epoch_num}_step_{step_num}". - :param data_silo: A DataSilo object that will contain the train, dev and test datasets as PyTorch DataLoaders - """ - if not path.exists(): - raise Exception(f"The checkpoint path {path} does not exists.") - - # In distributed mode, we save the model only once from process 0 (using cuda:0) - # At loading time, we need to load the model to the current cuda device (instead of back to cuda:0) - # Note: This assumes exactly one GPU per process (as recommended by PyTorch) - if local_rank == -1: - map_location = None - else: - device = torch.device(f"cuda:{local_rank}") - map_location = {"cuda:0": f"cuda:{local_rank}"} - - trainer_checkpoint = torch.load(path / "trainer", map_location=map_location) - trainer_state_dict = trainer_checkpoint["trainer_state"] - if local_rank != -1: - trainer_state_dict["device"] = device - trainer_state_dict["local_rank"] = local_rank - - # Just setting seeds is not sufficient to have deterministic results when resuming - # training from a checkpoint. Additionally, the previous states of Random Number - # Generators also need to be restored from the saved checkpoint. - numpy_rng_state = trainer_checkpoint["numpy_rng_state"] - numpy.random.set_state(numpy_rng_state) - rng_state = trainer_checkpoint["rng_state"] - cuda_rng_state = trainer_checkpoint["cuda_rng_state"] - torch.set_rng_state(rng_state) - torch.cuda.set_rng_state(cuda_rng_state) - - model.load_state_dict(trainer_checkpoint["model_state"], strict=True) - optimizer.load_state_dict(trainer_checkpoint["optimizer_state"]) - - scheduler_state_dict = trainer_checkpoint["scheduler_state"] - scheduler_opts = trainer_checkpoint["scheduler_opts"] - scheduler = get_scheduler(optimizer, scheduler_opts) - scheduler.load_state_dict(scheduler_state_dict) - - trainer = Trainer( - data_silo=data_silo, model=model, optimizer=optimizer, lr_schedule=scheduler, **trainer_state_dict - ) - - logger.info("Loaded a train checkpoint from %s", path) - return trainer - - @classmethod - def _get_checkpoints(cls, checkpoint_root_dir: Path): - """ - Get a list of checkpoint dirs sorted by the number of training steps. - """ - dirs = [d for d in checkpoint_root_dir.iterdir() if d.is_dir() and d.name.startswith("epoch")] - - checkpoints_with_epoch_and_step = [] # list of tuple(checkpoint_dir, epoch, step) - for d in dirs: - epoch, step = [int(s) for s in str(d).split("_") if s.isdigit()] - checkpoints_with_epoch_and_step.append((d, epoch, step)) - - sorted_checkpoints_with_epoch_and_step = sorted( - checkpoints_with_epoch_and_step, key=lambda tup: (tup[1], tup[2]), reverse=True # sort by epoch and step - ) - sorted_checkpoints = [tup[0] for tup in sorted_checkpoints_with_epoch_and_step] - - return sorted_checkpoints - - def _save(self): - """ - Save a train checkpoint at the Trainer's checkpoint_path. - - Some objects(eg, scheduler) in the Trainer are not serializable using the Pickle module. For these objects, - the state_dict is stored for the checkpoint, that can be used to reconstruct a similar state upon resuming - train from the checkpoint. - - #TODO The model is currently saved as a whole serialized object. The disadvantage of this approach is that it is - bound to specifics Python version, haystack version, directory structures etc. A more modular and reusable approach - is to save using AdaptiveModel's save() method where the model and the state_dict are stored separately. - - # TODO custom defined evaluators are not saved in the checkpoint. - """ - logger.info("Saving a train checkpoint ...") - checkpoint_path = self.checkpoint_root_dir / "checkpoint_in_progress" - checkpoint_path.mkdir(parents=True, exist_ok=True) - - trainer_state_dict = self._get_state_dict() - - # save as a regular AdaptiveModel (e.g. for down-stream eval during training from scratch) - self.model.save(checkpoint_path) - - # save all state dicst (incl. the model) to have full reproducibility - torch.save( - { - "trainer_state": trainer_state_dict, - "model_state": self.model.state_dict(), - "optimizer_state": self.optimizer.state_dict(), - "scheduler_opts": self.lr_schedule.opts, - "scheduler_state": self.lr_schedule.state_dict(), - "numpy_rng_state": numpy.random.get_state(), - "rng_state": torch.get_rng_state(), - "cuda_rng_state": torch.cuda.get_rng_state() if torch.cuda.is_available() else None, - }, - checkpoint_path / "trainer", - ) - - checkpoint_name = f"epoch_{self.from_epoch}_step_{self.from_step-1}" - checkpoint_path.replace(Path(checkpoint_path.parent) / checkpoint_name) - - saved_checkpoints = self._get_checkpoints(self.checkpoint_root_dir) - if len(saved_checkpoints) > self.checkpoints_to_keep: - for cp in saved_checkpoints[self.checkpoints_to_keep :]: - shutil.rmtree(cp) - - logger.info("Saved a training checkpoint after %s", checkpoint_name) - - def _get_state_dict(self): - """ - Serializable state dictionary of a Trainer object - """ - state_dict = { - "evaluate_every": self.evaluate_every, - "n_gpu": self.n_gpu, - "grad_acc_steps": self.grad_acc_steps, - "device": self.device, - "local_rank": self.local_rank, - "early_stopping": self.early_stopping, - "epochs": self.epochs, - "checkpoint_on_sigterm": self.checkpoint_on_sigterm, - "checkpoint_root_dir": self.checkpoint_root_dir, - "checkpoint_every": self.checkpoint_every, - "checkpoints_to_keep": self.checkpoints_to_keep, - "from_epoch": self.from_epoch, - "from_step": self.from_step, - "global_step": self.global_step, - "log_learning_rate": self.log_learning_rate, - "log_loss_every": self.log_loss_every, - "disable_tqdm": self.disable_tqdm, - "use_amp": self.use_amp, - } - - return state_dict - - def _all_ranks_have_data(self, has_data: bool, step: Optional[int] = None): - """ - Verify in distributed training if all ranks still have data left. We send a "1" from here if this rank has data - and a "0" if a process has none . - If all ranks have data, they'll all send a 1, our sum equals world_size and we continue training. - If not, we must break the loop for those who still have data to synchronize again. - :param has_data: bool, whether the current rank has still data - :param step: int, current step (only used for logging) - :return: bool, whether all ranks have training data left - """ - if has_data: - ranks_with_data = torch.ones(1).to(self.device) - else: - ranks_with_data = torch.zeros(1).to(self.device) - - torch.distributed.all_reduce(ranks_with_data, op=torch.distributed.ReduceOp.SUM) - - if ranks_with_data < torch.distributed.get_world_size(): - if step is not None: - logger.info( - "Stopping epoch %s at step %s for rank %s since at least one other rank " - "(~ one GPU) in distributed training doesn't have any more batches... ", - self.from_epoch, - step, - self.local_rank, - ) - return False - else: - return True - - -class DistillationTrainer(Trainer): - """ - This trainer uses the teacher logits from DistillationDataSilo - to compute a distillation loss in addition to the loss based on the labels. - - **Example** - ```python - student = FARMReader(model_name_or_path="prajjwal1/bert-medium") - teacher = FARMReader(model_name_or_path="deepset/bert-large-uncased-whole-word-masking-squad2") - - processor = SquadProcessor(tokenizer=student.inferencer.processor.tokenizer, max_seq_len=384) - student, optimizer, _ = initialize_optimizer(student, n_batches=len(data_silo.loaders["train"]), n_epochs=3, device="cuda:0", learning_rate=3e-5) - - data_silo = DistillationDataSilo(teacher_model=teacher, teacher_batch_size=2, batch_size=8, device="cuda:0", processor=processor) - trainer = DistillationTrainer(student=student, optimizer=optimizer, data_silo=data_silo, epochs=3, n_gpu=1, device="cuda:0") - - trainer.train() - ``` - """ - - def __init__( - self, - model: "AdaptiveModel", - optimizer: Optimizer, - data_silo: DistillationDataSilo, - epochs: int, - n_gpu: int, - device: torch.device, - lr_schedule: Optional[_LRScheduler] = None, - evaluate_every: int = 100, - eval_report: bool = True, - use_amp: bool = False, - grad_acc_steps: int = 1, - local_rank: int = -1, - early_stopping: Optional[EarlyStopping] = None, - log_learning_rate: bool = False, - log_loss_every: int = 10, - checkpoint_on_sigterm: bool = False, - checkpoint_every: Optional[int] = None, - checkpoint_root_dir: Optional[Path] = None, - checkpoints_to_keep: int = 3, - from_epoch: int = 0, - from_step: int = 0, - global_step: int = 0, - evaluator_test: bool = True, - disable_tqdm: bool = False, - max_grad_norm: float = 1.0, - distillation_loss_weight: float = 0.5, - distillation_loss: Union[str, Callable[[torch.Tensor, torch.Tensor], torch.Tensor]] = "kl_div", - temperature: float = 1.0, - ): - """ - :param optimizer: An optimizer object that determines the learning strategy to be used during training - :param model: The model to be trained - :param data_silo: A DataSilo object that will contain the train, dev and test datasets as PyTorch DataLoaders - :param epochs: How many times the training procedure will loop through the train dataset - :param n_gpu: The number of gpus available for training and evaluation. - :param device: The device on which the train, dev and test tensors should be hosted. Choose from torch.device("cpu") and torch.device("cuda"). - :param lr_schedule: An optional scheduler object that can regulate the learning rate of the optimizer - :param evaluate_every: Perform dev set evaluation after this many steps of training. - :param eval_report: If evaluate_every is not 0, specifies if an eval report should be generated when evaluating - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param grad_acc_steps: Number of training steps for which the gradients should be accumulated. - Useful to achieve larger effective batch sizes that would not fit in GPU memory. - :param local_rank: Local rank of process when distributed training via DDP is used. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - :param log_learning_rate: Whether to log learning rate to experiment tracker (e.g. Mlflow) - :param log_loss_every: Log current train loss after this many train steps. - :param checkpoint_on_sigterm: save a checkpoint for the Trainer when a SIGTERM signal is sent. The checkpoint - can be used to resume training. It is useful in frameworks like AWS SageMaker with Spot instances where - a SIGTERM notifies to save the training state and subsequently the instance is terminated. - :param checkpoint_every: save a train checkpoint after this many steps of training. - :param checkpoint_root_dir: the Path of directory where all train checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoints_to_keep: maximum number of train checkpoints to save. - :param from_epoch: the epoch number to start the training from. In the case when training resumes from a saved - checkpoint, it is used to fast-forward training to the last epoch in the checkpoint. - :param from_step: the step number to start the training from. In the case when training resumes from a saved - checkpoint, it is used to fast-forward training to the last step in the checkpoint. - :param global_step: the global step number across the training epochs. - :param evaluator_test: whether to perform evaluation on the test set - :param disable_tqdm: Disable tqdm progress bar (helps to reduce verbosity in some environments) - :param max_grad_norm: Max gradient norm for clipping, default 1.0, set to None to disable - :param distillation_loss_weight: The weight of the distillation loss. A higher weight means the teacher outputs are more important. - :param distillation_loss: Specifies how teacher and model logits should be compared. Can either be a string ("mse" for mean squared error or "kl_div" for kl divergence loss) or a callable loss function (needs to have named parameters student_logits and teacher_logits) - :param temperature: The temperature for distillation. A higher temperature will result in less certainty of teacher outputs. A lower temperature means more certainty. A temperature of 1.0 does not change the certainty of the model. - """ - super().__init__( - model=model, - optimizer=optimizer, - data_silo=data_silo, - epochs=epochs, - n_gpu=n_gpu, - device=device, - lr_schedule=lr_schedule, - evaluate_every=evaluate_every, - eval_report=eval_report, - use_amp=use_amp, - grad_acc_steps=grad_acc_steps, - local_rank=local_rank, - early_stopping=early_stopping, - log_learning_rate=log_learning_rate, - log_loss_every=log_loss_every, - checkpoint_on_sigterm=checkpoint_on_sigterm, - checkpoint_every=checkpoint_every, - checkpoint_root_dir=checkpoint_root_dir, - checkpoints_to_keep=checkpoints_to_keep, - from_epoch=from_epoch, - from_step=from_step, - global_step=global_step, - evaluator_test=evaluator_test, - disable_tqdm=disable_tqdm, - max_grad_norm=max_grad_norm, - ) - self.distillation_loss_weight = distillation_loss_weight - if distillation_loss == "mse": - self.distillation_loss_fn = MSELoss() - elif distillation_loss == "kl_div": - self.distillation_loss_fn = self._kl_div # type: ignore [assignment] - self.temperature = temperature - - def _kl_div(self, student_logits, teacher_logits): - student_log_probs = F.log_softmax(student_logits, dim=-2) - teacher_probs = F.softmax(teacher_logits, dim=-2) - return F.kl_div(student_log_probs, teacher_probs, reduction="batchmean") - - def compute_loss(self, batch: dict, step: int) -> torch.Tensor: - keys = list(batch.keys()) - keys = [key for key in keys if key.startswith("teacher_output")] - teacher_logits = [batch.pop(key) for key in keys] - with torch.cuda.amp.autocast(enabled=self.use_amp): - logits = self.model.forward( - input_ids=batch.get("input_ids"), - segment_ids=batch.get("segment_ids"), - padding_mask=batch.get("padding_mask"), - output_hidden_states=batch.get("output_hidden_states"), - output_attentions=batch.get("output_attentions"), - ) - student_loss = self.model.logits_to_loss(logits=logits, global_step=self.global_step, **batch) - distillation_loss = self.distillation_loss_fn( - student_logits=logits[0] / self.temperature, teacher_logits=teacher_logits[0] / self.temperature - ) - combined_loss = distillation_loss * self.distillation_loss_weight * ( - self.temperature**2 - ) + student_loss * (1 - self.distillation_loss_weight) - loss = self.adjust_loss(combined_loss) - return self.backward_propagate(loss, step) - - -class TinyBERTDistillationTrainer(Trainer): - """ - This Trainer implements the first stage of task specific distillation as described in the TinyBERT paper. - The standard DistillationTrainer can be used for the second stage. Unlike the DistillationTrainer, this Trainer does not use - cached teacher outputs as it would be too memory expensive. This means it is much slower than the DistillationTrainer. - - **Example** - ```python - student = FARMReader(model_name_or_path="huawei-noah/TinyBERT_General_6L_768D") - teacher = FARMReader(model_name_or_path="twmkn9/bert-base-uncased-squad2") - - processor = SquadProcessor(tokenizer=student.inferencer.processor.tokenizer, max_seq_len=384) - student, optimizer, _ = initialize_optimizer(student, n_batches=len(data_silo.loaders["train"]), n_epochs=3, device="cuda:0", learning_rate=3e-5) - - data_silo = DataSilo(teacher_model=teacher, batch_size=8, device="cuda:0", processor=processor) - trainer = TinyBertDistillationTrainer(student=student, optimizer=optimizer, data_silo=data_silo, epochs=3, n_gpu=1, device="cuda:0") - - trainer.train() - ``` - """ - - def __init__( - self, - model: AdaptiveModel, - teacher_model: AdaptiveModel, - optimizer: Optimizer, - data_silo: DistillationDataSilo, - epochs: int, - n_gpu: int, - device: torch.device, - lr_schedule: Optional[_LRScheduler] = None, - evaluate_every: int = 100, - eval_report: bool = True, - use_amp: bool = False, - grad_acc_steps: int = 1, - local_rank: int = -1, - early_stopping: Optional[EarlyStopping] = None, - log_learning_rate: bool = False, - log_loss_every: int = 10, - checkpoint_on_sigterm: bool = False, - checkpoint_every: Optional[int] = None, - checkpoint_root_dir: Optional[Path] = None, - checkpoints_to_keep: int = 3, - from_epoch: int = 0, - from_step: int = 0, - global_step: int = 0, - evaluator_test: bool = True, - disable_tqdm: bool = False, - max_grad_norm: float = 1.0, - ): - """ - :param optimizer: An optimizer object that determines the learning strategy to be used during training - :param model: The model to be trained. It needs to be a TinyBERT model. - :param teacher_model: The teacher model used for distillation. This has to be based on bert-base-uncased. - :param data_silo: A DataSilo object that will contain the train, dev and test datasets as PyTorch DataLoaders - :param epochs: How many times the training procedure will loop through the train dataset - :param n_gpu: The number of gpus available for training and evaluation. - :param device: The device on which the train, dev and test tensors should be hosted. Choose from torch.device("cpu") and torch.device("cuda"). - :param lr_schedule: An optional scheduler object that can regulate the learning rate of the optimizer - :param evaluate_every: Perform dev set evaluation after this many steps of training. - :param eval_report: If evaluate_every is not 0, specifies if an eval report should be generated when evaluating - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param grad_acc_steps: Number of training steps for which the gradients should be accumulated. - Useful to achieve larger effective batch sizes that would not fit in GPU memory. - :param local_rank: Local rank of process when distributed training via DDP is used. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - :param log_learning_rate: Whether to log learning rate to experiment tracker (e.g. Mlflow) - :param log_loss_every: Log current train loss after this many train steps. - :param checkpoint_on_sigterm: save a checkpoint for the Trainer when a SIGTERM signal is sent. The checkpoint - can be used to resume training. It is useful in frameworks like AWS SageMaker with Spot instances where - a SIGTERM notifies to save the training state and subsequently the instance is terminated. - :param checkpoint_every: save a train checkpoint after this many steps of training. - :param checkpoint_root_dir: the Path of directory where all train checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoints_to_keep: maximum number of train checkpoints to save. - :param from_epoch: the epoch number to start the training from. In the case when training resumes from a saved - checkpoint, it is used to fast-forward training to the last epoch in the checkpoint. - :param from_step: the step number to start the training from. In the case when training resumes from a saved - checkpoint, it is used to fast-forward training to the last step in the checkpoint. - :param global_step: the global step number across the training epochs. - :param evaluator_test: whether to perform evaluation on the test set - :param disable_tqdm: Disable tqdm progress bar (helps to reduce verbosity in some environments) - :param max_grad_norm: Max gradient norm for clipping, default 1.0, set to None to disable - :param distillation_loss_weight: The weight of the distillation loss. A higher weight means the teacher outputs are more important. - :param distillation_loss: Specifies how teacher and model logits should be compared. Can either be a string ("mse" for mean squared error or "kl_div" for kl divergence loss) or a callable loss function (needs to have named parameters student_logits and teacher_logits) - :param temperature: The temperature for distillation. A higher temperature will result in less certainty of teacher outputs. A lower temperature means more certainty. A temperature of 1.0 does not change the certainty of the model. - """ - super().__init__( - model=model, - optimizer=optimizer, - data_silo=data_silo, - epochs=epochs, - n_gpu=n_gpu, - device=device, - lr_schedule=lr_schedule, - evaluate_every=evaluate_every, - eval_report=eval_report, - use_amp=use_amp, - grad_acc_steps=grad_acc_steps, - local_rank=local_rank, - early_stopping=early_stopping, - log_learning_rate=log_learning_rate, - log_loss_every=log_loss_every, - checkpoint_on_sigterm=checkpoint_on_sigterm, - checkpoint_every=checkpoint_every, - checkpoint_root_dir=checkpoint_root_dir, - checkpoints_to_keep=checkpoints_to_keep, - from_epoch=from_epoch, - from_step=from_step, - global_step=global_step, - evaluator_test=evaluator_test, - disable_tqdm=disable_tqdm, - max_grad_norm=max_grad_norm, - ) - - self.loss = DistillationLoss(model, teacher_model, device) - if torch.cuda.device_count() > 1 and device.type == "cuda": - self.loss = DataParallel(self.loss).to(device) # type: ignore [assignment] - - def compute_loss(self, batch: dict, step: int) -> torch.Tensor: - with torch.cuda.amp.autocast(enabled=self.use_amp): - loss = torch.sum( - self.loss( - input_ids=batch.get("input_ids"), - segment_ids=batch.get("segment_ids"), - padding_mask=batch.get("padding_mask"), - ) - ) - loss = self.adjust_loss(loss) - return self.backward_propagate(loss, step) - - -class DistillationLoss(Module): - """ - Calculates the distillation loss in a separate module to allow for data parallelization. - """ - - def __init__(self, model: Union[DataParallel, AdaptiveModel], teacher_model: Module, device: torch.device): - super().__init__() - self.model = model.module.to(device) if isinstance(model, DataParallel) else model.to(device) - self.teacher_model = teacher_model.to(device) - - # creating dummy inputs to get the shapes of hidden states and attention of teacher and student model - dummy_inputs = teacher_model.language_model.model.dummy_inputs # type: ignore [union-attr] - dummy_inputs["input_ids"] = dummy_inputs["input_ids"].to(device) # type: ignore [operator,index] - dummy_inputs["padding_mask"] = torch.ones_like(dummy_inputs["input_ids"], device=device) # type: ignore [operator,index] - dummy_inputs["segment_ids"] = torch.zeros_like(dummy_inputs["input_ids"], device=device) # type: ignore [operator,index] - - with torch.no_grad(): - _, teacher_hidden_states, teacher_attentions = self.teacher_model.forward( # type: ignore [arg-type] - **dummy_inputs, output_attentions=True, output_hidden_states=True - ) - _, hidden_states, attentions = self.model.forward( # type: ignore [arg-type] - **dummy_inputs, output_attentions=True, output_hidden_states=True - ) - - if len(teacher_attentions) % len(attentions) != 0: - raise ValueError( - "Teacher and student model do not seem to be compatible. Have you made sure that the student is a TinyBERT model and that the teacher is a BERT model?" - ) - - self.teacher_block_size = len(teacher_attentions) // len(attentions) - - teacher_dims = [hidden_state.shape[-1] for hidden_state in teacher_hidden_states] - student_dims = [hidden_state.shape[-1] for hidden_state in hidden_states] - - # creating linear mappings in case the teacher and student model have different hidden state dimensions - self.dim_mappings: List[Optional[Linear]] = ModuleList([]) # type: ignore [assignment] - - for teacher_dim, student_dim in zip(teacher_dims, student_dims): - if teacher_dim != student_dim: - self.dim_mappings.append(Linear(student_dim, teacher_dim, bias=False).to(device)) - else: - self.dim_mappings.append(None) - - def forward(self, input_ids: torch.Tensor, segment_ids: torch.Tensor, padding_mask: torch.Tensor): - with torch.no_grad(): - _, teacher_hidden_states, teacher_attentions = self.teacher_model.forward( - input_ids=input_ids, - segment_ids=segment_ids, - padding_mask=padding_mask, - output_attentions=True, - output_hidden_states=True, - ) - _, hidden_states, attentions = self.model.forward( - input_ids=input_ids, - segment_ids=segment_ids, - padding_mask=padding_mask, - output_attentions=True, - output_hidden_states=True, - ) - loss = torch.tensor(0.0, device=input_ids.device) - - # calculating attention loss - for student_attention, teacher_attention, dim_mapping in zip( - attentions, teacher_attentions[self.teacher_block_size - 1 :: self.teacher_block_size], self.dim_mappings - ): - # this wasn't described in the paper, but it was used in the original implementation - student_attention = torch.where( - student_attention <= -1e2, torch.zeros_like(student_attention), student_attention - ) - teacher_attention = torch.where( - teacher_attention <= -1e2, torch.zeros_like(teacher_attention), teacher_attention - ) - - loss += F.mse_loss(student_attention, teacher_attention) - - # calculating hidden state loss - for student_hidden_state, teacher_hidden_state in zip( - hidden_states, teacher_hidden_states[:: self.teacher_block_size] - ): - # linear mapping in case the teacher and student model have different hidden state dimensions, not necessary for attention as attention shape is determined by number of attention heads and sequence length - if dim_mapping: - student_hidden_state = dim_mapping(student_hidden_state) - - loss += F.mse_loss(student_hidden_state, teacher_hidden_state) - - return torch.unsqueeze(loss, -1) diff --git a/haystack/modeling/training/dpr.py b/haystack/modeling/training/dpr.py deleted file mode 100644 index 4c71262ed8..0000000000 --- a/haystack/modeling/training/dpr.py +++ /dev/null @@ -1 +0,0 @@ -# TODO create DPR_Trainer class here that can be called from retriever.dense.DPR.train() diff --git a/haystack/modeling/training/question_answering.py b/haystack/modeling/training/question_answering.py deleted file mode 100644 index 7e9df23e35..0000000000 --- a/haystack/modeling/training/question_answering.py +++ /dev/null @@ -1 +0,0 @@ -# TODO make QA_Trainer class and use insider reader.train diff --git a/haystack/modeling/utils.py b/haystack/modeling/utils.py deleted file mode 100644 index c2dff09cdb..0000000000 --- a/haystack/modeling/utils.py +++ /dev/null @@ -1,349 +0,0 @@ -from typing import Tuple, List, Optional, Union - -import logging -import os -import pickle -import random -import signal -from functools import wraps -from copy import deepcopy -from itertools import islice - -import numpy as np -import torch -import torch.distributed as dist -from torch import multiprocessing as mp - -from haystack.modeling.visual import WORKER_M, WORKER_F, WORKER_X - - -logger = logging.getLogger(__name__) - - -class GracefulKiller: - kill_now = False - - def __init__(self): - signal.signal(signal.SIGTERM, self.exit_gracefully) - - def exit_gracefully(self, signum, frame): - self.kill_now = True - - -def silence_transformers_logs(from_pretrained_func): - """ - A wrapper that raises the log level of Transformers to - ERROR to hide some unnecessary warnings. - """ - - @wraps(from_pretrained_func) - def quiet_from_pretrained_func(cls, *args, **kwargs): - # Raise the log level of Transformers - t_logger = logging.getLogger("transformers") - original_log_level = t_logger.level - t_logger.setLevel(logging.ERROR) - - result = from_pretrained_func(cls, *args, **kwargs) - - # Restore the log level - t_logger.setLevel(original_log_level) - - return result - - return quiet_from_pretrained_func - - -def set_all_seeds(seed: int, deterministic_cudnn: bool = False) -> None: - """ - Setting multiple seeds to make runs reproducible. - - Important: Enabling `deterministic_cudnn` gives you full reproducibility with CUDA, - but might slow down your training (see https://pytorch.org/docs/stable/notes/randomness.html#cudnn) ! - - :param seed:number to use as seed - :param deterministic_cudnn: Enable for full reproducibility when using CUDA. Caution: might slow down training. - """ - random.seed(seed) - np.random.seed(seed) - torch.manual_seed(seed) - os.environ["PYTHONHASHSEED"] = str(seed) - torch.cuda.manual_seed_all(seed) - if deterministic_cudnn: - torch.backends.cudnn.deterministic = True - torch.backends.cudnn.benchmark = False - - -def initialize_device_settings( - use_cuda: Optional[bool] = None, - local_rank: int = -1, - multi_gpu: bool = True, - devices: Optional[List[Union[str, torch.device]]] = None, -) -> Tuple[List[torch.device], int]: - """ - Returns a list of available devices. - - :param use_cuda: Whether to make use of CUDA GPUs (if available). - :param local_rank: Ordinal of device to be used. If -1 and `multi_gpu` is True, all devices will be used. - Unused if `devices` is set or `use_cuda` is False. - :param multi_gpu: Whether to make use of all GPUs (if available). - Unused if `devices` is set or `use_cuda` is False. - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - """ - if use_cuda is False: # Note that it could be None, in which case we also want to just skip this step. - devices_to_use = [torch.device("cpu")] - n_gpu = 0 - elif devices: - if not isinstance(devices, list): - raise ValueError(f"devices must be a list, but got {devices} of type {type(devices)}") - if any(isinstance(device, str) for device in devices): - torch_devices: List[torch.device] = [torch.device(device) for device in devices] - devices_to_use = torch_devices - else: - devices_to_use = devices # type: ignore [assignment] - n_gpu = sum(1 for device in devices_to_use if "cpu" not in device.type) - elif local_rank == -1: - if torch.cuda.is_available(): - if multi_gpu: - devices_to_use = [torch.device(device) for device in range(torch.cuda.device_count())] - n_gpu = torch.cuda.device_count() - else: - devices_to_use = [torch.device("cuda:0")] - n_gpu = 1 - elif ( - hasattr(torch.backends, "mps") - and torch.backends.mps.is_available() - and os.getenv("HAYSTACK_MPS_ENABLED", "true") != "false" - ): - devices_to_use = [torch.device("mps")] - n_gpu = 1 - else: - devices_to_use = [torch.device("cpu")] - n_gpu = 0 - else: - devices_to_use = [torch.device("cuda", local_rank)] - torch.cuda.set_device(devices_to_use[0]) - n_gpu = 1 - # Initializes the distributed backend which will take care of sychronizing nodes/GPUs - torch.distributed.init_process_group(backend="nccl") - - # HF transformers v4.21.2 pipeline object doesn't accept torch.device("cuda"), it has to be an indexed cuda device - # TODO eventually remove once the limitation is fixed in HF transformers - device_to_replace = torch.device("cuda") - devices_to_use = [torch.device("cuda:0") if device == device_to_replace else device for device in devices_to_use] - - logger.info( - "Using devices: %s - Number of GPUs: %s", ", ".join([str(device) for device in devices_to_use]).upper(), n_gpu - ) - return devices_to_use, n_gpu - - -def flatten_list(nested_list): - """Flatten an arbitrarily nested list, without recursion (to avoid - stack overflows). Returns a new list, the original list is unchanged. - >> list(flatten_list([1, 2, 3, [4], [], [[[[[[[[[5]]]]]]]]]])) - [1, 2, 3, 4, 5] - >> list(flatten_list([[1, 2], 3])) - [1, 2, 3] - """ - nested_list = deepcopy(nested_list) - - while nested_list: - sublist = nested_list.pop(0) - - if isinstance(sublist, list): - nested_list = sublist + nested_list - else: - yield sublist - - -def try_get(keys, dictionary): - try: - for key in keys: - if key in dictionary: - ret = dictionary[key] - if type(ret) == list: - ret = ret[0] - return ret - except Exception as e: - logger.warning("Cannot extract from dict %s with error: %s", dictionary, e) - return None - - -# DDP utils -def all_reduce(tensor, group=None): - if group is None: - group = dist.group.WORLD - return dist.all_reduce(tensor, group=group) - - -def all_gather_list(data, group=None, max_size=16384): - """Gathers arbitrary data from all nodes into a list. - Similar to :func:`~torch.distributed.all_gather` but for arbitrary Python - data. Note that *data* must be picklable. - Args: - data (Any): data from the local worker to be gathered on other workers - group (optional): group of the collective - """ - # pylint: disable=all - SIZE_STORAGE_BYTES = 4 # int32 to encode the payload size - - enc = pickle.dumps(data) - enc_size = len(enc) - - if enc_size + SIZE_STORAGE_BYTES > max_size: - raise ValueError( - "encoded data exceeds max_size, this can be fixed by increasing buffer size: {}".format(enc_size) - ) - - rank = dist.get_rank() - world_size = dist.get_world_size() - buffer_size = max_size * world_size - - if not hasattr(all_gather_list, "_buffer") or all_gather_list._buffer.numel() < buffer_size: - all_gather_list._buffer = torch.cuda.ByteTensor(buffer_size) - all_gather_list._cpu_buffer = torch.ByteTensor(max_size).pin_memory() - - buffer = all_gather_list._buffer - buffer.zero_() - cpu_buffer = all_gather_list._cpu_buffer - - assert enc_size < 256**SIZE_STORAGE_BYTES, "Encoded object size should be less than {} bytes".format( - 256**SIZE_STORAGE_BYTES - ) - - size_bytes = enc_size.to_bytes(SIZE_STORAGE_BYTES, byteorder="big") - - cpu_buffer[0:SIZE_STORAGE_BYTES] = torch.ByteTensor(list(size_bytes)) - cpu_buffer[SIZE_STORAGE_BYTES : enc_size + SIZE_STORAGE_BYTES] = torch.ByteTensor(list(enc)) - - start = rank * max_size - size = enc_size + SIZE_STORAGE_BYTES - buffer[start : start + size].copy_(cpu_buffer[:size]) - - all_reduce(buffer, group=group) - - try: - result = [] - for i in range(world_size): - out_buffer = buffer[i * max_size : (i + 1) * max_size] - size = int.from_bytes(out_buffer[0:SIZE_STORAGE_BYTES], byteorder="big") - if size > 0: - result.append(pickle.loads(bytes(out_buffer[SIZE_STORAGE_BYTES : size + SIZE_STORAGE_BYTES].tolist()))) - return result - except pickle.UnpicklingError: - raise Exception( - "Unable to unpickle data from other workers. all_gather_list requires all " - "workers to enter the function together, so this error usually indicates " - "that the workers have fallen out of sync somehow. Workers can fall out of " - "sync if one of them runs out of memory, or if there are other conditions " - "in your training script that can cause one worker to finish an epoch " - "while other workers are still iterating over their portions of the data." - ) - - -def grouper(iterable, n: int, worker_id: int = 0, total_workers: int = 1): - """ - Split an iterable into a list of n-sized chunks. Each element in the chunk is a tuple of (index_num, element). - - Example: - - >>> list(grouper('ABCDEFG', 3)) - [[(0, 'A'), (1, 'B'), (2, 'C')], [(3, 'D'), (4, 'E'), (5, 'F')], [(6, 'G')]] - - - Use with the StreamingDataSilo - - When StreamingDataSilo is used with multiple PyTorch DataLoader workers, the generator - yielding dicts(that gets converted to datasets) is replicated across the workers. - - To avoid duplicates, we split the dicts across workers by creating a new generator for - each worker using this method. - - Input --> [dictA, dictB, dictC, dictD, dictE, ...] with total worker=3 and n=2 - - Output for worker 1: [(dictA, dictB), (dictG, dictH), ...] - Output for worker 2: [(dictC, dictD), (dictI, dictJ), ...] - Output for worker 3: [(dictE, dictF), (dictK, dictL), ...] - - This method also adds an index number to every dict yielded. - - :param iterable: a generator object that yields dicts - :param n: the dicts are grouped in n-sized chunks that gets converted to datasets - :param worker_id: the worker_id for the PyTorch DataLoader - :param total_workers: total number of workers for the PyTorch DataLoader - """ - - # TODO make me comprehensible :) - def get_iter_start_pos(gen): - start_pos = worker_id * n - for i in gen: - if start_pos: - start_pos -= 1 - continue - yield i - - def filter_elements_per_worker(gen): - x = n - y = (total_workers - 1) * n - for i in gen: - if x: - yield i - x -= 1 - else: - if y != 1: - y -= 1 - else: - x = n - y = (total_workers - 1) * n - - iterable = iter(enumerate(iterable)) - iterable = get_iter_start_pos(iterable) - if total_workers > 1: - iterable = filter_elements_per_worker(iterable) - - return iter(lambda: list(islice(iterable, n)), []) - - -def calc_chunksize(num_dicts, min_chunksize=4, max_chunksize=2000, max_processes=128): - if mp.cpu_count() > 3: - num_cpus = min(mp.cpu_count() - 1 or 1, max_processes) # -1 to keep a CPU core free for xxx - else: - num_cpus = min(mp.cpu_count(), max_processes) # when there are few cores, we use all of them - - dicts_per_cpu = np.ceil(num_dicts / num_cpus) - # automatic adjustment of multiprocessing chunksize - # for small files (containing few dicts) we want small chunksize to ulitize all available cores but never less - # than 2, because we need it to sample another random sentence in LM finetuning - # for large files we want to minimize processor spawning without giving too much data to one process, so we - # clip it at 5k - multiprocessing_chunk_size = int(np.clip((np.ceil(dicts_per_cpu / 5)), a_min=min_chunksize, a_max=max_chunksize)) - # This lets us avoid cases in lm_finetuning where a chunk only has a single doc and hence cannot pick - # a valid next sentence substitute from another document - if num_dicts != 1: - while num_dicts % multiprocessing_chunk_size == 1: - multiprocessing_chunk_size -= -1 - dict_batches_to_process = int(num_dicts / multiprocessing_chunk_size) - num_processes = min(num_cpus, dict_batches_to_process) or 1 - - return multiprocessing_chunk_size, num_processes - - -def log_ascii_workers(n, logger): - m_worker_lines = WORKER_M.split("\n") - f_worker_lines = WORKER_F.split("\n") - x_worker_lines = WORKER_X.split("\n") - all_worker_lines = [] - for _ in range(n): - rand = np.random.randint(low=0, high=3) - if rand % 3 == 0: - all_worker_lines.append(f_worker_lines) - elif rand % 3 == 1: - all_worker_lines.append(m_worker_lines) - else: - all_worker_lines.append(x_worker_lines) - zipped = zip(*all_worker_lines) - for z in zipped: - logger.info(" ".join(z)) diff --git a/haystack/modeling/visual.py b/haystack/modeling/visual.py deleted file mode 100644 index 8368f38dc4..0000000000 --- a/haystack/modeling/visual.py +++ /dev/null @@ -1,103 +0,0 @@ -FLOWERS = r""" - - vVVVv vVVVv - (___) vVVVv (___) vVVVv - ~Y~ (___) ~Y~ (___) - \| \~Y~/ \| \~Y~/ - \\|// \\|// \\|// \\|// - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -""" - -SAMPLE = r""" - .--. _____ _ - .'_\/_'. / ____| | | - '. /\ .' | (___ __ _ _ __ ___ _ __ | | ___ - "||" \___ \ / _` | '_ ` _ \| '_ \| |/ _ \ - || /\ ____) | (_| | | | | | | |_) | | __/ - /\ ||//\) |_____/ \__,_|_| |_| |_| .__/|_|\___| - (/\\||/ |_| -______\||/___________________________________________ -""" - -FENCE = r""" - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_ --| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |- - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | -_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_ --| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |-| |- - |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, - -""" - -TRACTOR_SMALL = r""" - ______ - |o | ! - __ |:`_|---'-. - |__|______.-/ _ \-----.| - (o)(o)------'\ _ / ( ) - """ - - -TRACTOR_WITH_SILO_LINE = r""" - ____ - /____\ - ______ | | - |o | ! | | - __ |:`_|---'-. | | - |__|______.-/ _ \-----.| |______| - (o)(o)------'\ _ / ( ) | | - """ - - -ROOSTER = r""" - _ m - ,`.\/'> - (`\<_/` - `<< -""" - -PIG = r""" - - .-~~~~-. |\\_ - @_/ / oo\_ - | \ \ _(") - \ /-| ||'--' - \_\ \_\\ - -""" -SMALL_PIG = r""" - @___,__ - ( ^'_] - //-\\' - ^^ ^^ -""" -FENCE_SEP = r""" -|---||---|---|---|---|---|---|---| -""" - -BUSH_SEP = r"""\\|// \\|// \\|// \\|// \\|// -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^""" - -WATERING_CAN = r""" - ______ - _ ,',----.`. -'.`-. .-' '----. || - `.`-'--------| ;; - `.|--------|// - \ / - '--------' -""" - -WORKER_M = r""" 0 # pylint: disable=trailing-whitespace -/|\ -/'\ """ - -WORKER_F = r""" 0 # pylint: disable=trailing-whitespace -/w\ -/ \ """ - -WORKER_X = r""" 0 # pylint: disable=trailing-whitespace -/w\ -/'\ """ diff --git a/haystack/nodes/__init__.py b/haystack/nodes/__init__.py deleted file mode 100644 index 9ac1f3268b..0000000000 --- a/haystack/nodes/__init__.py +++ /dev/null @@ -1,64 +0,0 @@ -from haystack.nodes.base import BaseComponent - -from haystack.nodes.answer_generator import BaseGenerator, OpenAIAnswerGenerator -from haystack.nodes.document_classifier import BaseDocumentClassifier, TransformersDocumentClassifier -from haystack.nodes.extractor import EntityExtractor, simplify_ner_for_qa -from haystack.nodes.file_classifier import FileTypeClassifier -from haystack.nodes.file_converter import ( - BaseConverter, - DocxToTextConverter, - PptxConverter, - ImageToTextConverter, - MarkdownConverter, - PDFToTextConverter, - TikaConverter, - TikaXHTMLParser, - TextConverter, - AzureConverter, - ParsrConverter, - CsvTextConverter, - JsonConverter, -) -from haystack.nodes.image_to_text import TransformersImageToText -from haystack.nodes.label_generator import PseudoLabelGenerator -from haystack.nodes.other import Docs2Answers, JoinDocuments, RouteDocuments, JoinAnswers, DocumentMerger, Shaper -from haystack.nodes.preprocessor import BasePreProcessor, PreProcessor -from haystack.nodes.prompt import PromptNode, PromptTemplate, PromptModel, BaseOutputParser, AnswerParser -from haystack.nodes.prompt.invocation_layer import PromptModelInvocationLayer -from haystack.nodes.query_classifier import TransformersQueryClassifier -from haystack.nodes.question_generator import QuestionGenerator -from haystack.nodes.ranker import ( - BaseRanker, - SentenceTransformersRanker, - CohereRanker, - LostInTheMiddleRanker, - DiversityRanker, - RecentnessRanker, -) -from haystack.nodes.reader import BaseReader, FARMReader, TransformersReader, TableReader, RCIReader -from haystack.nodes.retriever import ( - BaseRetriever, - DenseRetriever, - DensePassageRetriever, - EmbeddingRetriever, - BM25Retriever, - FilterRetriever, - MultihopEmbeddingRetriever, - TfidfRetriever, - TableTextRetriever, - MultiModalRetriever, - LinkContentFetcher, - WebRetriever, -) - -from haystack.nodes.sampler import BaseSampler, TopPSampler -from haystack.nodes.search_engine import WebSearch -from haystack.nodes.summarizer import BaseSummarizer, TransformersSummarizer -from haystack.nodes.translator import BaseTranslator, TransformersTranslator -from haystack.nodes.doc_language_classifier import ( - LangdetectDocumentLanguageClassifier, - TransformersDocumentLanguageClassifier, -) - -from haystack.nodes.audio import WhisperTranscriber, WhisperModel -from haystack.nodes.connector.crawler import Crawler diff --git a/haystack/nodes/_json_schema.py b/haystack/nodes/_json_schema.py deleted file mode 100644 index 1f7e0aee75..0000000000 --- a/haystack/nodes/_json_schema.py +++ /dev/null @@ -1,471 +0,0 @@ -from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union - -import os -import sys -import json -import inspect -import logging -from pathlib import Path - -import pydantic.schema -from pydantic import BaseConfig, BaseSettings, Required, SecretStr, create_model -from pydantic.typing import ForwardRef, evaluate_forwardref, is_callable_type -from pydantic.fields import ModelField -from pydantic.schema import ( - SkipField, - TypeModelOrEnum, - TypeModelSet, - encode_default, - field_singleton_schema as _field_singleton_schema, -) - -from haystack import __version__ as haystack_version -from haystack.errors import PipelineSchemaError -from haystack.nodes.base import BaseComponent - - -logger = logging.getLogger(__name__) - - -JSON_SCHEMAS_PATH = Path(__file__).parent.parent.parent / "haystack" / "json-schemas" -SCHEMA_URL = "https://raw.githubusercontent.com/deepset-ai/haystack-json-schema/main/json-schema/" - -# Allows accessory classes (like enums and helpers) to be registered as valid input for -# custom node's init parameters. For now we disable this feature, but flipping this variables -# re-enables it. Mind that string validation will still cut out most attempts to load anything -# else than enums and class constants: see Pipeline.load_from_config() -ALLOW_ACCESSORY_CLASSES = False - - -class Settings(BaseSettings): - input_token: SecretStr - github_repository: str - - -# Monkey patch Pydantic's field_singleton_schema to convert classes and functions to -# strings in JSON Schema -def field_singleton_schema( - field: ModelField, - *, - by_alias: bool, - model_name_map: Dict[TypeModelOrEnum, str], - ref_template: str, - schema_overrides: bool = False, - ref_prefix: Optional[str] = None, - known_models: TypeModelSet, -) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: - try: - # Typing with optional dependencies is really tricky. Let's just use Any for now. To be fixed. - if isinstance(field.type_, ForwardRef): - logger.debug(field.type_) - field.type_ = Any - return _field_singleton_schema( - field, - by_alias=by_alias, - model_name_map=model_name_map, - ref_template=ref_template, - schema_overrides=schema_overrides, - ref_prefix=ref_prefix, - known_models=known_models, - ) - except (ValueError, SkipField): - schema: Dict[str, Any] = {"type": "string"} - - if isinstance(field.default, type) or is_callable_type(field.default): - default = field.default.__name__ - else: - default = field.default - if not field.required: - schema["default"] = encode_default(default) - return schema, {}, set() - - -# Monkeypatch Pydantic's field_singleton_schema -pydantic.schema.field_singleton_schema = field_singleton_schema - - -# From FastAPI's internals -def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: - signature = inspect.signature(call) - globalns = getattr(call, "__globals__", {}) - typed_params = [ - inspect.Parameter( - name=param.name, kind=param.kind, default=param.default, annotation=get_typed_annotation(param, globalns) - ) - for param in signature.parameters.values() - ] - typed_signature = inspect.Signature(typed_params) - return typed_signature - - -# From FastAPI's internals -def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any: - annotation = param.annotation - if isinstance(annotation, str): - annotation = ForwardRef(annotation) - annotation = evaluate_forwardref(annotation, globalns, globalns) - return annotation - - -class Config(BaseConfig): - extra = "forbid" # type: ignore - - -def is_valid_component_class(class_): - return inspect.isclass(class_) and not inspect.isabstract(class_) and issubclass(class_, BaseComponent) - - -def find_subclasses_in_modules(importable_modules: List[str]): - """ - This function returns a list `(module, class)` of all the classes that can be imported - dynamically, for example from a pipeline YAML definition or to generate documentation. - - By default it won't include Base classes, which should be abstract. - """ - return [ - (module, class_) - for module in importable_modules - for _, class_ in inspect.getmembers(sys.modules[module]) - if is_valid_component_class(class_) - ] - - -def handle_optional_params(param_fields: List[inspect.Parameter], params_schema: Dict[str, Any]) -> Dict[str, Any]: - """ - Pydantic v1 cannot generate correct JSON schemas including Optional fields. - (https://github.com/samuelcolvin/pydantic/issues/1270) - This function detects optional parameters and updates the schema, - to allow null values for these parameters. - To be removed when Pydantic v2 is released and adopted - """ - optional_params = [] - for param in param_fields: - is_param_optional = ( - hasattr(param.annotation, "__origin__") - and param.annotation.__origin__ == Union - and type(None) in param.annotation.__args__ - ) - if is_param_optional: - optional_params.append(param) - - for param in optional_params: - param_dict = params_schema["properties"][param.name] - type_ = param_dict.pop("type", None) - if type_ is not None: - if "items" in param_dict: - items = param_dict.pop("items") - param_dict["anyOf"] = [{"type": type_, "items": items}, {"type": "null"}] - else: - param_dict["anyOf"] = [{"type": type_}, {"type": "null"}] - else: - anyof_list = param_dict.pop("anyOf", None) - if anyof_list is not None: - anyof_list = sorted( - [item for item in anyof_list if item and "type" in item.keys()], key=lambda x: x["type"] - ) - anyof_list.append({"type": "null"}) - param_dict["anyOf"] = anyof_list - return params_schema - - -def create_schema_for_node_class(node_class: Type[BaseComponent]) -> Tuple[Dict[str, Any], Dict[str, Any]]: - """ - Create the JSON schema for a single BaseComponent subclass, - including all accessory classes. - - :returns: the schema for the node and all accessory classes, - and a dict with the reference to the node only. - """ - if not hasattr(node_class, "__name__"): - raise PipelineSchemaError( - f"Node class '{node_class}' has no '__name__' attribute, cannot create a schema for it." - ) - - node_name = getattr(node_class, "__name__") - - logger.debug("Creating schema for '%s'", node_name) - - # Read the relevant init parameters from __init__'s signature - init_method = getattr(node_class, "__init__", None) - if not init_method: - raise PipelineSchemaError(f"Could not read the __init__ method of {node_name} to create its schema.") - - signature = get_typed_signature(init_method) - - # Check for variadic parameters (*args or **kwargs) and raise an exception if found - if any(param.kind in {param.VAR_POSITIONAL, param.VAR_KEYWORD} for param in signature.parameters.values()): - raise PipelineSchemaError( - "Nodes cannot use variadic parameters like *args or **kwargs in their __init__ function." - ) - - param_fields = [ - param for param in signature.parameters.values() if param.kind not in {param.VAR_POSITIONAL, param.VAR_KEYWORD} - ] - # Remove self parameter - param_fields.pop(0) - param_fields_kwargs: Dict[str, Any] = {} - - # Read all the parameters extracted from the __init__ method with type and default value - for param in param_fields: - annotation = Any - if param.annotation != param.empty: - annotation = param.annotation - default = Required - if param.default != param.empty: - default = param.default - param_fields_kwargs[param.name] = (annotation, default) - - # Create the model with Pydantic and extract the schema - model = create_model(f"{node_name}ComponentParams", __config__=Config, **param_fields_kwargs) - try: - model.update_forward_refs(**model.__dict__) - except NameError as exc: - logger.debug("%s", str(exc)) - params_schema = model.schema() - - # Pydantic v1 patch to generate JSON schemas including Optional fields - # to be removed when Pydantic v2 is released and adopted - params_schema = handle_optional_params(param_fields, params_schema) - - params_schema["title"] = "Parameters" - desc = "Each parameter can reference other components defined in the same YAML file." - params_schema["description"] = desc - - # Definitions for accessory classes will show up here - params_definitions = {} - if "definitions" in params_schema: - if ALLOW_ACCESSORY_CLASSES: - params_definitions = params_schema.pop("definitions") - else: - raise PipelineSchemaError( - f"Node {node_name} takes object instances as parameters " - "in its __init__ function. This is currently not allowed: " - "please use only Python primitives" - ) - - # Write out the schema and ref and return them - component_name = f"{node_name}Component" - component_schema = { - component_name: { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Custom name for the component. Helpful for visualization and debugging.", - "type": "string", - }, - "type": { - "title": "Type", - "description": "Haystack Class name for the component.", - "type": "string", - "const": f"{node_name}", - }, - "params": params_schema, - }, - "required": ["type", "name"], - "additionalProperties": False, - }, - **params_definitions, - } - return component_schema, {"$ref": f"#/definitions/{component_name}"} - - -def get_json_schema(filename: str, version: str, modules: Optional[List[str]] = None): - """ - Generate JSON schema for Haystack pipelines. - """ - if modules is None: - modules = ["haystack.document_stores", "haystack.nodes"] - schema_definitions = {} # All the schemas for the node and accessory classes - node_refs = [] # References to the nodes only (accessory classes cannot be listed among the nodes in a config) - - # List all known nodes in the given modules - possible_node_classes = find_subclasses_in_modules(importable_modules=modules) - - # Build the definitions and refs for the nodes - for _, node_class in possible_node_classes: - node_definition, node_ref = create_schema_for_node_class(node_class) - schema_definitions.update(node_definition) - node_refs.append(node_ref) - - pipeline_schema = { - "$schema": "http://json-schema.org/draft-07/schema", - "$id": f"{SCHEMA_URL}{filename}", - "title": "Haystack Pipeline", - "description": "Haystack Pipeline YAML file describing the nodes of the pipelines. For more info read the docs at: https://haystack.deepset.ai/components/pipelines#yaml-file-definitions", - "type": "object", - "properties": { - "version": { - "title": "Version", - "description": "Version of the Haystack Pipeline file.", - "type": "string", - "const": version, - }, - "extras": { - "title": "Additional properties group", - "description": "To be specified only if contains special pipelines (for example, if this is a Ray pipeline)", - "type": "string", - "enum": ["ray"], - }, - "components": { - "title": "Components", - "description": "Component nodes and their configurations, to later be used in the pipelines section. Define here all the building blocks for the pipelines.", - "type": "array", - "items": {"anyOf": node_refs}, - "required": ["type", "name"], - "additionalProperties": True, # To allow for custom components in IDEs - will be set to False at validation time. - }, - "pipelines": { - "title": "Pipelines", - "description": "Multiple pipelines can be defined using the components from the same YAML file.", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"title": "Name", "description": "Name of the pipeline.", "type": "string"}, - "nodes": { - "title": "Nodes", - "description": "Nodes to be used by this particular pipeline", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "The name of this particular node in the pipeline. This should be one of the names from the components defined in the same file.", - "type": "string", - }, - "inputs": { - "title": "Inputs", - "description": "Input parameters for this node.", - "type": "array", - "items": {"type": "string"}, - }, - "serve_deployment_kwargs": { - "title": "serve_deployment_kwargs", - "description": "Arguments to be passed to the Ray Serve `deployment()` method (only for Ray pipelines)", - "type": "object", - "properties": { - "num_replicas": { - "description": "How many replicas Ray should create for this node (only for Ray pipelines)", - "type": "integer", - }, - "version": {"type": "string"}, - "prev_version": {"type": "string"}, - "init_args": {"type": "array"}, - "init_kwargs": {"type": "object"}, - "router_prefix": {"type": "string"}, - "ray_actor_options": {"type": "object"}, - "user_config": {"type": {}}, - "max_concurrent_queries": {"type": "integer"}, - }, - "additionalProperties": True, - }, - }, - "required": ["name", "inputs"], - "additionalProperties": False, - }, - "required": ["name", "nodes"], - "additionalProperties": False, - }, - "additionalProperties": False, - }, - "additionalProperties": False, - }, - }, - }, - "required": ["version", "components", "pipelines"], - "additionalProperties": False, - "oneOf": [ - { - "not": {"required": ["extras"]}, - "properties": { - "pipelines": { - "title": "Pipelines", - "items": { - "properties": {"nodes": {"items": {"not": {"required": ["serve_deployment_kwargs"]}}}} - }, - } - }, - }, - {"properties": {"extras": {"enum": ["ray"]}}, "required": ["extras"]}, - ], - "definitions": schema_definitions, - } - - return pipeline_schema - - -def inject_definition_in_schema(node_class: Type[BaseComponent], schema: Dict[str, Any]) -> Dict[str, Any]: - """ - Given a node and a schema in dict form, injects the JSON schema for the new component - so that pipelines containing such note can be validated against it. - - :returns: the updated schema - """ - if not is_valid_component_class(node_class): - raise PipelineSchemaError( - f"Can't generate a valid schema for node of type '{node_class.__name__}'. " - "Possible causes: \n" - " - it has abstract methods\n" - " - its __init__() take something else than Python primitive types or other nodes as parameter.\n" - ) - schema_definition, node_ref = create_schema_for_node_class(node_class) - schema["definitions"].update(schema_definition) - schema["properties"]["components"]["items"]["anyOf"].append(node_ref) - logger.info("Added definition for %s", getattr(node_class, "__name__")) - return schema - - -def load_schema(): - """ - Generate the json schema if it doesn't exist and load it - """ - schema_file_path = JSON_SCHEMAS_PATH / "haystack-pipeline-main.schema.json" - if not os.path.exists(schema_file_path): - logger.info("Json schema not found, generating one at: %s", schema_file_path) - try: - update_json_schema(main_only=True) - except Exception as e: - # Be sure not to remain with an empty file if something went wrong - if schema_file_path.exists(): - schema_file_path.unlink() - # This error is not recoverable - raise e - - with open(schema_file_path, "r") as schema_file: - return json.load(schema_file) - - -def update_json_schema(destination_path: Path = JSON_SCHEMAS_PATH, main_only: bool = False): - """ - Create (or update) a new schema. - """ - # `main` schema is always updated and will contain the same data as the latest - # commit from `main` or a release branch - filename = "haystack-pipeline-main.schema.json" - - os.makedirs(destination_path, exist_ok=True) - with open(destination_path / filename, "w") as json_file: - json.dump(get_json_schema(filename=filename, version="ignore"), json_file, indent=2) - - if not main_only and "rc" not in haystack_version: - # Create/update the specific version file too - filename = f"haystack-pipeline-{haystack_version}.schema.json" - with open(destination_path / filename, "w") as json_file: - json.dump(get_json_schema(filename=filename, version=haystack_version), json_file, indent=2) - - # Update the index - index_name = "haystack-pipeline.schema.json" - with open(destination_path / index_name, "r") as json_file: - index = json.load(json_file) - new_entry = { - "allOf": [ - {"properties": {"version": {"const": haystack_version}}}, - {"$ref": f"{SCHEMA_URL}haystack-pipeline-{haystack_version}.schema.json"}, - ] - } - if new_entry not in index["oneOf"]: - index["oneOf"].append(new_entry) - with open(destination_path / index_name, "w") as json_file: - json.dump(obj=index, fp=json_file, indent=2, sort_keys=True) diff --git a/haystack/nodes/answer_generator/__init__.py b/haystack/nodes/answer_generator/__init__.py deleted file mode 100644 index d4c7eeb558..0000000000 --- a/haystack/nodes/answer_generator/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.answer_generator.base import BaseGenerator -from haystack.nodes.answer_generator.openai import OpenAIAnswerGenerator diff --git a/haystack/nodes/answer_generator/base.py b/haystack/nodes/answer_generator/base.py deleted file mode 100644 index 3aedff4ac8..0000000000 --- a/haystack/nodes/answer_generator/base.py +++ /dev/null @@ -1,226 +0,0 @@ -from abc import abstractmethod -from typing import Any, List, Optional, Dict, Union - -from tqdm import tqdm - -from haystack.errors import HaystackError -from haystack.schema import Answer, Document, MultiLabel -from haystack.nodes.base import BaseComponent - - -class BaseGenerator(BaseComponent): - """ - Abstract class for Generators - """ - - outgoing_edges = 1 - - def __init__(self, progress_bar: bool = True): - super().__init__() - self.progress_bar = progress_bar - - @abstractmethod - def predict(self, query: str, documents: List[Document], top_k: Optional[int], max_tokens: Optional[int]) -> Dict: - """ - Abstract method to generate answers. - - :param query: Query string. - :param documents: Related documents (for example, coming from a retriever) the answer should be based on. - :param top_k: Number of returned answers. - :param max_tokens: The maximum number of tokens the generated answer can have. - :return: Generated answers plus additional infos in a dict. - """ - pass - - def run( # type: ignore - self, - query: str, - documents: List[Document], - top_k: Optional[int] = None, - labels: Optional[MultiLabel] = None, - add_isolated_node_eval: bool = False, - max_tokens: Optional[int] = None, - ): # type: ignore - """ - :param query: Query string. - :param documents: List of Documents the answer should be based on. - :param top_k: The maximum number of answers to return. - :param labels: Labels to be used for evaluation. - :param add_isolated_node_eval: If True, the answer generator will be evaluated in isolation. - :param max_tokens: The maximum number of tokens the generated answer can have. - """ - if documents: - results = self.predict(query=query, documents=documents, top_k=top_k, max_tokens=max_tokens) - else: - results = {"answers": []} - - # run evaluation with "perfect" labels as node inputs to calculate "upper bound" metrics for just this node - if add_isolated_node_eval and labels is not None: - relevant_documents = list({label.document.id: label.document for label in labels.labels}.values()) - results_label_input = self.predict( - query=query, documents=relevant_documents, top_k=top_k, max_tokens=max_tokens - ) - results["answers_isolated"] = results_label_input["answers"] - - return results, "output_1" - - def run_batch( # type: ignore - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - labels: Optional[List[MultiLabel]] = None, - batch_size: Optional[int] = None, - add_isolated_node_eval: bool = False, - max_tokens: Optional[int] = None, - ): - """ - :param queries: List of query strings. - :param documents: List of list of Documents the answer should be based on. - :param top_k: The maximum number of answers to return. - :param labels: Labels to be used for evaluation. - :param add_isolated_node_eval: If True, the answer generator will be evaluated in isolation. - :param max_tokens: The maximum number of tokens the generated answer can have. - """ - results = self.predict_batch( - queries=queries, documents=documents, top_k=top_k, batch_size=batch_size, max_tokens=max_tokens - ) - - # run evaluation with "perfect" labels as node inputs to calculate "upper bound" metrics for just this node - if add_isolated_node_eval and labels is not None: - relevant_documents = [] - for labelx in labels: - # Deduplicate same Documents in a MultiLabel based on their Document ID and filter out empty Documents - relevant_docs_labels = list( - { - label.document.id: label.document - for label in labelx.labels - if not isinstance(label.document.content, str) or label.document.content.strip() != "" - }.values() - ) - relevant_documents.append(relevant_docs_labels) - results_label_input = self.predict_batch(queries=queries, documents=relevant_documents, top_k=top_k) - - results["answers_isolated"] = results_label_input["answers"] - return results, "output_1" - - def _flatten_docs(self, documents: List[Document]): - flat_docs_dict: Dict[str, Any] = {} - for document in documents: - for k, v in document.to_dict().items(): - if k not in flat_docs_dict: - flat_docs_dict[k] = [] - flat_docs_dict[k].append(v) - return flat_docs_dict - - def _create_answers( - self, generated_answers: List[str], documents: List[Document], prompt: Optional[str] = None - ) -> List[Answer]: - flat_docs_dict = self._flatten_docs(documents) - answers: List[Any] = [] - for generated_answer in generated_answers: - answers.append( - Answer( - answer=generated_answer, - document_ids=flat_docs_dict.get("id"), - type="generative", - meta={ - "doc_scores": flat_docs_dict.get("score"), - "content": flat_docs_dict.get("content"), - "titles": [d.get("name", "") for d in flat_docs_dict.get("meta", [])], - "doc_metas": flat_docs_dict.get("meta"), - "prompt": prompt, - }, - ) - ) - return answers - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - max_tokens: Optional[int] = None, - ): - """ - Generate the answer to the input queries. The generation will be conditioned on the supplied documents. - These documents can for example be retrieved via the Retriever. - - - If you provide a list containing a single query... - - - ... and a single list of Documents, the query will be applied to each Document individually. - - ... and a list of lists of Documents, the query will be applied to each list of Documents and the Answers - will be aggregated per Document list. - - - If you provide a list of multiple queries... - - - ... and a single list of Documents, each query will be applied to each Document individually. - - ... and a list of lists of Documents, each query will be applied to its corresponding list of Documents - and the Answers will be aggregated per query-Document pair. - - :param queries: List of queries. - :param documents: Related documents (for example, coming from a retriever) the answer should be based on. - Can be a single list of Documents or a list of lists of Documents. - :param top_k: Number of returned answers per query. - :param batch_size: Not applicable. - :param max_tokens: The maximum number of tokens the generated answer can have. - :return: Generated answers plus additional infos in a dict like this: - - ```python - {'queries': 'who got the first nobel prize in physics', - 'answers': - [{'query': 'who got the first nobel prize in physics', - 'answer': ' albert einstein', - 'meta': { 'doc_ids': [...], - 'doc_scores': [80.42758 ...], - 'doc_probabilities': [40.71379089355469, ... - 'content': ['Albert Einstein was a ...] - 'titles': ['"Albert Einstein"', ...] - }}]} - ``` - """ - # TODO: This method currently just calls the predict method multiple times, so there is room for improvement. - - results: Dict = {"queries": queries, "answers": []} - - single_doc_list = False - # Docs case 1: single list of Documents -> apply each query to all Documents - if len(documents) > 0 and isinstance(documents[0], Document): - single_doc_list = True - pb = tqdm(total=len(queries) * len(documents), disable=not self.progress_bar, desc="Generating answers") - for query in queries: - for doc in documents: - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - preds = self.predict(query=query, documents=[doc], top_k=top_k, max_tokens=max_tokens) - results["answers"].append(preds["answers"]) - pb.update(1) - pb.close() - - # Docs case 2: list of lists of Documents -> apply each query to corresponding list of Documents, if queries - # contains only one query, apply it to each list of Documents - elif len(documents) > 0 and isinstance(documents[0], list): - if len(queries) == 1: - queries = queries * len(documents) - if len(queries) != len(documents): - raise HaystackError("Number of queries must be equal to number of provided Document lists.") - pb = tqdm(total=min(len(queries), len(documents)), disable=not self.progress_bar, desc="Generating answers") - for query, cur_docs in zip(queries, documents): - if not isinstance(cur_docs, list): - raise HaystackError(f"cur_docs was of type {type(cur_docs)}, but expected a list of Documents.") - preds = self.predict(query=query, documents=cur_docs, top_k=top_k, max_tokens=max_tokens) - results["answers"].append(preds["answers"]) - pb.update(1) - pb.close() - - # Group answers by question in case of multiple queries and single doc list - if single_doc_list and len(queries) > 1: - answers_per_query = int(len(results["answers"]) / len(queries)) - answers = [] - for i in range(0, len(results["answers"]), answers_per_query): - answer_group = results["answers"][i : i + answers_per_query] - answers.append(answer_group) - results["answers"] = answers - - return results diff --git a/haystack/nodes/answer_generator/openai.py b/haystack/nodes/answer_generator/openai.py deleted file mode 100644 index 68edd16b03..0000000000 --- a/haystack/nodes/answer_generator/openai.py +++ /dev/null @@ -1,338 +0,0 @@ -import logging -import os -from typing import List, Optional, Tuple, Union -import warnings - -from haystack import Document -from haystack.environment import HAYSTACK_REMOTE_API_TIMEOUT_SEC -from haystack.nodes.answer_generator import BaseGenerator -from haystack.nodes.prompt import PromptTemplate -from haystack.utils.openai_utils import ( - load_openai_tokenizer, - openai_request, - _openai_text_completion_tokenization_details, - _check_openai_finish_reason, - check_openai_policy_violation, -) - -logger = logging.getLogger(__name__) - -OPENAI_TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) - - -class OpenAIAnswerGenerator(BaseGenerator): - """ - This component is now deprecated and will be removed in future versions. - Use `PromptNode` instead of `OpenAIAnswerGenerator`, - as explained in https://haystack.deepset.ai/tutorials/22_pipeline_with_promptnode. - - Uses the GPT-3 models from the OpenAI API to generate Answers based on the Documents it receives. - The Documents can come from a Retriever or you can supply them manually. - - To use this Node, you need an API key from an active OpenAI account. You can sign-up for an account - on the [OpenAI API website](https://openai.com/api/). - """ - - def __init__( - self, - api_key: str, - azure_base_url: Optional[str] = None, - azure_deployment_name: Optional[str] = None, - model: str = "text-davinci-003", - max_tokens: int = 50, - api_version: str = "2022-12-01", - top_k: int = 5, - temperature: float = 0.2, - presence_penalty: float = 0.1, - frequency_penalty: float = 0.1, - examples_context: Optional[str] = None, - examples: Optional[List[List[str]]] = None, - stop_words: Optional[List[str]] = None, - progress_bar: bool = True, - prompt_template: Optional[PromptTemplate] = None, - context_join_str: str = " ", - moderate_content: bool = False, - api_base: str = "https://api.openai.com/v1", - openai_organization: Optional[str] = None, - ): - """ - :param api_key: Your API key from OpenAI. It is required for this node to work. - :param azure_base_url: The base URL for the Azure OpenAI API. If not supplied, Azure OpenAI API will not be used. - This parameter is an OpenAI Azure endpoint, usually in the form `https://.openai.azure.com`. - :param azure_deployment_name: The name of the Azure OpenAI API deployment. If not supplied, Azure OpenAI API will not be used. - :param model: ID of the engine to use for generating the answer. You can select one of `"text-ada-001"`, - `"text-babbage-001"`, `"text-curie-001"`, or `"text-davinci-003"` - (from worst to best and from cheapest to most expensive). For more information about the models, - refer to the [OpenAI Documentation](https://platform.openai.com/docs/models/gpt-3). - :param max_tokens: The maximum number of tokens reserved for the generated Answer. - A higher number allows for longer answers without exceeding the max prompt length of the OpenAI model. - A lower number allows longer prompts with more documents passed as context, but the generated answer might be cut after max_tokens. - :param api_version: The version of the Azure OpenAI API to use. The default is `2022-12-01` version. - :param top_k: Number of generated Answers. - :param temperature: What sampling temperature to use. Higher values mean the model will take more risks and - value 0 (argmax sampling) works better for scenarios with a well-defined Answer. - :param presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they have already appeared - in the text. This increases the model's likelihood to talk about new topics. For more information about frequency and presence penalties, see - [parameter details in OpenAI](https://platform.openai.com/docs/api-reference/parameter-details). - :param frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing - frequency in the text so far, decreasing the model's likelihood to repeat the same line - verbatim. - [See more information about frequency and presence penalties.](https://platform.openai.com/docs/api-reference/parameter-details) - :param examples_context: A text snippet containing the contextual information used to generate the Answers for - the examples you provide. - If not supplied, the default from OpenAI API docs is used: - `"In 2017, U.S. life expectancy was 78.6 years."` - :param examples: List of (question, answer) pairs that helps steer the model towards the tone and answer - format you'd like. We recommend adding 2 to 3 examples. - If not supplied, the default from OpenAI API docs is used: - `[["Q: What is human life expectancy in the United States?", "A: 78 years."]]` - :param stop_words: Up to four sequences where the API stops generating further tokens. The returned text does not contain the stop sequence. - If you don't provide any stop words, the default value from OpenAI API docs is used: `["\\n", "<|endoftext|>"]`. - :param prompt_template: A PromptTemplate that tells the model how to generate answers given a - `context` and `query` supplied at runtime. The `context` is automatically constructed at runtime from a - list of provided documents. Use `example_context` and a list of `examples` to provide the model with examples to steer it towards the tone and answer format you would like. - If not supplied, the default prompt template is: - ```python - PromptTemplate( - "Please answer the question according to the above context." - "\\n===\\nContext: {examples_context}\\n===\\n{examples}\\n\\n" - "===\\nContext: {context}\\n===\\n{query}", - ) - ``` - To learn how variables, such as '{context}', are substituted in the prompt text, see - [PromptTemplate](https://docs.haystack.deepset.ai/docs/prompt_node#template-structure). - :param context_join_str: The separation string used to join the input documents to create the context - used by the PromptTemplate. - :param moderate_content: Whether to filter input and generated answers for potentially sensitive content - using the [OpenAI Moderation API](https://platform.openai.com/docs/guides/moderation). If the input or - answers are flagged, an empty list is returned in place of the answers. - :param api_base: The base URL for the OpenAI API, defaults to `"https://api.openai.com/v1"`. - :param openai_organization: The OpenAI-Organization ID, defaults to `None`. For more details, see see OpenAI - [documentation](https://platform.openai.com/docs/api-reference/requesting-organization). - """ - - warnings.warn( - "`OpenAIAnswerGenerator component is deprecated and will be removed in future versions. Use `PromptNode` " - "instead of `OpenAIAnswerGenerator`.", - category=DeprecationWarning, - ) - - super().__init__(progress_bar=progress_bar) - if (examples is None and examples_context is not None) or (examples is not None and examples_context is None): - logger.warning( - "If providing examples or examples_context, we recommend providing both of them " - "so the examples correctly refer to the examples_context." - ) - if examples_context is None: - examples_context = "In 2017, U.S. life expectancy was 78.6 years." - if examples is None: - examples = [["Q: What is human life expectancy in the United States?", "A: 78 years."]] - if stop_words is None: - stop_words = ["\n", "<|endoftext|>"] - if prompt_template is None: - prompt_template = PromptTemplate( - "Please answer the question according to the above context." - "\n===\nContext: {examples_context}\n===\n{examples}\n\n" - "===\nContext: {context}\n===\n{query}" - ) - else: - # Check for required prompts - required_params = ["context", "query"] - if not all(p in prompt_template.prompt_params for p in required_params): - raise ValueError( - "The OpenAIAnswerGenerator requires a PromptTemplate that has `context` and " - "`query` in its `prompt_params`. Supply a different `prompt_template` or " - "use the default one." - ) - - # Check for unsupported prompt parameters - optional_params = ["examples_context", "examples"] - unknown_params = [] - for p in prompt_template.prompt_params: - if p not in set(required_params + optional_params): - unknown_params.append(p) - if len(unknown_params) > 1: - raise ValueError( - f"The provided PromptTemplate has the prompt parameters, {unknown_params}, that are not supported " - f"by the OpenAIAnswerGenerator. The only prompt parameters that are supported are " - f"`examples_context`, `examples`, `context`, and `query`." - ) - - self.api_key = api_key - self.azure_base_url = azure_base_url - self.azure_deployment_name = azure_deployment_name - self.api_version = api_version - self.api_base = api_base - self.model = model - self.max_tokens = max_tokens - self.top_k = top_k - self.temperature = temperature - self.presence_penalty = presence_penalty - self.frequency_penalty = frequency_penalty - self.examples_context = examples_context - self.examples = examples - self.stop_words = stop_words - self.prompt_template = prompt_template - self.context_join_str = context_join_str - self.using_azure = self.azure_deployment_name is not None and self.azure_base_url is not None - self.moderate_content = moderate_content - self.openai_organization = openai_organization - - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details(model_name=self.model) - - self.MAX_TOKENS_LIMIT = max_tokens_limit - self._tokenizer = load_openai_tokenizer(tokenizer_name=tokenizer_name) - - def predict( - self, - query: str, - documents: List[Document], - top_k: Optional[int] = None, - max_tokens: Optional[int] = None, - timeout: Union[float, Tuple[float, float]] = OPENAI_TIMEOUT, - ): - """ - Use the loaded QA model to generate Answers for a query based on the Documents it receives. - - Returns dictionaries containing Answers. - Note that OpenAI doesn't return scores for those Answers. - - Example: - ```python - { - 'query': 'Who is the father of Arya Stark?', - 'answers':[Answer( - 'answer': 'Eddard,', - 'score': None, - ),... - ] - } - ``` - - :param query: The query you want to provide. It's a string. - :param documents: List of Documents in which to search for the Answer. - :param top_k: The maximum number of Answers to return. - :param max_tokens: The maximum number of tokens the generated Answer can have. - :param timeout: How many seconds to wait for the server to send data before giving up, - as a float, or a :ref:`(connect timeout, read timeout) ` tuple. - Defaults to 10 seconds. - :return: Dictionary containing query and Answers. - """ - if top_k is None: - top_k = self.top_k - - # convert input to OpenAI format - prompt, input_docs = self._build_prompt_within_max_length(query=query, documents=documents) - logger.debug("Prompt being sent to OpenAI API with prompt %s.", prompt) - - payload = { - "model": self.model, - "prompt": prompt, - "max_tokens": max_tokens or self.max_tokens, - "stop": self.stop_words, - "n": top_k, - "temperature": self.temperature, - "presence_penalty": self.presence_penalty, - "frequency_penalty": self.frequency_penalty, - } - if self.using_azure: - url = f"{self.azure_base_url}/openai/deployments/{self.azure_deployment_name}/completions?api-version={self.api_version}" - else: - url = f"{self.api_base}/completions" - - headers = {"Content-Type": "application/json"} - if self.using_azure: - headers["api-key"] = self.api_key - else: - headers["Authorization"] = f"Bearer {self.api_key}" - if self.openai_organization: - headers["OpenAI-Organization"] = self.openai_organization - - if self.moderate_content and check_openai_policy_violation(input=prompt, headers=headers): - logger.info("Prompt '%s' will not be sent to OpenAI due to potential policy violation.", prompt) - return {"query": query, "answers": []} - - logger.debug("Prompt being sent to OpenAI API with prompt %s.", prompt) - res = openai_request(url=url, headers=headers, payload=payload, timeout=timeout) - _check_openai_finish_reason(result=res, payload=payload) - generated_answers = [ans["text"] for ans in res["choices"]] - if self.moderate_content and check_openai_policy_violation(input=generated_answers, headers=headers): - logger.info( - "Generated answers '%s' will not be returned due to potential policy violation.", generated_answers - ) - return {"query": query, "answers": []} - answers = self._create_answers(generated_answers, input_docs, prompt=prompt) - result = {"query": query, "answers": answers} - return result - - @staticmethod - def _create_context(documents: List[Document], join_str: str = " ") -> str: - """Join the documents to create a single context to be used in the PromptTemplate.""" - doc_contents = [doc.content for doc in documents] - # We reverse the docs to put the most relevant documents at the bottom of the context - context = join_str.join(reversed(doc_contents)) - return context - - def _fill_prompt(self, query: str, documents: List[Document]) -> str: - """Fills in the `prompt_template` with its `prompt_params` and returns the full prompt.""" - example_prompts = "\n---\n".join([f"{query}\n{answer}" for query, answer in self.examples]) - qa_prompt = f"Q: {query}\nA:" - - kwargs = {"context": self._create_context(documents, join_str=self.context_join_str), "query": qa_prompt} - if ( - "examples_context" in self.prompt_template.prompt_params - and "examples" in self.prompt_template.prompt_params - ): - kwargs["examples_context"] = self.examples_context - kwargs["examples"] = example_prompts - full_prompt = next(self.prompt_template.fill(**kwargs)) - return full_prompt - - def _build_prompt_within_max_length(self, query: str, documents: List[Document]) -> Tuple[str, List[Document]]: - """ - Builds the prompt for the GPT-3 model so that it can generate an Answer. If the prompt is too long based on the - MAX_TOKENS_LIMIT of the OpenAI model and `max_tokens` you specify, then documents (used to - construct the context) are thrown away until the prompt length fits within the MAX_TOKENS_LIMIT. - """ - full_prompt = self._fill_prompt(query, documents) - n_full_prompt_tokens = len(self._tokenizer.encode(full_prompt)) - - # for length restrictions of prompt see: https://platform.openai.com/docs/api-reference/completions/create#completions/create-max_tokens - leftover_token_len = self.MAX_TOKENS_LIMIT - n_full_prompt_tokens - self.max_tokens - - # Trim down the prompt (by removing documents) until it fits the models MAX_TOKENS_LIMIT - input_docs = documents - skipped_docs = 0 - # If leftover_token_len is negative we have gone past the MAX_TOKENS_LIMIT and the prompt must be trimmed - if leftover_token_len < 0: - n_skipped_tokens = 0 - # Reversing the order of documents b/c we want to throw away less relevant docs first - for doc in reversed(documents): - skipped_docs += 1 - n_skipped_tokens += len(self._tokenizer.encode(doc.content)) - - # Only skip enough tokens to fit within the MAX_TOKENS_LIMIT - if n_skipped_tokens >= abs(leftover_token_len): - break - - # Throw away least relevant docs - input_docs = documents[:-skipped_docs] - full_prompt = self._fill_prompt(query, input_docs) - n_full_prompt_tokens = len(self._tokenizer.encode(full_prompt)) - - if len(input_docs) == 0: - logger.warning( - "Skipping all of the provided Documents, as none of them fits the maximum token limit of %s. " - "The generated answers will therefore not be conditioned on any context.", - self.MAX_TOKENS_LIMIT, - ) - elif skipped_docs >= 1: - logger.warning( - "Skipping %s of the provided Documents, as using them would exceed the maximum token limit of %s.", - skipped_docs, - self.MAX_TOKENS_LIMIT, - ) - - logger.debug("Number of tokens in full prompt: %s", n_full_prompt_tokens) - logger.debug("Full prompt: %s", full_prompt) - return full_prompt, input_docs diff --git a/haystack/nodes/asyncio/sleeper.py b/haystack/nodes/asyncio/sleeper.py deleted file mode 100644 index a6406cd8b4..0000000000 --- a/haystack/nodes/asyncio/sleeper.py +++ /dev/null @@ -1,74 +0,0 @@ -from typing import Optional, List, Dict, Union, Any, Literal -import asyncio - -import numpy as np - -from haystack.schema import Document, MultiLabel, Answer -from haystack.nodes.base import BaseComponent - - -class Sleeper(BaseComponent): - """ - Simple component that sleeps for a random amount of time and then returns a dummy answer. - """ - - outgoing_edges: int = 1 - - def __init__( - self, - mean_sleep_in_seconds: float = 10, - sleep_scale: float = 1.0, - answer_type: Literal["generative", "extractive", "other"] = "generative", - answer_score: Optional[float] = None, - answer: str = "Placeholder", - ) -> None: - super().__init__() - self._mean_sleep_in_seconds = mean_sleep_in_seconds - self._sleep_scale = sleep_scale - self._answer_type = answer_type - self._answer = answer - self._answer_score = answer_score - - # pylint: disable=invalid-overridden-method - async def run( # type: ignore - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - ): - if query is None: - return {"answers": []}, "output_1" - - meta_data = meta if meta is not None else {} - - # Sleep to mock processing time - sleep_time_seconds = max(0.0, np.random.normal(self._mean_sleep_in_seconds, self._sleep_scale)) - await asyncio.sleep(sleep_time_seconds) - - return { - "answers": [Answer(answer=self._answer, type=self._answer_type, meta=meta_data, score=self._answer_score)] - }, "output_1" - - # pylint: disable=too-many-arguments - def run_batch( # type: ignore - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - queries = queries or [] - query_list: List[str] = [queries] if isinstance(queries, str) else queries - result: Dict[Any, Any] = {"answers": [], "queries": []} - - for query in query_list: - iteration_result, _ = self.run(query=query) # type: ignore - result["answers"].append(iteration_result["answers"]) # type: ignore - result["queries"].append(query) - - return result, "output_1" diff --git a/haystack/nodes/audio/__init__.py b/haystack/nodes/audio/__init__.py deleted file mode 100644 index 47dde53d58..0000000000 --- a/haystack/nodes/audio/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.nodes.audio.whisper_transcriber import WhisperTranscriber, WhisperModel diff --git a/haystack/nodes/audio/whisper_transcriber.py b/haystack/nodes/audio/whisper_transcriber.py deleted file mode 100644 index 21482cc3dd..0000000000 --- a/haystack/nodes/audio/whisper_transcriber.py +++ /dev/null @@ -1,217 +0,0 @@ -import json -from typing import List, Optional, Dict, Any, Union, BinaryIO, Literal - -import requests -from requests import PreparedRequest - -from haystack import MultiLabel, Document -from haystack.errors import OpenAIError, OpenAIRateLimitError -from haystack.nodes.base import BaseComponent -from haystack.utils.import_utils import is_whisper_available -from haystack.lazy_imports import LazyImport - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_import: - import torch - - -WhisperModel = Literal["tiny", "small", "medium", "large", "large-v2"] - - -class WhisperTranscriber(BaseComponent): - """ - Transcribes audio files using OpenAI's Whisper. This class supports two underlying implementations: - - - API (default): Uses the OpenAI API and requires an API key. See the [OpenAI blog post](https://beta.openai.com/docs/api-reference/whisper for more details. - - Local (requires installing Whisper): Uses the local installation - of [Whisper](https://github.com/openai/whisper). - - To use Whisper locally, install it following the instructions on - the Whisper [GitHub repo](https://github.com/openai/whisper) and omit the `api_key` parameter. - - To use the API implementation, provide an api_key. You can get one by signing up - for an [OpenAI account](https://beta.openai.com/). - - For the supported audio formats, languages, and other parameters, see the - [Whisper API documentation](https://platform.openai.com/docs/guides/speech-to-text) and the official Whisper - [github repo](https://github.com/openai/whisper). - """ - - # If it's not a decision component, there is only one outgoing edge - outgoing_edges = 1 - - def __init__( - self, - api_key: Optional[str] = None, - model_name_or_path: WhisperModel = "medium", - device: Optional[Union[str, "torch.device"]] = None, - api_base: str = "https://api.openai.com/v1", - ) -> None: - """ - Creates a WhisperTranscriber instance. - - :param api_key: OpenAI API key. If None, a local installation of Whisper is used. - :param model_name_or_path: Name of the model to use. If using a local installation of Whisper, set this to one of the following values: "tiny", "small", "medium", "large", "large-v2". If using - the API, set this value to: "whisper-1" (default). - :param device: Device to use for inference. Only used if you're using a local - installation of Whisper. If None, the device is automatically selected. - :param api_base: The OpenAI API Base url, defaults to `https://api.openai.com/v1`. - """ - super().__init__() - self.api_key = api_key - self.api_base = api_base - self.use_local_whisper = is_whisper_available() and self.api_key is None - - if self.use_local_whisper: - import whisper - - self._model = whisper.load_model(model_name_or_path, device=device) - else: - if api_key is None: - raise ValueError( - "Provide a valid api_key for OpenAI API. Alternatively, " - "install OpenAI Whisper (see [Whisper](https://github.com/openai/whisper) for more details)." - ) - - def transcribe( - self, - audio_file: Union[str, BinaryIO], - language: Optional[str] = None, - return_segments: bool = False, - translate: bool = False, - **kwargs, - ) -> Dict[str, Any]: - """ - Transcribe an audio file. - - :param audio_file: Path to the audio file or a binary file-like object. - :param language: Language of the audio file. If None, the language is automatically detected. - :param return_segments: If True, returns the transcription for each segment of the audio file. Supported with - local installation of whisper only. - :param translate: If True, translates the transcription to English. - :return: A dictionary containing the transcription text and metadata like timings, segments etc. - - """ - transcript: Dict[str, Any] = {} - - new_kwargs = {k: v for k, v in kwargs.items() if v is not None} - if language is not None: - new_kwargs["language"] = language - - if self.use_local_whisper: - new_kwargs["return_segments"] = return_segments - transcript = self._invoke_local(audio_file, translate, **new_kwargs) - elif self.api_key: - transcript = self._invoke_api(audio_file, translate, **new_kwargs) - return transcript - - def _invoke_api( - self, audio_file: Union[str, BinaryIO], translate: Optional[bool] = False, **kwargs - ) -> Dict[str, Any]: - if isinstance(audio_file, str): - with open(audio_file, "rb") as f: - return self._invoke_api(f, translate, **kwargs) - else: - headers = {"Authorization": f"Bearer {self.api_key}"} - request = PreparedRequest() - url: str = ( - f"{self.api_base}/audio/transcriptions" if not translate else f"{self.api_base}/audio/translations" - ) - - request.prepare( - method="POST", - url=url, - headers=headers, - data={"model": "whisper-1", **kwargs}, - files=[("file", (audio_file.name, audio_file, "application/octet-stream"))], - ) - response = requests.post(url, data=request.body, headers=request.headers, timeout=600) - - if response.status_code != 200: - openai_error: OpenAIError - if response.status_code == 429: - openai_error = OpenAIRateLimitError(f"API rate limit exceeded: {response.text}") - else: - openai_error = OpenAIError( - f"OpenAI returned an error.\n" - f"Status code: {response.status_code}\n" - f"Response body: {response.text}", - status_code=response.status_code, - ) - raise openai_error - - return json.loads(response.content) - - def _invoke_local( - self, audio_file: Union[str, BinaryIO], translate: Optional[bool] = False, **kwargs - ) -> Dict[str, Any]: - torch_import.check() - - if isinstance(audio_file, str): - with open(audio_file, "rb") as f: - return self._invoke_local(f, translate, **kwargs) - else: - return_segments = kwargs.pop("return_segments", None) - kwargs["task"] = "translate" if translate else "transcribe" - transcription = self._model.transcribe(audio_file.name, **kwargs) - if not return_segments: - transcription.pop("segments", None) - - return transcription - - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - ): # type: ignore - """ - Transcribe audio files. - - :param query: Ignored - :param file_paths: List of paths to audio files. - :param labels: Ignored - :param documents: Ignored - :param meta: Ignored - :return: A dictionary containing a list of Document objects, one for each input file. - - """ - transcribed_documents: List[Document] = [] - if file_paths: - for file_path in file_paths: - transcription = self.transcribe(file_path) - d = Document.from_dict(transcription, field_map={"text": "content"}) - transcribed_documents.append(d) - - output = {"documents": transcribed_documents} - return output, "output_1" - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): # type: ignore - """ - Transcribe audio files. - - :param queries: Ignored - :param file_paths: List of paths to audio files. - :param labels: Ignored - :param documents: Ignored - :param meta: Ignored - :param params: Ignored - :param debug: Ignored - """ - if file_paths and isinstance(file_paths[0], list): - all_files = [] - for files_list in file_paths: - all_files += files_list - return self.run(file_paths=all_files) - return self.run(file_paths=file_paths) diff --git a/haystack/nodes/base.py b/haystack/nodes/base.py deleted file mode 100644 index ca212cc92e..0000000000 --- a/haystack/nodes/base.py +++ /dev/null @@ -1,362 +0,0 @@ -from __future__ import annotations -from typing import Any, Optional, Dict, List, Tuple, Union, Callable, Type - -from copy import deepcopy -from abc import ABC, abstractmethod -from functools import wraps -import inspect -import logging - -from haystack.schema import Document, MultiLabel -from haystack.errors import PipelineSchemaError -from haystack.utils.reflection import args_to_kwargs - - -logger = logging.getLogger(__name__) - - -def exportable_to_yaml(init_func): - """ - Decorator that saves the init parameters of a node that later can - be used with exporting YAML configuration of a Pipeline. We ensure - that only params passed to the __init__ function of the implementation - are saved, ignoring calls to the ancestors. - """ - - @wraps(init_func) - def wrapper_exportable_to_yaml(self, *args, **kwargs): - # Create the configuration dictionary if it doesn't exist yet - if not self._component_config: - self._component_config = {"params": {}, "type": type(self).__name__} - - # NOTE: inner classes constructor's __qualname__ will include the outer class' name, - # e.g. "OuterClass.InnerClass.__init__". We then take only the last two parts of the - # fully qualified name, in the previous example that would be "InnerClass.__init__" - name_components = init_func.__qualname__.split(".") - # Reconstruct the inner class' __qualname__ and compare with the __qualname__ of the implementation class. - # If the number of components is wrong, let the IndexError bubble up, there's nothing we can do anyways. - if f"{name_components[-2]}.{name_components[-1]}" == f"{self.__class__.__name__}.{init_func.__name__}": - # Store all the input parameters in self._component_config - args_as_kwargs = args_to_kwargs(args, init_func) - params = {**args_as_kwargs, **kwargs} - for k, v in params.items(): - self._component_config["params"][k] = v - - # Call the actual __init__ function with all the arguments - init_func(self, *args, **kwargs) - - return wrapper_exportable_to_yaml - - -class BaseComponent(ABC): - """ - A base class for implementing nodes in a Pipeline. - """ - - outgoing_edges: int - _subclasses: dict = {} - _component_config: dict = {} - - def __init__(self): - component_params = self._component_config.get("params", {}) - self.outgoing_edges = self._calculate_outgoing_edges(component_params=component_params) - - # __init_subclass__ is invoked when a subclass of BaseComponent is _imported_ - # (not instantiated). It works approximately as a metaclass. - def __init_subclass__(cls, **kwargs): - super().__init_subclass__(**kwargs) - - # Each component must specify the number of outgoing edges (= different outputs). - # During pipeline validation this number is compared to the requested number of output edges. - if not hasattr(cls, "outgoing_edges"): - raise ValueError( - "BaseComponent subclasses must define the outgoing_edges class attribute. " - "If this number depends on the component's parameters, make sure to override the _calculate_outgoing_edges() method. " - "See https://haystack.deepset.ai/pipeline_nodes/custom-nodes for more information." - ) - - # Automatically registers all the init parameters in - # an instance attribute called `_component_config`, - # used to save this component to YAML. See exportable_to_yaml() - cls.__init__ = exportable_to_yaml(cls.__init__) - - # Keeps track of all available subclasses by name. - # Enables generic load() for all specific component implementations. - # Registers abstract classes and base classes too. - cls._subclasses[cls.__name__] = cls - - @property - def name(self) -> Optional[str]: - return self._component_config.get("name", None) - - @name.setter - def name(self, value: str): - self._component_config["name"] = value - - @property - def utilized_components(self) -> List[BaseComponent]: - if "params" not in self._component_config: - return [] - return [param for param in self._component_config["params"].values() if isinstance(param, BaseComponent)] - - @property - def type(self) -> str: - return self._component_config["type"] - - def get_params(self, return_defaults: bool = False) -> Dict[str, Any]: - component_signature = dict(inspect.signature(self.__class__).parameters) - params: Dict[str, Any] = {} - for key, value in self._component_config["params"].items(): - if value != component_signature[key].default or return_defaults: - params[key] = value - if return_defaults: - for key, param in component_signature.items(): - if key not in params: - params[key] = param.default - return params - - @classmethod - def get_subclass(cls, component_type: str) -> Type[BaseComponent]: - if component_type not in cls._subclasses.keys(): - raise PipelineSchemaError( - f"Haystack component with the name '{component_type}' not found. " - "Check the class name of your component for spelling mistakes and make sure you installed " - "Haystack with the proper extras: https://docs.haystack.deepset.ai/docs/installation#custom-installation" - ) - - subclass = cls._subclasses[component_type] - return subclass - - @classmethod - def _calculate_outgoing_edges(cls, component_params: Dict[str, Any]) -> int: - """ - Returns the number of outgoing edges for an instance of the component class given its component params. - - In some cases (e.g. RouteDocuments) the number of outgoing edges is not static but rather depends on its component params. - Setting the number of outgoing edges inside the constructor would not be sufficient, since it is already required for validating the pipeline when there is no instance yet. - Hence, this method is responsible for calculating the number of outgoing edges - - during pipeline validation - - to set the effective instance value of `outgoing_edges`. - - Override this method if the number of outgoing edges depends on the component params. - If not overridden, returns the number of outgoing edges as defined in the component class. - - :param component_params: parameters to pass to the __init__() of the component. - """ - return cls.outgoing_edges - - @classmethod - def _create_instance(cls, component_type: str, component_params: Dict[str, Any], name: Optional[str] = None): - """ - Returns an instance of the given subclass of BaseComponent. - - :param component_type: name of the component class to load. - :param component_params: parameters to pass to the __init__() of the component. - :param name: name of the component instance - """ - subclass = cls.get_subclass(component_type) - instance = subclass(**component_params) - instance.name = name - return instance - - @abstractmethod - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - ) -> Tuple[Dict, str]: - """ - Method that will be executed when the node in the graph is called. - - The argument that are passed can vary between different types of nodes - (e.g. retriever nodes expect different args than a reader node) - - - See an example for an implementation in haystack/reader/base/BaseReader.py - :return: - """ - pass - - @abstractmethod - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - pass - - def _dispatch_run(self, **kwargs) -> Tuple[Dict, str]: - """ - The Pipelines call this method when run() is executed. This method in turn executes the _dispatch_run_general() - method with the correct run method. - """ - return self._dispatch_run_general(self.run, **kwargs) - - def _dispatch_run_batch(self, **kwargs): - """ - The Pipelines call this method when run_batch() is executed. This method in turn executes the - _dispatch_run_general() method with the correct run method. - """ - return self._dispatch_run_general(self.run_batch, **kwargs) - - def _dispatch_run_general(self, run_method: Callable, **kwargs): - """ - This method takes care of the following: - - inspect run_method's signature to validate if all necessary arguments are available - - pop `debug` and sets them on the instance to control debug output - - call run_method with the corresponding arguments and gather output - - collate `_debug` information if present - - merge component output with the preceding output and pass it on to the subsequent Component in the Pipeline - """ - arguments = deepcopy(kwargs) - params = arguments.get("params") or {} - - run_signature_args = inspect.signature(run_method).parameters.keys() - - run_params: Dict[str, Any] = {} - for key, value in params.items(): - if key == self.name: # targeted params for this node - if isinstance(value, dict): - # Extract debug attributes - if "debug" in value.keys(): - self.debug = value.pop("debug") - - for _k in value.keys(): - if _k not in run_signature_args: - raise Exception(f"Invalid parameter '{_k}' for the node '{self.name}'.") - - run_params.update(**value) - elif key in run_signature_args: # global params - run_params[key] = value - - run_inputs = {} - for key, value in arguments.items(): - if key in run_signature_args: - run_inputs[key] = value - - output, stream = run_method(**run_inputs, **run_params) - - # Collect debug information - debug_info = {} - if getattr(self, "debug", None): - # Include input - debug_info["input"] = {**run_inputs, **run_params} - debug_info["input"]["debug"] = self.debug - # Include output, exclude _debug to avoid recursion - filtered_output = {key: value for key, value in output.items() if key != "_debug"} - debug_info["output"] = filtered_output - # Include custom debug info - custom_debug = output.get("_debug", {}) - if custom_debug: - debug_info["runtime"] = custom_debug - - # append _debug information from nodes - all_debug = arguments.get("_debug", {}) - if debug_info: - all_debug[self.name] = debug_info - if all_debug: - output["_debug"] = all_debug - - # add "extra" args that were not used by the node, but not the 'inputs' value - for k, v in arguments.items(): - if k not in output.keys() and k != "inputs": - output[k] = v - - output["params"] = params - return output, stream - - async def _adispatch_run_general(self, run_method: Callable, **kwargs): - """ - This is the async version of _dispatch_run_general and is used indirectly by Pipeline._arun(). - When actually running the node it tries to run it asynchronously, if that fails fall back to a synchronous run. - This makes it possible to run a pipeline asynchronously with a mix of async and sync nodes. - - This method takes care of the following: - - inspect run_method's signature to validate if all necessary arguments are available - - pop `debug` and sets them on the instance to control debug output - - call run_method with the corresponding arguments and gather output - - collate `_debug` information if present - - merge component output with the preceding output and pass it on to the subsequent Component in the Pipeline - - """ - arguments = deepcopy(kwargs) - params = arguments.get("params") or {} - - run_signature_args = inspect.signature(run_method).parameters.keys() - - run_params: Dict[str, Any] = {} - for key, value in params.items(): - if key == self.name: # targeted params for this node - if isinstance(value, dict): - # Extract debug attributes - if "debug" in value.keys(): - self.debug = value.pop("debug") - - for key in value.keys(): - if key not in run_signature_args: - raise Exception(f"Invalid parameter '{key}' for the node '{self.name}'.") - - run_params.update(**value) - elif key in run_signature_args: # global params - run_params[key] = value - - run_inputs = {} - for key, value in arguments.items(): - if key in run_signature_args: - run_inputs[key] = value - - try: - output, stream = await run_method(**run_inputs, **run_params) - except TypeError: - output, stream = run_method(**run_inputs, **run_params) - - # Collect debug information - debug_info = {} - if getattr(self, "debug", None): - # Include input - debug_info["input"] = {**run_inputs, **run_params} - debug_info["input"]["debug"] = self.debug - # Include output, exclude _debug to avoid recursion - filtered_output = {key: value for key, value in output.items() if key != "_debug"} - debug_info["output"] = filtered_output - # Include custom debug info - custom_debug = output.get("_debug", {}) - if custom_debug: - debug_info["runtime"] = custom_debug - - # append _debug information from nodes - all_debug = arguments.get("_debug", {}) - if debug_info: - all_debug[self.name] = debug_info - if all_debug: - output["_debug"] = all_debug - - # add "extra" args that were not used by the node, but not the 'inputs' value - for k, v in arguments.items(): - if k not in output.keys() and k != "inputs": - output[k] = v - - output["params"] = params - return output, stream - - -class RootNode(BaseComponent): - """ - RootNode feeds inputs together with corresponding params to a Pipeline. - """ - - outgoing_edges = 1 - - def run(self): # type: ignore - return {}, "output_1" - - def run_batch(self): # type: ignore - return {}, "output_1" diff --git a/haystack/nodes/connector/__init__.py b/haystack/nodes/connector/__init__.py deleted file mode 100644 index 94cf45285f..0000000000 --- a/haystack/nodes/connector/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.nodes.connector.crawler import Crawler diff --git a/haystack/nodes/connector/crawler.py b/haystack/nodes/connector/crawler.py deleted file mode 100644 index 415f3b6cf7..0000000000 --- a/haystack/nodes/connector/crawler.py +++ /dev/null @@ -1,500 +0,0 @@ -import hashlib -import json -import logging -import os -import re -import sys -import time -from pathlib import Path -from typing import Any, Callable, Dict, List, Optional, Tuple, Union, Set -from urllib.parse import urlparse - -from haystack.nodes.base import BaseComponent -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install farm-haystack[crawler]'") as selenium_import: - from selenium import webdriver - from selenium.common.exceptions import StaleElementReferenceException - from selenium.webdriver.chrome.options import Options - from selenium.webdriver.chrome.service import Service - from selenium.webdriver.common.by import By - -logger = logging.getLogger(__name__) - - -class Crawler(BaseComponent): - """ - Crawl texts from a website so that we can use them later in Haystack as a corpus for search / question answering etc. - - **Example:** - ```python - from haystack.nodes.connector import Crawler - - crawler = Crawler(output_dir="crawled_files") - # crawl Haystack docs, i.e. all pages that include haystack.deepset.ai/overview/ - docs = crawler.crawl(urls=["https://haystack.deepset.ai/overview/get-started"], - filter_urls= ["haystack.deepset.ai/overview/"]) - ``` - """ - - outgoing_edges = 1 - - def __init__( - self, - urls: Optional[List[str]] = None, - crawler_depth: int = 1, - filter_urls: Optional[List] = None, - id_hash_keys: Optional[List[str]] = None, - extract_hidden_text=True, - loading_wait_time: Optional[int] = None, - output_dir: Union[str, Path, None] = None, - overwrite_existing_files=True, - file_path_meta_field_name: Optional[str] = None, - crawler_naming_function: Optional[Callable[[str, str], str]] = None, - webdriver_options: Optional[List[str]] = None, - ): - """ - Init object with basic params for crawling (can be overwritten later). - - :param urls: List of http(s) address(es) (can also be supplied later when calling crawl()) - :param crawler_depth: How many sublinks to follow from the initial list of URLs. Can be any integer >= 0. - For example: - 0: Only initial list of urls. - 1: Follow links found on the initial URLs (but no further). - 2: Additionally follow links found on the second-level URLs. - :param filter_urls: Optional list of regular expressions that the crawled URLs must comply with. - All URLs not matching at least one of the regular expressions will be dropped. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param extract_hidden_text: Whether to extract the hidden text contained in page. - E.g. the text can be inside a span with style="display: none" - :param loading_wait_time: Seconds to wait for page loading before scraping. Recommended when page relies on - dynamic DOM manipulations. Use carefully and only when needed. Crawler will have scraping speed impacted. - E.g. 2: Crawler will wait 2 seconds before scraping page - :param output_dir: If provided, the crawled documents will be saved as JSON files in this directory. - :param overwrite_existing_files: Whether to overwrite existing files in output_dir with new content - :param file_path_meta_field_name: If provided, the file path will be stored in this meta field. - :param crawler_naming_function: A function mapping the crawled page to a file name. - By default, the file name is generated from the processed page url (string compatible with Mac, Unix and Windows paths) and the last 6 digits of the MD5 sum of this unprocessed page url. - E.g. 1) crawler_naming_function=lambda url, page_content: re.sub("[<>:'/\\|?*\0 ]", "_", link) - This example will generate a file name from the url by replacing all characters that are not allowed in file names with underscores. - 2) crawler_naming_function=lambda url, page_content: hashlib.md5(f"{url}{page_content}".encode("utf-8")).hexdigest() - This example will generate a file name from the url and the page content by using the MD5 hash of the concatenation of the url and the page content. - :param webdriver_options: A list of options to send to Selenium webdriver. If none is provided, - Crawler uses, as a default option, a reasonable selection for operating locally, on restricted docker containers, - and avoids using GPU. - Crawler always appends the following option: "--headless" - For example: 1) ["--disable-gpu", "--no-sandbox", "--disable-dev-shm-usage", "--single-process"] - These are the default options which disable GPU, disable shared memory usage - and spawn a single process. - 2) ["--no-sandbox"] - This option disables the sandbox, which is required for running Chrome as root. - 3) ["--remote-debugging-port=9222"] - This option enables remote debug over HTTP. - See [Chromium Command Line Switches](https://peter.sh/experiments/chromium-command-line-switches/) for more details on the available options. - If your crawler fails, raising a `selenium.WebDriverException`, this [Stack Overflow thread](https://stackoverflow.com/questions/50642308/webdriverexception-unknown-error-devtoolsactiveport-file-doesnt-exist-while-t) can be helpful. Contains useful suggestions for webdriver_options. - """ - selenium_import.check() - super().__init__() - - IN_COLAB = "google.colab" in sys.modules - IN_AZUREML = os.environ.get("AZUREML_ENVIRONMENT_IMAGE", None) == "True" - IN_WINDOWS = sys.platform in ["win32", "cygwin"] - IS_ROOT = not IN_WINDOWS and os.geteuid() == 0 # type: ignore # This is a mypy issue of sorts, that fails on Windows. - - if webdriver_options is None: - webdriver_options = ["--headless", "--disable-gpu", "--disable-dev-shm-usage", "--single-process"] - webdriver_options.append("--headless") - if IS_ROOT or IN_WINDOWS or IN_COLAB: - webdriver_options.append("--no-sandbox") - if IS_ROOT or IN_WINDOWS: - webdriver_options.append("--remote-debugging-port=9222") - if IN_COLAB or IN_AZUREML: - webdriver_options.append("--disable-dev-shm-usage") - - options = Options() - for option in set(webdriver_options): - options.add_argument(option) - - self.driver = webdriver.Chrome(service=Service(), options=options) - self.urls = urls - self.crawler_depth = crawler_depth - self.filter_urls = filter_urls - self.overwrite_existing_files = overwrite_existing_files - self.id_hash_keys = id_hash_keys - self.extract_hidden_text = extract_hidden_text - self.loading_wait_time = loading_wait_time - self.crawler_naming_function = crawler_naming_function - self.output_dir = output_dir - self.file_path_meta_field_name = file_path_meta_field_name - - def __del__(self): - self.driver.quit() - - def crawl( - self, - urls: Optional[List[str]] = None, - crawler_depth: Optional[int] = None, - filter_urls: Optional[List] = None, - id_hash_keys: Optional[List[str]] = None, - extract_hidden_text: Optional[bool] = None, - loading_wait_time: Optional[int] = None, - output_dir: Union[str, Path, None] = None, - overwrite_existing_files: Optional[bool] = None, - file_path_meta_field_name: Optional[str] = None, - crawler_naming_function: Optional[Callable[[str, str], str]] = None, - ) -> List[Document]: - """ - Craw URL(s), extract the text from the HTML, create a Haystack Document object out of it and save it (one JSON - file per URL, including text and basic meta data). - You can optionally specify via `filter_urls` to only crawl URLs that match a certain pattern. - All parameters are optional here and only meant to overwrite instance attributes at runtime. - If no parameters are provided to this method, the instance attributes that were passed during __init__ will be used. - - :param urls: List of http addresses or single http address - :param crawler_depth: How many sublinks to follow from the initial list of URLs. Can be any integer >= 0. - For example: - 0: Only initial list of urls. - 1: Follow links found on the initial URLs (but no further). - 2: Additionally follow links found on the second-level URLs. - :param filter_urls: Optional list of regular expressions that the crawled URLs must comply with. - All URLs not matching at least one of the regular expressions will be dropped. - :param overwrite_existing_files: Whether to overwrite existing files in output_dir with new content - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param loading_wait_time: Seconds to wait for page loading before scraping. Recommended when page relies on - dynamic DOM manipulations. Use carefully and only when needed. Crawler will have scraping speed impacted. - E.g. 2: Crawler will wait 2 seconds before scraping page - :param output_dir: If provided, the crawled documents will be saved as JSON files in this directory. - :param file_path_meta_field_name: If provided, the file path will be stored in this meta field. - :param crawler_naming_function: A function mapping the crawled page to a file name. - By default, the file name is generated from the processed page url (string compatible with Mac, Unix and Windows paths) and the last 6 digits of the MD5 sum of this unprocessed page url. - E.g. 1) crawler_naming_function=lambda url, page_content: re.sub("[<>:'/\\|?*\0 ]", "_", link) - This example will generate a file name from the url by replacing all characters that are not allowed in file names with underscores. - 2) crawler_naming_function=lambda url, page_content: hashlib.md5(f"{url}{page_content}".encode("utf-8")).hexdigest() - This example will generate a file name from the url and the page content by using the MD5 hash of the concatenation of the url and the page content. - - :return: List of Documents that were created during crawling - """ - # use passed params or fallback to instance attributes - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - urls = urls or self.urls - if urls is None: - raise ValueError("Got no urls to crawl. Set `urls` to a list of URLs in __init__(), crawl() or run(). `") - output_dir = output_dir or self.output_dir - filter_urls = filter_urls or self.filter_urls - if overwrite_existing_files is None: - overwrite_existing_files = self.overwrite_existing_files - if crawler_depth is None: - crawler_depth = self.crawler_depth - if extract_hidden_text is None: - extract_hidden_text = self.extract_hidden_text - if loading_wait_time is None: - loading_wait_time = self.loading_wait_time - if file_path_meta_field_name is None: - file_path_meta_field_name = self.file_path_meta_field_name - if crawler_naming_function is None: - crawler_naming_function = self.crawler_naming_function - - if isinstance(output_dir, str): - output_dir = Path(output_dir) - - if output_dir: - if not output_dir.exists(): - output_dir.mkdir(parents=True) - - is_not_empty = len(list(output_dir.rglob("*"))) > 0 - if is_not_empty and not overwrite_existing_files: - logger.warning( - "Found data stored in `%s`. Use an empty folder or set `overwrite_existing_files=True`, " - "if you want to overwrite any already present saved files.", - output_dir, - ) - else: - logger.info("Fetching from %s to `%s`", urls, output_dir) - - documents: List[Document] = [] - uncrawled_urls = {base_url: {base_url} for base_url in urls} - crawled_urls = set() - for current_depth in range(crawler_depth + 1): - for base_url, uncrawled_urls_for_base in uncrawled_urls.items(): - urls_to_crawl = list( - filter( - lambda u: (not filter_urls or re.search("|".join(filter_urls), u)) and u not in crawled_urls, - uncrawled_urls_for_base, - ) - ) - crawled_documents = self._crawl_urls( - urls_to_crawl, - extract_hidden_text=extract_hidden_text, - loading_wait_time=loading_wait_time, - id_hash_keys=id_hash_keys, - output_dir=output_dir, - overwrite_existing_files=overwrite_existing_files, - file_path_meta_field_name=file_path_meta_field_name, - crawler_naming_function=crawler_naming_function, - ) - documents += crawled_documents - crawled_urls.update(urls_to_crawl) - if current_depth < crawler_depth: - uncrawled_urls[base_url] = set() - for url_ in urls_to_crawl: - uncrawled_urls[base_url].update( - self._extract_sublinks_from_url( - base_url=url_, - filter_urls=filter_urls, - already_found_links=list(crawled_urls), - loading_wait_time=loading_wait_time, - ) - ) - return documents - - def _create_document( - self, url: str, text: str, base_url: Optional[str] = None, id_hash_keys: Optional[List[str]] = None - ) -> Document: - """ - Create a Document object from the given url and text. - :param url: The current url of the webpage. - :param text: The text content of the webpage. - :param base_url: The original url where we started to crawl. - :param id_hash_keys: The fields that should be used to generate the document id. - """ - - data: Dict[str, Any] = {} - data["meta"] = {"url": url} - if base_url: - data["meta"]["base_url"] = base_url - data["content"] = text - if id_hash_keys: - data["id_hash_keys"] = id_hash_keys - - return Document.from_dict(data) - - def _write_file( - self, - document: Document, - output_dir: Path, - crawler_naming_function: Optional[Callable[[str, str], str]] = None, - overwrite_existing_files: Optional[bool] = None, - file_path_meta_field_name: Optional[str] = None, - ) -> Path: - url = document.meta["url"] - if crawler_naming_function is not None: - file_name_prefix = crawler_naming_function(url, document.content) # type: ignore - else: - file_name_link = re.sub("[<>:'/\\|?*\0 ]", "_", url[:129]) - file_name_hash = hashlib.md5(f"{url}".encode("utf-8")).hexdigest() - file_name_prefix = f"{file_name_link}_{file_name_hash[-6:]}" - - file_path = output_dir / f"{file_name_prefix}.json" - - if file_path_meta_field_name: - document.meta[file_path_meta_field_name] = str(file_path) - - try: - if overwrite_existing_files or not file_path.exists(): - with open(file_path, "w", encoding="utf-8") as f: - json.dump(document.to_dict(), f) - else: - logger.debug( - "File '%s' already exists. Set 'overwrite_existing_files=True' to overwrite it.", file_path - ) - except Exception: - logger.exception( - "Crawler can't save the content of '%s' under '%s'. " - "This webpage will be skipped, but links from this page will still be crawled. " - "Make sure the path above is accessible and the file name is valid. " - "If the file name is invalid, consider setting 'crawler_naming_function' to another function.", - url, - file_path, - ) - - return file_path - - def _crawl_urls( - self, - urls: List[str], - extract_hidden_text: bool, - base_url: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - loading_wait_time: Optional[int] = None, - overwrite_existing_files: Optional[bool] = False, - output_dir: Optional[Path] = None, - crawler_naming_function: Optional[Callable[[str, str], str]] = None, - file_path_meta_field_name: Optional[str] = None, - ) -> List[Document]: - documents: List[Document] = [] - for link in urls: - logger.info("Scraping contents from '%s'", link) - self.driver.get(link) - if loading_wait_time is not None: - time.sleep(loading_wait_time) - el = self.driver.find_element(by=By.TAG_NAME, value="body") - if extract_hidden_text: - text = el.get_attribute("textContent") - else: - text = el.text - - document = self._create_document(url=link, text=text or "", base_url=base_url, id_hash_keys=id_hash_keys) - - if output_dir: - file_path = self._write_file( - document, - output_dir, - crawler_naming_function, - file_path_meta_field_name=file_path_meta_field_name, - overwrite_existing_files=overwrite_existing_files, - ) - logger.debug("Saved content to '%s'", file_path) - - documents.append(document) - - logger.debug("Crawler results: %s Documents", len(documents)) - - return documents - - def run( # type: ignore - self, - urls: Optional[List[str]] = None, - crawler_depth: Optional[int] = None, - filter_urls: Optional[List] = None, - id_hash_keys: Optional[List[str]] = None, - extract_hidden_text: Optional[bool] = True, - loading_wait_time: Optional[int] = None, - output_dir: Union[str, Path, None] = None, - overwrite_existing_files: Optional[bool] = None, - crawler_naming_function: Optional[Callable[[str, str], str]] = None, - file_path_meta_field_name: Optional[str] = None, - ) -> Tuple[Dict[str, List[Document]], str]: - """ - Method to be executed when the Crawler is used as a Node within a Haystack pipeline. - - :param output_dir: Path for the directory to store files - :param urls: List of http addresses or single http address - :param crawler_depth: How many sublinks to follow from the initial list of URLs. Can be any integer >= 0. - For example: - 0: Only initial list of urls. - 1: Follow links found on the initial URLs (but no further). - 2: Additionally follow links found on the second-level URLs. - :param filter_urls: Optional list of regular expressions that the crawled URLs must comply with. - All URLs not matching at least one of the regular expressions will be dropped. - :param overwrite_existing_files: Whether to overwrite existing files in output_dir with new content - :param return_documents: Return json files content - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param extract_hidden_text: Whether to extract the hidden text contained in page. - E.g. the text can be inside a span with style="display: none" - :param loading_wait_time: Seconds to wait for page loading before scraping. Recommended when page relies on - dynamic DOM manipulations. Use carefully and only when needed. Crawler will have scraping speed impacted. - E.g. 2: Crawler will wait 2 seconds before scraping page - :param file_path_meta_field_name: If provided, the file path will be stored in this meta field. - :param crawler_naming_function: A function mapping the crawled page to a file name. - By default, the file name is generated from the processed page url (string compatible with Mac, Unix and Windows paths) and the last 6 digits of the MD5 sum of this unprocessed page url. - E.g. 1) crawler_naming_function=lambda url, page_content: re.sub("[<>:'/\\|?*\0 ]", "_", link) - This example will generate a file name from the url by replacing all characters that are not allowed in file names with underscores. - 2) crawler_naming_function=lambda url, page_content: hashlib.md5(f"{url}{page_content}".encode("utf-8")).hexdigest() - This example will generate a file name from the url and the page content by using the MD5 hash of the concatenation of the url and the page content. - - :return: Tuple({"documents": List of Documents, ...}, Name of output edge) - """ - - documents = self.crawl( - urls=urls, - output_dir=output_dir, - crawler_depth=crawler_depth, - filter_urls=filter_urls, - overwrite_existing_files=overwrite_existing_files, - extract_hidden_text=extract_hidden_text, - loading_wait_time=loading_wait_time, - id_hash_keys=id_hash_keys, - file_path_meta_field_name=file_path_meta_field_name, - crawler_naming_function=crawler_naming_function, - ) - results = {"documents": documents} - - return results, "output_1" - - def run_batch( # type: ignore - self, - urls: Optional[List[str]] = None, - crawler_depth: Optional[int] = None, - filter_urls: Optional[List] = None, - id_hash_keys: Optional[List[str]] = None, - extract_hidden_text: Optional[bool] = True, - loading_wait_time: Optional[int] = None, - output_dir: Union[str, Path, None] = None, - overwrite_existing_files: Optional[bool] = None, - crawler_naming_function: Optional[Callable[[str, str], str]] = None, - file_path_meta_field_name: Optional[str] = None, - ): - return self.run( - output_dir=output_dir, - urls=urls, - crawler_depth=crawler_depth, - filter_urls=filter_urls, - overwrite_existing_files=overwrite_existing_files, - id_hash_keys=id_hash_keys, - extract_hidden_text=extract_hidden_text, - loading_wait_time=loading_wait_time, - crawler_naming_function=crawler_naming_function, - file_path_meta_field_name=file_path_meta_field_name, - ) - - @staticmethod - def _is_internal_url(base_url: str, sub_link: str) -> bool: - base_url_ = urlparse(base_url) - sub_link_ = urlparse(sub_link) - return base_url_.scheme == sub_link_.scheme and base_url_.netloc == sub_link_.netloc - - @staticmethod - def _is_inpage_navigation(base_url: str, sub_link: str) -> bool: - base_url_ = urlparse(base_url) - sub_link_ = urlparse(sub_link) - return base_url_.path == sub_link_.path and base_url_.netloc == sub_link_.netloc - - def _extract_sublinks_from_url( - self, - base_url: str, - filter_urls: Optional[List] = None, - already_found_links: Optional[List] = None, - loading_wait_time: Optional[int] = None, - ) -> Set[str]: - self.driver.get(base_url) - if loading_wait_time is not None: - time.sleep(loading_wait_time) - a_elements = self.driver.find_elements(by=By.XPATH, value="//a[@href]") - sub_links = set() - - filter_pattern = re.compile("|".join(filter_urls)) if filter_urls is not None else None - - for i in a_elements: - try: - sub_link = i.get_attribute("href") - except StaleElementReferenceException: - logger.error( - "The crawler couldn't find the link anymore. It has probably been removed from DOM by JavaScript." - ) - continue - - if ( - sub_link - and not (already_found_links and sub_link in already_found_links) - and self._is_internal_url(base_url=base_url, sub_link=sub_link) - and (not self._is_inpage_navigation(base_url=base_url, sub_link=sub_link)) - ): - if filter_pattern is not None: - if filter_pattern.search(sub_link): - sub_links.add(sub_link) - else: - sub_links.add(sub_link) - - return sub_links diff --git a/haystack/nodes/doc_language_classifier/__init__.py b/haystack/nodes/doc_language_classifier/__init__.py deleted file mode 100644 index 8383f02690..0000000000 --- a/haystack/nodes/doc_language_classifier/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.doc_language_classifier.langdetect import LangdetectDocumentLanguageClassifier -from haystack.nodes.doc_language_classifier.transformers import TransformersDocumentLanguageClassifier diff --git a/haystack/nodes/doc_language_classifier/base.py b/haystack/nodes/doc_language_classifier/base.py deleted file mode 100644 index 1578584506..0000000000 --- a/haystack/nodes/doc_language_classifier/base.py +++ /dev/null @@ -1,136 +0,0 @@ -import logging -from abc import abstractmethod -from typing import Dict, List, Optional, Tuple, Any - -from haystack.nodes.base import BaseComponent, Document - - -logger = logging.getLogger(__name__) - -DEFAULT_LANGUAGES = ["en", "de", "es", "cs", "nl"] - - -class BaseDocumentLanguageClassifier(BaseComponent): - """ - Abstract class for Document Language Classifiers. - """ - - outgoing_edges = len(DEFAULT_LANGUAGES) - - @classmethod - def _calculate_outgoing_edges(cls, component_params: Dict[str, Any]) -> int: - route_by_language = component_params.get("route_by_language", True) - if route_by_language is False: - return 1 - languages_to_route = component_params.get("languages_to_route", DEFAULT_LANGUAGES) - return len(languages_to_route) - - def __init__(self, route_by_language: bool = True, languages_to_route: Optional[List[str]] = None): - """ - :param route_by_language: Routes Documents to a different output edge depending on their language. - :param languages_to_route: A list of languages in ISO code, each corresponding to a different output edge (see [langdetect documentation](https://github.com/Mimino666/langdetect#languages)). - """ - super().__init__() - - if languages_to_route is None: - languages_to_route = DEFAULT_LANGUAGES - if route_by_language is True: - logger.info( - "The languages_to_route list is not defined. The default list will be used: %s", languages_to_route - ) - - if len(set(languages_to_route)) != len(languages_to_route): - duplicates = {lang for lang in languages_to_route if languages_to_route.count(lang) > 1} - raise ValueError(f"The languages_to_route parameter can't contain duplicate values ({duplicates}).") - - self.route_by_language = route_by_language - self.languages_to_route = languages_to_route - - @abstractmethod - def predict(self, documents: List[Document], batch_size: Optional[int] = None) -> List[Document]: - pass - - @abstractmethod - def predict_batch(self, documents: List[List[Document]], batch_size: Optional[int] = None) -> List[List[Document]]: - pass - - def _get_edge_from_language(self, language: str) -> str: - return f"output_{self.languages_to_route.index(language) + 1}" - - def run(self, documents: List[Document]) -> Tuple[Dict[str, List[Document]], str]: # type: ignore - """ - Run language document classifier on a list of documents. - - :param documents: A list of documents whose language you want to detect. - """ - docs_with_languages = self.predict(documents=documents) - output = {"documents": docs_with_languages} - - if self.route_by_language is False: - return output, "output_1" - - # self.route_by_language is True - languages = [doc.meta["language"] for doc in docs_with_languages] - unique_languages = list(set(languages)) - if len(unique_languages) > 1: - raise ValueError( - f"If the route_by_language parameter is True, Documents of multiple languages ({unique_languages}) are not allowed together. " - "If you want to route documents by language, you can call Pipeline.run() once for each Document." - ) - language = unique_languages[0] - if language is None: - logger.warning( - "The model cannot detect the language of any of the documents." - "The first language in the list of supported languages will be used to route the document: %s", - self.languages_to_route[0], - ) - language = self.languages_to_route[0] - if language not in self.languages_to_route: - raise ValueError( - f"'{language}' is not in the list of languages to route ({', '.join(self.languages_to_route)})." - f"You should specify them when initializing the node, using the parameter languages_to_route." - ) - return output, self._get_edge_from_language(str(language)) - - def run_batch(self, documents: List[List[Document]], batch_size: Optional[int] = None) -> Tuple[Dict, str]: # type: ignore - """ - Run language document classifier on batches of documents. - - :param documents: A list of lists of documents whose language you want to detect. - """ - docs_lists_with_languages = self.predict_batch(documents=documents, batch_size=batch_size) - - if self.route_by_language is False: - output = {"documents": docs_lists_with_languages} - return output, "output_1" - - # self.route_by_language is True - split: Dict[str, Dict[str, List[List[Document]]]] = { - f"output_{pos}": {"documents": []} for pos in range(1, len(self.languages_to_route) + 1) - } - - for docs_list in docs_lists_with_languages: - languages = [doc.meta["language"] for doc in docs_list] - unique_languages = list(set(languages)) - if len(unique_languages) > 1: - raise ValueError( - f"If the route_by_language parameter is True, Documents of multiple languages ({unique_languages}) are not allowed together. " - "If you want to route documents by language, you can call Pipeline.run() once for each Document." - ) - if unique_languages[0] is None: - logger.warning( - "The model cannot detect the language of some of the documents." - "The first language in the list of supported languages will be used to route the documents: %s", - self.languages_to_route[0], - ) - language: Optional[str] = self.languages_to_route[0] - language = unique_languages[0] - if language not in self.languages_to_route: - raise ValueError( - f"'{language}' is not in the list of languages to route ({', '.join(self.languages_to_route)})." - f"Specify them when initializing the node, using the parameter languages_to_route." - ) - - edge_name = self._get_edge_from_language(str(language)) - split[edge_name]["documents"].append(docs_list) - return split, "split" diff --git a/haystack/nodes/doc_language_classifier/langdetect.py b/haystack/nodes/doc_language_classifier/langdetect.py deleted file mode 100644 index 7b2bf68da2..0000000000 --- a/haystack/nodes/doc_language_classifier/langdetect.py +++ /dev/null @@ -1,100 +0,0 @@ -import logging -from typing import List, Optional - -from haystack.nodes.base import Document -from haystack.nodes.doc_language_classifier.base import BaseDocumentLanguageClassifier -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport("Run 'pip install farm-haystack[preprocessing]' or 'pip install langdetect'") as langdetect_import: - import langdetect - - -class LangdetectDocumentLanguageClassifier(BaseDocumentLanguageClassifier): - """ - A node based on the lightweight and fast [langdetect library](https://github.com/Mimino666/langdetect) for classifying the language of documents. - This node detects the language of Documents and adds the output to the Documents metadata. - The meta field of the Document is a dictionary with the following format: - ``'meta': {'name': '450_Baelor.txt', 'language': 'en'}`` - - Using the document language classifier, you can directly get predictions with `predict()`. - - You can route the Documents to different branches depending on their language - by setting the `route_by_language` parameter to `True` and specifying the `languages_to_route` parameter. - **Usage example** - ```python - ... - docs = [Document(content="The black dog runs across the meadow")] - - doclangclassifier = LangdetectDocumentLanguageClassifier() - results = doclangclassifier.predict(documents=docs) - - # print the predicted language - print(results[0].to_dict()["meta"]["language"] - - **Usage example for routing** - ```python - ... - docs = [Document(content="My name is Ryan and I live in London"), - Document(content="Mi chiamo Matteo e vivo a Roma")] - - doclangclassifier = LangdetectDocumentLanguageClassifier( - route_by_language = True, - languages_to_route = ['en','it','es'] - ) - for doc in docs: - doclangclassifier.run(doc) - ``` - """ - - def __init__(self, route_by_language: bool = True, languages_to_route: Optional[List[str]] = None): - """ - :param route_by_language: Sends Documents to a different output edge depending on their language. - :param languages_to_route: A list of languages in ISO code, each corresponding to a different output edge (see - [langdetect` documentation](https://github.com/Mimino666/langdetect#languages)). - """ - langdetect_import.check() - super().__init__(route_by_language=route_by_language, languages_to_route=languages_to_route) - - def predict(self, documents: List[Document], batch_size: Optional[int] = None) -> List[Document]: - """ - Detect the language of Documents and add the output to the Documents metadata. - :param documents: A list of Documents whose language you want to detect. - :return: List of Documents, where Document.meta["language"] contains the predicted language. - """ - if len(documents) == 0: - raise ValueError( - "LangdetectDocumentLanguageClassifier needs at least one document to predict the language." - ) - if batch_size is not None: - logger.warning( - "LangdetectDocumentLanguageClassifier does not support batch_size. This parameter is ignored." - ) - - documents_with_language = [] - for document in documents: - try: - language = langdetect.detect(document.content) - except langdetect.LangDetectException: - logger.warning("Langdetect cannot detect the language of document: %s", document) - language = None - document.meta["language"] = language - documents_with_language.append(document) - return documents_with_language - - def predict_batch(self, documents: List[List[Document]], batch_size: Optional[int] = None) -> List[List[Document]]: - """ - Detect the Document's language and add the output to the Document's meta data. - :param documents: A list of lists of Documents to detect language. - :return: List of lists of Documents, where Document.meta["language"] contains the predicted language - """ - if len(documents) == 0 or all(len(docs_list) == 0 for docs_list in documents): - raise ValueError( - "LangdetectDocumentLanguageClassifier needs at least one document to predict the language." - ) - if batch_size is not None: - logger.warning( - "LangdetectDocumentLanguageClassifier does not support batch_size. This parameter is ignored." - ) - return [self.predict(documents=docs_list) for docs_list in documents] diff --git a/haystack/nodes/doc_language_classifier/transformers.py b/haystack/nodes/doc_language_classifier/transformers.py deleted file mode 100644 index 27d4fd960b..0000000000 --- a/haystack/nodes/doc_language_classifier/transformers.py +++ /dev/null @@ -1,182 +0,0 @@ -import logging -from typing import List, Optional, Union, Dict -import itertools - -from tqdm import tqdm - -from haystack.nodes.base import Document -from haystack.nodes.doc_language_classifier.base import BaseDocumentLanguageClassifier -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import pipeline - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class TransformersDocumentLanguageClassifier(BaseDocumentLanguageClassifier): - """ - Transformer-based model for classifying the document language using the Hugging Face's [transformers framework](https://github.com/huggingface/transformers). - While the underlying model can vary (BERT, Roberta, DistilBERT ...), the interface remains the same. - This node detects the language of Documents and adds the output to the Documents metadata. - The meta field of the Document is a dictionary with the following format: - ``'meta': {'name': '450_Baelor.txt', 'language': 'en'}`` - - Using the document language classifier, you can directly get predictions with the `predict()` method. - - You can route the Documents to different branches depending on their language - by setting the `route_by_language` parameter to True and specifying the `languages_to_route` parameter. - **Usage example** - ```python - ... - docs = [Document(content="The black dog runs across the meadow")] - - doclangclassifier = TransformersDocumentLanguageClassifier() - results = doclangclassifier.predict(documents=docs) - - # print the predicted language - print(results[0].to_dict()["meta"]["language"] - - **Usage example for routing** - ```python - ... - docs = [Document(content="My name is Ryan and I live in London"), - Document(content="Mi chiamo Matteo e vivo a Roma")] - - doclangclassifier = TransformersDocumentLanguageClassifier( - route_by_language = True, - languages_to_route = ['en','it','es'] - ) - for doc in docs: - doclangclassifier.run(doc) - ``` - """ - - def __init__( - self, - route_by_language: bool = True, - languages_to_route: Optional[List[str]] = None, - labels_to_languages_mapping: Optional[Dict[str, str]] = None, - model_name_or_path: str = "papluca/xlm-roberta-base-language-detection", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - use_gpu: bool = True, - batch_size: int = 16, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Load a language detection model from Transformers. - For a full list of available models, see [Hugging Face models](https://huggingface.co/models). - For language detection models, see [Language Detection models](https://huggingface.co/models?search=language%20detection) on Hugging Face. - - :param route_by_language: Sends Documents to a different output edge depending on their language. - :param languages_to_route: A list of languages, each corresponding to a different output edge (for the list of supported languages, see the model card of the chosen model). - :param labels_to_languages_mapping: Some Transformers models return generic labels instead of language names. In this case, you can provide a mapping indicating a language for each label. For example: {"LABEL_1": "ar", "LABEL_2": "bg", ...}. - - :param model_name_or_path: Directory of a saved model or the name of a public model, for example 'papluca/xlm-roberta-base-language-detection'. - See [Hugging Face models](https://huggingface.co/models) for a full list of available models. - :param model_version: The version of the model to use from the Hugging Face model hub. Can be a tag name, a branch name, or a commit hash. - :param tokenizer: Name of the tokenizer (usually the same as model). - :param use_gpu: Whether to use GPU (if available). - :param batch_size: Number of Documents to be processed at a time. - :param progress_bar: Whether to show a progress bar while processing. - :param use_auth_token: The API token used to download private models from Hugging Face. - If set to `True`, the token generated when running - `transformers-cli login` (stored in ~/.huggingface) is used. - For more information, see [Hugging Face documentation](https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained). - :param devices: List of torch devices (for example, cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects or strings is supported (for example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False`, the devices - parameter is not used and a single cpu device is used for inference. - - """ - torch_and_transformers_import.check() - super().__init__(route_by_language=route_by_language, languages_to_route=languages_to_route) - - resolved_devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(resolved_devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - resolved_devices[0], - ) - if tokenizer is None: - tokenizer = model_name_or_path - - self.model = pipeline( - task="text-classification", - model=model_name_or_path, - tokenizer=tokenizer, - device=resolved_devices[0], - revision=model_version, - top_k=1, - use_auth_token=use_auth_token, - ) - self.batch_size = batch_size - self.progress_bar = progress_bar - self.labels_to_languages_mapping = labels_to_languages_mapping or {} - - def predict(self, documents: List[Document], batch_size: Optional[int] = None) -> List[Document]: - """ - Detect the language of Documents and add the output to the Documents metadata. - :param documents: A list of Documents whose language you want to detect. - :param batch_size: The number of Documents to classify at a time. - :return: A list of Documents, where Document.meta["language"] contains the predicted language. - """ - if len(documents) == 0: - raise ValueError( - "TransformersDocumentLanguageClassifier needs at least one document to predict the language." - ) - if batch_size is None: - batch_size = self.batch_size - - texts = [doc.content for doc in documents] - batches = self._get_batches(texts, batch_size=batch_size) - predictions = [] - pb = tqdm(total=len(texts), disable=not self.progress_bar, desc="Predicting the language of documents") - for batch in batches: - batched_prediction = self.model(batch, top_k=1, truncation=True) - predictions.extend(batched_prediction) - pb.update(len(batch)) - pb.close() - for prediction, doc in zip(predictions, documents): - label = prediction[0]["label"] - # replace the label with the language, if present in the mapping - language = self.labels_to_languages_mapping.get(label, label) - doc.meta["language"] = language - return documents - - def predict_batch(self, documents: List[List[Document]], batch_size: Optional[int] = None) -> List[List[Document]]: - """ - Detect the Document's language and add the output to the Document's meta data. - :param documents: A list of lists of Documents whose language you want to detect. - :return: A list of lists of Documents where Document.meta["language"] contains the predicted language. - """ - if len(documents) == 0 or all(len(docs_list) == 0 for docs_list in documents): - raise ValueError( - "TransformersDocumentLanguageClassifier needs at least one document to predict the language." - ) - if batch_size is None: - batch_size = self.batch_size - - flattened_documents = list(itertools.chain.from_iterable(documents)) - docs_with_preds = self.predict(flattened_documents, batch_size=batch_size) - - # Group documents together - grouped_documents = [] - for docs_list in documents: - grouped_documents.append(docs_with_preds[: len(docs_list)]) - docs_with_preds = docs_with_preds[len(docs_list) :] - - return grouped_documents - - def _get_batches(self, items, batch_size): - if batch_size is None: - yield items - return - for index in range(0, len(items), batch_size): - yield items[index : index + batch_size] diff --git a/haystack/nodes/document_classifier/__init__.py b/haystack/nodes/document_classifier/__init__.py deleted file mode 100644 index 388ac55aad..0000000000 --- a/haystack/nodes/document_classifier/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.document_classifier.base import BaseDocumentClassifier -from haystack.nodes.document_classifier.transformers import TransformersDocumentClassifier diff --git a/haystack/nodes/document_classifier/base.py b/haystack/nodes/document_classifier/base.py deleted file mode 100644 index 791e8a8b4d..0000000000 --- a/haystack/nodes/document_classifier/base.py +++ /dev/null @@ -1,96 +0,0 @@ -from typing import List, Union, Optional - -import logging -from abc import abstractmethod -from functools import wraps -from time import perf_counter - -from haystack.schema import Document -from haystack.nodes.base import BaseComponent - - -logger = logging.getLogger(__name__) - - -class BaseDocumentClassifier(BaseComponent): - outgoing_edges = 1 - query_count = 0 - query_time = 0 - - @abstractmethod - def predict(self, documents: List[Document]): - pass - - @abstractmethod - def predict_batch( - self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None - ) -> Union[List[Document], List[List[Document]]]: - pass - - def run(self, documents: Union[List[dict], List[Document]], root_node: str): # type: ignore - """ - :param documents: A list of Document objects. - :param root_node: The root node of the pipeline's graph. - """ - self.query_count += 1 - if documents: - predict = self.timing(self.predict, "query_time") - documents = [Document.from_dict(doc) if isinstance(doc, dict) else doc for doc in documents] - results = predict(documents=documents) - else: - results = [] - - document_ids = [doc.id for doc in results] - logger.debug("Classified documents with IDs: %s", document_ids) - - # convert back to dicts if we are in an indexing pipeline - if root_node == "File": - results = [doc.to_dict() for doc in results] - - output = {"documents": results} - - return output, "output_1" - - def run_batch(self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None): # type: ignore - """ - :param documents: List of list of Documents. - :param batch_size: Number of Documents to process at a time. - """ - predict_batch = self.timing(self.predict_batch, "query_time") - results = predict_batch(documents=documents, batch_size=batch_size) - output = {"documents": results} - - if isinstance(documents[0], Document): - document_ids = [doc.id for doc in results] - logger.debug("Classified documents with IDs: %s", document_ids) - else: - for doc_list in results: - document_ids = [doc.id for doc in doc_list] - logger.debug("Classified documents with IDs: %s", document_ids) - - return output, "output_1" - - def timing(self, fn, attr_name): - """Wrapper method used to time functions.""" - - @wraps(fn) - def wrapper(*args, **kwargs): - if attr_name not in self.__dict__: - self.__dict__[attr_name] = 0 - tic = perf_counter() - ret = fn(*args, **kwargs) - toc = perf_counter() - self.__dict__[attr_name] += toc - tic - return ret - - return wrapper - - def print_time(self): - print("Classifier (Speed)") - print("---------------") - if not self.query_count: - print("No querying performed via Classifier.run()") - else: - print(f"Queries Performed: {self.query_count}") - print(f"Query time: {self.query_time}s") - print(f"{self.query_time / self.query_count} seconds per query") diff --git a/haystack/nodes/document_classifier/transformers.py b/haystack/nodes/document_classifier/transformers.py deleted file mode 100644 index f5c2a84f6b..0000000000 --- a/haystack/nodes/document_classifier/transformers.py +++ /dev/null @@ -1,252 +0,0 @@ -from typing import List, Optional, Union -import logging -import itertools - -from tqdm import tqdm - -from haystack.schema import Document -from haystack.nodes.document_classifier.base import BaseDocumentClassifier -from haystack.lazy_imports import LazyImport - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import pipeline - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -logger = logging.getLogger(__name__) - - -class TransformersDocumentClassifier(BaseDocumentClassifier): - """ - Transformer based model for document classification using the HuggingFace's transformers framework - (https://github.com/huggingface/transformers). - While the underlying model can vary (BERT, Roberta, DistilBERT ...), the interface remains the same. - This node classifies documents and adds the output from the classification step to the document's meta data. - The meta field of the document is a dictionary with the following format: - ``'meta': {'name': '450_Baelor.txt', 'classification': {'label': 'love', 'score': 0.960899, 'details': {'love': 0.960899, 'joy': 0.032584, ...}}}`` - - Classification is run on document's content field by default. If you want it to run on another field, - set the `classification_field` to one of document's meta fields. - - With this document_classifier, you can directly get predictions via predict() - - **Usage example at query time:** - - ```python - ... - retriever = BM25Retriever(document_store=document_store) - document_classifier = TransformersDocumentClassifier(model_name_or_path="bhadresh-savani/distilbert-base-uncased-emotion") - p = Pipeline() - p.add_node(component=retriever, name="Retriever", inputs=["Query"]) - p.add_node(component=document_classifier, name="Classifier", inputs=["Retriever"]) - res = p.run( - query="Who is the father of Arya Stark?", - params={"Retriever": {"top_k": 10}} - ) - - # print the classification results - print_documents(res, max_text_len=100, print_meta=True) - # or access the predicted class label directly - res["documents"][0].to_dict()["meta"]["classification"]["label"] - ``` - - **Usage example at index time:** - - ```python - ... - converter = TextConverter() - preprocessor = Preprocessor() - document_store = ElasticsearchDocumentStore() - document_classifier = TransformersDocumentClassifier(model_name_or_path="bhadresh-savani/distilbert-base-uncased-emotion", - batch_size=16) - p = Pipeline() - p.add_node(component=converter, name="TextConverter", inputs=["File"]) - p.add_node(component=preprocessor, name="Preprocessor", inputs=["TextConverter"]) - p.add_node(component=document_classifier, name="DocumentClassifier", inputs=["Preprocessor"]) - p.add_node(component=document_store, name="DocumentStore", inputs=["DocumentClassifier"]) - p.run(file_paths=file_paths) - ``` - """ - - def __init__( - self, - model_name_or_path: str = "bhadresh-savani/distilbert-base-uncased-emotion", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - use_gpu: bool = True, - top_k: Optional[int] = 1, - task: str = "text-classification", - labels: Optional[List[str]] = None, - batch_size: int = 16, - classification_field: Optional[str] = None, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Load a text classification model from Transformers. - Available models for the task of text-classification include: - - ``'bhadresh-savani/distilbert-base-uncased-emotion'`` - - ``'Hate-speech-CNERG/dehatebert-mono-english'`` - - Available models for the task of zero-shot-classification include: - - ``'valhalla/distilbart-mnli-12-3'`` - - ``'cross-encoder/nli-distilroberta-base'`` - - See https://huggingface.co/models for full list of available models. - Filter for text classification models: https://huggingface.co/models?pipeline_tag=text-classification&sort=downloads - Filter for zero-shot classification models (NLI): https://huggingface.co/models?pipeline_tag=zero-shot-classification&sort=downloads&search=nli - - :param model_name_or_path: Directory of a saved model or the name of a public model e.g. 'bhadresh-savani/distilbert-base-uncased-emotion'. - See https://huggingface.co/models for full list of available models. - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param tokenizer: Name of the tokenizer (usually the same as model) - :param use_gpu: Whether to use GPU (if available). - :param top_k: The number of top predictions to return. The default is 1. Enter None to return all the predictions. Only used for task 'text-classification'. - :param task: 'text-classification' or 'zero-shot-classification' - :param labels: Only used for task 'zero-shot-classification'. List of string defining class labels, e.g., - ["positive", "negative"] otherwise None. Given a LABEL, the sequence fed to the model is " sequence to - classify This example is LABEL . " and the model predicts whether that sequence is a contradiction - or an entailment. - :param batch_size: Number of Documents to be processed at a time. - :param classification_field: Name of Document's meta field to be used for classification. If left unset, Document.content is used by default. - :param progress_bar: Whether to show a progress bar while processing. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - """ - torch_and_transformers_import.check() - - super().__init__() - - if labels and task == "text-classification": - logger.warning( - "Provided labels %s will be ignored for task text-classification. Set task to " - "zero-shot-classification to use labels.", - labels, - ) - - resolved_devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(resolved_devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - resolved_devices[0], - ) - - if tokenizer is None: - tokenizer = model_name_or_path - if task == "zero-shot-classification": - self.model = pipeline( - task=task, - model=model_name_or_path, - tokenizer=tokenizer, - revision=model_version, - use_auth_token=use_auth_token, - device=resolved_devices[0], - ) - elif task == "text-classification": - self.model = pipeline( - task=task, - model=model_name_or_path, - tokenizer=tokenizer, - device=resolved_devices[0], - revision=model_version, - top_k=top_k, - use_auth_token=use_auth_token, - ) - self.top_k = top_k - self.labels = labels - self.task = task - self.batch_size = batch_size - self.classification_field = classification_field - self.progress_bar = progress_bar - - def predict(self, documents: List[Document], batch_size: Optional[int] = None) -> List[Document]: - """ - Returns documents containing classification result in a meta field. - Documents are updated in place. - - :param documents: A list of Documents to classify. - :param batch_size: The number of Documents to classify at a time. - :return: A list of Documents enriched with meta information. - """ - if batch_size is None: - batch_size = self.batch_size - - texts = [ - doc.content if self.classification_field is None else doc.meta[self.classification_field] - for doc in documents - ] - batches = self.get_batches(texts, batch_size=batch_size) - predictions = [] - pb = tqdm(total=len(texts), disable=not self.progress_bar, desc="Classifying documents") - for batch in batches: - if self.task == "zero-shot-classification": - batched_prediction = self.model(batch, candidate_labels=self.labels, truncation=True) - elif self.task == "text-classification": - batched_prediction = self.model(batch, top_k=self.top_k, truncation=True) - predictions.extend(batched_prediction) - pb.update(len(batch)) - pb.close() - - for prediction, doc in zip(predictions, documents): - if self.task == "zero-shot-classification": - formatted_prediction = { - "label": prediction["labels"][0], - "score": prediction["scores"][0], - "details": dict(zip(prediction["labels"], prediction["scores"])), - } - elif self.task == "text-classification": - formatted_prediction = { - "label": prediction[0]["label"], - "score": prediction[0]["score"], - "details": {el["label"]: el["score"] for el in prediction}, - } - doc.meta["classification"] = formatted_prediction - - return documents - - def predict_batch( - self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None - ) -> Union[List[Document], List[List[Document]]]: - """ - Returns documents containing classification result in meta field. - Documents are updated in place. - - :param documents: List of Documents or list of lists of Documents to classify. - :param batch_size: Number of Documents to classify at a time. - :return: List of Documents or list of lists of Documents enriched with meta information. - """ - if isinstance(documents[0], Document): - documents = self.predict(documents=documents, batch_size=batch_size) # type: ignore - return documents - else: - number_of_documents = [len(doc_list) for doc_list in documents if isinstance(doc_list, list)] - flattened_documents = list(itertools.chain.from_iterable(documents)) # type: ignore - docs_with_preds = self.predict(flattened_documents, batch_size=batch_size) - - # Group documents together - grouped_documents = [] - left_idx = 0 - right_idx = 0 - for number in number_of_documents: - right_idx = left_idx + number - grouped_documents.append(docs_with_preds[left_idx:right_idx]) - left_idx = right_idx - - return grouped_documents - - def get_batches(self, items, batch_size): - if batch_size is None: - yield items - return - for index in range(0, len(items), batch_size): - yield items[index : index + batch_size] diff --git a/haystack/nodes/extractor/__init__.py b/haystack/nodes/extractor/__init__.py deleted file mode 100644 index 659f4112af..0000000000 --- a/haystack/nodes/extractor/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.nodes.extractor.entity import EntityExtractor, simplify_ner_for_qa diff --git a/haystack/nodes/extractor/entity.py b/haystack/nodes/extractor/entity.py deleted file mode 100644 index 9b16528c53..0000000000 --- a/haystack/nodes/extractor/entity.py +++ /dev/null @@ -1,880 +0,0 @@ -# coding=utf-8 -# Copyright 2018 The HuggingFace Inc. Team and deepset Team. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Acknowledgements: Many of the postprocessing parts here come from the great transformers repository: https://github.com/huggingface/transformers. -Thanks for the great work! -""" - -import logging -from typing import List, Union, Dict, Optional, Tuple, Any, Literal - -import itertools -import numpy as np - -from tokenizers.pre_tokenizers import WhitespaceSplit -from tqdm import tqdm -from haystack.schema import Document -from haystack.nodes.base import BaseComponent -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from torch.utils.data import Dataset, DataLoader - from transformers import AutoTokenizer, AutoModelForTokenClassification - from haystack.utils.torch_utils import ensure_tensor_on_device # pylint: disable=ungrouped-imports - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - class TokenClassificationDataset(Dataset): - """Token Classification Dataset - - This is a wrapper class to create a Pytorch dataset object from the data attribute of a - `transformers.tokenization_utils_base.BatchEncoding` object. - - :param model_inputs: The data attribute of the output from a HuggingFace tokenizer which is needed to evaluate the - forward pass of a token classification model. - """ - - def __init__(self, model_inputs: dict): - self.model_inputs = model_inputs - self._len = len(model_inputs["input_ids"]) - - def __getitem__(self, item): - input_ids = self.model_inputs["input_ids"][item] - attention_mask = self.model_inputs["attention_mask"][item] - special_tokens_mask = self.model_inputs["special_tokens_mask"][item] - offset_mapping = self.model_inputs["offset_mapping"][item] - overflow_to_sample_mapping = self.model_inputs["overflow_to_sample_mapping"][item] - single_input = { - "input_ids": input_ids, - "attention_mask": attention_mask, - "special_tokens_mask": special_tokens_mask, - "offset_mapping": offset_mapping, - "overflow_to_sample_mapping": overflow_to_sample_mapping, - } - return single_input - - def __len__(self): - return self._len - - -class EntityExtractor(BaseComponent): - """ - This node is used to extract entities out of documents. - The most common use case for this would be as a named entity extractor. - The default model used is elastic/distilbert-base-cased-finetuned-conll03-english. - This node can be placed in a querying pipeline to perform entity extraction on retrieved documents only, - or it can be placed in an indexing pipeline so that all documents in the document store have extracted entities. - This Node will automatically split up long Documents based on the max token length of the underlying model and - aggregate the predictions of each split to predict the final set of entities for each Document. - The entities extracted by this Node will populate Document.meta.entities. - - :param model_name_or_path: The name of the model to use for entity extraction. - :param model_version: The version of the model to use for entity extraction. - :param use_gpu: Whether to use the GPU or not. - :param progress_bar: Whether to show a progress bar or not. - :param batch_size: The batch size to use for entity extraction. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :param aggregation_strategy: The strategy to fuse (or not) tokens based on the model prediction. - None: Will not do any aggregation and simply return raw results from the model. - "simple": Will attempt to group entities following the default schema. - (A, B-TAG), (B, I-TAG), (C, I-TAG), (D, B-TAG2) (E, B-TAG2) will end up being - [{"word": ABC, "entity": "TAG"}, {"word": "D", "entity": "TAG2"}, {"word": "E", "entity": "TAG2"}] - Notice that two consecutive B tags will end up as different entities. - On word based languages, we might end up splitting words undesirably: Imagine Microsoft being tagged - as [{"word": "Micro", "entity": "ENTERPRISE"}, {"word": "soft", "entity": "NAME"}]. - Look at the options FIRST, MAX, and AVERAGE for ways to mitigate this example and disambiguate words - (on languages that support that meaning, which is basically tokens separated by a space). - These mitigations will only work on real words, "New york" might still be tagged with two different entities. - "first": Will use the SIMPLE strategy except that words, cannot end up with - different tags. Words will simply use the tag of the first token of the word when there is ambiguity. - "average": Will use the SIMPLE strategy except that words, cannot end up with - different tags. The scores will be averaged across tokens, and then the label with the maximum score is chosen. - "max": Will use the SIMPLE strategy except that words, cannot end up with - different tags. Word entity will simply be the token with the maximum score. - :param add_prefix_space: Do this if you do not want the first word to be treated differently. This is relevant for - model types such as "bloom", "gpt2", and "roberta". - Explained in more detail here: - https://huggingface.co/docs/transformers/model_doc/roberta#transformers.RobertaTokenizer - :param num_workers: Number of workers to be used in the Pytorch Dataloader. - :param flatten_entities_in_meta_data: If True this converts all entities predicted for a document from a list of - dictionaries into a single list for each key in the dictionary. - :param max_seq_len: Max sequence length of one input text for the model. If not provided the max length is - automatically determined by the `model_max_length` variable of the tokenizer. - :param pre_split_text: If True split the text of a Document into words before being passed into the model. This is - common practice for models trained for named entity recognition and is recommended when using architectures that - do not use word-level tokenizers. - :param ignore_labels: Optionally specify a list of labels to ignore. If None is specified it - defaults to `["O"]`. - """ - - outgoing_edges = 1 - - def __init__( - self, - model_name_or_path: str = "elastic/distilbert-base-cased-finetuned-conll03-english", - model_version: Optional[str] = None, - use_gpu: bool = True, - batch_size: int = 16, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - aggregation_strategy: Literal[None, "simple", "first", "average", "max"] = "first", - add_prefix_space: Optional[bool] = None, - num_workers: int = 0, - flatten_entities_in_meta_data: bool = False, - max_seq_len: Optional[int] = None, - pre_split_text: bool = False, - ignore_labels: Optional[List[str]] = None, - ): - torch_and_transformers_import.check() - - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - self.batch_size = batch_size - self.progress_bar = progress_bar - self.model_name_or_path = model_name_or_path - self.use_auth_token = use_auth_token - self.num_workers = num_workers - self.flatten_entities_in_meta_data = flatten_entities_in_meta_data - self.aggregation_strategy = aggregation_strategy - self.ignore_labels = ignore_labels - - if add_prefix_space is None: - tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_auth_token=use_auth_token) - else: - tokenizer = AutoTokenizer.from_pretrained( - model_name_or_path, use_auth_token=use_auth_token, add_prefix_space=add_prefix_space - ) - if not tokenizer.is_fast: - logger.error( - "The EntityExtractor node only works when using a fast tokenizer. Please choose a model " - "that has a corresponding fast tokenizer." - ) - - self.tokenizer = tokenizer - self.max_seq_len = max_seq_len if max_seq_len else self.tokenizer.model_max_length - - self.pre_split_text = pre_split_text - self.pre_tokenizer = WhitespaceSplit() - - self.model = AutoModelForTokenClassification.from_pretrained( - model_name_or_path, use_auth_token=use_auth_token, revision=model_version - ) - self.model.to(str(self.devices[0])) - self.entity_postprocessor = _EntityPostProcessor(model=self.model, tokenizer=self.tokenizer) - - @staticmethod - def _add_entities_to_doc( - doc: Union[Document, dict], entities: List[dict], flatten_entities_in_meta_data: bool = False - ): - """Add the entities to the metadata of the document. - - :param doc: The document where the metadata will be added. - :param entities: The list of entities predicted for document `doc`. - :param flatten_entities_in_meta_data: If True this converts all entities predicted for a document from a list of - dictionaries into a single list for each key in the dictionary. - """ - is_doc = isinstance(doc, Document) - if flatten_entities_in_meta_data: - new_key_map = { - "entity_group": "entity_groups", - "score": "entity_scores", - "word": "entity_words", - "start": "entity_starts", - "end": "entity_ends", - } - entity_lists: Dict[str, List[Any]] = {v: [] for k, v in new_key_map.items()} - for entity in entities: - for key in entity: - new_key = new_key_map[key] - if isinstance(entity[key], np.float32): - entity_lists[new_key].append(float(entity[key])) - else: - entity_lists[new_key].append(entity[key]) - if is_doc: - doc.meta.update(entity_lists) # type: ignore - else: - doc["meta"].update(entity_lists) # type: ignore - else: - if is_doc: - doc.meta["entities"] = entities # type: ignore - else: - doc["meta"]["entities"] = entities # type: ignore - - def run(self, documents: Optional[Union[List[Document], List[dict]]] = None) -> Tuple[Dict, str]: # type: ignore - """ - This is the method called when this node is used in a pipeline - """ - if documents: - is_doc = isinstance(documents[0], Document) - for doc in tqdm(documents, disable=not self.progress_bar, desc="Extracting entities"): - # In a querying pipeline, doc is a haystack.schema.Document object - if is_doc: - content = doc.content # type: ignore - # In an indexing pipeline, doc is a dictionary - else: - content = doc["content"] # type: ignore - entities = self.extract(content) - self._add_entities_to_doc( - doc, entities=entities, flatten_entities_in_meta_data=self.flatten_entities_in_meta_data - ) - output = {"documents": documents} - return output, "output_1" - - def run_batch(self, documents: Union[List[Document], List[List[Document]], List[dict], List[List[dict]]], batch_size: Optional[int] = None): # type: ignore - if isinstance(documents[0], (Document, dict)): - flattened_documents = documents - else: - flattened_documents = list(itertools.chain.from_iterable(documents)) # type: ignore - - is_doc = isinstance(flattened_documents[0], Document) - - if batch_size is None: - batch_size = self.batch_size - - if is_doc: - docs = [doc.content for doc in flattened_documents] # type: ignore - else: - docs = [doc["content"] for doc in flattened_documents] # type: ignore - - all_entities = self.extract_batch(docs, batch_size=batch_size) - - for entities_per_doc, doc in zip(all_entities, flattened_documents): - self._add_entities_to_doc( - doc, entities=entities_per_doc, flatten_entities_in_meta_data=self.flatten_entities_in_meta_data # type: ignore - ) - - output = {"documents": documents} - return output, "output_1" - - def preprocess(self, sentence: List[str]): - """Preprocessing step to tokenize the provided text. - - :param sentence: List of text to tokenize. This expects a list of texts. - """ - text_to_tokenize = sentence - if self.pre_split_text: - word_offset_mapping = [self.pre_tokenizer.pre_tokenize_str(t) for t in sentence] - text_to_tokenize = [[word_with_pos[0] for word_with_pos in text] for text in word_offset_mapping] # type: ignore - - model_inputs = self.tokenizer( - text_to_tokenize, - return_tensors="pt", - return_special_tokens_mask=True, - return_offsets_mapping=True, - return_overflowing_tokens=True, - padding="max_length", - truncation=True, - max_length=self.max_seq_len, - is_split_into_words=self.pre_split_text, - ) - - model_inputs["sentence"] = text_to_tokenize - if self.pre_split_text: - model_inputs["word_offset_mapping"] = word_offset_mapping - - word_ids = [model_inputs.word_ids(i) for i in range(model_inputs.input_ids.shape[0])] - model_inputs["word_ids"] = word_ids - return model_inputs - - def forward(self, model_inputs: Dict[str, Any]) -> Dict[str, Any]: - """Forward step - - :param model_inputs: Dictionary of inputs to be given to the model. - """ - special_tokens_mask = model_inputs.pop("special_tokens_mask") - offset_mapping = model_inputs.pop("offset_mapping", None) - overflow_to_sample_mapping = model_inputs.pop("overflow_to_sample_mapping") - - logits = self.model(**model_inputs)[0].to(torch.float64) - - return { - "logits": logits, - "special_tokens_mask": special_tokens_mask, - "offset_mapping": offset_mapping, - "overflow_to_sample_mapping": overflow_to_sample_mapping, - **model_inputs, - } - - def postprocess(self, model_outputs_grouped_by_doc: List[Dict[str, Any]]) -> List[List[Dict]]: - """Postprocess the model outputs grouped by document to collect all entities detected for each document. - - :param model_outputs_grouped_by_doc: model outputs grouped by Document - """ - results_per_doc = [] - num_docs = len(model_outputs_grouped_by_doc) - for i in range(num_docs): - results = self.entity_postprocessor.postprocess( - model_outputs=model_outputs_grouped_by_doc[i], - aggregation_strategy=self.aggregation_strategy, - ignore_labels=self.ignore_labels, - ) - results_per_doc.append(results) - return results_per_doc - - def _group_predictions_by_doc( - self, - model_outputs: Dict[str, Any], - sentence: Union[List[str], List[List[str]]], - word_ids: List[List], - word_offset_mapping: Optional[List[List[Tuple]]] = None, - ) -> List[Dict[str, Any]]: - """Aggregate each of the items in `model_outputs` based on which Document they originally came from. - - :param model_outputs: Dictionary of model outputs. - :param sentence: num_docs x length of text - :param word_ids: List of list of integers or None types that provides the token index to word id mapping. - None types correspond to special tokens. The shape is (num_splits_per_doc * num_docs) x model_max_length. - :param word_offset_mapping: List of (word, (char_start, char_end)) tuples for each word in a text. The shape is - num_docs x num_words_per_doc. - """ - # overflow_to_sample_mapping tells me which documents need be aggregated - # e.g. model_outputs['overflow_to_sample_mapping'] = [0, 0, 1, 1, 1, 1] means first two elements of - # predictions belong to document 0 and the other four elements belong to document 1. - sample_mapping = model_outputs["overflow_to_sample_mapping"] - all_num_splits_per_doc = torch.zeros(sample_mapping[-1] + 1, dtype=torch.long) - for idx in sample_mapping: - all_num_splits_per_doc[idx] += 1 - - logits = model_outputs["logits"] # (num_splits_per_doc * num_docs) x model_max_length x num_classes - input_ids = model_outputs["input_ids"] # (num_splits_per_doc * num_docs) x model_max_length - offset_mapping = model_outputs["offset_mapping"] # (num_splits_per_doc * num_docs) x model_max_length x 2 - special_tokens_mask = model_outputs["special_tokens_mask"] # (num_splits_per_doc * num_docs) x model_max_length - - model_outputs_grouped_by_doc = [] - bef_idx = 0 - for i, num_splits_per_doc in enumerate(all_num_splits_per_doc): - aft_idx = bef_idx + num_splits_per_doc - - logits_per_doc = logits[bef_idx:aft_idx].reshape( - 1, -1, logits.shape[2] - ) # 1 x (num_splits_per_doc * model_max_length) x num_classes - input_ids_per_doc = input_ids[bef_idx:aft_idx].reshape(1, -1) # 1 x (num_splits_per_doc * model_max_length) - offset_mapping_per_doc = offset_mapping[bef_idx:aft_idx].reshape( - 1, -1, offset_mapping.shape[2] - ) # 1 x (num_splits_per_doc * model_max_length) x 2 - special_tokens_mask_per_doc = special_tokens_mask[bef_idx:aft_idx].reshape( - 1, -1 - ) # 1 x (num_splits_per_doc * model_max_length) - sentence_per_doc = sentence[i] - word_ids_per_doc = list( - itertools.chain.from_iterable(word_ids[bef_idx:aft_idx]) - ) # 1 x (num_splits_per_doc * model_max_length) - if word_offset_mapping is not None: - word_offset_mapping_per_doc = word_offset_mapping[i] # 1 x num_words_per_doc - - bef_idx += num_splits_per_doc - - output = { - "logits": logits_per_doc, - "sentence": sentence_per_doc, - "input_ids": input_ids_per_doc, - "offset_mapping": offset_mapping_per_doc, - "special_tokens_mask": special_tokens_mask_per_doc, - "word_ids": word_ids_per_doc, - } - if word_offset_mapping is not None: - output["word_offset_mapping"] = word_offset_mapping_per_doc - - model_outputs_grouped_by_doc.append(output) - return model_outputs_grouped_by_doc - - def _flatten_predictions(self, predictions: List[Dict[str, Any]]) -> Dict[str, Any]: - """Flatten the predictions across the batch dimension. - - :param predictions: List of model output dictionaries - """ - flattened_predictions: Dict[str, Any] = { - "logits": [], - "input_ids": [], - "special_tokens_mask": [], - "offset_mapping": [], - "overflow_to_sample_mapping": [], - } - for pred in predictions: - flattened_predictions["logits"].append(pred["logits"]) - flattened_predictions["input_ids"].append(pred["input_ids"]) - flattened_predictions["special_tokens_mask"].append(pred["special_tokens_mask"]) - flattened_predictions["offset_mapping"].append(pred["offset_mapping"]) - flattened_predictions["overflow_to_sample_mapping"].append(pred["overflow_to_sample_mapping"]) - - flattened_predictions["logits"] = torch.vstack(flattened_predictions["logits"]) - flattened_predictions["input_ids"] = torch.vstack(flattened_predictions["input_ids"]) - flattened_predictions["special_tokens_mask"] = torch.vstack(flattened_predictions["special_tokens_mask"]) - flattened_predictions["offset_mapping"] = torch.vstack(flattened_predictions["offset_mapping"]) - # Make sure to hstack overflow_to_sample_mapping since it doesn't have a batch dimension - flattened_predictions["overflow_to_sample_mapping"] = torch.hstack( - flattened_predictions["overflow_to_sample_mapping"] - ) - return flattened_predictions - - def extract(self, text: Union[str, List[str]], batch_size: int = 1): - """ - This function can be called to perform entity extraction when using the node in isolation. - - :param text: Text to extract entities from. Can be a str or a List of str. - :param batch_size: Number of texts to make predictions on at a time. - """ - is_single_text = False - - if isinstance(text, str): - is_single_text = True - text = [text] - elif isinstance(text, list) and isinstance(text[0], str): - pass - else: - raise ValueError("The variable text must be a string, or a list of strings.") - - # Preprocess - model_inputs = self.preprocess(text) - word_offset_mapping = model_inputs.pop("word_offset_mapping", None) - word_ids = model_inputs.pop("word_ids") - sentence = model_inputs.pop("sentence") - dataset = TokenClassificationDataset(model_inputs.data) - dataloader = DataLoader(dataset, shuffle=False, batch_size=batch_size, num_workers=self.num_workers) - - # Forward - predictions: List[Dict[str, Any]] = [] - for batch in tqdm(dataloader, disable=not self.progress_bar, total=len(dataloader), desc="Extracting entities"): - batch = ensure_tensor_on_device(batch, device=self.devices[0]) - with torch.inference_mode(): - model_outputs = self.forward(batch) - model_outputs = ensure_tensor_on_device(model_outputs, device=torch.device("cpu")) - predictions.append(model_outputs) - predictions = self._flatten_predictions(predictions) # type: ignore - predictions = self._group_predictions_by_doc(predictions, sentence, word_ids, word_offset_mapping) # type: ignore - - # Postprocess - predictions = self.postprocess(predictions) # type: ignore - - if is_single_text: - return predictions[0] # type: ignore - - return predictions - - def extract_batch(self, texts: Union[List[str], List[List[str]]], batch_size: int = 1) -> List[List[Dict]]: - """ - This function allows the extraction of entities out of a list of strings or a list of lists of strings. - The only difference between this function and `self.extract` is that it has additional logic to handle a - list of lists of strings. - - :param texts: List of str or list of lists of str to extract entities from. - :param batch_size: Number of texts to make predictions on at a time. - """ - if isinstance(texts[0], str): - single_list_of_texts = True - number_of_texts = [len(texts)] - else: - single_list_of_texts = False - number_of_texts = [len(text_list) for text_list in texts] - texts = list(itertools.chain.from_iterable(texts)) - - entities = self.extract(texts, batch_size=batch_size) # type: ignore - - if single_list_of_texts: - return entities # type: ignore - else: - # Group entities together - grouped_entities = [] - left_idx = 0 - for number in number_of_texts: - right_idx = left_idx + number - grouped_entities.append(entities[left_idx:right_idx]) - left_idx = right_idx - return grouped_entities - - -def simplify_ner_for_qa(output): - """ - Returns a simplified version of the output dictionary - with the following structure: - - ```python - [ - { - answer: { ... } - entities: [ { ... }, {} ] - } - ] - ``` - - The entities included are only the ones that overlap with - the answer itself. - - :param output: Output from a query pipeline - """ - compact_output = [] - for answer in output["answers"]: - entities = [] - for entity in answer.meta["entities"]: - if ( - entity["start"] >= answer.offsets_in_document[0].start - and entity["end"] <= answer.offsets_in_document[0].end - ): - entities.append(entity["word"]) - - compact_output.append({"answer": answer.answer, "entities": entities}) - return compact_output - - -class _EntityPostProcessor: - """This class is used to conveniently collect all functions related to the postprocessing of entity extraction. - - :param model: - :param tokenizer: - """ - - def __init__(self, model, tokenizer): - self.model = model - self.tokenizer = tokenizer - - def postprocess( - self, - model_outputs: Dict[str, Any], - aggregation_strategy: Literal[None, "simple", "first", "average", "max"], - ignore_labels: Optional[List[str]] = None, - ) -> List[Dict[str, Any]]: - """Postprocess the model outputs for a single Document. - - :param model_outputs: Model outputs for a single Document. - :param aggregation_strategy: The strategy to fuse (or not) tokens based on the model prediction. - None: Will not do any aggregation and simply return raw results from the model. - "simple": Will attempt to group entities following the default schema. - (A, B-TAG), (B, I-TAG), (C, I-TAG), (D, B-TAG2) (E, B-TAG2) will end up being - [{"word": ABC, "entity": "TAG"}, {"word": "D", "entity": "TAG2"}, {"word": "E", "entity": "TAG2"}] - Notice that two consecutive B tags will end up as different entities. - On word based languages, we might end up splitting words undesirably: Imagine Microsoft being tagged - as [{"word": "Micro", "entity": "ENTERPRISE"}, {"word": "soft", "entity": "NAME"}]. - Look at the options FIRST, MAX, and AVERAGE for ways to mitigate this example and disambiguate words - (on languages that support that meaning, which is basically tokens separated by a space). - These mitigations will only work on real words, "New york" might still be tagged with two different entities. - "first": Will use the SIMPLE strategy except that words, cannot end up with - different tags. Words will simply use the tag of the first token of the word when there is ambiguity. - "average": Will use the SIMPLE strategy except that words, cannot end up with - different tags. The scores will be averaged across tokens, and then the label with the maximum score is chosen. - "max": Will use the SIMPLE strategy except that words, cannot end up with - different tags. Word entity will simply be the token with the maximum score. - :param ignore_labels: Optionally specify a list of labels to ignore. If None is specified it - defaults to `["O"]`. - """ - if ignore_labels is None: - ignore_labels = ["O"] - logits = model_outputs["logits"][0].numpy() - sentence = model_outputs["sentence"] - input_ids = model_outputs["input_ids"][0] - offset_mapping = model_outputs["offset_mapping"][0].numpy() - special_tokens_mask = model_outputs["special_tokens_mask"][0].numpy() - word_ids = model_outputs["word_ids"] - word_offset_mapping = model_outputs.get("word_offset_mapping", None) - - maxes = np.max(logits, axis=-1, keepdims=True) - shifted_exp = np.exp(logits - maxes) - scores = shifted_exp / shifted_exp.sum(axis=-1, keepdims=True) - - updated_offset_mapping = offset_mapping - pre_entities = self.gather_pre_entities( - sentence, input_ids, scores, updated_offset_mapping, special_tokens_mask, word_ids - ) - grouped_entities = self.aggregate(pre_entities, aggregation_strategy, word_offset_mapping=word_offset_mapping) - # Filter anything that is in self.ignore_labels - entities = [ - entity - for entity in grouped_entities - if entity.get("entity", None) not in ignore_labels and entity.get("entity_group", None) not in ignore_labels - ] - return entities - - def aggregate( - self, - pre_entities: List[Dict[str, Any]], - aggregation_strategy: Literal[None, "simple", "first", "average", "max"], - word_offset_mapping: Optional[List[Tuple]] = None, - ) -> List[Dict[str, Any]]: - """Aggregate the `pre_entities` depending on the `aggregation_strategy`. - - :param pre_entities: List of entity predictions for each token in a text. - :param aggregation_strategy: The strategy to fuse (or not) tokens based on the model prediction. - :param word_offset_mapping: List of (word, (char_start, char_end)) tuples for each word in a text. - """ - if aggregation_strategy is None or aggregation_strategy == "simple": - entities = [] - for pre_entity in pre_entities: - entity_idx = pre_entity["scores"].argmax() - score = pre_entity["scores"][entity_idx] - entity = { - "entity": self.model.config.id2label[entity_idx], - "score": score, - "index": pre_entity["index"], - "word": pre_entity["word"], - "start": pre_entity["start"], - "end": pre_entity["end"], - } - entities.append(entity) - else: - entities = self.aggregate_words(pre_entities, aggregation_strategy) - if word_offset_mapping is not None: - entities = self.update_character_spans(entities, word_offset_mapping) - - return self.group_entities(entities) - - @staticmethod - def update_character_spans( - word_entities: List[Dict[str, Any]], word_offset_mapping: List[Tuple] - ) -> List[Dict[str, Any]]: - """Update the character spans of each word in `word_entities` to match the character spans provided in - `word_offset_mapping`. - - :param word_entities: List of entity predictions for each word in the text. - :param word_offset_mapping: List of (word, (char_start, char_end)) tuples for each word in a text. - """ - if len(word_entities) != len(word_offset_mapping): - logger.warning( - "Unable to determine the character spans of the entities in the original text." - " Returning entities as is." - ) - return word_entities - - entities = [] - for idx, entity in enumerate(word_entities): - _, (start, end) = word_offset_mapping[idx] - entity["start"] = start - entity["end"] = end - entities.append(entity) - - return entities - - def gather_pre_entities( - self, - sentence: Union[str, List[str]], - input_ids: np.ndarray, - scores: np.ndarray, - offset_mapping: np.ndarray, - special_tokens_mask: np.ndarray, - word_ids: List, - ) -> List[Dict[str, Any]]: - """Gather the pre-entities from the model outputs. - - :param sentence: The original text. Will be a list of words if `self.pre_split_text` is set to True. - :param input_ids: Array of token ids. - :param scores: Array of confidence scores of the model for the classification of each token. - :param offset_mapping: Array of (char_start, char_end) tuples for each token. - :param special_tokens_mask: Special tokens mask used to identify which tokens are special. - :param word_ids: List of integers or None types that provides the token index to word id mapping. None types - correspond to special tokens. - """ - previous_word_id = -1 - pre_entities = [] - for token_idx, token_scores in enumerate(scores): - current_word_id = word_ids[token_idx] - - # Filter special_tokens, they should only occur - # at the sentence boundaries since we're not encoding pairs of - # sentences so we don't have to keep track of those. - if special_tokens_mask[token_idx]: - continue - - word = self.tokenizer.convert_ids_to_tokens(int(input_ids[token_idx])) - - if current_word_id != previous_word_id: - is_subword = False - else: - is_subword = True - - start_ind, end_ind = offset_mapping[token_idx] - if int(input_ids[token_idx]) == self.tokenizer.unk_token_id: - if isinstance(sentence, list): - word = sentence[current_word_id][start_ind:end_ind] - else: - word = sentence[start_ind:end_ind] - is_subword = False - - pre_entity = { - "word": word, - "scores": token_scores, - "start": start_ind, - "end": end_ind, - "index": token_idx, - "is_subword": is_subword, - } - pre_entities.append(pre_entity) - - previous_word_id = current_word_id - return pre_entities - - def aggregate_word( - self, entities: List[Dict[str, Any]], aggregation_strategy: Literal["first", "average", "max"] - ) -> Dict[str, Any]: - """Aggregate token entities into a single word entity. - - :param entities: List of token entities to be combined. - :param aggregation_strategy: The strategy to fuse the tokens based on the model prediction. - """ - word = self.tokenizer.convert_tokens_to_string([entity["word"] for entity in entities]) - tokens = [entity["word"] for entity in entities] - if aggregation_strategy == "first": - scores = entities[0]["scores"] - idx = scores.argmax() - score = scores[idx] - entity = self.model.config.id2label[idx] - elif aggregation_strategy == "max": - max_entity = max(entities, key=lambda entity: entity["scores"].max()) - scores = max_entity["scores"] - idx = scores.argmax() - score = scores[idx] - entity = self.model.config.id2label[idx] - elif aggregation_strategy == "average": - scores = np.stack([entity["scores"] for entity in entities]) - average_scores = np.nanmean(scores, axis=0) - entity_idx = average_scores.argmax() - entity = self.model.config.id2label[entity_idx] - score = average_scores[entity_idx] - else: - raise ValueError("Invalid aggregation_strategy") - new_entity = { - "entity": entity, - "score": score, - "word": word, - "tokens": tokens, - "start": int(entities[0]["start"]), - "end": int(entities[-1]["end"]), - } - return new_entity - - def aggregate_words( - self, entities: List[Dict[str, Any]], aggregation_strategy: Literal[None, "simple", "first", "average", "max"] - ) -> List[Dict[str, Any]]: - """ - Override tokens from a given word that disagree to force agreement on word boundaries. - - Example: micro|soft| com|pany| B-ENT I-NAME I-ENT I-ENT will be rewritten with first strategy as microsoft| - company| B-ENT I-ENT - - :param entities: List of predicted entities for each token in the text. - :param aggregation_strategy: The strategy to fuse (or not) tokens based on the model prediction. - """ - if aggregation_strategy is None or aggregation_strategy == "simple": - logger.error("None and simple aggregation strategies are invalid for word aggregation") - - word_entities = [] - word_group = None - for entity in entities: - if word_group is None: - word_group = [entity] - elif entity["is_subword"]: - word_group.append(entity) - else: - word_entities.append(self.aggregate_word(word_group, aggregation_strategy)) # type: ignore - word_group = [entity] - # Last item - word_entities.append(self.aggregate_word(word_group, aggregation_strategy)) # type: ignore - return word_entities - - def group_sub_entities(self, entities: List[Dict[str, Any]]) -> Dict[str, Any]: - """ - Group together the adjacent tokens with the same entity predicted. - - :param entities: The entities predicted by the pipeline. - """ - # Get the first entity in the entity group - entity = entities[0]["entity"].split("-")[-1] - scores = np.nanmean([entity["score"] for entity in entities]) - try: - tokens = [entity["tokens"] for entity in entities] - tokens = list(itertools.chain.from_iterable(tokens)) - except KeyError: - tokens = [entity["word"] for entity in entities] - - entity_group = { - "entity_group": entity, - "score": np.mean(scores), - "word": self.tokenizer.convert_tokens_to_string(tokens), - "start": entities[0]["start"], - "end": entities[-1]["end"], - } - return entity_group - - @staticmethod - def get_tag(entity_name: str) -> Tuple[str, str]: - """Get the entity tag and its prefix. - - :param entity_name: name of the entity - """ - if entity_name.startswith("B-"): - bi = "B" - tag = entity_name[2:] - elif entity_name.startswith("I-"): - bi = "I" - tag = entity_name[2:] - else: - # It's not in B-, I- format - # Default to I- for continuation. - bi = "I" - tag = entity_name - return bi, tag - - def group_entities(self, entities: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """ - Find and group together the adjacent tokens (or words) with the same entity predicted. - - :param entities: List of predicted entities. - """ - - entity_groups = [] - entity_group_disagg: List[Dict[str, Any]] = [] - - for entity in entities: - if not entity_group_disagg: - entity_group_disagg.append(entity) - continue - - # If the current entity is similar and adjacent to the previous entity, - # append it to the disaggregated entity group - # The split is meant to account for the "B" and "I" prefixes - # Shouldn't merge if both entities are B-type - bi, tag = self.get_tag(entity["entity"]) - _, last_tag = self.get_tag(entity_group_disagg[-1]["entity"]) - - if tag == last_tag and bi != "B": - # Modify subword type to be previous_type - entity_group_disagg.append(entity) - else: - # If the current entity is different from the previous entity - # aggregate the disaggregated entity group - entity_groups.append(self.group_sub_entities(entity_group_disagg)) - entity_group_disagg = [entity] - if entity_group_disagg: - # it's the last entity, add it to the entity groups - entity_groups.append(self.group_sub_entities(entity_group_disagg)) - - return entity_groups diff --git a/haystack/nodes/file_classifier/__init__.py b/haystack/nodes/file_classifier/__init__.py deleted file mode 100644 index 4246a80e1f..0000000000 --- a/haystack/nodes/file_classifier/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.nodes.file_classifier.file_type import FileTypeClassifier diff --git a/haystack/nodes/file_classifier/file_type.py b/haystack/nodes/file_classifier/file_type.py deleted file mode 100644 index 3a91a89de3..0000000000 --- a/haystack/nodes/file_classifier/file_type.py +++ /dev/null @@ -1,133 +0,0 @@ -import mimetypes -from typing import Any, Dict, List, Union, Optional - -import logging -from pathlib import Path - -from haystack.nodes.base import BaseComponent -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - -with LazyImport() as magic_import: - import magic - - -DEFAULT_TYPES = ["txt", "pdf", "md", "docx", "html", "media"] - -DEFAULT_MEDIA_TYPES = ["mp3", "mp4", "mpeg", "m4a", "wav", "webm"] - - -class FileTypeClassifier(BaseComponent): - """ - Route files in an Indexing Pipeline to corresponding file converters. - """ - - outgoing_edges = len(DEFAULT_TYPES) - - def __init__(self, supported_types: Optional[List[str]] = None, full_analysis: bool = False): - """ - Node that sends out files on a different output edge depending on their extension. - - :param supported_types: The file types this node distinguishes. Optional. - If you don't provide any value, the default is: `txt`, `pdf`, `md`, `docx`, and `html`. - You can't use lists with duplicate elements. - :param full_analysis: If True, the whole file is analyzed to determine the file type. - If False, only the first 2049 bytes are analyzed. - """ - self.full_analysis = full_analysis - self._default_types = False - if supported_types is None: - self._default_types = True - supported_types = DEFAULT_TYPES - if len(set(supported_types)) != len(supported_types): - duplicates = supported_types - for item in set(supported_types): - duplicates.remove(item) - raise ValueError(f"supported_types can't contain duplicate values ({duplicates}).") - - super().__init__() - - self.supported_types = supported_types - - @classmethod - def _calculate_outgoing_edges(cls, component_params: Dict[str, Any]) -> int: - supported_types = component_params.get("supported_types", DEFAULT_TYPES) - return len(supported_types) - - def _estimate_extension(self, file_path: Path) -> str: - """ - Return the extension found based on the contents of the given file - - :param file_path: the path to extract the extension from - """ - try: - with open(file_path, "rb") as f: - if self.full_analysis: - buffer = f.read() - else: - buffer = f.read(2049) - extension = magic.from_buffer(buffer, mime=True) - real_extension = mimetypes.guess_extension(extension) or "" - real_extension = real_extension.lstrip(".") - if self._default_types and real_extension in DEFAULT_MEDIA_TYPES: - return "media" - return real_extension or "" - except (NameError, ImportError): - logger.error( - "The type of '%s' could not be guessed, probably because 'python-magic' is not installed. Ignoring this error." - "Please make sure the necessary OS libraries are installed if you need this functionality ('python-magic' or 'python-magic-bin' on Windows).", - file_path, - ) - return "" - - def _get_extension(self, file_paths: List[Path]) -> str: - """ - Return the extension found in the given list of files. - Also makes sure that all files have the same extension. - If this is not true, it throws an exception. - - :param file_paths: the paths to extract the extension from - :return: a set of strings with all the extensions (without duplicates), the extension will be guessed if the file has none - """ - extension = file_paths[0].suffix.lower().lstrip(".") - - if extension == "" or (self._default_types and extension in DEFAULT_MEDIA_TYPES): - extension = self._estimate_extension(file_paths[0]) - - for path in file_paths: - path_suffix = path.suffix.lower().lstrip(".") - if path_suffix == "" or (self._default_types and path_suffix in DEFAULT_MEDIA_TYPES): - path_suffix = self._estimate_extension(path) - if path_suffix != extension: - raise ValueError("Multiple non-default file types are not allowed at once.") - - return extension - - def run(self, file_paths: Union[Path, List[Path], str, List[str], List[Union[Path, str]]]): # type: ignore - """ - Sends out files on a different output edge depending on their extension. - - :param file_paths: paths to route on different edges. - """ - if not isinstance(file_paths, list): - file_paths = [file_paths] - - paths = [Path(path) for path in file_paths] - - output = {"file_paths": paths} - extension = self._get_extension(paths) - try: - index = self.supported_types.index(extension) + 1 - except ValueError: - raise ValueError( - f"Files of type '{extension}' ({paths[0]}) are not supported. " - f"The supported types are: {self.supported_types}. " - "Consider using the 'supported_types' parameter to " - "change the types accepted by this node." - ) - return output, f"output_{index}" - - def run_batch(self, file_paths: Union[Path, List[Path], str, List[str], List[Union[Path, str]]]): # type: ignore - return self.run(file_paths=file_paths) diff --git a/haystack/nodes/file_converter/__init__.py b/haystack/nodes/file_converter/__init__.py deleted file mode 100644 index 76a5dd1aa3..0000000000 --- a/haystack/nodes/file_converter/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -from haystack.lazy_imports import LazyImport -from haystack.nodes.file_converter.base import BaseConverter - -from haystack.nodes.file_converter.csv import CsvTextConverter -from haystack.nodes.file_converter.docx import DocxToTextConverter -from haystack.nodes.file_converter.pptx import PptxConverter -from haystack.nodes.file_converter.json import JsonConverter -from haystack.nodes.file_converter.tika import TikaConverter, TikaXHTMLParser -from haystack.nodes.file_converter.txt import TextConverter -from haystack.nodes.file_converter.azure import AzureConverter -from haystack.nodes.file_converter.parsr import ParsrConverter - - -try: - with LazyImport() as fitz_import: - # Try to use PyMuPDF, if not available fall back to xpdf - from haystack.nodes.file_converter.pdf import PDFToTextConverter # type: ignore - - fitz_import.check() -except (ModuleNotFoundError, ImportError): - from haystack.nodes.file_converter.pdf_xpdf import PDFToTextConverter # type: ignore # pylint: disable=reimported,ungrouped-imports - -from haystack.nodes.file_converter.markdown import MarkdownConverter -from haystack.nodes.file_converter.image import ImageToTextConverter diff --git a/haystack/nodes/file_converter/azure.py b/haystack/nodes/file_converter/azure.py deleted file mode 100644 index b0c1cf2894..0000000000 --- a/haystack/nodes/file_converter/azure.py +++ /dev/null @@ -1,345 +0,0 @@ -import logging -from pathlib import Path -from typing import List, Optional, Dict, Any -from collections import defaultdict -import json -import copy - -import pandas as pd - -from haystack.lazy_imports import LazyImport -from haystack.nodes.file_converter.base import BaseConverter -from haystack.errors import HaystackError -from haystack.schema import Document - -logger = logging.getLogger(__name__) - -with LazyImport( - message="Run 'pip install farm-haystack[file-conversion]' or 'pip install \"azure-ai-formrecognizer>=3.2.0b2\"'" -) as azure_import: - from azure.ai.formrecognizer import DocumentAnalysisClient, AnalyzeResult - from azure.core.credentials import AzureKeyCredential - - -class AzureConverter(BaseConverter): - """ - File converter that makes use of Microsoft Azure's Form Recognizer service - (https://azure.microsoft.com/en-us/services/form-recognizer/). - This Converter extracts both text and tables. - Supported file formats are: PDF, JPEG, PNG, BMP and TIFF. - - In order to be able to use this Converter, you need an active Azure account - and a Form Recognizer or Cognitive Services resource. - (Here you can find information on how to set this up: - https://docs.microsoft.com/en-us/azure/applied-ai-services/form-recognizer/quickstarts/try-v3-python-sdk#prerequisites) - - """ - - def __init__( - self, - endpoint: str, - credential_key: str, - model_id: str = "prebuilt-document", - valid_languages: Optional[List[str]] = None, - save_json: bool = False, - preceding_context_len: int = 3, - following_context_len: int = 3, - merge_multiple_column_headers: bool = True, - id_hash_keys: Optional[List[str]] = None, - add_page_number: bool = True, - ): - """ - :param endpoint: Your Form Recognizer or Cognitive Services resource's endpoint. - :param credential_key: Your Form Recognizer or Cognitive Services resource's subscription key. - :param model_id: The identifier of the model you want to use to extract information out of your file. - Default: "prebuilt-document". General purpose models are "prebuilt-document" - and "prebuilt-layout". - List of available prebuilt models: - https://azuresdkdocs.blob.core.windows.net/$web/python/azure-ai-formrecognizer/3.2.0b1/index.html#documentanalysisclient - :param valid_languages: Validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param save_json: Whether to save the output of the Form Recognizer to a JSON file. - :param preceding_context_len: Number of lines before a table to extract as preceding context (will be returned as part of meta data). - :param following_context_len: Number of lines after a table to extract as subsequent context (will be returned as part of meta data). - :param merge_multiple_column_headers: Some tables contain more than one row as a column header (i.e., column description). - This parameter lets you choose, whether to merge multiple column header - rows to a single row. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param add_page_number: Adds the number of the page a table occurs in to the Document's meta field - `"page"`. - """ - # ensure the required dependencies were actually imported - azure_import.check() - - super().__init__(valid_languages=valid_languages, id_hash_keys=id_hash_keys) - - self.document_analysis_client = DocumentAnalysisClient( - endpoint=endpoint, credential=AzureKeyCredential(credential_key) - ) - self.model_id = model_id - self.valid_languages = valid_languages - self.save_json = save_json - self.preceding_context_len = preceding_context_len - self.following_context_len = following_context_len - self.merge_multiple_column_headers = merge_multiple_column_headers - self.add_page_number = add_page_number - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, Any]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "utf-8", - id_hash_keys: Optional[List[str]] = None, - pages: Optional[str] = None, - known_language: Optional[str] = None, - ) -> List[Document]: - """ - Extract text and tables from a PDF, JPEG, PNG, BMP or TIFF file using Azure's Form Recognizer service. - - :param file_path: Path to the file you want to convert. - :param meta: Optional dictionary with metadata that shall be attached to all resulting documents. - Can be any custom keys and values. - :param remove_numeric_tables: Not applicable. - :param valid_languages: Validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Not applicable. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param pages: Custom page numbers for multi-page documents(PDF/TIFF). Input the page numbers and/or ranges - of pages you want to get in the result. For a range of pages, use a hyphen, - like pages=”1-3, 5-6”. Separate each page number or range with a comma. - :param known_language: Locale hint of the input document. - See supported locales here: https://aka.ms/azsdk/formrecognizer/supportedlocales. - """ - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - if isinstance(file_path, str): - file_path = Path(file_path) - - if valid_languages is None: - valid_languages = self.valid_languages - - with open(file_path, "rb") as file: - poller = self.document_analysis_client.begin_analyze_document( - self.model_id, file, pages=pages, locale=known_language - ) - result = poller.result() - - if self.save_json: - with open(file_path.with_suffix(".json"), "w") as json_file: - json.dump(result.to_dict(), json_file, indent=2) - - docs = self._convert_tables_and_text(result, meta, valid_languages, file_path, id_hash_keys) - - return docs - - def convert_azure_json( - self, - file_path: Path, - meta: Optional[Dict[str, Any]] = None, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Extract text and tables from the JSON output of Azure's Form Recognizer service. - - :param file_path: Path to the JSON-file you want to convert. - :param meta: Optional dictionary with metadata that shall be attached to all resulting documents. - Can be any custom keys and values. - :param valid_languages: Validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - """ - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - if valid_languages is None: - valid_languages = self.valid_languages - - with open(file_path) as azure_file: - azure_result = json.load(azure_file) - azure_result = AnalyzeResult.from_dict(azure_result) - - docs = self._convert_tables_and_text(azure_result, meta, valid_languages, file_path, id_hash_keys) - - return docs - - def _convert_tables_and_text( - self, - result: "AnalyzeResult", - meta: Optional[Dict[str, Any]], - valid_languages: Optional[List[str]], - file_path: Path, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - tables = self._convert_tables(result, meta, id_hash_keys) - text = self._convert_text(result, meta, id_hash_keys) - docs = tables + [text] - - if valid_languages: - file_text = text.content - for table in tables: - # Mainly needed for type checking - if not isinstance(table.content, pd.DataFrame): - raise HaystackError("Document's content field must be of type 'pd.DataFrame'.") - for _, row in table.content.iterrows(): - for cell in row.values(): - file_text += f" {cell}" - if not self.validate_language(file_text, valid_languages): - logger.warning( - "The language for %s is not one of %s. The file may not have " - "been decoded in the correct text format.", - file_path, - valid_languages, - ) - - return docs - - def _convert_tables( - self, result: "AnalyzeResult", meta: Optional[Dict[str, Any]], id_hash_keys: Optional[List[str]] = None - ) -> List[Document]: - converted_tables: List[Document] = [] - - if not result.tables: - return converted_tables - - for table in result.tables: - # Initialize table with empty cells - table_list = [[""] * table.column_count for _ in range(table.row_count)] - additional_column_header_rows = set() - caption = "" - row_idx_start = 0 - - for idx, cell in enumerate(table.cells): - # Remove ':selected:'/':unselected:' tags from cell's content - cell.content = cell.content.replace(":selected:", "") - cell.content = cell.content.replace(":unselected:", "") - - # Check if first row is a merged cell spanning whole table - # -> exclude this row and use as a caption - if idx == 0 and cell.column_span == table.column_count: - caption = cell.content - row_idx_start = 1 - table_list.pop(0) - continue - - column_span = cell.column_span if cell.column_span else 0 - for c in range(column_span): - row_span = cell.row_span if cell.row_span else 0 - for r in range(row_span): - if ( - self.merge_multiple_column_headers - and cell.kind == "columnHeader" - and cell.row_index > row_idx_start - ): - # More than one row serves as column header - table_list[0][cell.column_index + c] += f"\n{cell.content}" - additional_column_header_rows.add(cell.row_index - row_idx_start) - else: - table_list[cell.row_index + r - row_idx_start][cell.column_index + c] = cell.content - - # Remove additional column header rows, as these got attached to the first row - for row_idx in sorted(additional_column_header_rows, reverse=True): - del table_list[row_idx] - - # Get preceding context of table - if table.bounding_regions: - table_beginning_page = next( - page for page in result.pages if page.page_number == table.bounding_regions[0].page_number - ) - else: - table_beginning_page = None - table_start_offset = table.spans[0].offset - if table_beginning_page and table_beginning_page.lines: - preceding_lines = [ - line.content for line in table_beginning_page.lines if line.spans[0].offset < table_start_offset - ] - else: - preceding_lines = [] - preceding_context = "\n".join(preceding_lines[-self.preceding_context_len :]) + f"\n{caption}" - preceding_context = preceding_context.strip() - - # Get following context - if table.bounding_regions and len(table.bounding_regions) == 1: - table_end_page = table_beginning_page - elif table.bounding_regions: - table_end_page = next( - page for page in result.pages if page.page_number == table.bounding_regions[-1].page_number - ) - else: - table_end_page = None - - table_end_offset = table_start_offset + table.spans[0].length - if table_end_page and table_end_page.lines: - following_lines = [ - line.content for line in table_end_page.lines if line.spans[0].offset > table_end_offset - ] - else: - following_lines = [] - following_context = "\n".join(following_lines[: self.following_context_len]) - - table_meta = copy.deepcopy(meta) - - if isinstance(table_meta, dict): - table_meta["preceding_context"] = preceding_context - table_meta["following_context"] = following_context - else: - table_meta = {"preceding_context": preceding_context, "following_context": following_context} - - if self.add_page_number and table.bounding_regions: - table_meta["page"] = table.bounding_regions[0].page_number - - table_df = pd.DataFrame(columns=table_list[0], data=table_list[1:]) - converted_tables.append( - Document(content=table_df, content_type="table", meta=table_meta, id_hash_keys=id_hash_keys) - ) - - return converted_tables - - def _convert_text( - self, result: "AnalyzeResult", meta: Optional[Dict[str, str]], id_hash_keys: Optional[List[str]] = None - ) -> Document: - text = "" - table_spans_by_page = defaultdict(list) - tables = result.tables if result.tables else [] - for table in tables: - if not table.bounding_regions: - continue - table_spans_by_page[table.bounding_regions[0].page_number].append(table.spans[0]) - - for page in result.pages: - tables_on_page = table_spans_by_page[page.page_number] - lines = page.lines if page.lines else [] - for line in lines: - in_table = False - # Check if line is part of a table - for t in tables_on_page: - if t.offset <= line.spans[0].offset <= t.offset + t.length: - in_table = True - break - if in_table: - continue - text += f"{line.content}\n" - text += "\f" - - return Document(content=text, meta=meta, id_hash_keys=id_hash_keys) diff --git a/haystack/nodes/file_converter/base.py b/haystack/nodes/file_converter/base.py deleted file mode 100644 index d5fbb3fc58..0000000000 --- a/haystack/nodes/file_converter/base.py +++ /dev/null @@ -1,241 +0,0 @@ -from typing import List, Optional, Dict, Union, Any - -import logging -from abc import abstractmethod -from pathlib import Path - -from tqdm import tqdm -from haystack.nodes.base import BaseComponent -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport("Run 'pip install farm-haystack[preprocessing]' or 'pip install langdetect'") as langdetect_import: - import langdetect - - -# https://en.wikipedia.org/wiki/Ligature_(writing) -KNOWN_LIGATURES = { - # Latin - "ff": "ff", - "fi": "fi", - "fl": "fl", - "ffi": "ffi", - "ffl": "ffl", - "ſt": "ft", - "st": "st", - "DZ": "DZ", - "Dz": "Dz", - "dz": "dz", - "DŽ": "DŽ", - "Dž": "Dž", - "dž": "dž", - "Ꜩ": "Tz", - "ꜩ": "tz", - "🙰": "et", - "℔": "lb", - "ᵫ": "ue", - "IJ": "IJ", - "ij": "ij", # They are both capitalized together, so the "Ij" ligature doesn't exist - "ꝏ": "oo", # Not the infinite sign but a double-o ligature: https://en.wikipedia.org/wiki/Ligature_(writing)#Massachusett_%EA%9D%8F - # Armenian - "ﬓ": "մն", - "ﬔ": "մե", - "ﬕ": "մի", - "ﬖ": "վն", - "ﬗ": "մխ", -} - - -class BaseConverter(BaseComponent): - """ - Base class for implementing file converts to transform input documents to text format for ingestion in DocumentStore. - """ - - outgoing_edges = 1 - - def __init__( - self, - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - progress_bar: bool = True, - ): - """ - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param progress_bar: Show a progress bar for the conversion. - """ - super().__init__() - - self.remove_numeric_tables = remove_numeric_tables - self.valid_languages = valid_languages - self.id_hash_keys = id_hash_keys - self.progress_bar = progress_bar - - @abstractmethod - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, Any]], - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "UTF-8", - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Convert a file to a dictionary containing the text and any associated meta data. - - File converters may extract file meta like name or size. In addition to it, user - supplied meta data like author, url, external IDs can be supplied as a dictionary. - - :param file_path: path of the file to convert - :param meta: dictionary of meta data key-value pairs to append in the returned document. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Select the file encoding (default is `UTF-8`) - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - """ - pass - - def validate_language(self, text: str, valid_languages: Optional[List[str]] = None) -> bool: - """ - Validate if the language of the text is one of valid languages. - """ - if valid_languages is None: - valid_languages = self.valid_languages - - if not valid_languages: - return True - - lang = None - try: - langdetect_import.check() - lang = langdetect.detect(text) - except langdetect.lang_detect_exception.LangDetectException: - pass - except ImportError as exc: - logger.debug( - "langdetect could not be imported. Haystack won't try to guess the document language. " - "Original error: %s", - exc, - ) - - return lang in valid_languages - - def run( # type: ignore - self, - file_paths: Union[Path, List[Path]], - meta: Optional[Union[Dict[str, str], List[Optional[Dict[str, str]]]]] = None, - remove_numeric_tables: Optional[bool] = None, - known_ligatures: Optional[Dict[str, str]] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "UTF-8", - id_hash_keys: Optional[List[str]] = None, - ): - """ - Extract text from a file. - - :param file_paths: Path to the files you want to convert - :param meta: Optional dictionary with metadata that shall be attached to all resulting documents. - Can be any custom keys and values. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param known_ligatures: Some converters tend to recognize clusters of letters as ligatures, such as "ff" (double f). - Such ligatures however make text hard to compare with the content of other files, - which are generally ligature free. Therefore we automatically find and replace the most - common ligatures with their split counterparts. The default mapping is in - `haystack.nodes.file_converter.base.KNOWN_LIGATURES`: it is rather biased towards Latin alphabeths - but excludes all ligatures that are known to be used in IPA. - If no value is provided, this default is created and used. - You can use this parameter to provide your own set of ligatures to clean up from the documents. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Select the file encoding (default is `UTF-8`) - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - """ - if known_ligatures is None: - known_ligatures = KNOWN_LIGATURES - - if isinstance(file_paths, Path): - file_paths = [file_paths] - - if isinstance(meta, dict) or meta is None: - meta = [meta] * len(file_paths) - - documents: list = [] - for file_path, file_meta in tqdm( - zip(file_paths, meta), total=len(file_paths), disable=not self.progress_bar, desc="Converting files" - ): - documents += self.convert( - file_path=file_path, - meta=file_meta, - remove_numeric_tables=remove_numeric_tables, - valid_languages=valid_languages, - encoding=encoding, - id_hash_keys=id_hash_keys, - ) - - # Cleanup ligatures - for document in documents: - for ligature, letters in known_ligatures.items(): - if document.content is not None: - document.content = document.content.replace(ligature, letters) - - result = {"documents": documents} - return result, "output_1" - - def run_batch( # type: ignore - self, - file_paths: Union[Path, List[Path]], - meta: Optional[Union[Dict[str, str], List[Optional[Dict[str, str]]]]] = None, - remove_numeric_tables: Optional[bool] = None, - known_ligatures: Optional[Dict[str, str]] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "UTF-8", - id_hash_keys: Optional[List[str]] = None, - ): - return self.run( - file_paths=file_paths, - meta=meta, - remove_numeric_tables=remove_numeric_tables, - known_ligatures=known_ligatures, - valid_languages=valid_languages, - encoding=encoding, - id_hash_keys=id_hash_keys, - ) diff --git a/haystack/nodes/file_converter/csv.py b/haystack/nodes/file_converter/csv.py deleted file mode 100644 index ac69203f2a..0000000000 --- a/haystack/nodes/file_converter/csv.py +++ /dev/null @@ -1,69 +0,0 @@ -from typing import Union, List, Optional, Any, Dict - -import logging -from pathlib import Path - -import pandas as pd - -from haystack import Document -from haystack.nodes.file_converter import BaseConverter - - -logger = logging.getLogger(__name__) - - -class CsvTextConverter(BaseConverter): - """ - Converts a CSV file containing FAQs to text Documents. The CSV file must have two columns: 'question' and 'answer'. Use this node for FAQ-style question answering. - """ - - outgoing_edges = 1 - - def convert( - self, - file_path: Union[Path, List[Path], str, List[str], List[Union[Path, str]]], - meta: Optional[Dict[str, Any]], - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "UTF-8", - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Load a CSV file containing question-answer pairs and convert it to Documents. - - :param file_path: Path to the CSV file you want to convert. The file must have two columns called 'question' and 'answer'. - The first will be interpreted as a question, the second as content. - :param meta: A dictionary of metadata key-value pairs that you want to append to the returned document. It's optional. - :param encoding: Specifies the file encoding. It's optional. The default value is `UTF-8`. - :param id_hash_keys: Generates the document ID from a custom list of strings that refer to the document's - attributes. To ensure you don't have duplicate documents in your DocumentStore when texts are - not unique, modify the metadata and pass, for example, "meta" to this field (example: ["content", "meta"]). - Then the ID is generated by using the content and the metadata you defined. - :param remove_numeric_tables: unused - :param valid_languages: unused - :returns: List of document, 1 document per line in the CSV. - """ - if not isinstance(file_path, list): - file_path = [file_path] - - docs: List[Document] = [] - for path in file_path: - df = pd.read_csv(path, encoding=encoding) - - if len(df.columns) != 2 or df.columns[0] != "question" or df.columns[1] != "answer": - raise ValueError("The CSV must contain two columns named 'question' and 'answer'") - - df.fillna(value="", inplace=True) - df["question"] = df["question"].apply(lambda x: x.strip()) - - df = df.rename(columns={"question": "content"}) - docs_dicts = df.to_dict(orient="records") - - for dictionary in docs_dicts: - if meta: - dictionary["meta"] = meta - if id_hash_keys: - dictionary["id_hash_keys"] = id_hash_keys - docs.append(Document.from_dict(dictionary)) - - return docs diff --git a/haystack/nodes/file_converter/docx.py b/haystack/nodes/file_converter/docx.py deleted file mode 100644 index ae59f13919..0000000000 --- a/haystack/nodes/file_converter/docx.py +++ /dev/null @@ -1,81 +0,0 @@ -from typing import Dict, Optional, List - -import logging -from pathlib import Path - -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport("Run 'pip install farm-haystack[file-conversion]' or 'pip install docx'") as docx_import: - import docx - - -class DocxToTextConverter(BaseConverter): - def __init__( - self, - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - progress_bar: bool = True, - ): - docx_import.check() - super().__init__( - remove_numeric_tables=remove_numeric_tables, - valid_languages=valid_languages, - id_hash_keys=id_hash_keys, - progress_bar=progress_bar, - ) - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, str]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Extract text from a .docx file. - Note: As docx doesn't contain "page" information, we actually extract and return a list of paragraphs here. - For compliance with other converters we nevertheless opted for keeping the methods name. - - :param file_path: Path to the .docx file you want to convert - :param meta: dictionary of meta data key-value pairs to append in the returned document. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Not applicable - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - """ - if remove_numeric_tables is None: - remove_numeric_tables = self.remove_numeric_tables - if valid_languages is None: - valid_languages = self.valid_languages - if remove_numeric_tables is True: - raise Exception("'remove_numeric_tables' is not supported by DocxToTextConverter.") - if valid_languages is True: - raise Exception("Language validation using 'valid_languages' is not supported by DocxToTextConverter.") - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - file = docx.Document(file_path) # Creating word reader object. - paragraphs = [para.text for para in file.paragraphs] - text = "\n".join(paragraphs) - document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys) - return [document] diff --git a/haystack/nodes/file_converter/image.py b/haystack/nodes/file_converter/image.py deleted file mode 100644 index 1e4db2d392..0000000000 --- a/haystack/nodes/file_converter/image.py +++ /dev/null @@ -1,170 +0,0 @@ -from typing import List, Optional, Dict, Union - -import logging -import subprocess -from pathlib import Path - -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install farm-haystack[ocr]'") as ocr_imports: - import pytesseract - from PIL.PpmImagePlugin import PpmImageFile - from PIL import Image - - -logger = logging.getLogger(__name__) - - -class ImageToTextConverter(BaseConverter): - def __init__( - self, - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - ): - """ - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified here - (https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html) - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. If no value is provided, English will be set as default. - Run the following line of code to check available language packs: - `# List of available languages - print(pytesseract.get_languages(config=''))` - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - """ - ocr_imports.check() - if valid_languages is None: - valid_languages = ["eng"] - super().__init__( - remove_numeric_tables=remove_numeric_tables, valid_languages=valid_languages, id_hash_keys=id_hash_keys - ) - - verify_installation = subprocess.run(["tesseract -v"], shell=True) - if verify_installation.returncode == 127: - raise Exception( - """tesseract is not installed. - - Installation on Linux: - apt-get install tesseract-ocr libtesseract-dev poppler-utils - - Installation on MacOS: - brew install tesseract - - For installing specific language packs check here: https://tesseract-ocr.github.io/tessdoc/Installation.html - """ - ) - tesseract_langs = [] - if valid_languages: - for language in valid_languages: - if language in pytesseract.get_languages(config="") and language not in tesseract_langs: - tesseract_langs.append(language) - else: - raise Exception( - f"""{language} is not either a valid tesseract language code or its language pack isn't installed. - - Check the list of valid tesseract language codes here: https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html - - For installing specific language packs check here: https://tesseract-ocr.github.io/tessdoc/Installation.html - """ - ) - - ## if you have more than one language in images, then pass it to tesseract like this e.g., `fra+eng` - self.tesseract_langs = "+".join(tesseract_langs) - super().__init__(remove_numeric_tables=remove_numeric_tables, valid_languages=valid_languages) - - def convert( - self, - file_path: Union[Path, str], - meta: Optional[Dict[str, str]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Extract text from image file using the pytesseract library (https://github.com/madmaze/pytesseract) - - :param file_path: path to image file - :param meta: Optional dictionary with metadata that shall be attached to all resulting documents. - Can be any custom keys and values. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages supported by tessarect - (https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html). - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Not applicable - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - """ - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - file_path = Path(file_path) - image = Image.open(file_path) - pages = self._image_to_text(image) - if remove_numeric_tables is None: - remove_numeric_tables = self.remove_numeric_tables - if valid_languages is None: - valid_languages = self.valid_languages - - cleaned_pages = [] - for page in pages: - lines = page.splitlines() - cleaned_lines = [] - for line in lines: - words = line.split() - digits = [word for word in words if any(i.isdigit() for i in word)] - - # remove lines having > 40% of words as digits AND not ending with a period(.) - if ( - remove_numeric_tables - and words - and len(digits) / len(words) > 0.4 - and not line.strip().endswith(".") - ): - logger.debug("Removing line '%s' from file", line) - continue - cleaned_lines.append(line) - - page = "\n".join(cleaned_lines) - cleaned_pages.append(page) - - if valid_languages: - document_text = "".join(cleaned_pages) - if not self.validate_language(document_text, valid_languages): - logger.warning( - "The language for image is not one of %s. The file may not have " - "been decoded in the correct text format.", - valid_languages, - ) - - text = "\f".join(cleaned_pages) - document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys) - return [document] - - def _image_to_text(self, image: "PpmImageFile") -> List[str]: - """ - Extract text from image file. - - :param image: input image file - """ - text = [pytesseract.image_to_string(image, lang=self.tesseract_langs)] - return text diff --git a/haystack/nodes/file_converter/json.py b/haystack/nodes/file_converter/json.py deleted file mode 100644 index 6e74675f66..0000000000 --- a/haystack/nodes/file_converter/json.py +++ /dev/null @@ -1,96 +0,0 @@ -import json -from json import JSONDecodeError - -from typing import List, Optional, Any, Dict - -import logging -from pathlib import Path - -from haystack import Document -from haystack.nodes.file_converter import BaseConverter - - -logger = logging.getLogger(__name__) - - -class JsonConverter(BaseConverter): - """Extracts text from JSON files and casts it into Document objects.""" - - outgoing_edges = 1 - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, Any]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "UTF-8", - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Reads a JSON file and converts it into a list of Documents. - - It's a wrapper around `Document.from_dict()` and, as such, acts as the inverse of `Document.to_dict()`. - - It expects one of these formats: - - A JSON file with a list of Document dicts. - - A JSONL file with every line containing either a Document dict or a list of dicts. - - :param file_path: Path to the JSON file you want to convert. - :param meta: Optional dictionary with metadata you want to attach to all resulting documents. - Can be any custom keys and values. - The result will have a union of metadata specified here and already present in the json. - In case of same keys being used, the one passed here takes precedence/overwrites the one from the json. - :param remove_numeric_tables: Uses heuristics to remove numeric rows from the tables. - Note: Not currently used in this Converter. - :param valid_languages: Validates languages from a list of languages specified in the [ISO 639-1] - Note: Not currently used in this Converter. - :param encoding: Encoding used when opening the json file. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. To ensure you don't have duplicate documents in your DocumentStore if texts are - not unique, modify the metadata and pass, for example, `"meta"` to this field (example: [`"content"`, `"meta"`]). - The id is then generated by using the content and the defined metadata. - If specified here or during initialization of the JsonConverter, it will overwrite any `id_hash_keys` present in the json file. - """ - - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - docs: List[Document] = [] - - with open(file_path, mode="r", encoding=encoding, errors="ignore") as f: - data: List[Dict] = [] - try: - for line in f: - line_obj = json.loads(line) - if isinstance(line_obj, list): - data.extend(line_obj) - elif isinstance(line_obj, dict): - data.append(line_obj) - except JSONDecodeError: - try: - f.seek(0) - # Assume it's a full json file - data = json.load(f) - except JSONDecodeError as e: - msg = ( - f"Couldn't decode the json file provided: {file_path}. " - "Please check if it's a valid json or jsonl file." - ) - error_with_custom_message = JSONDecodeError(msg, e.doc, e.pos) - raise error_with_custom_message from e - - for doc_dict in data: - # Overwrite the id_hash_keys if specified - # Else we let it be whatever it is in the doc_dict - if id_hash_keys is not None: - doc_dict["id_hash_keys"] = id_hash_keys - - if meta is not None: - existing_meta = doc_dict.get("meta", {}) - # In case of duplicate keys, the newly specified vals (in `meta`) take precedence - doc_dict["meta"] = {**existing_meta, **meta} - - docs.append(Document.from_dict(doc_dict)) - - return docs diff --git a/haystack/nodes/file_converter/markdown.py b/haystack/nodes/file_converter/markdown.py deleted file mode 100644 index 25e97f7125..0000000000 --- a/haystack/nodes/file_converter/markdown.py +++ /dev/null @@ -1,137 +0,0 @@ -import logging -import re -from pathlib import Path -from typing import Dict, List, Optional, Tuple, Any - -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install farm-haystack[file-conversion]'") as conversion_imports: - import frontmatter - from bs4 import BeautifulSoup, NavigableString - from markdown import markdown - - -logger = logging.getLogger(__name__) - - -class MarkdownConverter(BaseConverter): - def __init__( - self, - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - progress_bar: bool = True, - remove_code_snippets: bool = True, - extract_headlines: bool = False, - add_frontmatter_to_meta: bool = False, - ): - """ - :param remove_numeric_tables: Not applicable. - :param valid_languages: Not applicable. - :param id_hash_keys: Generate the document ID from a custom list of strings that refer to the document's - attributes. To make sure you don't have duplicate documents in your DocumentStore if texts are - not unique, you can modify the metadata and pass for example, `"meta"` to this field ([`"content"`, `"meta"`]). - In this case, the ID is generated by using the content and the defined metadata. - :param progress_bar: Show a progress bar for the conversion. - :param remove_code_snippets: Whether to remove snippets from the markdown file. - :param extract_headlines: Whether to extract headings from the markdown file. - :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`. - """ - conversion_imports.check() - super().__init__( - remove_numeric_tables=remove_numeric_tables, - valid_languages=valid_languages, - id_hash_keys=id_hash_keys, - progress_bar=progress_bar, - ) - - self.remove_code_snippets = remove_code_snippets - self.extract_headlines = extract_headlines - self.add_frontmatter_to_meta = add_frontmatter_to_meta - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, Any]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "utf-8", - id_hash_keys: Optional[List[str]] = None, - remove_code_snippets: Optional[bool] = None, - extract_headlines: Optional[bool] = None, - add_frontmatter_to_meta: Optional[bool] = None, - ) -> List[Document]: - """ - Reads text from a markdown file and executes optional preprocessing steps. - - :param file_path: path of the file to convert - :param meta: dictionary of meta data key-value pairs to append in the returned document. - :param encoding: Select the file encoding (default is `utf-8`) - :param remove_numeric_tables: Not applicable - :param valid_languages: Not applicable - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param remove_code_snippets: Whether to remove snippets from the markdown file. - :param extract_headlines: Whether to extract headings from the markdown file. - :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`. - """ - - id_hash_keys = id_hash_keys if id_hash_keys is not None else self.id_hash_keys - remove_code_snippets = remove_code_snippets if remove_code_snippets is not None else self.remove_code_snippets - extract_headlines = extract_headlines if extract_headlines is not None else self.extract_headlines - add_frontmatter_to_meta = ( - add_frontmatter_to_meta if add_frontmatter_to_meta is not None else self.add_frontmatter_to_meta - ) - - with open(file_path, encoding=encoding, errors="ignore") as f: - metadata, markdown_text = frontmatter.parse(f.read()) - - # md -> html -> text since BeautifulSoup can extract text cleanly - html = markdown(markdown_text, extensions=["fenced_code"]) - - # remove code snippets - if remove_code_snippets: - html = re.sub(r"
(.*?)
", " ", html, flags=re.DOTALL) - html = re.sub(r"(.*?)", " ", html, flags=re.DOTALL) - soup = BeautifulSoup(html, "html.parser") - - if add_frontmatter_to_meta: - if meta is None: - meta = metadata - else: - meta.update(metadata) - - if extract_headlines: - text, headlines = self._extract_text_and_headlines(soup) - if meta is None: - meta = {} - meta["headlines"] = headlines - else: - text = soup.get_text() - - document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys) - return [document] - - @staticmethod - def _extract_text_and_headlines(soup: "BeautifulSoup") -> Tuple[str, List[Dict]]: - """ - Extracts text and headings from a soup object. - """ - headline_tags = {"h1", "h2", "h3", "h4", "h5", "h6"} - headlines = [] - text = "" - for desc in soup.descendants: - if desc.name in headline_tags: - current_headline = desc.get_text() - current_start_idx = len(text) - current_level = int(desc.name[-1]) - 1 - headlines.append({"headline": current_headline, "start_idx": current_start_idx, "level": current_level}) - - if isinstance(desc, NavigableString): - text += desc.get_text() - - return text, headlines diff --git a/haystack/nodes/file_converter/parsr.py b/haystack/nodes/file_converter/parsr.py deleted file mode 100644 index 55217c2eb7..0000000000 --- a/haystack/nodes/file_converter/parsr.py +++ /dev/null @@ -1,334 +0,0 @@ -import sys -from typing import Optional, Dict, List, Any, Union, Tuple, Literal - -import json -import copy -import logging -from pathlib import Path - -import requests -import pandas as pd - -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document -from haystack.errors import HaystackError - - -logger = logging.getLogger(__name__) - - -class ParsrConverter(BaseConverter): - """ - File converter that makes use of the open-source Parsr tool by axa-group. - (https://github.com/axa-group/Parsr). - This Converter extracts both text and tables. - Supported file formats are: PDF, DOCX - """ - - def __init__( - self, - parsr_url: str = "http://localhost:3001", - extractor: Literal["pdfminer", "pdfjs"] = "pdfminer", - table_detection_mode: Literal["lattice", "stream"] = "lattice", - preceding_context_len: int = 3, - following_context_len: int = 3, - remove_page_headers: bool = False, - remove_page_footers: bool = False, - remove_table_of_contents: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - add_page_number: bool = True, - extract_headlines: bool = True, - timeout: Union[float, Tuple[float, float]] = 10.0, - ): - """ - :param parsr_url: URL endpoint to Parsr"s REST API. - :param extractor: Backend used to extract textual structured from PDFs. ("pdfminer" or "pdfjs") - :param table_detection_mode: Parsing method used to detect tables and their cells. - "lattice" detects tables and their cells by demarcated lines between cells. - "stream" detects tables and their cells by looking at whitespace between cells. - :param preceding_context_len: Number of lines before a table to extract as preceding context - (will be returned as part of meta data). - :param following_context_len: Number of lines after a table to extract as preceding context - (will be returned as part of meta data). - :param remove_page_headers: Whether to remove text that Parsr detected as a page header. - :param remove_page_footers: Whether to remove text that Parsr detected as a page footer. - :param remove_table_of_contents: Whether to remove text that Parsr detected as a table of contents. - :param valid_languages: Validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param add_page_number: Adds the number of the page a table occurs in to the Document's meta field - `"page"`. - :param extract_headlines: Whether to extract headings from the PDF file. - :param timeout: How many seconds to wait for the server to send data before giving up, - as a float, or a :ref:`(connect timeout, read timeout) ` tuple. - Defaults to 10 seconds. - """ - super().__init__(valid_languages=valid_languages, id_hash_keys=id_hash_keys) - - try: - ping = requests.get(parsr_url, timeout=timeout) - except requests.exceptions.ConnectionError: - raise Exception( - f"Parsr server is not reachable at the URL '{parsr_url}'. To run it locally " - f"with Docker, execute: 'docker run -p 3001:3001 axarev/parsr:v1.2.2'" - ) - if ping.status_code != 200: - raise Exception( - f"Parsr server is not reachable at the URL '{parsr_url}'. (Status code: {ping.status_code} {ping.reason})\n" - f"To run it locally with Docker, execute: 'docker run -p 3001:3001 axarev/parsr:v1.2.2'" - ) - - self.parsr_url = parsr_url - self.valid_languages = valid_languages - res = requests.get(f"{self.parsr_url}/api/v1/default-config", timeout=timeout) - self.config = json.loads(res.content) - self.config["extractor"]["pdf"] = extractor - self.config["cleaner"][5][1]["runConfig"][0]["flavor"] = table_detection_mode - self.preceding_context_len = preceding_context_len - self.following_context_len = following_context_len - self.remove_page_headers = remove_page_headers - self.remove_page_footers = remove_page_footers - self.remove_table_of_contents = remove_table_of_contents - self.add_page_number = add_page_number - self.extract_headlines = extract_headlines - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, Any]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "utf-8", - id_hash_keys: Optional[List[str]] = None, - extract_headlines: Optional[bool] = None, - timeout: Union[float, Tuple[float, float]] = 10.0, - ) -> List[Document]: - """ - Extract text and tables from a PDF or DOCX using the open-source Parsr tool. - - :param file_path: Path to the file you want to convert. - :param meta: Optional dictionary with metadata that shall be attached to all resulting documents. - Can be any custom keys and values. - :param remove_numeric_tables: Not applicable. - :param valid_languages: Validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Not applicable. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param extract_headlines: Whether to extract headings from the PDF file. - :param timeout: How many seconds to wait for the server to send data before giving up, - as a float, or a :ref:`(connect timeout, read timeout) ` tuple. - Defaults to 10 seconds. - """ - if valid_languages is None: - valid_languages = self.valid_languages - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - if extract_headlines is None: - extract_headlines = self.extract_headlines - if meta is None: - meta = {} - - with open(file_path, "rb") as pdf_file: - # Send file to Parsr - send_response = requests.post( - url=f"{self.parsr_url}/api/v1/document", - files={ # type: ignore - "file": (str(file_path), pdf_file, "application/pdf"), - "config": ("config", json.dumps(self.config), "application/json"), - }, - timeout=timeout, - ) - queue_id = send_response.text - - # Wait until Parsr processing is done - status_response = requests.get(url=f"{self.parsr_url}/api/v1/queue/{queue_id}", timeout=timeout) - while status_response.status_code == 200 and status_response.status_code != 201: - status_response = requests.get(url=f"{self.parsr_url}/api/v1/queue/{queue_id}", timeout=timeout) - - # Get Parsr output - result_response = requests.get(url=f"{self.parsr_url}/api/v1/json/{queue_id}", timeout=timeout) - parsr_output = json.loads(result_response.content) - - # Convert Parsr output to Haystack Documents - text = "" - tables = [] - headlines = [] - for page_idx, page in enumerate(parsr_output["pages"]): - for elem_idx, element in enumerate(page["elements"]): - if element["type"] in ["paragraph", "heading", "table-of-contents", "list"]: - current_paragraph = self._convert_text_element(element) - if current_paragraph: - if element["type"] == "heading" and extract_headlines: - headlines.append( - {"headline": current_paragraph, "start_idx": len(text), "level": element["level"]} - ) - text += f"{current_paragraph}\n\n" - - elif element["type"] == "table": - table = self._convert_table_element( - element, - parsr_output["pages"], - page_idx, - elem_idx, - headlines, - extract_headlines, - meta, - id_hash_keys, - ) - tables.append(table) - if len(text) == 0 or text[-1] != "\f": - text += "\f" - - if valid_languages: - file_text = text - for table in tables: - # Mainly needed for type checking - if not isinstance(table.content, pd.DataFrame): - raise HaystackError("Document's content field must be of type 'pd.DataFrame'.") - for _, row in table.content.iterrows(): - for cell in row.values(): - file_text += f" {cell}" - if not self.validate_language(file_text, valid_languages): - logger.warning( - "The language for %s is not one of %s. The file may not have " - "been decoded in the correct text format.", - file_path, - valid_languages, - ) - - if extract_headlines: - meta["headlines"] = headlines - - docs = tables + [Document(content=text.strip(), meta=meta, id_hash_keys=id_hash_keys)] - return docs - - def _get_paragraph_string(self, paragraph: Dict[str, Any]) -> str: - current_lines = [] - for line in paragraph["content"]: - current_lines.append(self._get_line_string(line)) - current_paragraph = "\n".join(current_lines) - - return current_paragraph - - def _get_line_string(self, line: Dict[str, Any]) -> str: - return " ".join([word["content"] for word in line["content"]]) - - def _convert_text_element(self, element: Dict[str, Any]) -> str: - if self.remove_page_headers and "isHeader" in element["properties"]: - return "" - if self.remove_page_footers and "isFooter" in element["properties"]: - return "" - if element["type"] in ["table-of-contents", "list"]: - if self.remove_table_of_contents and element["type"] == "table-of-contents": - return "" - current_paragraph = "\n".join([self._get_paragraph_string(elem) for elem in element["content"]]) - return current_paragraph - - current_paragraph = self._get_paragraph_string(element) - return current_paragraph - - def _convert_table_element( - self, - element: Dict[str, Any], - all_pages: List[Dict], - page_idx: int, - elem_idx: int, - headlines: List[Dict], - extract_headlines: bool, - meta: Optional[Dict[str, Any]] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> Document: - row_idx_start = 0 - caption = "" - number_of_columns = max(len(row["content"]) for row in element["content"]) - number_of_rows = len(element["content"]) - table_list = [[""] * number_of_columns for _ in range(number_of_rows)] - - for row_idx, row in enumerate(element["content"]): - for col_idx, cell in enumerate(row["content"]): - # Check if first row is a merged cell spanning whole table - # -> exclude this row and use as caption - if (row_idx == col_idx == 0) and (cell["colspan"] == len(table_list[0])): - cell_paragraphs = [self._get_paragraph_string(par) for par in cell["content"]] - cell_content = "\n\n".join(cell_paragraphs) - caption = cell_content - row_idx_start = 1 - table_list.pop(0) - break - - if cell["type"] == "table-cell": - cell_paragraphs = [self._get_paragraph_string(par) for par in cell["content"]] - cell_content = "\n\n".join(cell_paragraphs) - for c in range(cell["colspan"]): - for r in range(cell["rowspan"]): - table_list[row_idx + r - row_idx_start][col_idx + c] = cell_content - - # Get preceding and following elements of table - preceding_lines = [] - following_lines = [] - for cur_page_idx, cur_page in enumerate(all_pages): - for cur_elem_index, elem in enumerate(cur_page["elements"]): - if elem["type"] in ["paragraph", "heading"]: - if (self.remove_page_headers and "isHeader" in elem["properties"]) or ( - self.remove_page_footers and "isFooter" in elem["properties"] - ): - # Skip header and footer elements if remove_page_header/footer is set to True - continue - for line in elem["content"]: - if cur_page_idx < page_idx: - preceding_lines.append(line) - elif cur_page_idx == page_idx: - if cur_elem_index < elem_idx: - preceding_lines.append(line) - elif cur_elem_index > elem_idx: - following_lines.append(line) - elif cur_page_idx > page_idx: - following_lines.append(line) - - preceding_context = ( - "\n".join([self._get_line_string(line) for line in preceding_lines[-self.preceding_context_len :]]) - + f"\n\n{caption}" - ) - preceding_context = preceding_context.strip() - following_context = "\n".join( - [self._get_line_string(line) for line in following_lines[: self.following_context_len]] - ) - following_context = following_context.strip() - - if meta is not None: - table_meta = copy.deepcopy(meta) - table_meta["preceding_context"] = preceding_context - table_meta["following_context"] = following_context - else: - table_meta = {"preceding_context": preceding_context, "following_context": following_context} - - if self.add_page_number: - table_meta["page"] = page_idx + 1 - - if extract_headlines: - relevant_headlines = [] - cur_lowest_headline_level = sys.maxsize - for headline in reversed(headlines): - if headline["level"] < cur_lowest_headline_level: - headline_copy = copy.deepcopy(headline) - headline_copy["start_idx"] = None - relevant_headlines.append(headline_copy) - cur_lowest_headline_level = headline_copy["level"] - relevant_headlines = relevant_headlines[::-1] - table_meta["headlines"] = relevant_headlines - - table_df = pd.DataFrame(columns=table_list[0], data=table_list[1:]) - return Document(content=table_df, content_type="table", meta=table_meta, id_hash_keys=id_hash_keys) diff --git a/haystack/nodes/file_converter/pdf.py b/haystack/nodes/file_converter/pdf.py deleted file mode 100644 index e5348671dc..0000000000 --- a/haystack/nodes/file_converter/pdf.py +++ /dev/null @@ -1,307 +0,0 @@ -import logging -import os -import warnings -from concurrent.futures import ProcessPoolExecutor -from multiprocessing import cpu_count -from pathlib import Path -from typing import Any, Dict, List, Literal, Optional, Union - -import fitz -from more_itertools import divide - -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document - - -logger = logging.getLogger(__name__) - - -class PDFToTextConverter(BaseConverter): - def __init__( - self, - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - encoding: Optional[str] = None, - keep_physical_layout: Optional[bool] = None, - sort_by_position: bool = False, - ocr: Optional[Literal["auto", "full"]] = None, - ocr_language: str = "eng", - multiprocessing: Union[bool, int] = True, - ) -> None: - """ - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param encoding: This parameter is being deprecated. - It will be automatically detected by PyMuPDF. - :param keep_physical_layout: This parameter is being deprecated. - :param sort_by_position: Specifies whether to sort the extracted text by positional coordinates or logical reading order. - If set to True, the text is sorted first by vertical position, and then by horizontal position. - If set to False (default), the logical reading order in the PDF is used. - :param ocr: Specifies whether to use OCR to extract text from images in the PDF. If set to "auto", OCR is used only to extract text - from images and integrate into the existing text. If set to "full", OCR is used to extract text from the entire PDF. - :param ocr_language: Specifies the language to use for OCR. The default language is English, which language code is `eng`. - For a list of supported languages and the respective codes access https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html. - You can combine multiple languages by passing a string with the language codes separated by `+`. For example, to use English and German, pass `eng+deu`. - :param multiprocessing: We use multiprocessing to speed up PyMuPDF conversion, you can disable it by setting it to False. - If set to True (the default value), the total number of cores is used. To specify the number of cores to use, set it to an integer. - """ - super().__init__( - remove_numeric_tables=remove_numeric_tables, valid_languages=valid_languages, id_hash_keys=id_hash_keys - ) - - self.sort_by_position = sort_by_position - self.multiprocessing = multiprocessing - self.ocr = ocr - self.ocr_language = ocr_language - - if ocr is not None: - if ocr not in ["auto", "full"]: - raise ValueError("The ocr parameter must be either 'auto' or 'full'.") - self._check_tessdata() - - if encoding: - warnings.warn( - "The encoding parameter is being deprecated. It will be automatically detected by PyMuPDF.", - DeprecationWarning, - ) - - if keep_physical_layout: - warnings.warn("The keep_physical_layout parameter is being deprecated.", DeprecationWarning) - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, Any]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - start_page: Optional[int] = None, - end_page: Optional[int] = None, - keep_physical_layout: Optional[bool] = None, - sort_by_position: Optional[bool] = None, - ocr: Optional[Literal["auto", "full"]] = None, - ocr_language: Optional[str] = None, - multiprocessing: Optional[Union[bool, int]] = None, - ) -> List[Document]: - """ - Extract text from a PDF file and convert it to a Document. - :param file_path: Path to the .pdf file you want to convert - :param meta: Optional dictionary with metadata that shall be attached to all resulting documents. - Can be any custom keys and values. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: This parameter is being deprecated. - It will be automatically detected by PyMuPDF. - :param keep_physical_layout: This parameter is being deprecated. - :param sort_by_position: Specifies whether to sort the extracted text by positional coordinates or logical reading order. - If set to True, the text is sorted first by vertical position, and then by horizontal position. - If set to False (default), the logical reading order in the PDF is used. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param start_page: The page number where to start the conversion - :param end_page: The page number where to end the conversion. - :param ocr: Specifies whether to use OCR to extract text from images in the PDF. If set to "auto", OCR is used only to extract text - from images and integrate into the existing text. If set to "full", OCR is used to extract text from the entire PDF. - To use this feature you must install Tesseract-OCR. For more information, see https://github.com/tesseract-ocr/tesseract#installing-tesseract. - :param ocr_language: Specifies the language to use for OCR. The default language is English, which language code is `eng`. - For a list of supported languages and the respective codes access https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html. - You can combine multiple languages by passing a string with the language codes separated by `+`. For example, to use English and German, pass `eng+deu`. - :param multiprocessing: We use multiprocessing to speed up PyMuPDF conversion, you can disable it by setting it to False. - If set to None (the default value), the value defined in the class initialization is used. - If set to True, the total number of cores is used. To specify the number of cores to use, set it to an integer. - """ - if remove_numeric_tables is None: - remove_numeric_tables = self.remove_numeric_tables - if valid_languages is None: - valid_languages = self.valid_languages - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - if multiprocessing is None: - multiprocessing = self.multiprocessing - if sort_by_position is None: - sort_by_position = self.sort_by_position - if ocr is None: - ocr = self.ocr - if ocr_language is None: - ocr_language = self.ocr_language - - if encoding: - warnings.warn( - "The encoding parameter is being deprecated. It will be automatically detected by PyMuPDF.", - DeprecationWarning, - ) - - if keep_physical_layout: - warnings.warn("The keep_physical_layout parameter is being deprecated.", DeprecationWarning) - - if ocr is not None: - if ocr not in ["auto", "full"]: - raise ValueError("The ocr parameter must be either 'auto' or 'full'.") - self._check_tessdata() - - pages = self._read_pdf( - file_path, - sort_by_position=sort_by_position, - start_page=start_page, - end_page=end_page, - ocr=ocr, - ocr_language=ocr_language, - multiprocessing=multiprocessing, - ) - - cleaned_pages = [] - for page in pages: - lines = page.splitlines() - cleaned_lines = [] - for line in lines: - words = line.split() - digits = [word for word in words if any(i.isdigit() for i in word)] - - # remove lines having > 40% of words as digits AND not ending with a period(.) - if ( - remove_numeric_tables - and words - and len(digits) / len(words) > 0.4 - and not line.strip().endswith(".") - ): - logger.debug("Removing line '%s' from %s", line, file_path) - continue - cleaned_lines.append(line) - - page = "\n".join(cleaned_lines) - cleaned_pages.append(page) - - if valid_languages: - document_text = "".join(cleaned_pages) - if not self.validate_language(document_text, valid_languages): - logger.warning( - "The language for %s is not one of %s. The file may not have " - "been decoded in the correct text format.", - file_path, - valid_languages, - ) - - text = "\f".join(cleaned_pages) - document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys) - return [document] - - def _check_tessdata(self): - if os.getenv("TESSDATA_PREFIX") is None: - raise EnvironmentError( - """ - To enable OCR support via PDFToTextConverter, you need to install Tesseract: - - Windows: choco install tesseract-ocr - - Linux (Ubuntu): sudo apt-get install tesseract-ocr - - Mac: brew install tesseract - After that, you need to set the environment variable TESSDATA_PREFIX to the path - of your Tesseract data directory. Typically this is: - - Windows: C:\\Program Files\\Tesseract-OCR\\tessdata - - Linux (Ubuntu): /usr/share/tesseract-ocr/4.00/tessdata - - Mac (Intel): /usr/local/Cellar/tesseract/5.3.0_1/share/tessdata - - Mac (M1/M2): /opt/homebrew/Cellar/tesseract/5.3.0_1/share/tessdata - """ - ) - - def _get_text_parallel(self, page_mp): - idx, filename, parts, sort_by_position, ocr, ocr_language = page_mp - - doc = fitz.open(filename) - - text = "" - for i in parts[idx]: - page = doc[i] - partial_tp = None - if ocr is not None: - full = ocr == "full" - partial_tp = page.get_textpage_ocr(flags=0, full=full, dpi=300, language=ocr_language) - text += page.get_text("text", textpage=partial_tp, sort=sort_by_position) + "\f" - - return text - - def _read_pdf( - self, - file_path: Path, - ocr_language: str, - sort_by_position: bool = False, - start_page: Optional[int] = None, - end_page: Optional[int] = None, - ocr: Optional[Literal["auto", "full"]] = None, - multiprocessing: Optional[Union[bool, int]] = None, - ) -> List[str]: - """ - Extract pages from the pdf file at file_path. - - :param file_path: path of the pdf file - :param sort_by_position: Specifies whether to sort the extracted text by positional coordinates or logical reading order. - If set to True, the text is sorted first by vertical position, and then by horizontal position. - If set to False (default), the logical reading order in the PDF is used. - :param start_page: The page number where to start the conversion, starting from 1. - :param end_page: The page number where to end the conversion. - :param encoding: This parameter is being deprecated. - It will be automatically detected by PyMuPDF. - :param multiprocessing: We use multiprocessing to speed up PyMuPDF conversion, you can disable it by setting it to False. - If set to None (the default value), the value defined in the class initialization is used. - If set to True, the total number of cores is used. To specify the number of cores to use, set it to an integer. - """ - if start_page is None: - start_page = 0 - else: - start_page = start_page - 1 - - doc = fitz.open(file_path) - page_count = int(doc.page_count) - - if end_page is None or (end_page is not None and end_page > page_count): - end_page = page_count - - document = "" - - if not multiprocessing: - for i in range(start_page, end_page): - page = doc[i] - partial_tp = None - if ocr is not None: - full = ocr == "full" - partial_tp = page.get_textpage_ocr(flags=0, full=full, dpi=300, language=ocr_language) - document += page.get_text("text", textpage=partial_tp, sort=sort_by_position) + "\f" - else: - cpu = cpu_count() if isinstance(multiprocessing, bool) else multiprocessing - page_list = list(range(start_page, end_page)) - cpu = cpu if len(page_list) > cpu else len(page_list) - parts = divide(cpu, page_list) - pages_mp = [(i, file_path, parts, sort_by_position, ocr, ocr_language) for i in range(cpu)] - - with ProcessPoolExecutor(max_workers=cpu) as pool: - results = pool.map(self._get_text_parallel, pages_mp) - for page in results: - document += page - - document = "\f" * start_page + document # tracking skipped pages for correct page numbering - pages = document.split("\f") - pages = pages[:-1] # the last page in the split is always empty. - - return pages diff --git a/haystack/nodes/file_converter/pdf_xpdf.py b/haystack/nodes/file_converter/pdf_xpdf.py deleted file mode 100644 index 8674e33931..0000000000 --- a/haystack/nodes/file_converter/pdf_xpdf.py +++ /dev/null @@ -1,199 +0,0 @@ -import logging -import subprocess -from pathlib import Path -from typing import Any, Dict, List, Optional - -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document - -logger = logging.getLogger(__name__) - - -class PDFToTextConverter(BaseConverter): - def __init__( - self, - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - encoding: Optional[str] = "UTF-8", - keep_physical_layout: bool = False, - ): - """ - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param encoding: Encoding that will be passed as `-enc` parameter to `pdftotext`. - Defaults to "UTF-8" in order to support special characters (e.g. German Umlauts, Cyrillic ...). - (See list of available encodings, such as "Latin1", by running `pdftotext -listenc` in the terminal) - :param keep_physical_layout: This option will maintain original physical layout on the extracted text. - It works by passing the `-layout` parameter to `pdftotext`. When disabled, PDF is read in the stream order. - """ - super().__init__( - remove_numeric_tables=remove_numeric_tables, valid_languages=valid_languages, id_hash_keys=id_hash_keys - ) - try: - subprocess.run(["pdftotext", "-v"], shell=False, check=False) - except FileNotFoundError: - raise FileNotFoundError( - """pdftotext is not installed. It is part of xpdf or poppler-utils software suite. - - Installation on Linux: - wget --no-check-certificate https://dl.xpdfreader.com/xpdf-tools-linux-4.04.tar.gz && - tar -xvf xpdf-tools-linux-4.04.tar.gz && sudo cp xpdf-tools-linux-4.04/bin64/pdftotext /usr/local/bin - - Installation on MacOS: - brew install xpdf - - You can find more details here: https://www.xpdfreader.com - """ - ) - - self.encoding = encoding - self.keep_physical_layout = keep_physical_layout - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, Any]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - start_page: Optional[int] = None, - end_page: Optional[int] = None, - ) -> List[Document]: - """ - Extract text from a .pdf file using the pdftotext library (https://www.xpdfreader.com/pdftotext-man.html) - - :param file_path: Path to the .pdf file you want to convert - :param meta: Optional dictionary with metadata that shall be attached to all resulting documents. - Can be any custom keys and values. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Encoding that overwrites self.encoding and will be passed as `-enc` parameter to `pdftotext`. - (See list of available encodings by running `pdftotext -listenc` in the terminal) - :param keep_physical_layout: This option will maintain original physical layout on the extracted text. - It works by passing the `-layout` parameter to `pdftotext`. When disabled, PDF is read in the stream order. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param start_page: The page number where to start the conversion - :param end_page: The page number where to end the conversion. - """ - if remove_numeric_tables is None: - remove_numeric_tables = self.remove_numeric_tables - if valid_languages is None: - valid_languages = self.valid_languages - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - keep_physical_layout = self.keep_physical_layout - - pages = self._read_pdf( - file_path, layout=keep_physical_layout, encoding=encoding, start_page=start_page, end_page=end_page - ) - - cleaned_pages = [] - for page in pages: - # pdftotext tool provides an option to retain the original physical layout of a PDF page. This behaviour - # can be toggled by using the layout param. - # layout=True - # + table structures get retained better - # - multi-column pages(eg, research papers) gets extracted with text from multiple columns on same line - # layout=False - # + keeps strings in content stream order, hence multi column layout works well - # - cells of tables gets split across line - # - # Here, as a "safe" default, layout is turned off. - lines = page.splitlines() - cleaned_lines = [] - for line in lines: - words = line.split() - digits = [word for word in words if any(i.isdigit() for i in word)] - - # remove lines having > 40% of words as digits AND not ending with a period(.) - if ( - remove_numeric_tables - and words - and len(digits) / len(words) > 0.4 - and not line.strip().endswith(".") - ): - logger.debug("Removing line '%s' from %s", line, file_path) - continue - cleaned_lines.append(line) - - page = "\n".join(cleaned_lines) - cleaned_pages.append(page) - - if valid_languages: - document_text = "".join(cleaned_pages) - if not self.validate_language(document_text, valid_languages): - logger.warning( - "The language for %s is not one of %s. The file may not have " - "been decoded in the correct text format.", - file_path, - valid_languages, - ) - - text = "\f".join(cleaned_pages) - document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys) - return [document] - - def _read_pdf( - self, - file_path: Path, - layout: bool, - encoding: Optional[str] = None, - start_page: Optional[int] = None, - end_page: Optional[int] = None, - ) -> List[str]: - """ - Extract pages from the pdf file at file_path. - - :param file_path: path of the pdf file - :param layout: whether to retain the original physical layout for a page. If disabled, PDF pages are read in - the content stream order. - :param encoding: Encoding that overwrites self.encoding and will be passed as `-enc` parameter to `pdftotext`. - (See list of available encodings by running `pdftotext -listenc` in the terminal) - :param start_page: The page number where to start the conversion - :param end_page: The page number where to end the conversion. - """ - if not encoding: - encoding = self.encoding - - start_page = start_page or 1 - - command = ["pdftotext", "-enc", str(encoding), "-layout" if layout else "-raw", "-f", str(start_page)] - - if end_page is not None: - command.extend(["-l", str(end_page)]) - - command.extend([str(file_path), "-"]) - - output = subprocess.run(command, stdout=subprocess.PIPE, shell=False, check=False) - document = output.stdout.decode(errors="ignore") - document = "\f" * (start_page - 1) + document # tracking skipped pages for correct page numbering - pages = document.split("\f") - pages = pages[:-1] # the last page in the split is always empty. - - return pages diff --git a/haystack/nodes/file_converter/pptx.py b/haystack/nodes/file_converter/pptx.py deleted file mode 100644 index 84fe46b1d2..0000000000 --- a/haystack/nodes/file_converter/pptx.py +++ /dev/null @@ -1,85 +0,0 @@ -from typing import List, Optional, Dict -from pathlib import Path -import logging - -from haystack.schema import Document -from haystack.lazy_imports import LazyImport -from haystack.nodes.file_converter.base import BaseConverter - - -logger = logging.getLogger(__name__) - - -with LazyImport("Run 'pip install python-pptx'") as pptx_import: - from pptx import Presentation - - -class PptxConverter(BaseConverter): - def __init__( - self, - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - progress_bar: bool = True, - ): - pptx_import.check() - super().__init__( - remove_numeric_tables=remove_numeric_tables, - valid_languages=valid_languages, - id_hash_keys=id_hash_keys, - progress_bar=progress_bar, - ) - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, str]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Extract text from a .pptx file. - Note: As pptx doesn't contain "page" information, we actually extract and return a list of texts from each slide here. - For compliance with other converters we nevertheless opted for keeping the methods name. - - :param file_path: Path to the .pptx file you want to convert - :param meta: dictionary of meta data key-value pairs to append in the returned document. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Not applicable - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - """ - if remove_numeric_tables is None: - remove_numeric_tables = self.remove_numeric_tables - if valid_languages is None: - valid_languages = self.valid_languages - if remove_numeric_tables is True: - raise Exception("'remove_numeric_tables' is not supported by PptxToTextConverter.") - if valid_languages is True: - raise Exception("Language validation using 'valid_languages' is not supported by PptxToTextConverter.") - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - pres = Presentation(file_path) - text_parts = [] - for slide in pres.slides: - for shape in slide.shapes: - if hasattr(shape, "text"): - text_parts.append(shape.text) - text = "\n".join(text_parts) - - document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys) - return [document] diff --git a/haystack/nodes/file_converter/tika.py b/haystack/nodes/file_converter/tika.py deleted file mode 100644 index 46ff729c85..0000000000 --- a/haystack/nodes/file_converter/tika.py +++ /dev/null @@ -1,198 +0,0 @@ -from typing import List, Optional, Dict, Union, Tuple - -import time -import logging -from pathlib import Path -import subprocess -from html.parser import HTMLParser - -import requests - -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport("Run 'pip install farm-haystack[file-conversion]' or 'pip install tika'") as tika_import: - from tika import parser as tika_parser - - -TIKA_CONTAINER_NAME = "tika" - - -def launch_tika(sleep=15, delete_existing=False): - tika_import.check() - # Start a Tika server via Docker - - logger.debug("Starting Tika ...") - # This line is needed since it is not possible to start a new docker container with the name tika if there is a stopped image with the same name - # docker rm only succeeds if the container is stopped, not if it is running - if delete_existing: - _ = subprocess.run([f"docker rm --force {TIKA_CONTAINER_NAME}"], shell=True, stdout=subprocess.DEVNULL) - status = subprocess.run( - [ - f"docker start {TIKA_CONTAINER_NAME} > /dev/null 2>&1 || docker run -p 9998:9998 --name {TIKA_CONTAINER_NAME} apache/tika:1.28.4" - ], - shell=True, - ) - if status.returncode: - logger.warning( - "Tried to start Tika through Docker but this failed. " - "It is likely that there is already an existing Tika instance running. " - ) - else: - time.sleep(sleep) - - -class TikaXHTMLParser(HTMLParser): - # Use the built-in HTML parser with minimum dependencies - def __init__(self): - tika_import.check() - self.ingest = True - self.page = "" - self.pages: List[str] = [] - super(TikaXHTMLParser, self).__init__() - - def handle_starttag(self, tag, attrs): - # find page div - pagediv = [value for attr, value in attrs if attr == "class" and value == "page"] - if tag == "div" and pagediv: - self.ingest = True - - def handle_endtag(self, tag): - # close page div, or a single page without page div, save page and open a new page - if (tag == "div" or tag == "body") and self.ingest: - self.ingest = False - # restore words hyphened to the next line - self.pages.append(self.page.replace("-\n", "")) - self.page = "" - - def handle_data(self, data): - if self.ingest: - self.page += data - - -class TikaConverter(BaseConverter): - def __init__( - self, - tika_url: str = "http://localhost:9998/tika", - remove_numeric_tables: bool = False, - valid_languages: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - timeout: Union[float, Tuple[float, float]] = 10.0, - ): - """ - :param tika_url: URL of the Tika server - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param timeout: How many seconds to wait for the server to send data before giving up, - as a float, or a :ref:`(connect timeout, read timeout) ` tuple. - Defaults to 10 seconds. - """ - tika_import.check() - super().__init__( - remove_numeric_tables=remove_numeric_tables, valid_languages=valid_languages, id_hash_keys=id_hash_keys - ) - - ping = requests.get(tika_url, timeout=timeout) - if ping.status_code != 200: - raise Exception( - f"Apache Tika server is not reachable at the URL '{tika_url}'. To run it locally" - f"with Docker, execute: 'docker run -p 9998:9998 apache/tika:1.28.4'" - ) - self.tika_url = tika_url - super().__init__(remove_numeric_tables=remove_numeric_tables, valid_languages=valid_languages) - - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, str]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - :param file_path: path of the file to convert - :param meta: dictionary of meta data key-value pairs to append in the returned document. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Not applicable - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - - :return: A list of pages and the extracted meta data of the file. - """ - if remove_numeric_tables is None: - remove_numeric_tables = self.remove_numeric_tables - if valid_languages is None: - valid_languages = self.valid_languages - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - parsed = tika_parser.from_file(file_path.as_posix(), self.tika_url, xmlContent=True) - parser = TikaXHTMLParser() - parser.feed(parsed["content"]) - - cleaned_pages = [] - # TODO investigate title of document appearing in the first extracted page - for page in parser.pages: - lines = page.splitlines() - cleaned_lines = [] - for line in lines: - words = line.split() - digits = [word for word in words if any(i.isdigit() for i in word)] - - # remove lines having > 40% of words as digits AND not ending with a period(.) - if ( - remove_numeric_tables - and words - and len(digits) / len(words) > 0.4 - and not line.strip().endswith(".") - ): - logger.debug("Removing line '%s' from %s", line, file_path) - continue - - cleaned_lines.append(line) - - page = "\n".join(cleaned_lines) - cleaned_pages.append(page) - - if valid_languages: - document_text = "".join(cleaned_pages) - if not self.validate_language(document_text, valid_languages): - logger.warning( - "The language for %s is not one of %s. The file may not have " - "been decoded in the correct text format.", - file_path, - valid_languages, - ) - - text = "\f".join(cleaned_pages) - document = Document(content=text, meta={**parsed["metadata"], **(meta or {})}, id_hash_keys=id_hash_keys) - return [document] diff --git a/haystack/nodes/file_converter/txt.py b/haystack/nodes/file_converter/txt.py deleted file mode 100644 index 0a2cd8d87e..0000000000 --- a/haystack/nodes/file_converter/txt.py +++ /dev/null @@ -1,90 +0,0 @@ -from typing import List, Optional, Dict - -import logging -from pathlib import Path -from haystack.nodes.file_converter.base import BaseConverter -from haystack.schema import Document - - -logger = logging.getLogger(__name__) - - -class TextConverter(BaseConverter): - def convert( - self, - file_path: Path, - meta: Optional[Dict[str, str]] = None, - remove_numeric_tables: Optional[bool] = None, - valid_languages: Optional[List[str]] = None, - encoding: Optional[str] = "utf-8", - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Reads text from a txt file and executes optional preprocessing steps. - - :param file_path: path of the file to convert - :param meta: dictionary of meta data key-value pairs to append in the returned document. - :param remove_numeric_tables: This option uses heuristics to remove numeric rows from the tables. - The tabular structures in documents might be noise for the reader model if it - does not have table parsing capability for finding answers. However, tables - may also have long strings that could possible candidate for searching answers. - The rows containing strings are thus retained in this option. - :param valid_languages: validate languages from a list of languages specified in the ISO 639-1 - (https://en.wikipedia.org/wiki/ISO_639-1) format. - This option can be used to add test for encoding errors. If the extracted text is - not one of the valid languages, then it might likely be encoding error resulting - in garbled text. - :param encoding: Select the file encoding (default is `utf-8`) - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - - """ - if remove_numeric_tables is None: - remove_numeric_tables = self.remove_numeric_tables - if valid_languages is None: - valid_languages = self.valid_languages - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - with open(file_path, encoding=encoding, errors="ignore") as f: - text = f.read() - pages = text.split("\f") - - cleaned_pages = [] - for page in pages: - lines = page.splitlines() - cleaned_lines = [] - for line in lines: - words = line.split() - digits = [word for word in words if any(i.isdigit() for i in word)] - - # remove lines having > 40% of words as digits AND not ending with a period(.) - if ( - remove_numeric_tables - and words - and len(digits) / len(words) > 0.4 - and not line.strip().endswith(".") - ): - logger.debug("Removing line '%s' from %s", line, file_path) - continue - - cleaned_lines.append(line) - - page = "\n".join(cleaned_lines) - cleaned_pages.append(page) - - if valid_languages: - document_text = "".join(cleaned_pages) - if not self.validate_language(document_text, valid_languages): - logger.warning( - "The language for %s is not one of %s. The file may not have " - "been decoded in the correct text format.", - file_path, - valid_languages, - ) - - text = "".join(cleaned_pages) - document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys) - return [document] diff --git a/haystack/nodes/image_to_text/__init__.py b/haystack/nodes/image_to_text/__init__.py deleted file mode 100644 index 44a8bb419c..0000000000 --- a/haystack/nodes/image_to_text/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.image_to_text.base import BaseImageToText -from haystack.nodes.image_to_text.transformers import TransformersImageToText diff --git a/haystack/nodes/image_to_text/base.py b/haystack/nodes/image_to_text/base.py deleted file mode 100644 index 466fddfc65..0000000000 --- a/haystack/nodes/image_to_text/base.py +++ /dev/null @@ -1,59 +0,0 @@ -from typing import List, Optional - -from abc import abstractmethod - -from haystack.schema import Document -from haystack.nodes.base import BaseComponent - - -class BaseImageToText(BaseComponent): - """ - Abstract class for ImageToText. - """ - - outgoing_edges = 1 - - @abstractmethod - def generate_captions( - self, image_file_paths: List[str], generation_kwargs: Optional[dict] = None, batch_size: Optional[int] = None - ) -> List[Document]: - """ - Abstract method for generating captions. - - :param image_file_paths: Paths to the images for which you want to generate captions. - :param generation_kwargs: Dictionary containing arguments for the `generate()` method of the Hugging Face model. - See [generate()](https://huggingface.co/docs/transformers/en/main_classes/text_generation#transformers.GenerationMixin.generate) on Hugging Face. - :param batch_size: Number of images to process at a time. - :return: List of Documents. `Document.content` is the caption. `Document.meta["image_file_path"]` contains the path to the image file. - """ - pass - - def run(self, file_paths: Optional[List[str]] = None, documents: Optional[List[Document]] = None): # type: ignore - """ - :param file_paths: Paths to the images for which you want to generate captions. - :param documents: List of image Documents to process into text. - """ - if file_paths is None and documents is None: - raise ValueError("You must either specify documents or image file_paths to process.") - - image_file_paths = [] - if file_paths is not None: - image_file_paths.extend(file_paths) - if documents is not None: - if any((doc.content_type != "image" for doc in documents)): - raise ValueError("The ImageToText node only supports image documents.") - image_file_paths.extend([doc.content for doc in documents]) - - results: dict = {} - results["documents"] = self.generate_captions(image_file_paths=image_file_paths) - - return results, "output_1" - - def run_batch( # type: ignore - self, file_paths: Optional[List[str]] = None, documents: Optional[List[Document]] = None - ): - """ - :param file_paths: Paths to the images for which you want to generate captions. - :param documents: List of image Documents to process into text. - """ - return self.run(file_paths=file_paths, documents=documents) diff --git a/haystack/nodes/image_to_text/transformers.py b/haystack/nodes/image_to_text/transformers.py deleted file mode 100644 index 8dfadc3620..0000000000 --- a/haystack/nodes/image_to_text/transformers.py +++ /dev/null @@ -1,187 +0,0 @@ -from typing import List, Optional, Union - -import logging - -from tqdm import tqdm - -from haystack.schema import Document -from haystack.nodes.image_to_text.base import BaseImageToText -from haystack.errors import ImageToTextError -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import pipeline - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - from haystack.utils.torch_utils import ListDataset - - -# supported models classes should be extended when HF image-to-text pipeline will support more classes -# see https://github.com/huggingface/transformers/issues/21110 -SUPPORTED_MODELS_CLASSES = [ - "VisionEncoderDecoderModel", - "BlipForConditionalGeneration", - "Blip2ForConditionalGeneration", -] - -UNSUPPORTED_MODEL_MESSAGE = ( - f"The supported classes are: {SUPPORTED_MODELS_CLASSES}. \n" - f"To find the supported models: \n" - f"1. Visit [image-to-text models on Hugging Face](https://huggingface.co/models?pipeline_tag=image-to-text). \n" - f"2. Open a model you want to check. \n" - f'3. On the model page, go to the "Files and Versions" tab \n' - f"4. Open the `config.json` file, and make sure the `architectures` field contains one of the supported classes: {SUPPORTED_MODELS_CLASSES}." -) - - -class TransformersImageToText(BaseImageToText): - """ - A transformer-based model to generate captions for images using the Hugging Face's transformers framework. - - **Example** - - ```python - image_file_paths = ["/path/to/images/apple.jpg", - "/path/to/images/cat.jpg", ] - - # Generate captions - documents = image_to_text.generate_captions(image_file_paths=image_file_paths) - - # Show results (List of Documents, containing caption and image file_path) - print(documents) - - [ - { - "content": "a red apple is sitting on a pile of hay", - ... - "meta": { - "image_path": "/path/to/images/apple.jpg", - ... - }, - ... - }, - ... - ] - ``` - """ - - def __init__( - self, - model_name_or_path: str = "Salesforce/blip-image-captioning-base", - model_version: Optional[str] = None, - generation_kwargs: Optional[dict] = None, - use_gpu: bool = True, - batch_size: int = 16, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Load an Image-to-Text model from transformers. - - :param model_name_or_path: Directory of a saved model or the name of a public model. - To find these models: - 1. Visit [Hugging Face image to text models](https://huggingface.co/models?pipeline_tag=image-to-text).` - 2. Open the model you want to check. - 3. On the model page, go to the "Files and Versions" tab. - 4. Open the `config.json` file and make sure the `architectures` field contains `VisionEncoderDecoderModel`, `BlipForConditionalGeneration`, or `Blip2ForConditionalGeneration`. - :param model_version: The version of the model to use from the Hugging Face model hub. This can be the tag name, branch name, or commit hash. - :param generation_kwargs: Dictionary containing arguments for the `generate()` method of the Hugging Face model. - See [generate()](https://huggingface.co/docs/transformers/en/main_classes/text_generation#transformers.GenerationMixin.generate) in Hugging Face documentation. - :param use_gpu: Whether to use GPU (if available). - :param batch_size: Number of documents to process at a time. - :param progress_bar: Whether to show a progress bar. - :param use_auth_token: The API token used to download private models from Hugging Face. - If set to `True`, the token generated when running - `transformers-cli login` (stored in ~/.huggingface) is used. - For more information, see [from_pretrained()](https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained) in Hugging Face documentation. - :param devices: List of torch devices (for example, cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects or strings is supported (for example - [torch.device('cuda:0'), "mps", "cuda:1"]). If you set `use_gpu=False`, the devices - parameter is not used and a single CPU device is used for inference. - """ - torch_and_transformers_import.check() - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - try: - self.model = pipeline( - task="image-to-text", - model=model_name_or_path, - revision=model_version, - device=self.devices[0], - use_auth_token=use_auth_token, - ) - except KeyError as err: - raise ValueError( - f"The model '{model_name_or_path}' is not supported for ImageToText. " f"{UNSUPPORTED_MODEL_MESSAGE}" - ) from err - - # for some unsupported models, initializing the HF pipeline doesn't raise errors but does not work - model_class_name = self.model.model.__class__.__name__ - if model_class_name not in SUPPORTED_MODELS_CLASSES: - raise ValueError( - f"The model '{model_name_or_path}' (class '{model_class_name}') is not supported for ImageToText. " - f"{UNSUPPORTED_MODEL_MESSAGE}" - ) - - self.generation_kwargs = generation_kwargs - self.batch_size = batch_size - self.progress_bar = progress_bar - - def generate_captions( - self, image_file_paths: List[str], generation_kwargs: Optional[dict] = None, batch_size: Optional[int] = None - ) -> List[Document]: - """ - Generate captions for the image files you specify. - - :param image_file_paths: Paths to the images for which you want to generate captions. - :param generation_kwargs: Dictionary containing arguments for the generate method of the Hugging Face model. - See [generate()](https://huggingface.co/docs/transformers/en/main_classes/text_generation#transformers.GenerationMixin.generate) in Hugging Face documentation. - :param batch_size: Number of images to process at a time. - :return: List of Documents. `Document.content` is the caption. `Document.meta["image_file_path"]` contains the path to the image file. - """ - generation_kwargs = generation_kwargs or self.generation_kwargs - batch_size = batch_size or self.batch_size - - if len(image_file_paths) == 0: - raise ImageToTextError("ImageToText needs at least one file path to produce a caption.") - - if type(image_file_paths) is not list: - raise ImageToTextError( - "Expected List[str] for image_file_paths, got %s instead" % str(type(image_file_paths)) - ) - - images_dataset = ListDataset(image_file_paths) - - captions: List[str] = [] - - try: - for captions_batch in tqdm( - self.model(images_dataset, generate_kwargs=generation_kwargs, batch_size=batch_size), - disable=not self.progress_bar, - total=len(images_dataset), - desc="Generating captions", - ): - captions.append("".join([el["generated_text"] for el in captions_batch]).strip()) - - except Exception as exc: - raise ImageToTextError(str(exc)) from exc - - result: List[Document] = [] - for caption, image_file_path in zip(captions, image_file_paths): - document = Document(content=caption, content_type="text", meta={"image_path": image_file_path}) - result.append(document) - - return result diff --git a/haystack/nodes/label_generator/__init__.py b/haystack/nodes/label_generator/__init__.py deleted file mode 100644 index 53ec567c4c..0000000000 --- a/haystack/nodes/label_generator/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.nodes.label_generator.pseudo_label_generator import PseudoLabelGenerator diff --git a/haystack/nodes/label_generator/pseudo_label_generator.py b/haystack/nodes/label_generator/pseudo_label_generator.py deleted file mode 100644 index 510acea222..0000000000 --- a/haystack/nodes/label_generator/pseudo_label_generator.py +++ /dev/null @@ -1,292 +0,0 @@ -import logging -import random -from typing import Dict, Iterable, List, Optional, Tuple, Union - -from tqdm import tqdm - -from haystack.nodes.base import BaseComponent -from haystack.nodes.question_generator import QuestionGenerator -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from sentence_transformers import CrossEncoder - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class PseudoLabelGenerator(BaseComponent): - """ - PseudoLabelGenerator is a component that creates Generative Pseudo Labeling (GPL) training data for the - training of dense retrievers. - - GPL is an unsupervised domain adaptation method for the training of dense retrievers. It is based on question - generation and pseudo labelling with powerful cross-encoders. To train a domain-adapted model, it needs access - to an unlabeled target corpus, usually through DocumentStore and a Retriever to mine for negatives. - - For more details, see [GPL](https://github.com/UKPLab/gpl). - - For example: - - ```python - document_store = ElasticsearchDocumentStore(...) - retriever = BM25Retriever(...) - qg = QuestionGenerator(model_name_or_path="doc2query/msmarco-t5-base-v1") - plg = PseudoLabelGenerator(qg, retriever) - output, output_id = psg.run(documents=document_store.get_all_documents()) - ``` - - Note: - - While the NLP researchers trained the default question - [generation](https://huggingface.co/doc2query/msmarco-t5-base-v1) and the cross - [encoder](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L-6-v2) models on - the English language corpus, we can also use the language-specific question generation and - cross-encoder models in the target language of our choice to apply GPL to documents in languages - other than English. - - As of this writing, the German language question - [generation](https://huggingface.co/ml6team/mt5-small-german-query-generation) and the cross - [encoder](https://huggingface.co/ml6team/cross-encoder-mmarco-german-distilbert-base) models are - already available, as well as question [generation](https://huggingface.co/doc2query/msmarco-14langs-mt5-base-v1) - and the cross [encoder](https://huggingface.co/cross-encoder/mmarco-mMiniLMv2-L12-H384-v1) - models trained on fourteen languages. - - - """ - - outgoing_edges: int = 1 - - def __init__( - self, - question_producer: Union[QuestionGenerator, List[Dict[str, str]]], - retriever, - cross_encoder_model_name_or_path: str = "cross-encoder/ms-marco-MiniLM-L-6-v2", - max_questions_per_document: int = 3, - top_k: int = 50, - batch_size: int = 16, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - use_gpu: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Loads the cross-encoder model and prepares PseudoLabelGenerator. - - :param question_producer: The question producer used to generate questions or a list of already produced - questions/document pairs in a Dictionary format {"question": "question text ...", "document": "document text ..."}. - :type question_producer: Union[QuestionGenerator, List[Dict[str, str]]] - :param retriever: The Retriever used to query document stores. - :type retriever: BaseRetriever - :param cross_encoder_model_name_or_path: The path to the cross encoder model, defaults to - `cross-encoder/ms-marco-MiniLM-L-6-v2`. - :type cross_encoder_model_name_or_path: str (optional) - :param max_questions_per_document: The max number of questions generated per document, defaults to 3. - :type max_questions_per_document: int - :param top_k: The number of answers retrieved for each question, defaults to 50. - :type top_k: int (optional) - :param batch_size: The number of documents to process at a time. - :type batch_size: int (optional) - :param progress_bar: Whether to show a progress bar, defaults to True. - :type progress_bar: bool (optional) - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :type use_auth_token: Union[str, bool] (optional) - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit CrossEncoder inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - """ - torch_and_transformers_import.check() - super().__init__() - self.question_document_pairs = None - self.question_generator = None # type: ignore - if isinstance(question_producer, QuestionGenerator): - self.question_generator = question_producer - elif isinstance(question_producer, list) and len(question_producer) > 0: - example = question_producer[0] - if isinstance(example, dict) and "question" in example and "document" in example: - self.question_document_pairs = question_producer - else: - raise ValueError( - "The question_producer list must contain dictionaries with keys 'question' and 'document'." - ) - else: - raise ValueError("Provide either a QuestionGenerator or a non-empty list of questions/document pairs.") - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - self.retriever = retriever - - self.cross_encoder = CrossEncoder( - cross_encoder_model_name_or_path, - device=str(self.devices[0]), - tokenizer_args={"use_auth_token": use_auth_token}, - automodel_args={"use_auth_token": use_auth_token}, - ) - self.max_questions_per_document = max_questions_per_document - self.top_k = top_k - self.batch_size = batch_size - self.progress_bar = progress_bar - - def generate_questions(self, documents: List[Document], batch_size: Optional[int] = None) -> List[Dict[str, str]]: - """ - It takes a list of documents and generates a list of question-document pairs. - - :param documents: A list of documents to generate questions from. - :type documents: List[Document] - :param batch_size: The number of documents to process at a time. - :type batch_size: Optional[int] - :return: A list of question-document pairs. - """ - question_doc_pairs: List[Dict[str, str]] = [] - if self.question_document_pairs: - question_doc_pairs = self.question_document_pairs - else: - batch_size = batch_size if batch_size else self.batch_size - questions: List[List[str]] = self.question_generator.generate_batch( # type: ignore - [d.content for d in documents], batch_size=batch_size - ) - for idx, question_list_per_doc in enumerate(questions): - for q in question_list_per_doc[: self.max_questions_per_document]: # type: ignore - question_doc_pairs.append({"question": q.strip(), "document": documents[idx].content}) - return question_doc_pairs - - def mine_negatives( - self, question_doc_pairs: List[Dict[str, str]], batch_size: Optional[int] = None - ) -> List[Dict[str, str]]: - """ - Given a list of question and positive document pairs, this function returns a list of question/positive document/negative document - dictionaries. - - :param question_doc_pairs: A list of question/positive document pairs. - :type question_doc_pairs: List[Dict[str, str]] - :param batch_size: The number of queries to run in a batch. - :type batch_size: int (optional) - :return: A list of dictionaries, where each dictionary contains the question, positive document, - and negative document. - """ - question_pos_doc_neg_doc: List[Dict[str, str]] = [] - batch_size = batch_size if batch_size else self.batch_size - - for i in tqdm( - range(0, len(question_doc_pairs), batch_size), disable=not self.progress_bar, desc="Mine negatives" - ): - # question in batches to minimize network latency - i_end = min(i + batch_size, len(question_doc_pairs)) - queries: List[str] = [e["question"] for e in question_doc_pairs[i:i_end]] - pos_docs: List[str] = [e["document"] for e in question_doc_pairs[i:i_end]] - - docs: List[List[Document]] = self.retriever.retrieve_batch( - queries=queries, top_k=self.top_k, batch_size=batch_size - ) - - # iterate through queries and find negatives - for question, pos_doc, top_docs in zip(queries, pos_docs, docs): - random.shuffle(top_docs) - for doc_item in top_docs: - neg_doc = doc_item.content - if neg_doc != pos_doc: - question_pos_doc_neg_doc.append({"question": question, "pos_doc": pos_doc, "neg_doc": neg_doc}) - break - return question_pos_doc_neg_doc - - def generate_margin_scores( - self, mined_negatives: List[Dict[str, str]], batch_size: Optional[int] = None - ) -> List[Dict]: - """ - Given a list of mined negatives, this function predicts the score margin between the positive and negative document using - the cross-encoder. - - The function returns a list of examples, where each example is a dictionary with the following keys: - - * question: The question string. - * pos_doc: Positive document string (the document containing the answer). - * neg_doc: Negative document string (the document that doesn't contain the answer). - * score: The margin between the score for question-positive document pair and the score for question-negative document pair. - - :param mined_negatives: The list of mined negatives. - :type mined_negatives: List[Dict[str, str]] - :param batch_size: The number of mined negative lists to run in a batch. - :type batch_size: int (optional) - :return: A list of dictionaries, each of which has the following keys: - - question: The question string - - pos_doc: Positive document string - - neg_doc: Negative document string - - score: The score margin - """ - examples: List[Dict] = [] - batch_size = batch_size if batch_size else self.batch_size - for i in tqdm(range(0, len(mined_negatives), batch_size), disable=not self.progress_bar, desc="Score margin"): - negatives_batch = mined_negatives[i : i + batch_size] - pb = [] - for item in negatives_batch: - pb.append([item["question"], item["pos_doc"]]) - pb.append([item["question"], item["neg_doc"]]) - scores = self.cross_encoder.predict(pb) - for idx, item in enumerate(negatives_batch): - scores_idx = idx * 2 - score_margin = scores[scores_idx] - scores[scores_idx + 1] - examples.append( - { - "question": item["question"], - "pos_doc": item["pos_doc"], - "neg_doc": item["neg_doc"], - "score": score_margin, - } - ) - return examples - - def generate_pseudo_labels(self, documents: List[Document], batch_size: Optional[int] = None) -> Tuple[dict, str]: - """ - Given a list of documents, this function generates a list of question-document pairs, mines for negatives, and - scores a positive/negative margin with cross-encoder. The output is the training data for the - adaptation of dense retriever models. - - :param documents: List[Document] = The list of documents to mine negatives from. - :type documents: List[Document] - :param batch_size: The number of documents to process in a batch. - :type batch_size: Optional[int] - :return: A dictionary with a single key 'gpl_labels' representing a list of dictionaries, where each - dictionary contains the following keys: - - question: The question string. - - pos_doc: Positive document for the given question. - - neg_doc: Negative document for the given question. - - score: The margin between the score for question-positive document pair and the score for question-negative document pair. - """ - # see https://github.com/UKPLab/gpl for more information about GPL algorithm - batch_size = batch_size if batch_size else self.batch_size - - # step 1: generate questions - question_doc_pairs = self.generate_questions(documents=documents, batch_size=batch_size) - - # step 2: negative mining - mined_negatives = self.mine_negatives(question_doc_pairs=question_doc_pairs, batch_size=batch_size) - - # step 3: pseudo labeling (scoring) with cross-encoder - pseudo_labels: List[Dict[str, str]] = self.generate_margin_scores(mined_negatives, batch_size=batch_size) - return {"gpl_labels": pseudo_labels}, "output_1" - - def run(self, documents: List[Document]) -> Tuple[dict, str]: # type: ignore - return self.generate_pseudo_labels(documents=documents) - - def run_batch(self, documents: Union[List[Document], List[List[Document]]]) -> Tuple[dict, str]: # type: ignore - flat_list_of_documents = [] - for sub_list_documents in documents: - if isinstance(sub_list_documents, Iterable): - flat_list_of_documents += sub_list_documents - else: - flat_list_of_documents.append(sub_list_documents) - return self.generate_pseudo_labels(documents=flat_list_of_documents) diff --git a/haystack/nodes/other/__init__.py b/haystack/nodes/other/__init__.py deleted file mode 100644 index a92291f4ed..0000000000 --- a/haystack/nodes/other/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from haystack.nodes.other.docs2answers import Docs2Answers -from haystack.nodes.other.join_docs import JoinDocuments -from haystack.nodes.other.route_documents import RouteDocuments -from haystack.nodes.other.join_answers import JoinAnswers -from haystack.nodes.other.join import JoinNode -from haystack.nodes.other.document_merger import DocumentMerger -from haystack.nodes.other.shaper import Shaper diff --git a/haystack/nodes/other/docs2answers.py b/haystack/nodes/other/docs2answers.py deleted file mode 100644 index 3fe2acdf15..0000000000 --- a/haystack/nodes/other/docs2answers.py +++ /dev/null @@ -1,80 +0,0 @@ -from typing import List, Union, Dict - -from tqdm import tqdm - -from haystack.errors import HaystackError -from haystack.schema import Document, Answer, Span -from haystack.nodes.base import BaseComponent - - -class Docs2Answers(BaseComponent): - """ - This Node is used to convert retrieved documents into predicted answers format. - It is useful for situations where you are calling a Retriever only pipeline via REST API. - This ensures that your output is in a compatible format. - - :param progress_bar: Whether to show a progress bar - """ - - outgoing_edges = 1 - - def __init__(self, progress_bar: bool = True): - super().__init__() - self.progress_bar = progress_bar - - def run(self, query: str, documents: List[Document]): # type: ignore - # conversion from Document -> Answer - answers: List[Answer] = [] - for doc in documents: - cur_answer = self._convert_doc_to_answer(doc) - answers.append(cur_answer) - - output = {"query": query, "answers": answers} - - return output, "output_1" - - def run_batch(self, queries: List[str], documents: Union[List[Document], List[List[Document]]]): # type: ignore - output: Dict = {"queries": queries, "answers": []} - - # Docs case 1: single list of Documents - if len(documents) > 0 and isinstance(documents[0], Document): - for doc in tqdm(documents, disable=not self.progress_bar, desc="Converting to answers"): - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - answers = [self._convert_doc_to_answer(doc)] - output["answers"].append(answers) - - # Docs case 2: list of lists of Documents - elif len(documents) > 0 and isinstance(documents[0], list): - for docs in tqdm(documents, disable=not self.progress_bar, desc="Converting to answers"): - if not isinstance(docs, list): - raise HaystackError(f"docs was of type {type(docs)}, but expected a list of Documents.") - answers = [] - for doc in docs: - cur_answer = self._convert_doc_to_answer(doc) - answers.append(cur_answer) - output["answers"].append(answers) - - return output, "output_1" - - @staticmethod - def _convert_doc_to_answer(doc: Document) -> Answer: - # For FAQ style QA use cases - if "answer" in doc.meta: - doc.meta["query"] = doc.content # question from the existing FAQ - answer = Answer( - answer=doc.meta["answer"], - type="other", - score=doc.score, - context=doc.meta["answer"], - offsets_in_context=[Span(start=0, end=len(doc.meta["answer"]))], - document_ids=[doc.id], - meta=doc.meta, - ) - else: - # Regular docs - answer = Answer( - answer="", type="other", score=doc.score, context=doc.content, document_ids=[doc.id], meta=doc.meta - ) - - return answer diff --git a/haystack/nodes/other/document_merger.py b/haystack/nodes/other/document_merger.py deleted file mode 100644 index 72677fd368..0000000000 --- a/haystack/nodes/other/document_merger.py +++ /dev/null @@ -1,87 +0,0 @@ -import logging -from copy import deepcopy -from typing import Optional, List, Dict, Union, Any - -from haystack.schema import Document -from haystack.nodes.base import BaseComponent - -logger = logging.getLogger(__name__) - - -class DocumentMerger(BaseComponent): - """ - A node to merge the texts of the documents. - """ - - outgoing_edges = 1 - - def __init__(self, separator: str = " "): - """ - :param separator: The separator that appears between subsequent merged documents. - """ - super().__init__() - self.separator = separator - - def merge(self, documents: List[Document], separator: Optional[str] = None) -> List[Document]: - """ - Produce a list made up of a single document, which contains all the texts of the documents provided. - - :param separator: The separator that appears between subsequent merged documents. - :return: List of Documents - """ - if len(documents) == 0: - raise ValueError("Document Merger needs at least one document to merge.") - if not all(doc.content_type == "text" for doc in documents): - raise ValueError( - "Some of the documents provided are non-textual. Document Merger only works on textual documents." - ) - - separator = separator if separator is not None else self.separator - - merged_content = separator.join([doc.content for doc in documents]) - common_meta = self._keep_common_keys([doc.meta for doc in documents]) - - merged_document = Document(content=merged_content, meta=common_meta) - return [merged_document] - - def run(self, documents: List[Document], separator: Optional[str] = None): # type: ignore - results: Dict = {"documents": []} - if documents: - results["documents"] = self.merge(documents=documents, separator=separator) - return results, "output_1" - - def run_batch( # type: ignore - self, documents: Union[List[Document], List[List[Document]]], separator: Optional[str] = None - ): - is_doclist_flat = isinstance(documents[0], Document) - if is_doclist_flat: - flat_result: List[Document] = self.merge( - documents=[doc for doc in documents if isinstance(doc, Document)], separator=separator - ) - return {"documents": flat_result}, "output_1" - else: - nested_result: List[List[Document]] = [ - self.merge(documents=docs_lst, separator=separator) - for docs_lst in documents - if isinstance(docs_lst, list) - ] - return {"documents": nested_result}, "output_1" - - def _keep_common_keys(self, list_of_dicts: List[Dict[str, Any]]) -> dict: - merge_dictionary = deepcopy(list_of_dicts[0]) - for key, value in list_of_dicts[0].items(): - # if not all other dicts have this key, delete directly - if not all(key in dict.keys() for dict in list_of_dicts): - del merge_dictionary[key] - - # if they all have it and it's a dictionary, merge recursively - elif isinstance(value, dict): - # Get all the subkeys to merge in a new list - list_of_subdicts = [dictionary[key] for dictionary in list_of_dicts] - merge_dictionary[key] = self._keep_common_keys(list_of_subdicts) - - # If all dicts have this key and it's not a dictionary, delete only if the values differ - elif not all(value == dict[key] for dict in list_of_dicts): - del merge_dictionary[key] - - return merge_dictionary diff --git a/haystack/nodes/other/join.py b/haystack/nodes/other/join.py deleted file mode 100644 index d2809648ef..0000000000 --- a/haystack/nodes/other/join.py +++ /dev/null @@ -1,84 +0,0 @@ -from abc import abstractmethod -from typing import Optional, List, Tuple, Dict, Union, Any -import warnings - -from haystack import MultiLabel, Document, Answer -from haystack.nodes.base import BaseComponent - - -class JoinNode(BaseComponent): - outgoing_edges: int = 1 - - def run( # type: ignore - self, - inputs: Optional[List[dict]] = None, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - answers: Optional[List[Answer]] = None, - top_k_join: Optional[int] = None, - ) -> Tuple[Dict, str]: - if inputs: - results = self.run_accumulated(inputs, top_k_join=top_k_join) - if "root_node" in inputs[0]: - results[0]["root_node"] = inputs[0]["root_node"] - return results - warnings.warn("You are using a JoinNode with only one input. This is usually equivalent to a no-op.") - return self.run_accumulated( - inputs=[ - { - "query": query, - "file_paths": file_paths, - "labels": labels, - "documents": documents, - "meta": meta, - "answers": answers, - } - ], - top_k_join=top_k_join, - ) - - @abstractmethod - def run_accumulated(self, inputs: List[dict], top_k_join: Optional[int] = None) -> Tuple[Dict, str]: - pass - - def run_batch( # type: ignore - self, - inputs: Optional[List[dict]] = None, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - answers: Optional[List[Answer]] = None, - top_k_join: Optional[int] = None, - ) -> Tuple[Dict, str]: - if inputs: - results = self.run_batch_accumulated(inputs=inputs, top_k_join=top_k_join) - if "root_node" in inputs[0]: - results[0]["root_node"] = inputs[0]["root_node"] - return results - warnings.warn("You are using a JoinNode with only one input. This is usually equivalent to a no-op.") - return self.run_batch_accumulated( - inputs=[ - { - "queries": queries, - "file_paths": file_paths, - "labels": labels, - "documents": documents, - "meta": meta, - "params": params, - "debug": debug, - "answers": answers, - } - ], - top_k_join=top_k_join, - ) - - @abstractmethod - def run_batch_accumulated(self, inputs: List[dict], top_k_join: Optional[int] = None) -> Tuple[Dict, str]: - pass diff --git a/haystack/nodes/other/join_answers.py b/haystack/nodes/other/join_answers.py deleted file mode 100644 index ffabd3d55b..0000000000 --- a/haystack/nodes/other/join_answers.py +++ /dev/null @@ -1,91 +0,0 @@ -from typing import Optional, List, Dict, Tuple - -from haystack.schema import Answer -from haystack.nodes.other.join import JoinNode - - -class JoinAnswers(JoinNode): - """ - A node to join `Answer`s produced by multiple `Reader` nodes. - """ - - def __init__( - self, - join_mode: str = "concatenate", - weights: Optional[List[float]] = None, - top_k_join: Optional[int] = None, - sort_by_score: bool = True, - ): - """ - :param join_mode: `"concatenate"` to combine documents from multiple `Reader`s. `"merge"` to aggregate scores - of individual `Answer`s. - :param weights: A node-wise list (length of list must be equal to the number of input nodes) of weights for - adjusting `Answer` scores when using the `"merge"` join_mode. By default, equal weight is assigned to each - `Reader` score. This parameter is not compatible with the `"concatenate"` join_mode. - :param top_k_join: Limit `Answer`s to top_k based on the resulting scored of the join. - :param sort_by_score: Whether to sort the incoming answers by their score. Set this to True if your Answers - are coming from a Reader or TableReader. Set to False if any Answers come from a Generator since this assigns - None as a score to each. - """ - - assert join_mode in ["concatenate", "merge"], f"JoinAnswers node does not support '{join_mode}' join_mode." - assert not ( - weights is not None and join_mode == "concatenate" - ), "Weights are not compatible with 'concatenate' join_mode" - - super().__init__() - - self.join_mode = join_mode - self.weights = [float(i) / sum(weights) for i in weights] if weights else None - self.top_k_join = top_k_join - self.sort_by_score = sort_by_score - - def run_accumulated(self, inputs: List[Dict], top_k_join: Optional[int] = None) -> Tuple[Dict, str]: # type: ignore - reader_results = [inp["answers"] for inp in inputs] - - if not top_k_join: - top_k_join = self.top_k_join - - if self.join_mode == "concatenate": - concatenated_answers = [answer for cur_reader_result in reader_results for answer in cur_reader_result] - if self.sort_by_score: - concatenated_answers = sorted(concatenated_answers, reverse=True) - concatenated_answers = concatenated_answers[:top_k_join] - return {"answers": concatenated_answers, "labels": inputs[0].get("labels", None)}, "output_1" - - elif self.join_mode == "merge": - merged_answers = self._merge_answers(reader_results) - merged_answers = merged_answers[:top_k_join] - return {"answers": merged_answers, "labels": inputs[0].get("labels", None)}, "output_1" - - else: - raise ValueError(f"Invalid join_mode: {self.join_mode}") - - def run_batch_accumulated(self, inputs: List[Dict], top_k_join: Optional[int] = None) -> Tuple[Dict, str]: # type: ignore - output_ans = [] - incoming_edges = [inp["answers"] for inp in inputs] - # At each idx, we find predicted answers for the same query from different Readers - for idx in range(len(incoming_edges[0])): - cur_ans_to_join = [] - # Aggregate predicted answer from each Reader - for edge in incoming_edges: - cur_ans_to_join.append({"answers": edge[idx]}) - cur, _ = self.run(inputs=cur_ans_to_join, top_k_join=top_k_join) - output_ans.append(cur["answers"]) - - output = {"answers": output_ans, "labels": inputs[0].get("labels", None)} - - return output, "output_1" - - def _merge_answers(self, reader_results: List[List[Answer]]) -> List[Answer]: - weights = self.weights if self.weights else [1 / len(reader_results)] * len(reader_results) - - for result, weight in zip(reader_results, weights): - for answer in result: - if isinstance(answer.score, float): - answer.score *= weight - merged_answers = [answer for cur_reader_result in reader_results for answer in cur_reader_result] - if self.sort_by_score: - merged_answers = sorted(merged_answers, reverse=True) - - return sorted([answer for cur_reader_result in reader_results for answer in cur_reader_result], reverse=True) diff --git a/haystack/nodes/other/join_docs.py b/haystack/nodes/other/join_docs.py deleted file mode 100644 index 274e90a38d..0000000000 --- a/haystack/nodes/other/join_docs.py +++ /dev/null @@ -1,162 +0,0 @@ -import logging -from collections import defaultdict -from math import inf -from typing import List, Optional - -from haystack.nodes.other.join import JoinNode -from haystack.schema import Document - -logger = logging.getLogger(__name__) - - -class JoinDocuments(JoinNode): - """ - A node to join documents outputted by multiple retriever nodes. - - The node allows multiple join modes: - * concatenate: combine the documents from multiple nodes. - In case of duplicate documents, the one with the highest score is kept. - * merge: merge scores of documents from multiple nodes. Optionally, each input score can be given a different - `weight` & a `top_k` limit can be set. This mode can also be used for "reranking" retrieved documents. - * reciprocal_rank_fusion: combines the documents based on their rank in multiple nodes. - """ - - outgoing_edges = 1 - - def __init__( - self, - join_mode: str = "concatenate", - weights: Optional[List[float]] = None, - top_k_join: Optional[int] = None, - sort_by_score: bool = True, - ): - """ - :param join_mode: `concatenate` to combine documents from multiple retrievers `merge` to aggregate scores of - individual documents, `reciprocal_rank_fusion` to apply rank based scoring. - :param weights: A node-wise list(length of list must be equal to the number of input nodes) of weights for - adjusting document scores when using the `merge` join_mode. By default, equal weight is given - to each retriever score. This param is not compatible with the `concatenate` join_mode. - :param top_k_join: Limit documents to top_k based on the resulting scores of the join. - :param sort_by_score: Whether to sort the incoming documents by their score. Set this to True if all your - Documents are coming with `score` values. Set to False if any of the Documents come - from sources where the `score` is set to `None`, like `TfidfRetriever` on Elasticsearch. - """ - assert join_mode in [ - "concatenate", - "merge", - "reciprocal_rank_fusion", - ], f"JoinDocuments node does not support '{join_mode}' join_mode." - - assert not ( - weights is not None and join_mode == "concatenate" - ), "Weights are not compatible with 'concatenate' join_mode." - - super().__init__() - - self.join_mode = join_mode - self.weights = [float(i) / sum(weights) for i in weights] if weights else None - self.top_k_join = top_k_join - self.sort_by_score = sort_by_score - - def run_accumulated(self, inputs: List[dict], top_k_join: Optional[int] = None): # type: ignore - results = [inp["documents"] for inp in inputs] - document_map = {doc.id: doc for result in results for doc in result} - - if self.join_mode == "concatenate": - scores_map = self._concatenate_results(results, document_map) - elif self.join_mode == "merge": - scores_map = self._calculate_comb_sum(results) - elif self.join_mode == "reciprocal_rank_fusion": - scores_map = self._calculate_rrf(results) - else: - raise ValueError(f"Invalid join_mode: {self.join_mode}") - - # only sort the docs if that was requested - if self.sort_by_score: - sorted_docs = sorted(scores_map.items(), key=lambda d: d[1] if d[1] is not None else -inf, reverse=True) - if any(s is None for s in scores_map.values()): - logger.info( - "The `JoinDocuments` node has received some documents with `score=None` - and was requested " - "to sort the documents by score, so the `score=None` documents got sorted as if their " - "score would be `-infinity`." - ) - else: - sorted_docs = list(scores_map.items()) - - if not top_k_join: - top_k_join = self.top_k_join - if not top_k_join: - top_k_join = len(sorted_docs) - - docs = [] - for id, score in sorted_docs[:top_k_join]: - doc = document_map[id] - doc.score = score - docs.append(doc) - - output = {"documents": docs, "labels": inputs[0].get("labels", None)} - - return output, "output_1" - - def run_batch_accumulated(self, inputs: List[dict], top_k_join: Optional[int] = None): # type: ignore - # Join single document lists - if isinstance(inputs[0]["documents"][0], Document): - return self.run(inputs=inputs, top_k_join=top_k_join) - # Join lists of document lists - else: - output_docs = [] - incoming_edges = [inp["documents"] for inp in inputs] - for idx in range(len(incoming_edges[0])): - cur_docs_to_join = [] - for edge in incoming_edges: - cur_docs_to_join.append({"documents": edge[idx]}) - cur, _ = self.run(inputs=cur_docs_to_join, top_k_join=top_k_join) - output_docs.append(cur["documents"]) - - output = {"documents": output_docs, "labels": inputs[0].get("labels", None)} - - return output, "output_1" - - def _concatenate_results(self, results, document_map): - """ - Concatenates multiple document result lists. - Return the documents with the higher score. - """ - list_id = list(document_map.keys()) - scores_map = {} - for idx in list_id: - tmp = [] - for result in results: - for doc in result: - if doc.id == idx: - tmp.append(doc) - item_best_score = max(tmp, key=lambda x: x.score if x.score is not None else -inf) - scores_map.update({idx: item_best_score.score}) - return scores_map - - def _calculate_comb_sum(self, results): - """ - Calculates a combination sum by multiplying each score by its weight. - """ - scores_map = defaultdict(int) - weights = self.weights if self.weights else [1 / len(results)] * len(results) - - for result, weight in zip(results, weights): - for doc in result: - scores_map[doc.id] += (doc.score if doc.score else 0) * weight - - return scores_map - - def _calculate_rrf(self, results): - """ - Calculates the reciprocal rank fusion. The constant K is set to 61 (60 was suggested by the original paper, - plus 1 as python lists are 0-based and the paper used 1-based ranking). - """ - K = 61 - - scores_map = defaultdict(int) - for result in results: - for rank, doc in enumerate(result): - scores_map[doc.id] += 1 / (K + rank) - - return scores_map diff --git a/haystack/nodes/other/route_documents.py b/haystack/nodes/other/route_documents.py deleted file mode 100644 index e504d05e29..0000000000 --- a/haystack/nodes/other/route_documents.py +++ /dev/null @@ -1,154 +0,0 @@ -from typing import Any, List, Tuple, Dict, Optional, Union -from collections import defaultdict -import logging - -from haystack.nodes.base import BaseComponent -from haystack.schema import Document - -logger = logging.getLogger(__name__) - - -class RouteDocuments(BaseComponent): - """ - A node to split a list of `Document`s by `content_type` or by the values of a metadata field and route them to - different nodes. - """ - - # By default (split_by == "content_type"), the node has two outgoing edges. - outgoing_edges = 2 - - def __init__( - self, - split_by: str = "content_type", - metadata_values: Optional[Union[List[str], List[List[str]]]] = None, - return_remaining: bool = False, - ): - """ - :param split_by: Field to split the documents by, either `"content_type"` or a metadata field name. - If this parameter is set to `"content_type"`, the list of `Document`s will be split into a list containing - only `Document`s of type `"text"` (will be routed to `"output_1"`) and a list containing only `Document`s of - type `"table"` (will be routed to `"output_2"`). - If this parameter is set to a metadata field name, you need to specify the parameter `metadata_values` as - well. - :param metadata_values: A list of values to group `Document`s by metadata field. If the parameter `split_by` - is set to a metadata field name, you must provide a list of values (or a list of lists of values) to - group the `Document`s by. - If `metadata_values` is a list of strings, then the `Document`s whose metadata field is equal to the - corresponding value will be routed to the output with the same index. - If `metadata_values` is a list of lists, then the `Document`s whose metadata field is equal to the first - value of the provided sublist will be routed to `"output_1"`, the `Document`s whose metadata field is equal - to the second value of the provided sublist will be routed to `"output_2"`, and so on. - :param return_remaining: Whether to return all remaining documents that don't match the `split_by` or - `metadata_values` into an additional output route. This additional output route will be indexed to plus one - of the previous last output route. For example, if there would normally be `"output_1"` and `"output_2"` - when return_remaining is False, then when return_remaining is True the additional output route would be - `"output_3"`. - """ - super().__init__() - - self.split_by = split_by - self.metadata_values = metadata_values - self.return_remaining = return_remaining - - if self.split_by != "content_type" and (self.metadata_values is None or len(self.metadata_values) == 0): - raise ValueError( - "If split_by is set to the name of a metadata field, provide metadata_values if you want to split " - "a list of Documents by a metadata field." - ) - - @classmethod - def _calculate_outgoing_edges(cls, component_params: Dict[str, Any]) -> int: - split_by = component_params.get("split_by", "content_type") - metadata_values = component_params.get("metadata_values", None) - return_remaining = component_params.get("return_remaining", False) - - # If we split list of Documents by a metadata field, number of outgoing edges might change - if split_by != "content_type" and metadata_values is not None: - num_edges = len(metadata_values) - else: - num_edges = 2 - - if return_remaining: - num_edges += 1 - return num_edges - - def _split_by_content_type(self, documents: List[Document]) -> Dict[str, List[Document]]: - mapping = {"text": "output_1", "table": "output_2"} - split_documents: Dict[str, List[Document]] = {"output_1": [], "output_2": [], "output_3": []} - for doc in documents: - output_route = mapping.get(doc.content_type, "output_3") - split_documents[output_route].append(doc) - - if not self.return_remaining: - # Used to avoid unnecessarily calculating other_content_types depending on logging level - if logger.isEnabledFor(logging.WARNING) and len(split_documents["output_3"]) > 0: - other_content_types = {x.content_type for x in split_documents["output_3"]} - logger.warning( - "%s document(s) were skipped because they have content type(s) %s. Only the content " - "types 'text' and 'table' are routed.", - len(split_documents["output_3"]), - other_content_types, - ) - del split_documents["output_3"] - - return split_documents - - def _get_metadata_values_index(self, metadata_values: Union[List[str], List[List[str]]], value: str) -> int: - for idx, item in enumerate(metadata_values): - if isinstance(item, list): - if value in item: - return idx - else: - if value == item: - return idx - return len(metadata_values) - - def _split_by_metadata_values( - self, metadata_values: Union[List, List[List]], documents: List[Document] - ) -> Dict[str, List[Document]]: - # We need also to keep track of the excluded documents so we add 2 to the number of metadata_values - output_keys = [f"output_{i}" for i in range(1, len(metadata_values) + 2)] - split_documents: Dict[str, List[Document]] = {k: [] for k in output_keys} - # This is the key used for excluded documents - remaining_key = output_keys[-1] - - for doc in documents: - current_metadata_value = doc.meta.get(self.split_by, remaining_key) - index = self._get_metadata_values_index(metadata_values, current_metadata_value) - output = output_keys[index] - split_documents[output].append(doc) - - if not self.return_remaining: - if len(split_documents[remaining_key]) > 0: - logger.warning( - "%s documents were skipped because they were either missing the metadata field '%s' or the" - " corresponding metadata value is not included in `metadata_values`.", - len(split_documents[remaining_key]), - self.split_by, - ) - del split_documents[remaining_key] - - return split_documents - - def run(self, documents: List[Document]) -> Tuple[Dict, str]: # type: ignore - if self.split_by == "content_type": - split_documents = self._split_by_content_type(documents) - elif self.metadata_values: - split_documents = self._split_by_metadata_values(self.metadata_values, documents) - else: - raise ValueError( - "If split_by is set to the name of a metadata field, provide metadata_values if you want to split " - "a list of Documents by a metadata field." - ) - return split_documents, "split" - - def run_batch(self, documents: Union[List[Document], List[List[Document]]]) -> Tuple[Dict, str]: # type: ignore - if isinstance(documents[0], Document): - return self.run(documents) # type: ignore - else: - split_documents = defaultdict(list) - for doc_list in documents: - results, _ = self.run(documents=doc_list) # type: ignore - for key in results: - split_documents[key].append(results[key]) - return split_documents, "split" diff --git a/haystack/nodes/other/shaper.py b/haystack/nodes/other/shaper.py deleted file mode 100644 index b367969dcb..0000000000 --- a/haystack/nodes/other/shaper.py +++ /dev/null @@ -1,849 +0,0 @@ -from functools import reduce -import inspect -import re -from datetime import datetime -from string import Template -from typing import Literal, Optional, List, Dict, Any, Tuple, Union, Callable - -import logging - -from haystack.nodes.base import BaseComponent -from haystack.schema import Document, Answer, MultiLabel - - -logger = logging.getLogger(__name__) - - -def rename(value: Any) -> Any: - """ - An identity function. You can use it to rename values in the invocation context without changing them. - - Example: - - ```python - assert rename(1) == 1 - ``` - """ - return value - - -def current_datetime(format: str = "%H:%M:%S %d/%m/%y") -> str: - """ - Function that outputs the current time and/or date formatted according to the parameters. - - Example: - - ```python - assert current_datetime("%d.%m.%y %H:%M:%S") == 01.01.2023 12:30:10 - ``` - """ - return datetime.now().strftime(format) - - -def value_to_list(value: Any, target_list: List[Any]) -> List[Any]: - """ - Transforms a value into a list containing this value as many times as the length of the target list. - - Example: - - ```python - assert value_to_list(value=1, target_list=list(range(5))) == [1, 1, 1, 1, 1] - ``` - """ - return [value] * len(target_list) - - -def join_lists(lists: List[List[Any]]) -> List[Any]: - """ - Joins the lists you pass to it into a single list. - - Example: - - ```python - assert join_lists(lists=[[1, 2, 3], [4, 5]]) == [1, 2, 3, 4, 5] - ``` - """ - merged_list = [] - for inner_list in lists: - merged_list += inner_list - return merged_list - - -def join_strings(strings: List[str], delimiter: str = " ", str_replace: Optional[Dict[str, str]] = None) -> str: - """ - Transforms a list of strings into a single string. The content of this string - is the content of all of the original strings separated by the delimiter you specify. - - Example: - - ```python - assert join_strings(strings=["first", "second", "third"], delimiter=" - ", str_replace={"r": "R"}) == "fiRst - second - thiRd" - ``` - """ - str_replace = str_replace or {} - return delimiter.join([format_string(string, str_replace) for string in strings]) - - -def format_string(string: str, str_replace: Optional[Dict[str, str]] = None) -> str: - """ - Replaces strings. - - Example: - - ```python - assert format_string(string="first", str_replace={"r": "R"}) == "fiRst" - ``` - """ - str_replace = str_replace or {} - return reduce(lambda s, kv: s.replace(*kv), str_replace.items(), string) - - -def join_documents( - documents: List[Document], - delimiter: str = " ", - pattern: Optional[str] = None, - str_replace: Optional[Dict[str, str]] = None, -) -> List[Document]: - """ - Transforms a list of documents into a list containing a single document. The content of this document - is the joined result of all original documents, separated by the delimiter you specify. - Use regex in the `pattern` parameter to control how each document is represented. - You can use the following placeholders: - - $content: The content of the document. - - $idx: The index of the document in the list. - - $id: The ID of the document. - - $META_FIELD: The value of the metadata field called 'META_FIELD'. - - All metadata is dropped. - - Example: - - ```python - assert join_documents( - documents=[ - Document(content="first"), - Document(content="second"), - Document(content="third") - ], - delimiter=" - ", - pattern="[$idx] $content", - str_replace={"r": "R"} - ) == [Document(content="[1] fiRst - [2] second - [3] thiRd")] - ``` - """ - return [Document(content=join_documents_to_string(documents, delimiter, pattern, str_replace))] - - -def join_documents_and_scores(documents: List[Document]) -> Tuple[List[Document]]: - """ - Transforms a list of documents with scores in their metadata into a list containing a single document. - The resulting document contains the scores and the contents of all the original documents. - All metadata is dropped. - Example: - ```python - assert join_documents_and_scores( - documents=[ - Document(content="first", meta={"score": 0.9}), - Document(content="second", meta={"score": 0.7}), - Document(content="third", meta={"score": 0.5}) - ], - delimiter=" - " - ) == ([Document(content="-[0.9] first\n -[0.7] second\n -[0.5] third")], ) - ``` - """ - content = "\n".join([f"-[{round(float(doc.meta['score']),2)}] {doc.content}" for doc in documents]) - return ([Document(content=content)],) - - -def format_document( - document: Document, - pattern: Optional[str] = None, - str_replace: Optional[Dict[str, str]] = None, - idx: Optional[int] = None, -) -> str: - """ - Transforms a document into a single string. - Use regex in the `pattern` parameter to control how the document is represented. - You can use the following placeholders: - - $content: The content of the document. - - $idx: The index of the document in the list. - - $id: The ID of the document. - - $META_FIELD: The value of the metadata field called 'META_FIELD'. - - Example: - - ```python - assert format_document( - document=Document(content="first"), - pattern="prefix [$idx] $content", - str_replace={"r": "R"}, - idx=1, - ) == "prefix [1] fiRst" - ``` - """ - str_replace = str_replace or {} - pattern = pattern or "$content" - - template = Template(pattern) - pattern_params = [ - match.groupdict().get("named", match.groupdict().get("braced")) - for match in template.pattern.finditer(template.template) - ] - meta_params = [param for param in pattern_params if param and param not in ["content", "idx", "id"]] - content = template.substitute( - { - "idx": idx, - "content": reduce(lambda content, kv: content.replace(*kv), str_replace.items(), document.content), - "id": reduce(lambda id, kv: id.replace(*kv), str_replace.items(), document.id), - **{ - k: reduce(lambda val, kv: val.replace(*kv), str_replace.items(), document.meta.get(k, "")) - for k in meta_params - }, - } - ) - return content - - -def format_answer( - answer: Answer, - pattern: Optional[str] = None, - str_replace: Optional[Dict[str, str]] = None, - idx: Optional[int] = None, -) -> str: - """ - Transforms an answer into a single string. - Use regex in the `pattern` parameter to control how the answer is represented. - You can use the following placeholders: - - $answer: The answer text. - - $idx: The index of the answer in the list. - - $META_FIELD: The value of the metadata field called 'META_FIELD'. - - Example: - - ```python - assert format_answer( - answer=Answer(answer="first"), - pattern="prefix [$idx] $answer", - str_replace={"r": "R"}, - idx=1, - ) == "prefix [1] fiRst" - ``` - """ - str_replace = str_replace or {} - pattern = pattern or "$answer" - - template = Template(pattern) - pattern_params = [ - match.groupdict().get("named", match.groupdict().get("braced")) - for match in template.pattern.finditer(template.template) - ] - meta_params = [param for param in pattern_params if param and param not in ["answer", "idx"]] - meta = answer.meta or {} - content = template.substitute( - { - "idx": idx, - "answer": reduce(lambda content, kv: content.replace(*kv), str_replace.items(), answer.answer), - **{k: reduce(lambda val, kv: val.replace(*kv), str_replace.items(), meta.get(k, "")) for k in meta_params}, - } - ) - return content - - -def join_documents_to_string( - documents: List[Document], - delimiter: str = " ", - pattern: Optional[str] = None, - str_replace: Optional[Dict[str, str]] = None, -) -> str: - """ - Transforms a list of documents into a single string. The content of this string - is the joined result of all original documents separated by the delimiter you specify. - Use regex in the `pattern` parameter to control how the documents are represented. - You can use the following placeholders: - - $content: The content of the document. - - $idx: The index of the document in the list. - - $id: The ID of the document. - - $META_FIELD: The value of the metadata field called 'META_FIELD'. - - Example: - - ```python - assert join_documents_to_string( - documents=[ - Document(content="first"), - Document(content="second"), - Document(content="third") - ], - delimiter=" - ", - pattern="[$idx] $content", - str_replace={"r": "R"} - ) == "[1] fiRst - [2] second - [3] thiRd" - ``` - """ - content = delimiter.join( - format_document(doc, pattern, str_replace, idx=idx) for idx, doc in enumerate(documents, start=1) - ) - return content - - -def strings_to_answers( - strings: List[str], - prompts: Optional[List[Union[str, List[Dict[str, str]]]]] = None, - documents: Optional[List[Document]] = None, - pattern: Optional[str] = None, - reference_pattern: Optional[str] = None, - reference_mode: Literal["index", "id", "meta"] = "index", - reference_meta_field: Optional[str] = None, -) -> List[Answer]: - """ - Transforms a list of strings into a list of answers. - Specify `reference_pattern` to populate the answer's `document_ids` by extracting document references from the strings. - - :param strings: The list of strings to transform. - :param prompts: The prompts used to generate the answers. - :param documents: The documents used to generate the answers. - :param pattern: The regex pattern to use for parsing the answer. - Examples: - `[^\\n]+$` will find "this is an answer" in string "this is an argument.\nthis is an answer". - `Answer: (.*)` will find "this is an answer" in string "this is an argument. Answer: this is an answer". - If None, the whole string is used as the answer. If not None, the first group of the regex is used as the answer. If there is no group, the whole match is used as the answer. - :param reference_pattern: The regex pattern to use for parsing the document references. - Example: `\\[(\\d+)\\]` will find "1" in string "this is an answer[1]". - If None, no parsing is done and all documents are referenced. - :param reference_mode: The mode used to reference documents. Supported modes are: - - index: the document references are the one-based index of the document in the list of documents. - Example: "this is an answer[1]" will reference the first document in the list of documents. - - id: the document references are the document IDs. - Example: "this is an answer[123]" will reference the document with id "123". - - meta: the document references are the value of a metadata field of the document. - Example: "this is an answer[123]" will reference the document with the value "123" in the metadata field specified by reference_meta_field. - :param reference_meta_field: The name of the metadata field to use for document references in reference_mode "meta". - :return: The list of answers. - - Examples: - - Without reference parsing: - ```python - assert strings_to_answers(strings=["first", "second", "third"], prompt="prompt", documents=[Document(id="123", content="content")]) == [ - Answer(answer="first", type="generative", document_ids=["123"], meta={"prompt": "prompt"}), - Answer(answer="second", type="generative", document_ids=["123"], meta={"prompt": "prompt"}), - Answer(answer="third", type="generative", document_ids=["123"], meta={"prompt": "prompt"}), - ] - ``` - - With reference parsing: - ```python - assert strings_to_answers(strings=["first[1]", "second[2]", "third[1][3]"], prompt="prompt", - documents=[Document(id="123", content="content"), Document(id="456", content="content"), Document(id="789", content="content")], - reference_pattern=r"\\[(\\d+)\\]", - reference_mode="index" - ) == [ - Answer(answer="first", type="generative", document_ids=["123"], meta={"prompt": "prompt"}), - Answer(answer="second", type="generative", document_ids=["456"], meta={"prompt": "prompt"}), - Answer(answer="third", type="generative", document_ids=["123", "789"], meta={"prompt": "prompt"}), - ] - ``` - """ - if prompts: - if len(prompts) == 1: - # one prompt for all strings/documents - documents_per_string: List[Optional[List[Document]]] = [documents] * len(strings) - prompt_per_string: List[Optional[Union[str, List[Dict[str, str]]]]] = [prompts[0]] * len(strings) - elif len(prompts) > 1 and len(strings) % len(prompts) == 0: - # one prompt per string/document - if documents is not None and len(documents) != len(prompts): - raise ValueError("The number of documents must match the number of prompts.") - string_multiplier = len(strings) // len(prompts) - documents_per_string = ( - [[doc] for doc in documents for _ in range(string_multiplier)] if documents else [None] * len(strings) - ) - prompt_per_string = [prompt for prompt in prompts for _ in range(string_multiplier)] - else: - raise ValueError("The number of prompts must be one or a multiple of the number of strings.") - else: - documents_per_string = [documents] * len(strings) - prompt_per_string = [None] * len(strings) - - answers = [] - for string, prompt, _documents in zip(strings, prompt_per_string, documents_per_string): - answer = string_to_answer( - string=string, - prompt=prompt, - documents=_documents, - pattern=pattern, - reference_pattern=reference_pattern, - reference_mode=reference_mode, - reference_meta_field=reference_meta_field, - ) - answers.append(answer) - return answers - - -def string_to_answer( - string: str, - prompt: Optional[Union[str, List[Dict[str, str]]]], - documents: Optional[List[Document]], - pattern: Optional[str] = None, - reference_pattern: Optional[str] = None, - reference_mode: Literal["index", "id", "meta"] = "index", - reference_meta_field: Optional[str] = None, -) -> Answer: - """ - Transforms a string into an answer. - Specify `reference_pattern` to populate the answer's `document_ids` by extracting document references from the string. - - :param string: The string to transform. - :param prompt: The prompt used to generate the answer. - :param documents: The documents used to generate the answer. - :param pattern: The regex pattern to use for parsing the answer. - Examples: - `[^\\n]+$` will find "this is an answer" in string "this is an argument.\nthis is an answer". - `Answer: (.*)` will find "this is an answer" in string "this is an argument. Answer: this is an answer". - If None, the whole string is used as the answer. If not None, the first group of the regex is used as the answer. If there is no group, the whole match is used as the answer. - :param reference_pattern: The regex pattern to use for parsing the document references. - Example: `\\[(\\d+)\\]` will find "1" in string "this is an answer[1]". - If None, no parsing is done and all documents are referenced. - :param reference_mode: The mode used to reference documents. Supported modes are: - - index: the document references are the one-based index of the document in the list of documents. - Example: "this is an answer[1]" will reference the first document in the list of documents. - - id: the document references are the document IDs. - Example: "this is an answer[123]" will reference the document with id "123". - - meta: the document references are the value of a metadata field of the document. - Example: "this is an answer[123]" will reference the document with the value "123" in the metadata field specified by reference_meta_field. - :param reference_meta_field: The name of the metadata field to use for document references in reference_mode "meta". - :return: The answer - """ - if reference_mode == "index": - candidates = {str(idx): doc.id for idx, doc in enumerate(documents, start=1)} if documents else {} - elif reference_mode == "id": - candidates = {doc.id: doc.id for doc in documents} if documents else {} - elif reference_mode == "meta": - if not reference_meta_field: - raise ValueError("reference_meta_field must be specified when reference_mode is 'meta'") - candidates = ( - {doc.meta[reference_meta_field]: doc.id for doc in documents if doc.meta.get(reference_meta_field)} - if documents - else {} - ) - else: - raise ValueError(f"Invalid document_id_mode: {reference_mode}") - - if pattern: - match = re.search(pattern, string) - if match: - if not match.lastindex: - # no group in pattern -> take the whole match - string = match.group(0) - elif match.lastindex == 1: - # one group in pattern -> take the group - string = match.group(1) - else: - # more than one group in pattern -> raise error - raise ValueError(f"Pattern must have at most one group: {pattern}") - else: - string = "" - document_ids = parse_references(string=string, reference_pattern=reference_pattern, candidates=candidates) - answer = Answer(answer=string, type="generative", document_ids=document_ids, meta={"prompt": prompt}) - return answer - - -def parse_references( - string: str, reference_pattern: Optional[str] = None, candidates: Optional[Dict[str, str]] = None -) -> Optional[List[str]]: - """ - Parses an answer string for document references and returns the document IDs of the referenced documents. - - :param string: The string to parse. - :param reference_pattern: The regex pattern to use for parsing the document references. - Example: `\\[(\\d+)\\]` will find "1" in string "this is an answer[1]". - If None, no parsing is done and all candidate document IDs are returned. - :param candidates: A dictionary of candidates to choose from. The keys are the reference strings and the values are the document IDs. - If None, no parsing is done and None is returned. - :return: A list of document IDs. - """ - if not candidates: - return None - if not reference_pattern: - return list(candidates.values()) - - document_idxs = re.findall(reference_pattern, string) - return [candidates[idx] for idx in document_idxs if idx in candidates] - - -def answers_to_strings( - answers: List[Answer], pattern: Optional[str] = None, str_replace: Optional[Dict[str, str]] = None -) -> List[str]: - """ - Extracts the content field of answers and returns a list of strings. - - Example: - - ```python - assert answers_to_strings( - answers=[ - Answer(answer="first"), - Answer(answer="second"), - Answer(answer="third") - ], - pattern="[$idx] $answer", - str_replace={"r": "R"} - ) == ["[1] fiRst", "[2] second", "[3] thiRd"] - ``` - """ - return [format_answer(answer, pattern, str_replace, idx) for idx, answer in enumerate(answers, start=1)] - - -def strings_to_documents( - strings: List[str], - meta: Union[List[Optional[Dict[str, Any]]], Optional[Dict[str, Any]]] = None, - id_hash_keys: Optional[List[str]] = None, -) -> List[Document]: - """ - Transforms a list of strings into a list of documents. If you pass the metadata in a single - dictionary, all documents get the same metadata. If you pass the metadata as a list, the length of this list - must be the same as the length of the list of strings, and each document gets its own metadata. - You can specify `id_hash_keys` only once and it gets assigned to all documents. - - Example: - - ```python - assert strings_to_documents( - strings=["first", "second", "third"], - meta=[{"position": i} for i in range(3)], - id_hash_keys=['content', 'meta] - ) == [ - Document(content="first", metadata={"position": 1}, id_hash_keys=['content', 'meta])]), - Document(content="second", metadata={"position": 2}, id_hash_keys=['content', 'meta]), - Document(content="third", metadata={"position": 3}, id_hash_keys=['content', 'meta]) - ] - ``` - """ - all_metadata: List[Optional[Dict[str, Any]]] - if isinstance(meta, dict): - all_metadata = [meta] * len(strings) - elif isinstance(meta, list): - if len(meta) != len(strings): - raise ValueError( - f"Not enough metadata dictionaries. strings_to_documents received {len(strings)} and {len(meta)} metadata dictionaries." - ) - all_metadata = meta - else: - all_metadata = [None] * len(strings) - - return [Document(content=string, meta=m, id_hash_keys=id_hash_keys) for string, m in zip(strings, all_metadata)] - - -def documents_to_strings( - documents: List[Document], pattern: Optional[str] = None, str_replace: Optional[Dict[str, str]] = None -) -> List[str]: - """ - Extracts the content field of documents and returns a list of strings. Use regext in the `pattern` parameter to control how the documents are represented. - - Example: - - ```python - assert documents_to_strings( - documents=[ - Document(content="first"), - Document(content="second"), - Document(content="third") - ], - pattern="[$idx] $content", - str_replace={"r": "R"} - ) == ["[1] fiRst", "[2] second", "[3] thiRd"] - ``` - """ - return [format_document(doc, pattern, str_replace, idx) for idx, doc in enumerate(documents, start=1)] - - -REGISTERED_FUNCTIONS: Dict[str, Callable[..., Any]] = { - "rename": rename, - "current_datetime": current_datetime, - "value_to_list": value_to_list, - "join_lists": join_lists, - "join_strings": join_strings, - "join_documents": join_documents, - "join_documents_and_scores": join_documents_and_scores, - "strings_to_answers": strings_to_answers, - "answers_to_strings": answers_to_strings, - "strings_to_documents": strings_to_documents, - "documents_to_strings": documents_to_strings, -} - - -class Shaper(BaseComponent): - - """ - Shaper is a component that can invoke arbitrary, registered functions on the invocation context - (query, documents, and so on) of a pipeline. It then passes the new or modified variables further down the pipeline. - - Using YAML configuration, the Shaper component is initialized with functions to invoke on pipeline invocation - context. - - For example, in the YAML snippet below: - ```yaml - components: - - name: shaper - type: Shaper - params: - func: value_to_list - inputs: - value: query - target_list: documents - output: [questions] - ``` - the Shaper component is initialized with a directive to invoke function expand on the variable query and to store - the result in the invocation context variable questions. All other invocation context variables are passed down - the pipeline as they are. - - You can use multiple Shaper components in a pipeline to modify the invocation context as needed. - - Currently, `Shaper` supports the following functions: - - - `rename` - - `value_to_list` - - `join_lists` - - `join_strings` - - `format_string` - - `join_documents` - - `join_documents_and_scores` - - `format_document` - - `format_answer` - - `join_documents_to_string` - - `strings_to_answers` - - `string_to_answer` - - `parse_references` - - `answers_to_strings` - - `join_lists` - - `strings_to_documents` - - `documents_to_strings` - - See their descriptions in the code for details about their inputs, outputs, and other parameters. - """ - - outgoing_edges = 1 - - def __init__( - self, - func: str, - outputs: List[str], - inputs: Optional[Dict[str, Union[List[str], str]]] = None, - params: Optional[Dict[str, Any]] = None, - publish_outputs: Union[bool, List[str]] = True, - ): - """ - Initializes the Shaper component. - - Some examples: - - ```yaml - - name: shaper - type: Shaper - params: - func: value_to_list - inputs: - value: query - target_list: documents - outputs: - - questions - ``` - This node takes the content of `query` and creates a list that contains the value of `query` `len(documents)` times. - This list is stored in the invocation context under the key `questions`. - - ```yaml - - name: shaper - type: Shaper - params: - func: join_documents - inputs: - value: documents - params: - delimiter: ' - ' - outputs: - - documents - ``` - This node overwrites the content of `documents` in the invocation context with a list containing a single Document - whose content is the concatenation of all the original Documents. So if `documents` contained - `[Document("A"), Document("B"), Document("C")]`, this shaper overwrites it with `[Document("A - B - C")]` - - ```yaml - - name: shaper - type: Shaper - params: - func: join_strings - params: - strings: ['a', 'b', 'c'] - delimiter: ' . ' - outputs: - - single_string - - - name: shaper - type: Shaper - params: - func: strings_to_documents - inputs: - strings: single_string - metadata: - name: 'my_file.txt' - outputs: - - single_document - ``` - These two nodes, executed one after the other, first add a key in the invocation context called `single_string` - that contains `a . b . c`, and then create another key called `single_document` that contains instead - `[Document(content="a . b . c", metadata={'name': 'my_file.txt'})]`. - - :param func: The function to apply. - :param inputs: Maps the function's input kwargs to the key-value pairs in the invocation context. - For example, `value_to_list` expects the `value` and `target_list` parameters, so `inputs` might contain: - `{'value': 'query', 'target_list': 'documents'}`. It doesn't need to contain all keyword args, see `params`. - :param params: Maps the function's input kwargs to some fixed values. For example, `value_to_list` expects - `value` and `target_list` parameters, so `params` might contain - `{'value': 'A', 'target_list': [1, 1, 1, 1]}` and the node's output is `["A", "A", "A", "A"]`. - It doesn't need to contain all keyword args, see `inputs`. - You can use params to provide fallback values for arguments of `run` that you're not sure exist. - So if you need `query` to exist, you can provide a fallback value in the params, which will be used only if `query` - is not passed to this node by the pipeline. - :param outputs: The key to store the outputs in the invocation context. The length of the outputs must match - the number of outputs produced by the function invoked. - :param publish_outputs: Controls whether to publish the outputs to the pipeline's output. - Set `True` (default value) to publishes all outputs or `False` to publish None. - E.g. if `outputs = ["documents"]` result for `publish_outputs = True` looks like - ```python - { - "invocation_context": { - "documents": [...] - }, - "documents": [...] - } - ``` - For `publish_outputs = False` result looks like - ```python - { - "invocation_context": { - "documents": [...] - }, - } - ``` - If you want to have finer-grained control, pass a list of the outputs you want to publish. - """ - super().__init__() - self.function = REGISTERED_FUNCTIONS[func] - self.outputs = outputs - self.inputs = inputs or {} - self.params = params or {} - if isinstance(publish_outputs, bool): - self.publish_outputs = self.outputs if publish_outputs else [] - else: - self.publish_outputs = publish_outputs - - def run( # type: ignore - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - invocation_context: Optional[Dict[str, Any]] = None, - ) -> Tuple[Dict, str]: - invocation_context = invocation_context or {} - if query and "query" not in invocation_context.keys(): - invocation_context["query"] = query - - if file_paths and "file_paths" not in invocation_context.keys(): - invocation_context["file_paths"] = file_paths - - if labels and "labels" not in invocation_context.keys(): - invocation_context["labels"] = labels - - if documents != None and "documents" not in invocation_context.keys(): - invocation_context["documents"] = documents - - if meta and "meta" not in invocation_context.keys(): - invocation_context["meta"] = meta - - input_values: Dict[str, Any] = {} - for key, value in self.inputs.items(): - if isinstance(value, list): - input_values[key] = [] - for v in value: - if v in invocation_context.keys() and v is not None: - input_values[key].append(invocation_context[v]) - else: - if value in invocation_context.keys() and value is not None: - input_values[key] = invocation_context[value] - - # auto fill in input values if there's an invocation context value with the same name - function_params = inspect.signature(self.function).parameters - for parameter in function_params.values(): - if ( - parameter.name not in input_values.keys() - and parameter.name not in self.params.keys() - and parameter.name in invocation_context.keys() - ): - input_values[parameter.name] = invocation_context[parameter.name] - - input_values = {**self.params, **input_values} - try: - logger.debug( - "Shaper is invoking this function: %s(%s)", - self.function.__name__, - ", ".join([f"{key}={value}" for key, value in input_values.items()]), - ) - output_values = self.function(**input_values) - if not isinstance(output_values, tuple): - output_values = (output_values,) - except TypeError as e: - raise ValueError( - "Shaper couldn't apply the function to your inputs and parameters. " - "Check the above stacktrace and make sure you provided all the correct inputs, parameters, " - "and parameter types." - ) from e - - if len(self.outputs) < len(output_values): - logger.warning( - "The number of outputs from function %s is %s. However, only %s output key(s) were provided. " - "Only %s output(s) will be stored. " - "Provide %s output keys to store all outputs.", - self.function.__name__, - len(output_values), - len(self.outputs), - len(self.outputs), - len(output_values), - ) - - if len(self.outputs) > len(output_values): - logger.warning( - "The number of outputs from function %s is %s. However, %s output key(s) were provided. " - "Only the first %s output key(s) will be used.", - self.function.__name__, - len(output_values), - len(self.outputs), - len(output_values), - ) - - results = {} - for output_key, output_value in zip(self.outputs, output_values): - invocation_context[output_key] = output_value - if output_key in self.publish_outputs: - results[output_key] = output_value - results["invocation_context"] = invocation_context - - return results, "output_1" - - def run_batch( # type: ignore - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - invocation_context: Optional[Dict[str, Any]] = None, - ) -> Tuple[Dict, str]: - return self.run( - query=query, - file_paths=file_paths, - labels=labels, - documents=documents, - meta=meta, - invocation_context=invocation_context, - ) diff --git a/haystack/nodes/preprocessor/__init__.py b/haystack/nodes/preprocessor/__init__.py deleted file mode 100644 index 2ebe593951..0000000000 --- a/haystack/nodes/preprocessor/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.preprocessor.base import BasePreProcessor -from haystack.nodes.preprocessor.preprocessor import PreProcessor diff --git a/haystack/nodes/preprocessor/base.py b/haystack/nodes/preprocessor/base.py deleted file mode 100644 index 79480f254f..0000000000 --- a/haystack/nodes/preprocessor/base.py +++ /dev/null @@ -1,108 +0,0 @@ -from typing import List, Optional, Union, Literal - -from abc import abstractmethod - -from transformers import PreTrainedTokenizerBase - -from haystack.nodes.base import BaseComponent -from haystack.schema import Document - - -class BasePreProcessor(BaseComponent): - outgoing_edges = 1 - - @abstractmethod - def process( - self, - documents: Union[dict, Document, List[Union[dict, Document]]], - clean_whitespace: Optional[bool] = True, - clean_header_footer: Optional[bool] = False, - clean_empty_lines: Optional[bool] = True, - remove_substrings: Optional[List[str]] = None, - split_by: Literal["token", "word", "sentence", "passage", None] = "word", - split_length: Optional[int] = 1000, - split_overlap: Optional[int] = None, - split_respect_sentence_boundary: Optional[bool] = True, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = "tiktoken", - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Perform document cleaning and splitting. Takes a single Document or a List of Documents as input and returns a - list of Documents. - """ - raise NotImplementedError - - @abstractmethod - def clean( - self, - document: Union[dict, Document], - clean_whitespace: bool, - clean_header_footer: bool, - clean_empty_lines: bool, - remove_substrings: Optional[List[str]], - ) -> Document: - raise NotImplementedError - - @abstractmethod - def split( - self, - document: Union[dict, Document], - split_by: Literal["token", "word", "sentence", "passage", None], - split_length: int, - split_overlap: int, - split_respect_sentence_boundary: bool, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = None, - ) -> List[Document]: - raise NotImplementedError - - def run( # type: ignore - self, - documents: Union[dict, Document, List[Union[dict, Document]]], - clean_whitespace: Optional[bool] = None, - clean_header_footer: Optional[bool] = None, - clean_empty_lines: Optional[bool] = None, - split_by: Literal["token", "word", "sentence", "passage", None] = None, - split_length: Optional[int] = None, - split_overlap: Optional[int] = None, - split_respect_sentence_boundary: Optional[bool] = None, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = None, - id_hash_keys: Optional[List[str]] = None, - ): - processed_documents = self.process( - documents=documents, - clean_whitespace=clean_whitespace, - clean_header_footer=clean_header_footer, - clean_empty_lines=clean_empty_lines, - split_by=split_by, - split_length=split_length, - split_overlap=split_overlap, - split_respect_sentence_boundary=split_respect_sentence_boundary, - id_hash_keys=id_hash_keys, - ) - result = {"documents": processed_documents} - return result, "output_1" - - def run_batch( # type: ignore - self, - documents: Union[dict, Document, List[Union[dict, Document]]], - clean_whitespace: Optional[bool] = None, - clean_header_footer: Optional[bool] = None, - clean_empty_lines: Optional[bool] = None, - split_by: Literal["token", "word", "sentence", "passage", None] = None, - split_length: Optional[int] = None, - split_overlap: Optional[int] = None, - split_respect_sentence_boundary: Optional[bool] = None, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = None, - id_hash_keys: Optional[List[str]] = None, - ): - return self.run( - documents=documents, - clean_whitespace=clean_whitespace, - clean_header_footer=clean_header_footer, - clean_empty_lines=clean_empty_lines, - split_by=split_by, - split_length=split_length, - split_overlap=split_overlap, - split_respect_sentence_boundary=split_respect_sentence_boundary, - id_hash_keys=id_hash_keys, - ) diff --git a/haystack/nodes/preprocessor/preprocessor.py b/haystack/nodes/preprocessor/preprocessor.py deleted file mode 100644 index 9dddc22e7f..0000000000 --- a/haystack/nodes/preprocessor/preprocessor.py +++ /dev/null @@ -1,944 +0,0 @@ -from typing import List, Optional, Generator, Set, Union, Tuple, Dict, Literal, Callable, Any - -import logging -import re -from copy import deepcopy -from functools import partial, reduce -from itertools import chain -import warnings -from pathlib import Path -from pickle import UnpicklingError - -from tqdm import tqdm -from more_itertools import windowed - -from haystack.nodes.preprocessor.base import BasePreProcessor -from haystack.errors import HaystackError -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install transformers'") as transformers_import: - from transformers import PreTrainedTokenizerBase - from transformers import AutoTokenizer - -with LazyImport("Run 'pip install tiktoken'") as tiktoken_import: - import tiktoken - -logger = logging.getLogger(__name__) - -with LazyImport("Run 'pip install farm-haystack[preprocessing]' or 'pip install nltk'") as nltk_import: - import nltk - -iso639_to_nltk = { - "ru": "russian", - "sl": "slovene", - "es": "spanish", - "sv": "swedish", - "tr": "turkish", - "cs": "czech", - "da": "danish", - "nl": "dutch", - "en": "english", - "et": "estonian", - "fi": "finnish", - "fr": "french", - "de": "german", - "el": "greek", - "it": "italian", - "no": "norwegian", - "pl": "polish", - "pt": "portuguese", - "ml": "malayalam", -} - - -class PreProcessor(BasePreProcessor): - def __init__( - self, - clean_whitespace: bool = True, - clean_header_footer: bool = False, - clean_empty_lines: bool = True, - remove_substrings: Optional[List[str]] = None, - split_by: Optional[Literal["token", "word", "sentence", "passage"]] = "word", - split_length: int = 200, - split_overlap: int = 0, - split_respect_sentence_boundary: bool = True, - tokenizer_model_folder: Optional[Union[str, Path]] = None, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = "tiktoken", - language: str = "en", - id_hash_keys: Optional[List[str]] = None, - progress_bar: bool = True, - add_page_number: bool = False, - max_chars_check: int = 10_000, - ): - """ - :param clean_header_footer: Use heuristic to remove footers and headers across different pages by searching - for the longest common string. This heuristic uses exact matches and therefore - works well for footers like "Copyright 2019 by XXX", but won't detect "Page 3 of 4" - or similar. - :param clean_whitespace: Strip whitespaces before or after each line in the text. - :param clean_empty_lines: Remove more than two empty lines in the text. - :param remove_substrings: Remove specified substrings from the text. If no value is provided an empty list is created by default. - :param split_by: Unit for splitting the document. Can be "word", "sentence", or "passage". Set to None to disable splitting. - :param split_length: Max. number of the above split unit (e.g. words) that are allowed in one document. For instance, if n -> 10 & split_by -> - "sentence", then each output document will have 10 sentences. - :param split_overlap: Word overlap between two adjacent documents after a split. - Setting this to a positive number essentially enables the sliding window approach. - For example, if split_by -> `word`, - split_length -> 5 & split_overlap -> 2, then the splits would be like: - [w1 w2 w3 w4 w5, w4 w5 w6 w7 w8, w7 w8 w10 w11 w12]. - Set the value to 0 to ensure there is no overlap among the documents after splitting. - :param split_respect_sentence_boundary: Whether to split in partial sentences if split_by -> `word`. If set - to True, the individual split will always have complete sentences & - the number of words will be <= split_length. - :param tokenizer: Specifies the tokenizer to use if split_by="token". Supported options are "tiktoken" - (for OpenAI's GPT-3.5 and GPT-4) and any HuggingFace tokenizer (e.g. 'bert-base-uncased'). - HuggingFace tokenizers can also be passed directly as an PreTrainedTokenizerBase object. - :param language: The language used by "nltk.tokenize.sent_tokenize" in iso639 format. - Available options: "ru","sl","es","sv","tr","cs","da","nl","en","et","fi","fr","de","el","it","no","pl","pt","ml" - :param tokenizer_model_folder: Path to the folder containing the NTLK PunktSentenceTokenizer models, if loading a model from a local path. Leave empty otherwise. - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's - attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are - not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]). - In this case the id will be generated by using the content and the defined metadata. - :param progress_bar: Whether to show a progress bar. - :param add_page_number: Add the number of the page a paragraph occurs in to the Document's meta - field `"page"`. Page boundaries are determined by `"\f"` character which is added - in between pages by `PDFToTextConverter`, `TikaConverter`, `ParsrConverter` and - `AzureConverter`. - :param max_chars_check: the maximum length a document is expected to have. Each document that is longer than - max_chars_check in characters after pre-processing will raise a warning and is going to be split at the - `max_char_check`-th char, regardless of any other constraint. If the resulting documents are still too long, - they'll be cut again until all fragments are below the maximum allowed length. - """ - nltk_import.check() - if remove_substrings is None: - remove_substrings = [] - super().__init__() - - try: - nltk.data.find("tokenizers/punkt") - except LookupError: - try: - nltk.download("punkt") - except FileExistsError as error: - logger.debug("NLTK punkt tokenizer seems to be already downloaded. Error message: %s", error) - pass - self.clean_whitespace = clean_whitespace - self.clean_header_footer = clean_header_footer - self.clean_empty_lines = clean_empty_lines - self.remove_substrings = remove_substrings - self.split_by = split_by - self.split_length = split_length - self.split_overlap = split_overlap - self.split_respect_sentence_boundary = split_respect_sentence_boundary - self.tokenizer = tokenizer - self.language = language - self.tokenizer_model_folder = tokenizer_model_folder - self.print_log: Set[str] = set() - self.id_hash_keys = id_hash_keys - self.progress_bar = progress_bar - self.add_page_number = add_page_number - self.max_chars_check = max_chars_check - - def process( - self, - documents: Union[dict, Document, List[Union[dict, Document]]], - clean_whitespace: Optional[bool] = None, - clean_header_footer: Optional[bool] = None, - clean_empty_lines: Optional[bool] = None, - remove_substrings: Optional[List[str]] = None, - split_by: Optional[Literal["token", "word", "sentence", "passage"]] = None, - split_length: Optional[int] = None, - split_overlap: Optional[int] = None, - split_respect_sentence_boundary: Optional[bool] = None, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """ - Perform document cleaning and splitting. Can take a single document or a list of documents as input and returns a list of documents. - """ - if remove_substrings is None: - remove_substrings = [] - if not isinstance(documents, list): - warnings.warn( - "Using a single Document as argument to the 'documents' parameter is deprecated. Use a list " - "of (a single) Document instead.", - DeprecationWarning, - 2, - ) - - kwargs = { - "clean_whitespace": clean_whitespace, - "clean_header_footer": clean_header_footer, - "clean_empty_lines": clean_empty_lines, - "remove_substrings": remove_substrings, - "split_by": split_by, - "split_length": split_length, - "split_overlap": split_overlap, - "split_respect_sentence_boundary": split_respect_sentence_boundary, - "tokenizer": tokenizer, - } - - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - if isinstance(documents, (Document, dict)): - ret = self._process_single(document=documents, id_hash_keys=id_hash_keys, **kwargs) # type: ignore - elif isinstance(documents, list): - ret = self._process_batch(documents=list(documents), id_hash_keys=id_hash_keys, **kwargs) - else: - raise Exception("documents provided to PreProcessor.prepreprocess() is not of type list nor Document") - - return ret - - def _long_documents(self, documents: List[Document], max_chars_check=10_000): - """ - Function that tries to detect unusually long documents. When detected, such documents are going to be - split at the `max_char_check`-th char, regardless of any other constraint. If the resulting documents - are still too long, they'll be cut again until all fragments are below the maximum allowed length. - - NOTE: this function is a heuristic that is in place only because a proper fix that prevents such documents from forming - would imply a complete revamp of this class, including better definitions of what the various units (word, sentence, passage) mean exactly. - """ - for document in documents: - if len(document.content) > max_chars_check: - logger.warning( - "Document %s is %s characters long after preprocessing, where the maximum length should be %s. " - "Something might be wrong with the splitting, check the document affected to prevent issues at " - "query time. This document will be now hard-split at %s chars recursively.", - document.id, - len(document.content), - max_chars_check, - max_chars_check, - ) - fields = document.to_dict() - document.content = document.content[:max_chars_check] - fields.pop("id") - fields["content"] = fields["content"][max_chars_check:] - # recursively check if tail_document is still too long - tail_documents = self._long_documents( - documents=[Document.from_dict(fields)], max_chars_check=max_chars_check - ) - documents += tail_documents - return documents - - def _process_single( - self, - document: Union[dict, Document], - clean_whitespace: Optional[bool] = None, - clean_header_footer: Optional[bool] = None, - clean_empty_lines: Optional[bool] = None, - remove_substrings: Optional[List[str]] = None, - split_by: Optional[Literal["token", "word", "sentence", "passage"]] = None, - split_length: Optional[int] = None, - split_overlap: Optional[int] = None, - split_respect_sentence_boundary: Optional[bool] = None, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - if remove_substrings is None: - remove_substrings = [] - if clean_whitespace is None: - clean_whitespace = self.clean_whitespace - if clean_header_footer is None: - clean_header_footer = self.clean_header_footer - if clean_empty_lines is None: - clean_empty_lines = self.clean_empty_lines - if not remove_substrings: - remove_substrings = self.remove_substrings - if split_by is None: - split_by = self.split_by - if split_length is None: - split_length = self.split_length - if split_overlap is None: - split_overlap = self.split_overlap - if split_respect_sentence_boundary is None: - split_respect_sentence_boundary = self.split_respect_sentence_boundary - if tokenizer is None: - tokenizer = self.tokenizer - - cleaned_document = self.clean( - document=document, - clean_whitespace=clean_whitespace, - clean_header_footer=clean_header_footer, - clean_empty_lines=clean_empty_lines, - remove_substrings=remove_substrings, - id_hash_keys=id_hash_keys, - ) - split_documents = self.split( - document=cleaned_document, - split_by=split_by, - split_length=split_length, - split_overlap=split_overlap, - split_respect_sentence_boundary=split_respect_sentence_boundary, - tokenizer=tokenizer, - id_hash_keys=id_hash_keys, - ) - - split_documents = self._long_documents(split_documents, max_chars_check=self.max_chars_check) - - return split_documents - - def _process_batch( - self, documents: List[Union[dict, Document]], id_hash_keys: Optional[List[str]] = None, **kwargs - ) -> List[Document]: - nested_docs = [ - self._process_single(d, id_hash_keys=id_hash_keys, **kwargs) - for d in tqdm(documents, disable=not self.progress_bar, desc="Preprocessing", unit="docs") - ] - return [d for x in nested_docs for d in x] - - def clean( - self, - document: Union[dict, Document], - clean_whitespace: bool, - clean_header_footer: bool, - clean_empty_lines: bool, - remove_substrings: Optional[List[str]] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> Document: - """ - Perform document cleaning on a single document and return a single document. This method will deal with whitespaces, headers, footers - and empty lines. Its exact functionality is defined by the parameters passed into PreProcessor.__init__(). - """ - if remove_substrings is None: - remove_substrings = [] - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - if isinstance(document, dict): - document["id_hash_keys"] = id_hash_keys - document = Document.from_dict(document) - - # Mainly needed for type checking - if not isinstance(document, Document): - raise HaystackError("Document must not be of type 'dict' but of type 'Document'.") - - if type(document.content) is not str: - logger.error("Document content is not of type str. Nothing to clean.") - return document - - text = document.content - if clean_header_footer: - text = self._find_and_remove_header_footer( - text, n_chars=300, n_first_pages_to_ignore=1, n_last_pages_to_ignore=1 - ) - - headlines = document.meta["headlines"] if "headlines" in document.meta else [] - - if clean_whitespace: - text, headlines = self._clean_whitespace(text=text, headlines=headlines) - - if clean_empty_lines: - text, headlines = self._clean_empty_lines(text=text, headlines=headlines) - - for substring in remove_substrings: - text, _ = self._remove_substring(text=text, substring=substring, headlines=headlines) - - if text != document.content: - document = deepcopy(document) - document.content = text - if headlines: - document.meta["headlines"] = headlines - - return document - - def split( - self, - document: Union[dict, Document], - split_by: Optional[Literal["token", "word", "sentence", "passage"]], - split_length: int, - split_overlap: int, - split_respect_sentence_boundary: bool, - tokenizer: Optional[Union[str, PreTrainedTokenizerBase]] = None, - id_hash_keys: Optional[List[str]] = None, - ) -> List[Document]: - """Perform document splitting on a single document. This method can split on different units, at different lengths, - with different strides. It can also respect sentence boundaries. Its exact functionality is defined by - the parameters passed into PreProcessor.__init__(). Takes a single document as input and returns a list of documents. - """ - if id_hash_keys is None: - id_hash_keys = self.id_hash_keys - - if isinstance(document, dict): - document["id_hash_keys"] = id_hash_keys - document = Document.from_dict(document) - - # Mainly needed for type checking - if not isinstance(document, Document): - raise HaystackError("Document must not be of type 'dict' but of type 'Document'.") - - if not split_by: - return [document] - - if not split_length: - raise Exception("split_length needs be set when using split_by.") - - if split_respect_sentence_boundary and split_by not in ["word", "token"]: - raise NotImplementedError( - "'split_respect_sentence_boundary=True' is only compatible with split_by='word' or 'token'." - ) - - if type(document.content) is not str: - logger.error("Document content is not of type str. Nothing to split.") - return [document] - - text = document.content - headlines = document.meta["headlines"] if "headlines" in document.meta else [] - - if split_respect_sentence_boundary and split_by in ["word", "token"]: - - def split_function(text): - return self._split_tokens(text, tokenizer=tokenizer) if split_by == "token" else text.split() - - text_splits, splits_pages, splits_start_idxs = self._split_into_units_respecting_sent_boundary( - text=text, split_length=split_length, split_overlap=split_overlap, split_function=split_function - ) - else: - # create individual "elements" of passage, sentence, or word - elements, split_at = self._split_into_units(text=text, split_by=split_by, tokenizer=tokenizer) - - # concatenate individual elements based on split_length & split_stride - text_splits, splits_pages, splits_start_idxs = self._concatenate_units( - elements=elements, split_length=split_length, split_overlap=split_overlap, split_at=split_at - ) - - # create new document dicts for each text split - documents = self._create_docs_from_splits( - text_splits=text_splits, - splits_pages=splits_pages, - splits_start_idxs=splits_start_idxs, - headlines=headlines, - meta=document.meta or {}, - split_overlap=split_overlap, - id_hash_keys=id_hash_keys, - ) - - return documents - - @staticmethod - def _clean_whitespace(text: str, headlines: List[Dict]) -> Tuple[str, List[Dict]]: - """ - Strips whitespaces before or after each line in the text. - """ - pages = text.split("\f") - cleaned_pages = [] - cur_headline_idx = 0 - num_headlines = len(headlines) - cur_char_idx = 0 - num_removed_chars_total = 0 - for page in pages: - lines = page.splitlines() - cleaned_lines = [] - for line in lines: - old_line_len = len(line) - cleaned_line = line.strip() - cleaned_line_len = len(cleaned_line) - cur_char_idx += old_line_len + 1 # add 1 for newline char - if old_line_len != cleaned_line_len: - num_removed_chars_current = old_line_len - cleaned_line_len - num_removed_chars_total += num_removed_chars_current - for headline_idx in range(cur_headline_idx, num_headlines): - if cur_char_idx - num_removed_chars_total <= headlines[headline_idx]["start_idx"]: - headlines[headline_idx]["start_idx"] -= num_removed_chars_current - else: - cur_headline_idx += 1 - - cleaned_lines.append(cleaned_line) - cleaned_page = "\n".join(cleaned_lines) - cleaned_pages.append(cleaned_page) - - cleaned_text = "\f".join(cleaned_pages) - return cleaned_text, headlines - - @staticmethod - def _clean_empty_lines(text: str, headlines: List[Dict]) -> Tuple[str, List[Dict]]: - if headlines: - num_headlines = len(headlines) - multiple_new_line_matches = re.finditer(r"\n\n\n+", text) - cur_headline_idx = 0 - num_removed_chars_accumulated = 0 - for match in multiple_new_line_matches: - num_removed_chars_current = match.end() - match.start() - 2 - for headline_idx in range(cur_headline_idx, num_headlines): - if match.end() - num_removed_chars_accumulated <= headlines[headline_idx]["start_idx"]: - headlines[headline_idx]["start_idx"] -= num_removed_chars_current - else: - cur_headline_idx += 1 - num_removed_chars_accumulated += num_removed_chars_current - - cleaned_text = re.sub(r"\n\n\n+", "\n\n", text) - return cleaned_text, headlines - - @staticmethod - def _remove_substring(text: str, substring: str, headlines: List[Dict]) -> Tuple[str, List[Dict]]: - if headlines: - num_headlines = len(headlines) - multiple_substring_matches = re.finditer(substring, text) - cur_headline_idx = 0 - num_removed_chars_accumulated = 0 - for match in multiple_substring_matches: - for headline_idx in range(cur_headline_idx, num_headlines): - if match.end() - num_removed_chars_accumulated <= headlines[headline_idx]["start_idx"]: - headlines[headline_idx]["start_idx"] -= len(substring) - else: - cur_headline_idx += 1 - num_removed_chars_accumulated += len(substring) - - cleaned_text = text.replace(substring, "") - return cleaned_text, headlines - - def _split_into_units_respecting_sent_boundary( - self, text: str, split_length: int, split_overlap: int, split_function: Callable - ) -> Tuple[List[str], List[int], List[int]]: - """ - Splits the text into parts of split_length words while respecting sentence boundaries. - """ - sentences = self._split_sentences(text) - - unit_count_slice = 0 - cur_page = 1 - cur_start_idx = 0 - splits_pages = [] - list_splits = [] - splits_start_idxs = [] - current_slice: List[str] = [] - for sen in sentences: - unit_count_sen = len(split_function(sen)) - - if unit_count_sen > split_length: - long_sentence_message = ( - "We found one or more sentences whose split count is higher than the split length." - ) - if long_sentence_message not in self.print_log: - self.print_log.add(long_sentence_message) - logger.warning(long_sentence_message) - - if unit_count_slice + unit_count_sen > split_length: - # Number of words exceeds split_length -> save current slice and start a new one - if current_slice: - list_splits.append(current_slice) - splits_pages.append(cur_page) - splits_start_idxs.append(cur_start_idx) - - if split_overlap: - processed_sents, current_slice, unit_count_slice = self._get_overlap_from_slice( - current_slice, split_length, split_overlap, split_function - ) - else: - processed_sents = current_slice - current_slice = [] - unit_count_slice = 0 - - cur_start_idx += len("".join(processed_sents)) - - # Count number of page breaks in processed sentences - if self.add_page_number: - num_page_breaks = self._count_processed_page_breaks( - sentences=processed_sents, - split_overlap=split_overlap, - overlapping_sents=current_slice, - current_sent=sen, - ) - cur_page += num_page_breaks - - current_slice.append(sen) - unit_count_slice += unit_count_sen - - if current_slice: - list_splits.append(current_slice) - splits_pages.append(cur_page) - splits_start_idxs.append(cur_start_idx) - - text_splits = [] - for sl in list_splits: - txt = "".join(sl) - if len(txt) > 0: - text_splits.append(txt) - - return text_splits, splits_pages, splits_start_idxs - - @staticmethod - def _get_overlap_from_slice( - current_slice: List[str], split_length: int, split_overlap: int, split_function: Callable - ) -> Tuple[List[str], List[str], int]: - """ - Returns a tuple with the following elements: - - processed_sents: List of sentences that are not overlapping the with next slice (= completely processed sentences) - - next_slice: List of sentences that are overlapping with the next slice - - word_count_slice: Number of words in the next slice - """ - - overlap = [] - word_count_overlap = 0 - current_slice_copy = deepcopy(current_slice) - # Next overlapping Document should not start exactly the same as the previous one, so we skip the first sentence - for idx, s in reversed(list(enumerate(current_slice))[1:]): - sen_len = len(split_function(s)) - if word_count_overlap < split_overlap and sen_len < split_length: - overlap.append(s) - word_count_overlap += sen_len - current_slice_copy.pop(idx) - else: - break - processed_sents = current_slice_copy - next_slice = list(reversed(overlap)) - word_count_slice = word_count_overlap - - return processed_sents, next_slice, word_count_slice - - def _split_into_units(self, text: str, split_by: str, tokenizer: Any) -> Tuple[List[str], str]: - if split_by == "passage": - elements = text.split("\n\n") - split_at = "\n\n" - elif split_by == "sentence": - elements = self._split_sentences(text) - split_at = "" # whitespace will be preserved while splitting text into sentences - elif split_by == "word": - elements = text.split(" ") - split_at = " " - elif split_by == "token": - elements = self._split_tokens(text, tokenizer) - split_at = "" - else: - raise NotImplementedError( - "PreProcessor only supports 'passage', 'sentence', 'word' or 'token' split_by options." - ) - - return elements, split_at - - def _concatenate_units( - self, elements: List[str], split_length: int, split_overlap: int, split_at: str - ) -> Tuple[List[str], List[int], List[int]]: - """ - Concatenates the elements into parts of split_length units. - """ - segments = windowed(elements, n=split_length, step=split_length - split_overlap) - split_at_len = len(split_at) - text_splits = [] - splits_pages = [] - splits_start_idxs = [] - cur_page = 1 - cur_start_idx = 0 - for seg in segments: - current_units = [unit for unit in seg if unit is not None] - txt = split_at.join(current_units) - if len(txt) > 0: - text_splits.append(txt) - splits_pages.append(cur_page) - splits_start_idxs.append(cur_start_idx) - processed_units = current_units[: split_length - split_overlap] - cur_start_idx += len((split_at_len * " ").join(processed_units)) + split_at_len - if self.add_page_number: - num_page_breaks = sum(processed_unit.count("\f") for processed_unit in processed_units) - cur_page += num_page_breaks - - return text_splits, splits_pages, splits_start_idxs - - def _create_docs_from_splits( - self, - text_splits: List[str], - splits_pages: List[int], - splits_start_idxs: List[int], - headlines: List[Dict], - meta: Dict, - split_overlap: int, - id_hash_keys=Optional[List[str]], - ) -> List[Document]: - """ - Creates Document objects from text splits enriching them with page number and headline information if given. - """ - documents: List[Document] = [] - - earliest_rel_hl = 0 - for i, txt in enumerate(text_splits): - meta = deepcopy(meta) - doc = Document(content=txt, meta=meta, id_hash_keys=id_hash_keys) - doc.meta["_split_id"] = i - if self.add_page_number: - doc.meta["page"] = splits_pages[i] - if headlines: - split_start_idx = splits_start_idxs[i] - relevant_headlines, earliest_rel_hl = self._extract_relevant_headlines_for_split( - headlines=headlines, split_txt=txt, split_start_idx=split_start_idx, earliest_rel_hl=earliest_rel_hl - ) - doc.meta["headlines"] = relevant_headlines - if split_overlap > 0: - doc.meta["_split_overlap"] = [] - if i != 0: - doc_start_idx = splits_start_idxs[i] - previous_doc = documents[i - 1] - previous_doc_start_idx = splits_start_idxs[i - 1] - self._add_split_overlap_information(doc, doc_start_idx, previous_doc, previous_doc_start_idx) - - documents.append(doc) - - return documents - - @staticmethod - def _add_split_overlap_information( - current_doc: Document, current_doc_start_idx: int, previous_doc: Document, previos_doc_start_idx: int - ): - """ - Adds split overlap information to the current and previous Document's meta. - """ - overlapping_range = (current_doc_start_idx - previos_doc_start_idx, len(previous_doc.content) - 1) - if overlapping_range[0] < overlapping_range[1]: - overlapping_str = previous_doc.content[overlapping_range[0] : overlapping_range[1]] - if current_doc.content.startswith(overlapping_str): - # Add split overlap information to previous Document regarding this Document - previous_doc.meta["_split_overlap"].append({"doc_id": current_doc.id, "range": overlapping_range}) - # Add split overlap information to this Document regarding the previous Document - overlapping_range = (0, overlapping_range[1] - overlapping_range[0]) - current_doc.meta["_split_overlap"].append({"doc_id": previous_doc.id, "range": overlapping_range}) - - @staticmethod - def _extract_relevant_headlines_for_split( - headlines: List[Dict], split_txt: str, split_start_idx: int, earliest_rel_hl: int - ) -> Tuple[List[Dict], int]: - """ - If you give it a list of headlines, a text split, and the start index of the split in the original text, this method - extracts the headlines that are relevant for the split. - """ - relevant_headlines = [] - - for headline_idx in range(earliest_rel_hl, len(headlines)): - # Headline is part of current split - if split_start_idx <= headlines[headline_idx]["start_idx"] < split_start_idx + len(split_txt): - headline_copy = deepcopy(headlines[headline_idx]) - headline_copy["start_idx"] = headlines[headline_idx]["start_idx"] - split_start_idx - relevant_headlines.append(headline_copy) - # Headline appears before current split, but might be relevant for current split - elif headlines[headline_idx]["start_idx"] < split_start_idx: - # Check if following headlines are on a higher level - headline_to_check = headline_idx + 1 - headline_is_relevant = True - while ( - headline_to_check < len(headlines) and headlines[headline_to_check]["start_idx"] <= split_start_idx - ): - if headlines[headline_to_check]["level"] <= headlines[headline_idx]["level"]: - headline_is_relevant = False - break - headline_to_check += 1 - if headline_is_relevant: - headline_copy = deepcopy(headlines[headline_idx]) - headline_copy["start_idx"] = None - relevant_headlines.append(headline_copy) - else: - earliest_rel_hl += 1 - # Headline (and all subsequent ones) only relevant for later splits - elif headlines[headline_idx]["start_idx"] > split_start_idx + len(split_txt): - break - - return relevant_headlines, earliest_rel_hl - - def _find_and_remove_header_footer( - self, text: str, n_chars: int, n_first_pages_to_ignore: int, n_last_pages_to_ignore: int - ) -> str: - """ - Heuristic to find footers and headers across different pages by searching for the longest common string. - For headers we only search in the first n_chars characters (for footer: last n_chars). - Note: This heuristic uses exact matches and therefore works well for footers like "Copyright 2019 by XXX", - but won't detect "Page 3 of 4" or similar. - - :param n_chars: number of first/last characters where the header/footer shall be searched in - :param n_first_pages_to_ignore: number of first pages to ignore (e.g. TOCs often don't contain footer/header) - :param n_last_pages_to_ignore: number of last pages to ignore - :return: (cleaned pages, found_header_str, found_footer_str) - """ - - pages = text.split("\f") - - # header - start_of_pages = [p[:n_chars] for p in pages[n_first_pages_to_ignore:-n_last_pages_to_ignore]] - found_header = self._find_longest_common_ngram(start_of_pages) - if found_header: - pages = [page.replace(found_header, "") for page in pages] - - # footer - end_of_pages = [p[-n_chars:] for p in pages[n_first_pages_to_ignore:-n_last_pages_to_ignore]] - found_footer = self._find_longest_common_ngram(end_of_pages) - if found_footer: - pages = [page.replace(found_footer, "") for page in pages] - logger.debug("Removed header '%s' and footer '%s' in document", found_header, found_footer) - text = "\f".join(pages) - return text - - def _ngram(self, seq: str, n: int) -> Generator[str, None, None]: - """ - Return ngram (of tokens - currently split by whitespace) - :param seq: str, string from which the ngram shall be created - :param n: int, n of ngram - :return: str, ngram as string - """ - - # In order to maintain the original whitespace, but still consider \n and \t for n-gram tokenization, - # we add a space here and remove it after creation of the ngrams again (see below) - seq = seq.replace("\n", " \n") - seq = seq.replace("\t", " \t") - - words = seq.split(" ") - ngrams = ( - " ".join(words[i : i + n]).replace(" \n", "\n").replace(" \t", "\t") for i in range(0, len(words) - n + 1) - ) - - return ngrams - - def _allngram(self, seq: str, min_ngram: int, max_ngram: int) -> Set[str]: - lengths = range(min_ngram, max_ngram) if max_ngram else range(min_ngram, len(seq)) - ngrams = map(partial(self._ngram, seq), lengths) - res = set(chain.from_iterable(ngrams)) - return res - - def _find_longest_common_ngram( - self, sequences: List[str], max_ngram: int = 30, min_ngram: int = 3 - ) -> Optional[str]: - """ - Find the longest common ngram across different text sequences (e.g. start of pages). - Considering all ngrams between the specified range. Helpful for finding footers, headers etc. - - :param sequences: list[str], list of strings that shall be searched for common n_grams - :param max_ngram: int, maximum length of ngram to consider - :param min_ngram: minimum length of ngram to consider - :return: str, common string of all sections - """ - sequences = [s for s in sequences if s] # filter empty sequences - if not sequences: - return None - seqs_ngrams = map(partial(self._allngram, min_ngram=min_ngram, max_ngram=max_ngram), sequences) - intersection = reduce(set.intersection, seqs_ngrams) - - try: - longest = max(intersection, key=len) - except ValueError: - # no common sequence found - longest = "" - return longest if longest.strip() else None - - def _split_sentences(self, text: str) -> List[str]: - """ - Tokenize text into sentences. - :param text: str, text to tokenize - :return: list[str], list of sentences - """ - language_name = iso639_to_nltk.get(self.language) - - sentence_tokenizer = self._load_sentence_tokenizer(language_name) - # The following adjustment of PunktSentenceTokenizer is inspired by: - # https://stackoverflow.com/questions/33139531/preserve-empty-lines-with-nltks-punkt-tokenizer - # It is needed for preserving whitespace while splitting text into sentences. - period_context_fmt = r""" - %(SentEndChars)s # a potential sentence ending - \s* # match potential whitespace (is originally in lookahead assertion) - (?=(?P - %(NonWord)s # either other punctuation - | - (?P\S+) # or some other token - original version: \s+(?P\S+) - ))""" - re_period_context = re.compile( - period_context_fmt - % { - "NonWord": sentence_tokenizer._lang_vars._re_non_word_chars, - # SentEndChars might be followed by closing brackets, so we match them here. - "SentEndChars": sentence_tokenizer._lang_vars._re_sent_end_chars + r"[\)\]}]*", - }, - re.UNICODE | re.VERBOSE, - ) - sentence_tokenizer._lang_vars._re_period_context = re_period_context - - sentences = sentence_tokenizer.tokenize(text) - return sentences - - def _split_tokens(self, text: str, tokenizer: Any) -> List[str]: - if tokenizer == "tiktoken": - tiktoken_import.check() - enc = tiktoken.get_encoding("cl100k_base") # tiktoken is reversible and lossless - integer_tokens = enc.encode(text, disallowed_special=()) - elements = [enc.decode_single_token_bytes(token).decode(errors="ignore") for token in integer_tokens] - return elements - if isinstance(tokenizer, str): - transformers_import.check() - try: - tokenizer = AutoTokenizer.from_pretrained(tokenizer) - except Exception: - raise ValueError( - f"Could not load tokenizer '{tokenizer}' from HuggingFace model hub. " - f"Please make sure that the tokenizer is correct and exists." - ) - if isinstance(tokenizer, PreTrainedTokenizerBase): - encoded = tokenizer.encode_plus(text, return_offsets_mapping=True, add_special_tokens=False) - elements = [] - for i in range(l := len(encoded.offset_mapping)): - start_current = encoded.offset_mapping[i][0] - start_next = encoded.offset_mapping[i + 1][0] if i < l - 1 else len(text) - elements.append(text[start_current:start_next]) - return elements - raise ValueError( - f"Unsupported tokenizer specification {tokenizer}. " - f"Please provide either the string 'tiktoken' or a HuggingFace tokenizer (PreTrainedTokenizerBase)." - ) - - def _load_sentence_tokenizer(self, language_name: Optional[str]) -> "nltk.tokenize.punkt.PunktSentenceTokenizer": - # Try to load a custom model from 'tokenizer_model_path' - if self.tokenizer_model_folder is not None: - tokenizer_model_path = Path(self.tokenizer_model_folder).absolute() / f"{self.language}.pickle" - try: - sentence_tokenizer = nltk.data.load(f"file:{str(tokenizer_model_path)}", format="pickle") - except (LookupError, UnpicklingError, ValueError) as e: - if isinstance(e, LookupError): - logger.exception("PreProcessor couldn't load sentence tokenizer from %s", tokenizer_model_path) - else: - logger.exception( - "PreProcessor couldn't determine model format of sentence tokenizer at %s", tokenizer_model_path - ) - - # NLTK failed to load custom SentenceTokenizer, fallback to the default model or to English - if language_name is not None: - logger.error( - "PreProcessor couldn't find custom sentence tokenizer model for %s. Using default %s model.", - self.language, - self.language, - ) - sentence_tokenizer = nltk.data.load(f"tokenizers/punkt/{language_name}.pickle") - else: - logger.error( - "PreProcessor couldn't find default or custom sentence tokenizer model for %s. " - "Using English instead.", - self.language, - ) - sentence_tokenizer = nltk.data.load("tokenizers/punkt/english.pickle") - - # Use a default NLTK model - elif language_name is not None: - sentence_tokenizer = nltk.data.load(f"tokenizers/punkt/{language_name}.pickle") - else: - logger.error( - "PreProcessor couldn't find the default sentence tokenizer model for %s. " - " Using English instead. You may train your own model and use the 'tokenizer_model_folder' parameter.", - self.language, - ) - sentence_tokenizer = nltk.data.load("tokenizers/punkt/english.pickle") - - return sentence_tokenizer - - @staticmethod - def _count_processed_page_breaks( - sentences: List[str], split_overlap: int, overlapping_sents: List[str], current_sent: str - ) -> int: - """ - Counts the number of processed page breaks in a list of processed sentences. - """ - num_page_breaks = sum(sent.count("\f") for sent in sentences) - if sentences and sentences[0].startswith("\f"): - # Remove already used page break - num_page_breaks -= 1 - # Increment page counter if new split starts with a page break - if split_overlap and overlapping_sents: - if overlapping_sents[0].startswith("\f"): - num_page_breaks += 1 - else: - if current_sent.startswith("\f"): - num_page_breaks += 1 - - return num_page_breaks diff --git a/haystack/nodes/prompt/__init__.py b/haystack/nodes/prompt/__init__.py deleted file mode 100644 index 2c30fc7850..0000000000 --- a/haystack/nodes/prompt/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from haystack.nodes.prompt.prompt_node import PromptNode -from haystack.nodes.prompt.prompt_template import PromptTemplate -from haystack.nodes.prompt.prompt_model import PromptModel -from haystack.nodes.prompt.shapers import BaseOutputParser, AnswerParser diff --git a/haystack/nodes/prompt/invocation_layer/__init__.py b/haystack/nodes/prompt/invocation_layer/__init__.py deleted file mode 100644 index 778d557c10..0000000000 --- a/haystack/nodes/prompt/invocation_layer/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from haystack.nodes.prompt.invocation_layer.azure_open_ai import AzureOpenAIInvocationLayer -from haystack.nodes.prompt.invocation_layer.base import PromptModelInvocationLayer -from haystack.nodes.prompt.invocation_layer.chatgpt import ChatGPTInvocationLayer -from haystack.nodes.prompt.invocation_layer.azure_chatgpt import AzureChatGPTInvocationLayer -from haystack.nodes.prompt.invocation_layer.handlers import TokenStreamingHandler, DefaultTokenStreamingHandler -from haystack.nodes.prompt.invocation_layer.open_ai import OpenAIInvocationLayer -from haystack.nodes.prompt.invocation_layer.anthropic_claude import AnthropicClaudeInvocationLayer -from haystack.nodes.prompt.invocation_layer.cohere import CohereInvocationLayer -from haystack.nodes.prompt.invocation_layer.hugging_face import HFLocalInvocationLayer -from haystack.nodes.prompt.invocation_layer.hugging_face_inference import HFInferenceEndpointInvocationLayer -from haystack.nodes.prompt.invocation_layer.amazon_bedrock import AmazonBedrockInvocationLayer -from haystack.nodes.prompt.invocation_layer.sagemaker_meta import SageMakerMetaInvocationLayer -from haystack.nodes.prompt.invocation_layer.sagemaker_hf_infer import SageMakerHFInferenceInvocationLayer -from haystack.nodes.prompt.invocation_layer.sagemaker_hf_text_gen import SageMakerHFTextGenerationInvocationLayer diff --git a/haystack/nodes/prompt/invocation_layer/amazon_bedrock.py b/haystack/nodes/prompt/invocation_layer/amazon_bedrock.py deleted file mode 100644 index 51f88b14c4..0000000000 --- a/haystack/nodes/prompt/invocation_layer/amazon_bedrock.py +++ /dev/null @@ -1,372 +0,0 @@ -from abc import ABC, abstractmethod -import json -import logging -import re -from typing import Any, Optional, Dict, Type, Union, List - -from haystack.errors import AWSConfigurationError, AmazonBedrockConfigurationError, AmazonBedrockInferenceError -from haystack.lazy_imports import LazyImport -from haystack.nodes.prompt.invocation_layer.aws_base import AWSBaseInvocationLayer -from haystack.nodes.prompt.invocation_layer.handlers import ( - DefaultPromptHandler, - DefaultTokenStreamingHandler, - TokenStreamingHandler, -) - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[aws]'") as boto3_import: - from botocore.exceptions import ClientError - - -class BedrockModelAdapter(ABC): - """ - Base class for Amazon Bedrock model adapters. - """ - - def __init__(self, model_kwargs: Dict[str, Any], max_length: Optional[int]) -> None: - self.model_kwargs = model_kwargs - self.max_length = max_length - - @abstractmethod - def prepare_body(self, prompt: str, **inference_kwargs) -> Dict[str, Any]: - """Prepares the body for the Amazon Bedrock request.""" - - def get_responses(self, response_body: Dict[str, Any]) -> List[str]: - """Extracts the responses from the Amazon Bedrock response.""" - completions = self._extract_completions_from_response(response_body) - responses = [completion.lstrip() for completion in completions] - return responses - - def get_stream_responses(self, stream, stream_handler: TokenStreamingHandler) -> List[str]: - tokens: List[str] = [] - for event in stream: - chunk = event.get("chunk") - if chunk: - decoded_chunk = json.loads(chunk["bytes"].decode("utf-8")) - token = self._extract_token_from_stream(decoded_chunk) - tokens.append(stream_handler(token, event_data=decoded_chunk)) - responses = ["".join(tokens).lstrip()] - return responses - - def _get_params(self, inference_kwargs: Dict[str, Any], default_params: Dict[str, Any]) -> Dict[str, Any]: - """ - Merges the default params with the inference kwargs and model kwargs. - - Includes param if it's in kwargs or its default is not None (i.e. it is actually defined). - """ - kwargs = self.model_kwargs.copy() - kwargs.update(inference_kwargs) - return { - param: kwargs.get(param, default) - for param, default in default_params.items() - if param in kwargs or default is not None - } - - @abstractmethod - def _extract_completions_from_response(self, response_body: Dict[str, Any]) -> List[str]: - """Extracts the responses from the Amazon Bedrock response.""" - - @abstractmethod - def _extract_token_from_stream(self, chunk: Dict[str, Any]) -> str: - """Extracts the token from a streaming chunk.""" - - -class AnthropicClaudeAdapter(BedrockModelAdapter): - """ - Model adapter for the Anthropic's Claude model. - """ - - def prepare_body(self, prompt: str, **inference_kwargs) -> Dict[str, Any]: - default_params = { - "max_tokens_to_sample": self.max_length, - "stop_sequences": ["\n\nHuman:"], - "temperature": None, - "top_p": None, - "top_k": None, - } - params = self._get_params(inference_kwargs, default_params) - - body = {"prompt": f"\n\nHuman: {prompt}\n\nAssistant:", **params} - return body - - def _extract_completions_from_response(self, response_body: Dict[str, Any]) -> List[str]: - return [response_body["completion"]] - - def _extract_token_from_stream(self, chunk: Dict[str, Any]) -> str: - return chunk.get("completion", "") - - -class CohereCommandAdapter(BedrockModelAdapter): - """ - Model adapter for the Cohere's Command model. - """ - - def prepare_body(self, prompt: str, **inference_kwargs) -> Dict[str, Any]: - default_params = { - "max_tokens": self.max_length, - "stop_sequences": None, - "temperature": None, - "p": None, - "k": None, - "return_likelihoods": None, - "stream": None, - "logit_bias": None, - "num_generations": None, - "truncate": None, - } - params = self._get_params(inference_kwargs, default_params) - - body = {"prompt": prompt, **params} - return body - - def _extract_completions_from_response(self, response_body: Dict[str, Any]) -> List[str]: - responses = [generation["text"] for generation in response_body["generations"]] - return responses - - def _extract_token_from_stream(self, chunk: Dict[str, Any]) -> str: - return chunk.get("text", "") - - -class AI21LabsJurassic2Adapter(BedrockModelAdapter): - """ - Model adapter for AI21 Labs' Jurassic 2 models. - """ - - def prepare_body(self, prompt: str, **inference_kwargs) -> Dict[str, Any]: - default_params = { - "maxTokens": self.max_length, - "stopSequences": None, - "temperature": None, - "topP": None, - "countPenalty": None, - "presencePenalty": None, - "frequencyPenalty": None, - "numResults": None, - } - params = self._get_params(inference_kwargs, default_params) - - body = {"prompt": prompt, **params} - return body - - def _extract_completions_from_response(self, response_body: Dict[str, Any]) -> List[str]: - responses = [completion["data"]["text"] for completion in response_body["completions"]] - return responses - - def _extract_token_from_stream(self, chunk: Dict[str, Any]) -> str: - raise NotImplementedError("Streaming is not supported for AI21 Jurassic 2 models.") - - -class AmazonTitanAdapter(BedrockModelAdapter): - """ - Model adapter for Amazon's Titan models. - """ - - def prepare_body(self, prompt: str, **inference_kwargs) -> Dict[str, Any]: - default_params = {"maxTokenCount": self.max_length, "stopSequences": None, "temperature": None, "topP": None} - params = self._get_params(inference_kwargs, default_params) - - body = {"inputText": prompt, "textGenerationConfig": params} - return body - - def _extract_completions_from_response(self, response_body: Dict[str, Any]) -> List[str]: - responses = [result["outputText"] for result in response_body["results"]] - return responses - - def _extract_token_from_stream(self, chunk: Dict[str, Any]) -> str: - return chunk.get("outputText", "") - - -class MetaLlama2ChatAdapter(BedrockModelAdapter): - """ - Model adapter for Meta's Llama 2 Chat models. - """ - - def prepare_body(self, prompt: str, **inference_kwargs) -> Dict[str, Any]: - default_params = {"max_gen_len": self.max_length, "temperature": None, "top_p": None} - params = self._get_params(inference_kwargs, default_params) - - body = {"prompt": prompt, **params} - return body - - def _extract_completions_from_response(self, response_body: Dict[str, Any]) -> List[str]: - return [response_body["generation"]] - - def _extract_token_from_stream(self, chunk: Dict[str, Any]) -> str: - return chunk.get("generation", "") - - -class AmazonBedrockInvocationLayer(AWSBaseInvocationLayer): - """ - Invocation layer for Amazon Bedrock models. - """ - - SUPPORTED_MODEL_PATTERNS: Dict[str, Type[BedrockModelAdapter]] = { - r"amazon.titan-text.*": AmazonTitanAdapter, - r"ai21.j2.*": AI21LabsJurassic2Adapter, - r"cohere.command.*": CohereCommandAdapter, - r"anthropic.claude.*": AnthropicClaudeAdapter, - r"meta.llama2.*": MetaLlama2ChatAdapter, - } - - def __init__( - self, - model_name_or_path: str, - aws_access_key_id: Optional[str] = None, - aws_secret_access_key: Optional[str] = None, - aws_session_token: Optional[str] = None, - aws_region_name: Optional[str] = None, - aws_profile_name: Optional[str] = None, - max_length: Optional[int] = 100, - **kwargs, - ): - super().__init__(model_name_or_path, **kwargs) - self.max_length = max_length - - try: - session = self.get_aws_session( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token, - aws_region_name=aws_region_name, - aws_profile_name=aws_profile_name, - ) - self.client = session.client("bedrock-runtime") - except Exception as exception: - raise AmazonBedrockConfigurationError( - "Could not connect to Amazon Bedrock. Make sure the AWS environment is configured correctly. " - "See https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration" - ) from exception - - model_input_kwargs = kwargs - # We pop the model_max_length as it is not sent to the model - # but used to truncate the prompt if needed - model_max_length = kwargs.get("model_max_length", 4096) - - # Truncate prompt if prompt tokens > model_max_length-max_length - # (max_length is the length of the generated text) - # It is hard to determine which tokenizer to use for the SageMaker model - # so we use GPT2 tokenizer which will likely provide good token count approximation - self.prompt_handler = DefaultPromptHandler( - model_name_or_path="gpt2", model_max_length=model_max_length, max_length=self.max_length or 100 - ) - - model_apapter_cls = self.get_model_adapter(model_name_or_path=model_name_or_path) - if not model_apapter_cls: - raise AmazonBedrockConfigurationError( - f"This invocation layer doesn't support the model {model_name_or_path}." - ) - self.model_adapter = model_apapter_cls(model_kwargs=model_input_kwargs, max_length=self.max_length) - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - # the prompt for this model will be of the type str - if isinstance(prompt, List): - raise ValueError( - "The SageMaker invocation layer only supports a string as a prompt, " - "while currently, the prompt is a dictionary." - ) - - resize_info = self.prompt_handler(prompt) - if resize_info["prompt_length"] != resize_info["new_prompt_length"]: - logger.warning( - "The prompt was truncated from %s tokens to %s tokens so that the prompt length and " - "the answer length (%s tokens) fit within the model's max token limit (%s tokens). " - "Shorten the prompt or it will be cut off.", - resize_info["prompt_length"], - max(0, resize_info["model_max_length"] - resize_info["max_length"]), # type: ignore - resize_info["max_length"], - resize_info["model_max_length"], - ) - return str(resize_info["resized_prompt"]) - - @classmethod - def supports(cls, model_name_or_path, **kwargs): - model_supported = cls.get_model_adapter(model_name_or_path) is not None - if not model_supported or not cls.aws_configured(**kwargs): - return False - - try: - session = cls.get_aws_session(**kwargs) - bedrock = session.client("bedrock") - foundation_models_response = bedrock.list_foundation_models(byOutputModality="TEXT") - available_model_ids = [entry["modelId"] for entry in foundation_models_response.get("modelSummaries", [])] - model_ids_supporting_streaming = [ - entry["modelId"] - for entry in foundation_models_response.get("modelSummaries", []) - if entry.get("responseStreamingSupported", False) - ] - except AWSConfigurationError as exception: - raise AmazonBedrockConfigurationError(message=exception.message) from exception - except Exception as exception: - raise AmazonBedrockConfigurationError( - "Could not connect to Amazon Bedrock. Make sure the AWS environment is configured correctly. " - "See https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration" - ) from exception - - model_available = model_name_or_path in available_model_ids - if not model_available: - raise AmazonBedrockConfigurationError( - f"The model {model_name_or_path} is not available in Amazon Bedrock. " - f"Make sure the model you want to use is available in the configured AWS region and you have access." - ) - - stream: bool = kwargs.get("stream", False) - model_supports_streaming = model_name_or_path in model_ids_supporting_streaming - if stream and not model_supports_streaming: - raise AmazonBedrockConfigurationError( - f"The model {model_name_or_path} doesn't support streaming. Remove the `stream` parameter." - ) - - return model_supported - - def invoke(self, *args, **kwargs): - kwargs = kwargs.copy() - prompt: str = kwargs.pop("prompt", None) - stream: bool = kwargs.get("stream", self.model_adapter.model_kwargs.get("stream", False)) - - if not prompt or not isinstance(prompt, (str, list)): - raise ValueError( - f"The model {self.model_name_or_path} requires a valid prompt, but currently, it has no prompt. " - f"Make sure to provide a prompt in the format that the model expects." - ) - - body = self.model_adapter.prepare_body(prompt=prompt, **kwargs) - try: - if stream: - response = self.client.invoke_model_with_response_stream( - body=json.dumps(body), - modelId=self.model_name_or_path, - accept="application/json", - contentType="application/json", - ) - response_stream = response["body"] - handler: TokenStreamingHandler = kwargs.get( - "stream_handler", - self.model_adapter.model_kwargs.get("stream_handler", DefaultTokenStreamingHandler()), - ) - responses = self.model_adapter.get_stream_responses(stream=response_stream, stream_handler=handler) - else: - response = self.client.invoke_model( - body=json.dumps(body), - modelId=self.model_name_or_path, - accept="application/json", - contentType="application/json", - ) - response_body = json.loads(response.get("body").read().decode("utf-8")) - responses = self.model_adapter.get_responses(response_body=response_body) - except ClientError as exception: - raise AmazonBedrockInferenceError( - f"Could not connect to Amazon Bedrock model {self.model_name_or_path}. " - "Make sure your AWS environment is configured correctly, " - "the model is available in the configured AWS region, and you have access." - ) from exception - - return responses - - @classmethod - def get_model_adapter(cls, model_name_or_path: str) -> Optional[Type[BedrockModelAdapter]]: - for pattern, adapter in cls.SUPPORTED_MODEL_PATTERNS.items(): - if re.fullmatch(pattern, model_name_or_path): - return adapter - return None diff --git a/haystack/nodes/prompt/invocation_layer/anthropic_claude.py b/haystack/nodes/prompt/invocation_layer/anthropic_claude.py deleted file mode 100644 index edd1c6c28c..0000000000 --- a/haystack/nodes/prompt/invocation_layer/anthropic_claude.py +++ /dev/null @@ -1,242 +0,0 @@ -import os -from typing import Dict, List, Union, Optional -import json -import logging - -import requests -import requests_cache -import sseclient -from tokenizers import Tokenizer, Encoding - -from haystack.errors import AnthropicError, AnthropicRateLimitError, AnthropicUnauthorizedError -from haystack.nodes.prompt.invocation_layer.base import PromptModelInvocationLayer -from haystack.nodes.prompt.invocation_layer.handlers import TokenStreamingHandler, DefaultTokenStreamingHandler -from haystack.utils import request_with_retry -from haystack.environment import HAYSTACK_REMOTE_API_MAX_RETRIES, HAYSTACK_REMOTE_API_TIMEOUT_SEC - -ANTHROPIC_TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) -ANTHROPIC_MAX_RETRIES = int(os.environ.get(HAYSTACK_REMOTE_API_MAX_RETRIES, 5)) - -logger = logging.getLogger(__name__) - -# Taken from: -# https://github.com/anthropics/anthropic-sdk-python/blob/main/anthropic/tokenizer.py#L7 -# This is a JSON config to load the tokenizer used for Anthropic Claude. -CLAUDE_TOKENIZER_REMOTE_FILE = ( - "https://raw.githubusercontent.com/anthropics/anthropic-sdk-python/main/src/anthropic/tokenizer.json" -) - - -class AnthropicClaudeInvocationLayer(PromptModelInvocationLayer): - """ - Anthropic Claude Invocation Layer - This layer invokes the Claude API provided by Anthropic. - """ - - def __init__(self, api_key: str, model_name_or_path: str = "claude-2", max_length=200, **kwargs): - """ - Creates an instance of PromptModelInvocation Layer for Claude models by Anthropic. - :param model_name_or_path: The name or path of the underlying model. - :param max_tokens_to_sample: The maximum length of the output text. - :param api_key: The Anthropic API key. - :param kwargs: Additional keyword arguments passed to the underlying model. The list of Anthropic-relevant - kwargs includes: stop_sequences, temperature, top_p, top_k, and stream. For more details about these kwargs, - see Anthropic's [documentation](https://docs.anthropic.com/claude/reference/complete_post). - """ - super().__init__(model_name_or_path) - if not isinstance(api_key, str) or len(api_key) == 0: - raise AnthropicError( - f"api_key {api_key} must be a valid Anthropic key. Visit https://console.anthropic.com/account/keys to get one." - ) - self.api_key = api_key - self.max_length = max_length - - # Due to reflective construction of all invocation layers we might receive some - # unknown kwargs, so we need to take only the relevant. - # For more details refer to Anthropic documentation - supported_kwargs = ["temperature", "top_p", "top_k", "stop_sequences", "stream", "stream_handler"] - self.model_input_kwargs = {k: v for (k, v) in kwargs.items() if k in supported_kwargs} - - # Number of max tokens is based on the official Anthropic documentation - # at https://docs.anthropic.com/claude/docs but it is unclear if older models (i.e. claude-v1) - # have a different limit. Allow users to override it with model_max_length - - self.max_tokens_limit = kwargs.get("model_max_length", 100000) - self.tokenizer: Tokenizer = self._init_tokenizer() - - def _init_tokenizer(self) -> Tokenizer: - # Expire cache after a day - expire_after = 60 * 60 * 60 * 24 - # Cache the JSON config to avoid downloading it each time as it's a big file - with requests_cache.enabled(expire_after=expire_after): - res = request_with_retry(method="GET", url=CLAUDE_TOKENIZER_REMOTE_FILE) - res.raise_for_status() - return Tokenizer.from_str(res.text) - - def invoke(self, *args, **kwargs): - """ - Invokes a prompt on the model. It takes in a prompt and returns a list of responses using a REST invocation. - :return: The responses are being returned. - """ - - human_prompt = "\n\nHuman: " - assistant_prompt = "\n\nAssistant: " - - prompt = kwargs.get("prompt") - if not prompt: - raise ValueError( - f"No prompt provided. Model {self.model_name_or_path} requires prompt." - f"Make sure to provide prompt in kwargs." - ) - - kwargs_with_defaults = self.model_input_kwargs - - if "stop_sequence" in kwargs: - kwargs["stop_words"] = kwargs.pop("stop_sequence") - if "max_tokens_to_sample" in kwargs: - kwargs["max_length"] = kwargs.pop("max_tokens_to_sample") - - kwargs_with_defaults.update(kwargs) - - # Stream the response either in explicitly specified or if a custom handler is set - stream = ( - kwargs_with_defaults.get("stream", False) or kwargs_with_defaults.get("stream_handler", None) is not None - ) - stop_words = kwargs_with_defaults.get("stop_words") or [human_prompt] - - # The human prompt must always be in the stop words list, if it's not - # in there after the user specified some custom ones we append it - if human_prompt not in stop_words: - stop_words.append(human_prompt) - - # As specified by Anthropic the prompt must contain both - # the human and assistant prompt to be valid: - # https://console.anthropic.com/docs/prompt-design#what-is-a-prompt- - prompt = f"{human_prompt}{prompt}{assistant_prompt}" - - data = { - "model": self.model_name_or_path, - "prompt": prompt, - "max_tokens_to_sample": kwargs_with_defaults.get("max_length", self.max_length), - "temperature": kwargs_with_defaults.get("temperature", 1), - "top_p": kwargs_with_defaults.get("top_p", -1), - "top_k": kwargs_with_defaults.get("top_k", -1), - "stream": stream, - "stop_sequences": stop_words, - } - - if not stream: - res = self._post(data=data) - return [res.json()["completion"].strip()] - - res = self._post(data=data, stream=True) - # Anthropic streamed response always includes the whole string that has been - # streamed until that point, so we use a stream handler built ad hoc for this - # invocation layer. - handler: TokenStreamingHandler = kwargs_with_defaults.pop("stream_handler", DefaultTokenStreamingHandler()) - client = sseclient.SSEClient(res) - tokens = [] - try: - for event in client.events(): - ed = json.loads(event.data) - if "completion" in ed: - tokens.append(handler(ed["completion"])) - finally: - client.close() - return ["".join(tokens)] # return a list of strings just like non-streaming - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - """Make sure the length of the prompt and answer is within the max tokens limit of the model. - If needed, truncate the prompt text so that it fits within the limit. - :param prompt: Prompt text to be sent to the generative model. - """ - if isinstance(prompt, List): - raise ValueError("Anthropic invocation layer doesn't support a dictionary as prompt") - - # Tokenizer can handle truncation by itself - token_limit = self.max_tokens_limit - self.max_length - self.tokenizer.enable_truncation(token_limit) - - # The tokenizer we're using accepts either str or List[str], - # if a List[str] is used we must also set is_pretokenized to True. - # We split at spaces because if we pass the string directly the encoded prompts - # contains strange characters in place of spaces. - encoded_prompt: Encoding = self.tokenizer.encode(prompt.split(" "), is_pretokenized=True) - - # overflowing is the list of tokens that have been truncated - if encoded_prompt.overflowing: - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens so that the prompt length and " - "answer length (%s tokens) fits within the max token limit (%s tokens). " - "Reduce the length of the prompt to prevent it from being cut off.", - len(encoded_prompt.ids) + len(encoded_prompt.overflowing), - self.max_tokens_limit - self.max_length, - self.max_length, - self.max_tokens_limit, - ) - - return " ".join(encoded_prompt.tokens) - - def _post( - self, - data: Dict, - attempts: int = ANTHROPIC_MAX_RETRIES, - status_codes_to_retry: Optional[List[int]] = None, - timeout: float = ANTHROPIC_TIMEOUT, - **kwargs, - ): - """ - Post data to Anthropic. - Retries request in case it fails with any code in status_codes_to_retry - or with timeout. - All kwargs are passed to ``requests.request``, so it accepts the same arguments. - Returns a ``requests.Response`` object. - - :param data: Object to send in the body of the request. - :param attempts: Number of times to attempt a request in case of failures, defaults to 5. - :param timeout: Number of seconds to wait for the server to send data before giving up, defaults to 30. - :raises AnthropicRateLimitError: Raised if a request fails with the 429 status code. - :raises AnthropicUnauthorizedError: Raised if a request fails with the 401 status code. - :raises AnthropicError: Raised if requests fail for any other reason. - :return: :class:`Response ` object - """ - if status_codes_to_retry is None: - status_codes_to_retry = [429] - - try: - response = request_with_retry( - attempts=attempts, - status_codes_to_retry=status_codes_to_retry, - method="POST", - url="https://api.anthropic.com/v1/complete", - headers={ - "x-api-key": self.api_key, - "Content-Type": "application/json", - "anthropic-version": "2023-06-01", - }, - data=json.dumps(data), - timeout=timeout, - **kwargs, - ) - except requests.HTTPError as err: - res = err.response - if res.status_code == 429: # type: ignore[union-attr] - raise AnthropicRateLimitError(f"API rate limit exceeded: {res.text}") # type: ignore[union-attr] - if res.status_code == 401: # type: ignore[union-attr] - raise AnthropicUnauthorizedError(f"API key is invalid: {res.text}") # type: ignore[union-attr] - - raise AnthropicError( - f"Anthropic returned an error.\nStatus code: {res.status_code}\nResponse body: {res.text}", # type: ignore[union-attr] - status_code=res.status_code, # type: ignore[union-attr] - ) - - return response - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - """ - Ensures Anthropic Claude Invocation Layer is selected only when Claude models are specified in - the model name. - """ - # see https://docs.anthropic.com/claude/reference/selecting-a-model - return model_name_or_path.startswith("claude-") diff --git a/haystack/nodes/prompt/invocation_layer/aws_base.py b/haystack/nodes/prompt/invocation_layer/aws_base.py deleted file mode 100644 index 66a0ff7f55..0000000000 --- a/haystack/nodes/prompt/invocation_layer/aws_base.py +++ /dev/null @@ -1,79 +0,0 @@ -import logging -from abc import ABC -from typing import Optional - - -from haystack.errors import AWSConfigurationError -from haystack.lazy_imports import LazyImport -from haystack.nodes.prompt.invocation_layer import PromptModelInvocationLayer - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[aws]'") as boto3_import: - import boto3 - from botocore.exceptions import BotoCoreError - - -AWS_CONFIGURATION_KEYS = [ - "aws_access_key_id", - "aws_secret_access_key", - "aws_session_token", - "aws_region_name", - "aws_profile_name", -] - - -class AWSBaseInvocationLayer(PromptModelInvocationLayer, ABC): - """ - Base class for AWS based invocation layers. - """ - - @classmethod - def aws_configured(cls, **kwargs) -> bool: - """ - Checks whether this invocation layer is active. - :param kwargs: The kwargs passed down to the invocation layer. - :return: True if the invocation layer is active, False otherwise. - """ - aws_config_provided = any(key in kwargs for key in AWS_CONFIGURATION_KEYS) - return aws_config_provided - - @classmethod - def get_aws_session( - cls, - aws_access_key_id: Optional[str] = None, - aws_secret_access_key: Optional[str] = None, - aws_session_token: Optional[str] = None, - aws_region_name: Optional[str] = None, - aws_profile_name: Optional[str] = None, - **kwargs, - ): - """ - Creates an AWS Session with the given parameters. - Checks if the provided AWS credentials are valid and can be used to connect to AWS. - - :param aws_access_key_id: AWS access key ID. - :param aws_secret_access_key: AWS secret access key. - :param aws_session_token: AWS session token. - :param aws_region_name: AWS region name. - :param aws_profile_name: AWS profile name. - :param kwargs: The kwargs passed down to the service client. Supported kwargs depend on the model chosen. - See https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters.html. - :raises AWSConfigurationError: If the provided AWS credentials are invalid. - :return: The created AWS session. - """ - boto3_import.check() - try: - return boto3.Session( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token, - region_name=aws_region_name, - profile_name=aws_profile_name, - ) - except BotoCoreError as e: - provided_aws_config = {k: v for k, v in kwargs.items() if k in AWS_CONFIGURATION_KEYS} - raise AWSConfigurationError( - f"Failed to initialize the session with provided AWS credentials {provided_aws_config}" - ) from e diff --git a/haystack/nodes/prompt/invocation_layer/azure_chatgpt.py b/haystack/nodes/prompt/invocation_layer/azure_chatgpt.py deleted file mode 100644 index 582875edc2..0000000000 --- a/haystack/nodes/prompt/invocation_layer/azure_chatgpt.py +++ /dev/null @@ -1,47 +0,0 @@ -from typing import Dict, Optional - -from haystack.nodes.prompt.invocation_layer.chatgpt import ChatGPTInvocationLayer -from haystack.nodes.prompt.invocation_layer.utils import has_azure_parameters - - -class AzureChatGPTInvocationLayer(ChatGPTInvocationLayer): - """ - Azure ChatGPT Invocation Layer - - This layer is used to invoke the ChatGPT API on Azure. It is essentially the same as the ChatGPTInvocationLayer - with additional two parameters: `azure_base_url` and `azure_deployment_name`. The `azure_base_url` is the URL of the Azure OpenAI - endpoint and the `azure_deployment_name` is the name of the deployment. - """ - - def __init__( - self, - azure_base_url: str, - azure_deployment_name: str, - api_key: str, - api_version: str = "2023-03-15-preview", - model_name_or_path: str = "gpt-35-turbo", - max_length: Optional[int] = 800, - **kwargs, - ): - super().__init__(api_key, model_name_or_path, max_length, **kwargs) - self.azure_base_url = azure_base_url - self.azure_deployment_name = azure_deployment_name - self.api_version = api_version - - @property - def url(self) -> str: - return f"{self.azure_base_url}/openai/deployments/{self.azure_deployment_name}/chat/completions?api-version={self.api_version}" - - @property - def headers(self) -> Dict[str, str]: - return {"api-key": self.api_key, "Content-Type": "application/json"} - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - """ - Ensures Azure ChatGPT Invocation Layer is selected when `azure_base_url` and `azure_deployment_name` are provided in - addition to a list of supported models. - """ - - valid_model = any(m for m in ["gpt-35-turbo", "gpt-4", "gpt-4-32k"] if m in model_name_or_path) - return valid_model and has_azure_parameters(**kwargs) diff --git a/haystack/nodes/prompt/invocation_layer/azure_open_ai.py b/haystack/nodes/prompt/invocation_layer/azure_open_ai.py deleted file mode 100644 index d10dc65463..0000000000 --- a/haystack/nodes/prompt/invocation_layer/azure_open_ai.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import Dict, Optional - -from haystack.nodes.prompt.invocation_layer.open_ai import OpenAIInvocationLayer -from haystack.nodes.prompt.invocation_layer.utils import has_azure_parameters - - -class AzureOpenAIInvocationLayer(OpenAIInvocationLayer): - """ - Azure OpenAI Invocation Layer - - This layer is used to invoke the OpenAI API on Azure. It is essentially the same as the OpenAIInvocationLayer - with additional two parameters: `azure_base_url` and `azure_deployment_name`. The `azure_base_url` is the URL of the Azure OpenAI - endpoint and the `azure_deployment_name` is the name of the deployment. - """ - - def __init__( - self, - azure_base_url: str, - azure_deployment_name: str, - api_key: str, - api_version: str = "2022-12-01", - model_name_or_path: str = "text-davinci-003", - max_length: Optional[int] = 100, - **kwargs, - ): - super().__init__(api_key, model_name_or_path, max_length, **kwargs) - self.azure_base_url = azure_base_url - self.azure_deployment_name = azure_deployment_name - self.api_version = api_version - - @property - def url(self) -> str: - return f"{self.azure_base_url}/openai/deployments/{self.azure_deployment_name}/completions?api-version={self.api_version}" - - @property - def headers(self) -> Dict[str, str]: - return {"api-key": self.api_key, "Content-Type": "application/json"} - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - """ - Ensures Azure OpenAI Invocation Layer is selected when `azure_base_url` and `azure_deployment_name` are provided in - addition to a list of supported models. - """ - valid_model = model_name_or_path in ["ada", "babbage", "davinci", "curie"] or any( - m in model_name_or_path for m in ["-ada-", "-babbage-", "-davinci-", "-curie-"] - ) - return valid_model and has_azure_parameters(**kwargs) diff --git a/haystack/nodes/prompt/invocation_layer/base.py b/haystack/nodes/prompt/invocation_layer/base.py deleted file mode 100644 index 386dd59e6a..0000000000 --- a/haystack/nodes/prompt/invocation_layer/base.py +++ /dev/null @@ -1,62 +0,0 @@ -from abc import abstractmethod -from typing import Dict, List, Union, Type - - -class PromptModelInvocationLayer: - """ - PromptModelInvocationLayer implementations execute a prompt on an underlying model. - - The implementation can be a simple invocation on the underlying model running in a local runtime, or - could be even remote, for example, a call to a remote API endpoint. - """ - - invocation_layer_providers: List[Type["PromptModelInvocationLayer"]] = [] - - def __init__(self, model_name_or_path: str, **kwargs): - """ - Creates a new PromptModelInvocationLayer instance. - - :param model_name_or_path: The name or path of the underlying model. - :param kwargs: Additional keyword arguments passed to the underlying model. - """ - if model_name_or_path is None or len(model_name_or_path) == 0: - raise ValueError("model_name_or_path cannot be None or empty string") - - self.model_name_or_path = model_name_or_path - - def __init_subclass__(cls, **kwargs): - """ - Used to register user-defined invocation layers. - - Called when a subclass of PromptModelInvocationLayer is imported. - """ - super().__init_subclass__(**kwargs) - cls.invocation_layer_providers.append(cls) - - @abstractmethod - def invoke(self, *args, **kwargs): - """ - It takes a prompt and returns a list of generated text using the underlying model. - :return: A list of generated text. - """ - pass - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - """ - Checks if the given model is supported by this invocation layer. - - :param model_name_or_path: The name or path of the model. - :param kwargs: Additional keyword arguments passed to the underlying model which might be used to determine - if the model is supported. - :return: True if this invocation layer supports the model, False otherwise. - """ - return False - - @abstractmethod - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - """Ensure that length of the prompt and answer is within the maximum token length of the PromptModel. - - :param prompt: Prompt text to be sent to the generative model. - """ - pass diff --git a/haystack/nodes/prompt/invocation_layer/chatgpt.py b/haystack/nodes/prompt/invocation_layer/chatgpt.py deleted file mode 100644 index 65c2df7795..0000000000 --- a/haystack/nodes/prompt/invocation_layer/chatgpt.py +++ /dev/null @@ -1,223 +0,0 @@ -import logging -from typing import Any, Dict, List, Optional, Union - -from haystack.nodes.prompt.invocation_layer.handlers import DefaultTokenStreamingHandler, TokenStreamingHandler -from haystack.nodes.prompt.invocation_layer.open_ai import OpenAIInvocationLayer -from haystack.nodes.prompt.invocation_layer.utils import has_azure_parameters -from haystack.utils.openai_utils import ( - _check_openai_finish_reason, - check_openai_async_policy_violation, - check_openai_policy_violation, - count_openai_tokens_messages, - openai_async_request, - openai_request, -) - -logger = logging.getLogger(__name__) - - -class ChatGPTInvocationLayer(OpenAIInvocationLayer): - """ - ChatGPT Invocation Layer - - PromptModelInvocationLayer implementation for OpenAI's GPT-3 ChatGPT API. Invocations are made using REST API. - See [OpenAI ChatGPT API](https://platform.openai.com/docs/guides/chat) for more details. - - Note: kwargs other than init parameter names are ignored to enable reflective construction of the class - as many variants of PromptModelInvocationLayer are possible and they may have different parameters. - """ - - def __init__( - self, - api_key: str, - model_name_or_path: str = "gpt-3.5-turbo", - max_length: Optional[int] = 500, - api_base: str = "https://api.openai.com/v1", - timeout: Optional[float] = None, - **kwargs, - ): - """ - Creates an instance of ChatGPTInvocationLayer for OpenAI's GPT-3.5 GPT-4 models. - - :param model_name_or_path: The name or path of the underlying model. - :param max_length: The maximum number of tokens the output text can have. - :param api_key: The OpenAI API key. - :param api_base: The OpenAI API Base url, defaults to `https://api.openai.com/v1`. - :param kwargs: Additional keyword arguments passed to the underlying model. - [See OpenAI documentation](https://platform.openai.com/docs/api-reference/chat). - Note: additional model argument moderate_content will filter input and generated answers for potentially - sensitive content using the [OpenAI Moderation API](https://platform.openai.com/docs/guides/moderation) - if set. If the input or answers are flagged, an empty list is returned in place of the answers. - """ - super().__init__(api_key, model_name_or_path, max_length, api_base=api_base, timeout=timeout, **kwargs) - - def _extract_token(self, event_data: Dict[str, Any]): - delta = event_data["choices"][0]["delta"] - if "content" in delta: - return delta["content"] - return None - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - """Make sure the length of the prompt and answer is within the max tokens limit of the model. - If needed, truncate the prompt text so that it fits within the limit. - - :param prompt: Prompt text to be sent to the generative model. - """ - if isinstance(prompt, str): - messages = [{"role": "user", "content": prompt}] - elif isinstance(prompt, list) and len(prompt) > 0 and isinstance(prompt[0], dict): - messages = prompt - - n_message_tokens = count_openai_tokens_messages(messages, self._tokenizer) - n_answer_tokens = self.max_length - if (n_message_tokens + n_answer_tokens) <= self.max_tokens_limit: - return prompt - - if isinstance(prompt, str): - tokenized_prompt = self._tokenizer.encode(prompt) - n_other_tokens = n_message_tokens - len(tokenized_prompt) - truncated_prompt_length = self.max_tokens_limit - n_answer_tokens - n_other_tokens - - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens so that the prompt length and " - "answer length (%s tokens) fit within the max token limit (%s tokens). " - "Reduce the length of the prompt to prevent it from being cut off.", - len(tokenized_prompt), - truncated_prompt_length, - n_answer_tokens, - self.max_tokens_limit, - ) - - truncated_prompt = self._tokenizer.decode(tokenized_prompt[:truncated_prompt_length]) - return truncated_prompt - else: - # TODO: support truncation when there is a chat history - raise ValueError( - f"The prompt or the messages are too long ({n_message_tokens} tokens). " - f"The length of the prompt or messages and the answer ({n_answer_tokens} tokens) should be within the max " - f"token limit ({self.max_tokens_limit} tokens). " - f"Reduce the length of the prompt or messages." - ) - - @property - def url(self) -> str: - return f"{self.api_base}/chat/completions" - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - valid_model = ( - any(m for m in ["gpt-3.5-turbo", "gpt-4"] if m in model_name_or_path) - and not "gpt-3.5-turbo-instruct" in model_name_or_path - ) - return valid_model and not has_azure_parameters(**kwargs) - - async def ainvoke(self, *args, **kwargs): - """ - Invokes a prompt on the model. Based on the model, it takes in a prompt (or either a prompt or a list of messages) - and returns a list of responses using a REST invocation. - - :return: The responses are being returned. - - Note: Only kwargs relevant to OpenAI are passed to OpenAI rest API. Others kwargs are ignored. - For more details, see OpenAI [documentation](https://platform.openai.com/docs/api-reference/completions/create). - """ - prompt, base_payload, kwargs_with_defaults, stream, moderation = self._prepare_invoke(*args, **kwargs) - - if moderation and await check_openai_async_policy_violation(input=prompt, headers=self.headers): - logger.info("Prompt '%s' will not be sent to OpenAI due to potential policy violation.", prompt) - return [] - - if isinstance(prompt, str): - messages = [{"role": "user", "content": prompt}] - elif isinstance(prompt, list) and len(prompt) > 0 and isinstance(prompt[0], dict): - messages = prompt - else: - raise ValueError( - f"The prompt format is different than what the model expects. " - f"The model {self.model_name_or_path} requires either a string or messages in the ChatML format. " - f"For more details, see this [GitHub discussion](https://github.com/openai/openai-python/blob/main/chatml.md)." - ) - extra_payload = {"messages": messages} - payload = {**base_payload, **extra_payload} - if not stream: - response = await openai_async_request(url=self.url, headers=self.headers, payload=payload) - _check_openai_finish_reason(result=response, payload=payload) - assistant_response = [choice["message"]["content"].strip() for choice in response["choices"]] - else: - response = await openai_async_request( - url=self.url, headers=self.headers, payload=payload, read_response=False, stream=True - ) - handler: TokenStreamingHandler = kwargs_with_defaults.pop("stream_handler", DefaultTokenStreamingHandler()) - assistant_response = self._process_streaming_response(response=response, stream_handler=handler) - - # Although ChatGPT generates text until stop words are encountered, unfortunately it includes the stop word - # We want to exclude it to be consistent with other invocation layers - if "stop" in kwargs_with_defaults and kwargs_with_defaults["stop"] is not None: - stop_words = kwargs_with_defaults["stop"] - for idx, _ in enumerate(assistant_response): - for stop_word in stop_words: - assistant_response[idx] = assistant_response[idx].replace(stop_word, "").strip() - - if moderation and await check_openai_async_policy_violation(input=assistant_response, headers=self.headers): - logger.info("Response '%s' will not be returned due to potential policy violation.", assistant_response) - return [] - - return assistant_response - - def invoke(self, *args, **kwargs): - """ - Invokes a prompt on the model. Based on the model, it takes in a prompt (or either a prompt or a list of messages) - and returns a list of responses using a REST invocation. - - :return: The responses are being returned. - - Note: Only kwargs relevant to OpenAI are passed to OpenAI rest API. Others kwargs are ignored. - For more details, see OpenAI [documentation](https://platform.openai.com/docs/api-reference/completions/create). - """ - prompt, base_payload, kwargs_with_defaults, stream, moderation = self._prepare_invoke(*args, **kwargs) - - if moderation and check_openai_policy_violation(input=prompt, headers=self.headers): - logger.info("Prompt '%s' will not be sent to OpenAI due to potential policy violation.", prompt) - return [] - - if isinstance(prompt, str): - messages = [{"role": "user", "content": prompt}] - elif isinstance(prompt, list) and len(prompt) > 0 and isinstance(prompt[0], dict): - messages = prompt - else: - raise ValueError( - f"The prompt format is different than what the model expects. " - f"The model {self.model_name_or_path} requires either a string or messages in the ChatML format. " - f"For more details, see this [GitHub discussion](https://github.com/openai/openai-python/blob/main/chatml.md)." - ) - extra_payload = {"messages": messages} - payload = {**base_payload, **extra_payload} - if not stream: - response = openai_request(url=self.url, headers=self.headers, payload=payload, timeout=self.timeout) - _check_openai_finish_reason(result=response, payload=payload) - assistant_response = [choice["message"]["content"].strip() for choice in response["choices"]] - else: - response = openai_request( - url=self.url, - headers=self.headers, - payload=payload, - timeout=self.timeout, - read_response=False, - stream=True, - ) - handler: TokenStreamingHandler = kwargs_with_defaults.pop("stream_handler", DefaultTokenStreamingHandler()) - assistant_response = self._process_streaming_response(response=response, stream_handler=handler) - - # Although ChatGPT generates text until stop words are encountered, unfortunately it includes the stop word - # We want to exclude it to be consistent with other invocation layers - if "stop" in kwargs_with_defaults and kwargs_with_defaults["stop"] is not None: - stop_words = kwargs_with_defaults["stop"] - for idx, _ in enumerate(assistant_response): - for stop_word in stop_words: - assistant_response[idx] = assistant_response[idx].replace(stop_word, "").strip() - - if moderation and check_openai_policy_violation(input=assistant_response, headers=self.headers): - logger.info("Response '%s' will not be returned due to potential policy violation.", assistant_response) - return [] - - return assistant_response diff --git a/haystack/nodes/prompt/invocation_layer/cohere.py b/haystack/nodes/prompt/invocation_layer/cohere.py deleted file mode 100644 index b1426649ff..0000000000 --- a/haystack/nodes/prompt/invocation_layer/cohere.py +++ /dev/null @@ -1,222 +0,0 @@ -import json -import os -from typing import Optional, Dict, Union, List, Any -import logging - -import requests - -from haystack.environment import HAYSTACK_REMOTE_API_TIMEOUT_SEC, HAYSTACK_REMOTE_API_MAX_RETRIES -from haystack.errors import CohereInferenceLimitError, CohereUnauthorizedError, CohereError -from haystack.nodes.prompt.invocation_layer import ( - PromptModelInvocationLayer, - TokenStreamingHandler, - DefaultTokenStreamingHandler, -) -from haystack.nodes.prompt.invocation_layer.handlers import DefaultPromptHandler -from haystack.utils import request_with_retry - -logger = logging.getLogger(__name__) -TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) -RETRIES = int(os.environ.get(HAYSTACK_REMOTE_API_MAX_RETRIES, 5)) - - -class CohereInvocationLayer(PromptModelInvocationLayer): - """ - PromptModelInvocationLayer implementation for Cohere's command models. Invocations are made using REST API. - """ - - def __init__(self, api_key: str, model_name_or_path: str, max_length: Optional[int] = 100, **kwargs): - """ - Creates an instance of CohereInvocationLayer for the specified Cohere model - - :param api_key: Cohere API key - :param model_name_or_path: Cohere model name - :param max_length: The maximum length of the output text. - """ - super().__init__(model_name_or_path) - valid_api_key = isinstance(api_key, str) and api_key - if not valid_api_key: - raise ValueError( - f"api_key {api_key} must be a valid Cohere token. " - f"Your token is available in your Cohere settings page." - ) - valid_model_name_or_path = isinstance(model_name_or_path, str) and model_name_or_path - if not valid_model_name_or_path: - raise ValueError(f"model_name_or_path {model_name_or_path} must be a valid Cohere model name") - self.api_key = api_key - self.max_length = max_length - - # See https://docs.cohere.com/reference/generate - # for a list of supported parameters - self.model_input_kwargs = { - key: kwargs[key] - for key in [ - "end_sequences", - "frequency_penalty", - "k", - "logit_bias", - "max_tokens", - "model", - "num_generations", - "p", - "presence_penalty", - "return_likelihoods", - "stream", - "stream_handler", - "temperature", - "truncate", - ] - if key in kwargs - } - # cohere uses BPE tokenizer - # the tokenization lengths are very close to gpt2, in our experiments the differences were minimal - # See model info at https://docs.cohere.com/docs/models - model_max_length = 4096 if "command" in model_name_or_path else 2048 - self.prompt_handler = DefaultPromptHandler( - model_name_or_path="gpt2", model_max_length=model_max_length, max_length=self.max_length or 100 - ) - - @property - def url(self) -> str: - return "https://api.cohere.ai/v1/generate" - - @property - def headers(self) -> Dict[str, str]: - return { - "Authorization": f"Bearer {self.api_key}", - "Content-Type": "application/json", - "Request-Source": "python-sdk", - } - - def invoke(self, *args, **kwargs): - """ - Invokes a prompt on the model. It takes in a prompt and returns a list of responses using a REST invocation. - :return: The responses are being returned. - """ - prompt = kwargs.get("prompt") - if not prompt: - raise ValueError( - f"No prompt provided. Model {self.model_name_or_path} requires prompt." - f"Make sure to provide prompt in kwargs." - ) - stop_words = kwargs.pop("stop_words", None) - kwargs_with_defaults = self.model_input_kwargs - kwargs_with_defaults.update(kwargs) - - # either stream is True (will use default handler) or stream_handler is provided - stream = ( - kwargs_with_defaults.get("stream", False) or kwargs_with_defaults.get("stream_handler", None) is not None - ) - - # see https://docs.cohere.com/reference/generate - params = { - "end_sequences": kwargs_with_defaults.get("end_sequences", stop_words), - "frequency_penalty": kwargs_with_defaults.get("frequency_penalty", None), - "k": kwargs_with_defaults.get("k", None), - "max_tokens": kwargs_with_defaults.get("max_tokens", self.max_length), - "model": kwargs_with_defaults.get("model", self.model_name_or_path), - "num_generations": kwargs_with_defaults.get("num_generations", None), - "p": kwargs_with_defaults.get("p", None), - "presence_penalty": kwargs_with_defaults.get("presence_penalty", None), - "prompt": prompt, - "return_likelihoods": kwargs_with_defaults.get("return_likelihoods", None), - "stream": stream, - "temperature": kwargs_with_defaults.get("temperature", None), - "truncate": kwargs_with_defaults.get("truncate", None), - } - response = self._post(params, stream=stream) - if not stream: - output = json.loads(response.text) - generated_texts = [o["text"] for o in output["generations"] if "text" in o] - else: - handler: TokenStreamingHandler = kwargs_with_defaults.pop("stream_handler", DefaultTokenStreamingHandler()) - generated_texts = self._process_streaming_response(response=response, stream_handler=handler) - return generated_texts - - def _process_streaming_response(self, response, stream_handler: TokenStreamingHandler): - # sseclient doesn't work with Cohere streaming API - # let's do it manually - tokens = [] - for line in response.iter_lines(): - if line: - streaming_item = json.loads(line) - text = streaming_item.get("text") - if text: - tokens.append(stream_handler(text)) - return ["".join(tokens)] # return a list of strings just like non-streaming - - def _post( - self, - data: Dict[str, Any], - stream: bool = False, - attempts: int = RETRIES, - status_codes_to_retry: Optional[List[int]] = None, - timeout: float = TIMEOUT, - **kwargs, - ) -> requests.Response: - """ - Post data to the Cohere inference model. It takes in a prompt and returns a list of responses using a REST - invocation. - :param data: The data to be sent to the model. - :param stream: Whether to stream the response. - :param attempts: The number of attempts to make. - :param status_codes_to_retry: The status codes to retry on. - :param timeout: The timeout for the request. - :return: The response from the model as a requests.Response object. - """ - response: requests.Response - if status_codes_to_retry is None: - status_codes_to_retry = [429] - try: - response = request_with_retry( - method="POST", - status_codes_to_retry=status_codes_to_retry, - attempts=attempts, - url=self.url, - headers=self.headers, - json=data, - timeout=timeout, - stream=stream, - ) - except requests.HTTPError as err: - res = err.response - if res.status_code == 429: # type: ignore[union-attr] - raise CohereInferenceLimitError(f"API rate limit exceeded: {res.text}") # type: ignore[union-attr] - if res.status_code == 401: # type: ignore[union-attr] - raise CohereUnauthorizedError(f"API key is invalid: {res.text}") # type: ignore[union-attr] - - raise CohereError( - f"Cohere model returned an error.\nStatus code: {res.status_code}\nResponse body: {res.text}", # type: ignore[union-attr] - status_code=res.status_code, # type: ignore[union-attr] - ) - return response - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - if isinstance(prompt, List): - raise ValueError("Cohere invocation layer doesn't support a dictionary as prompt") - - resize_info = self.prompt_handler(prompt) - if resize_info["prompt_length"] != resize_info["new_prompt_length"]: - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens so that the prompt length and " - "answer length (%s tokens) fit within the max token limit (%s tokens). " - "Reduce the length of the prompt to prevent it from being cut off.", - resize_info["prompt_length"], - max(0, resize_info["model_max_length"] - resize_info["max_length"]), # type: ignore - resize_info["max_length"], - resize_info["model_max_length"], - ) - return str(resize_info["resized_prompt"]) - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - """ - Ensures CohereInvocationLayer is selected only when Cohere models are specified in - the model name. - """ - is_inference_api = "api_key" in kwargs - return ( - model_name_or_path is not None - and is_inference_api - and any(token == model_name_or_path for token in ["command", "command-light", "base", "base-light"]) - ) diff --git a/haystack/nodes/prompt/invocation_layer/handlers.py b/haystack/nodes/prompt/invocation_layer/handlers.py deleted file mode 100644 index 073561b3f4..0000000000 --- a/haystack/nodes/prompt/invocation_layer/handlers.py +++ /dev/null @@ -1,100 +0,0 @@ -from abc import abstractmethod, ABC -from typing import Union, Dict - -from haystack.lazy_imports import LazyImport - -TextStreamer = object -with LazyImport() as transformers_import: - from transformers import PreTrainedTokenizer, PreTrainedTokenizerFast, TextStreamer, AutoTokenizer # type: ignore - - -class TokenStreamingHandler(ABC): - """ - TokenStreamingHandler implementations handle the streaming of tokens from the stream. - """ - - DONE_MARKER = "[DONE]" - - @abstractmethod - def __call__(self, token_received: str, **kwargs) -> str: - """ - This callback method is called when a new token is received from the stream. - - :param token_received: The token received from the stream. - :param kwargs: Additional keyword arguments passed to the handler. - :return: The token to be sent to the stream. - """ - pass - - -class DefaultTokenStreamingHandler(TokenStreamingHandler): - def __call__(self, token_received, **kwargs) -> str: - """ - This callback method is called when a new token is received from the stream. - - :param token_received: The token received from the stream. - :param kwargs: Additional keyword arguments passed to the handler. - :return: The token to be sent to the stream. - """ - print(token_received, flush=True, end="") - return token_received - - -class HFTokenStreamingHandler(TextStreamer): # pylint: disable=useless-object-inheritance - def __init__( - self, - tokenizer: Union["PreTrainedTokenizer", "PreTrainedTokenizerFast"], - stream_handler: "TokenStreamingHandler", - ): - transformers_import.check() - super().__init__(tokenizer=tokenizer, skip_prompt=True) # type: ignore - self.token_handler = stream_handler - - def on_finalized_text(self, token: str, stream_end: bool = False): - token_to_send = token + "\n" if stream_end else token - self.token_handler(token_received=token_to_send, **{}) - - -class DefaultPromptHandler: - """ - DefaultPromptHandler resizes the prompt to ensure that the prompt and answer token lengths together - are within the model_max_length. - """ - - def __init__(self, model_name_or_path: str, model_max_length: int, max_length: int = 100): - self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path) - self.tokenizer.model_max_length = model_max_length - self.model_max_length = model_max_length - self.max_length = max_length - - def __call__(self, prompt: str, **kwargs) -> Dict[str, Union[str, int]]: - """ - Resizes the prompt to ensure that the prompt and answer is within the model_max_length - - :param prompt: the prompt to be sent to the model. - :param kwargs: Additional keyword arguments passed to the handler. - :return: A dictionary containing the resized prompt and additional information. - """ - resized_prompt = prompt - prompt_length = 0 - new_prompt_length = 0 - - if prompt: - tokenized_prompt = self.tokenizer.tokenize(prompt) - prompt_length = len(tokenized_prompt) - if (prompt_length + self.max_length) <= self.model_max_length: - resized_prompt = prompt - new_prompt_length = prompt_length - else: - resized_prompt = self.tokenizer.convert_tokens_to_string( - tokenized_prompt[: self.model_max_length - self.max_length] - ) - new_prompt_length = len(tokenized_prompt[: self.model_max_length - self.max_length]) - - return { - "resized_prompt": resized_prompt, - "prompt_length": prompt_length, - "new_prompt_length": new_prompt_length, - "model_max_length": self.model_max_length, - "max_length": self.max_length, - } diff --git a/haystack/nodes/prompt/invocation_layer/hugging_face.py b/haystack/nodes/prompt/invocation_layer/hugging_face.py deleted file mode 100644 index 83a1cfc9f2..0000000000 --- a/haystack/nodes/prompt/invocation_layer/hugging_face.py +++ /dev/null @@ -1,395 +0,0 @@ -from typing import Optional, Union, List, Dict, Any -import logging -import os - -from haystack.nodes.prompt.invocation_layer import PromptModelInvocationLayer, TokenStreamingHandler -from haystack.nodes.prompt.invocation_layer.handlers import DefaultTokenStreamingHandler -from haystack.nodes.prompt.invocation_layer.utils import get_task -from haystack.lazy_imports import LazyImport - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import ( - pipeline, - StoppingCriteriaList, - StoppingCriteria, - GenerationConfig, - PreTrainedTokenizer, - PreTrainedTokenizerFast, - PreTrainedModel, - Pipeline, - AutoTokenizer, - AutoConfig, - TOKENIZER_MAPPING, - ) - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - from haystack.nodes.prompt.invocation_layer.handlers import HFTokenStreamingHandler - - class StopWordsCriteria(StoppingCriteria): - """ - Stops text generation if any one of the stop words is generated. - - Note: When a stop word is encountered, the generation of new text is stopped. - However, if the stop word is in the prompt itself, it can stop generating new text - prematurely after the first token. This is particularly important for LLMs designed - for dialogue generation. For these models, like for example mosaicml/mpt-7b-chat, - the output includes both the new text and the original prompt. Therefore, it's important - to make sure your prompt has no stop words. - """ - - def __init__( - self, - tokenizer: Union[PreTrainedTokenizer, PreTrainedTokenizerFast], - stop_words: List[str], - device: Union[str, torch.device] = "cpu", - ): - super().__init__() - encoded_stop_words = tokenizer(stop_words, add_special_tokens=False, padding=True, return_tensors="pt") - self.stop_words = encoded_stop_words.input_ids.to(device) - - def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool: - for stop_word in self.stop_words: - found_stop_word = self.is_stop_word_found(input_ids, stop_word) - if found_stop_word: - return True - return False - - def is_stop_word_found(self, generated_text_ids: torch.Tensor, stop_word: torch.Tensor) -> bool: - generated_text_ids = generated_text_ids[-1] - len_generated_text_ids = generated_text_ids.size(0) - len_stop_word = stop_word.size(0) - result = all(generated_text_ids[len_generated_text_ids - len_stop_word :].eq(stop_word)) - return result - - -class HFLocalInvocationLayer(PromptModelInvocationLayer): - """ - A subclass of the PromptModelInvocationLayer class. It loads a pre-trained model from Hugging Face and - passes a prepared prompt into that model. - - Note: kwargs other than init parameter names are ignored to enable reflective construction of the class, - as many variants of PromptModelInvocationLayer are possible and they may have different parameters. - """ - - def __init__( - self, - model_name_or_path: str = "google/flan-t5-base", - max_length: int = 100, - use_auth_token: Optional[Union[str, bool]] = None, - use_gpu: Optional[bool] = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - **kwargs, - ): - """ - Creates an instance of HFLocalInvocationLayer used to invoke local Hugging Face models. - - :param model_name_or_path: The name or path of the underlying model. - :param max_length: The maximum number of tokens the output text can have. - :param use_auth_token: The token to use as HTTP bearer authorization for remote files. - :param use_gpu: Whether to use GPU for inference. - :param device: The device to use for inference. - :param kwargs: Additional keyword arguments passed to the underlying model. Due to reflective construction of - all PromptModelInvocationLayer instances, this instance of HFLocalInvocationLayer might receive some unrelated - kwargs. Only kwargs relevant to the HFLocalInvocationLayer are considered. The list of supported kwargs - includes: "task", "model", "config", "tokenizer", "feature_extractor", "revision", "use_auth_token", - "device_map", "device", "torch_dtype", "trust_remote_code", "model_kwargs", and "pipeline_class". - For more details about pipeline kwargs in general, see - Hugging Face [documentation](https://huggingface.co/docs/transformers/en/main_classes/pipelines#transformers.pipeline). - - This layer supports two additional kwargs: generation_kwargs and model_max_length. - - The generation_kwargs are used to customize text generation for the underlying pipeline. See Hugging - Face [docs](https://huggingface.co/docs/transformers/main/en/generation_strategies#customize-text-generation) - for more details. - - The model_max_length is used to specify the custom sequence length for the underlying pipeline. - """ - torch_and_transformers_import.check() - - super().__init__(model_name_or_path) - self.use_auth_token = use_auth_token - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - if "device" not in kwargs: - kwargs["device"] = self.devices[0] - - # save stream settings and stream_handler for pipeline invocation - self.stream_handler = kwargs.get("stream_handler", None) - self.stream = kwargs.get("stream", False) - - # save generation_kwargs for pipeline invocation - self.generation_kwargs = kwargs.get("generation_kwargs", {}) - - # If task_name is not provided, get the task name from the model name or path (uses HFApi) - self.task_name = ( - kwargs.get("task_name") - if "task_name" in kwargs - else get_task(model_name_or_path, use_auth_token=use_auth_token) - ) - # we check in supports class method if task_name is supported but here we check again as - # we could have gotten the task_name from kwargs - if self.task_name not in ["text2text-generation", "text-generation"]: - raise ValueError( - f"Task name {self.task_name} is not supported. " - f"We only support text2text-generation and text-generation tasks." - ) - pipeline_kwargs = self._prepare_pipeline_kwargs( - task=self.task_name, model_name_or_path=model_name_or_path, use_auth_token=use_auth_token, **kwargs - ) - # create the transformer pipeline - self.pipe: Pipeline = pipeline(**pipeline_kwargs) - - # This is how the default max_length is determined for Text2TextGenerationPipeline shown here - # https://huggingface.co/transformers/v4.6.0/_modules/transformers/pipelines/text2text_generation.html - # max_length must be set otherwise HFLocalInvocationLayer._ensure_token_limit will fail. - self.max_length = max_length or self.pipe.model.config.max_length - - model_max_length = kwargs.get("model_max_length", None) - # we allow users to override the tokenizer's model_max_length because models like T5 have relative positional - # embeddings and can accept sequences of more than 512 tokens - if model_max_length is not None: - self.pipe.tokenizer.model_max_length = model_max_length - - if self.max_length > self.pipe.tokenizer.model_max_length: - logger.warning( - "The max_length %s is greater than model_max_length %s. This might result in truncation of the " - "generated text. Please lower the max_length (number of answer tokens) parameter!", - self.max_length, - self.pipe.tokenizer.model_max_length, - ) - - def _prepare_pipeline_kwargs(self, **kwargs) -> Dict[str, Any]: - """ - Sanitizes and prepares the kwargs passed to the transformers pipeline function. - For more details about pipeline kwargs in general, see Hugging Face - [documentation](https://huggingface.co/docs/transformers/en/main_classes/pipelines#transformers.pipeline). - """ - # as device and device_map are mutually exclusive, we set device to None if device_map is provided - device_map = kwargs.get("device_map", None) - device = kwargs.get("device") if device_map is None else None - # prepare torch_dtype for pipeline invocation - torch_dtype = self._extract_torch_dtype(**kwargs) - # and the model (prefer model instance over model_name_or_path str identifier) - model = kwargs.get("model") or kwargs.get("model_name_or_path") - trust_remote_code = kwargs.get("trust_remote_code", False) - hub_kwargs = { - "revision": kwargs.get("revision", None), - "use_auth_token": kwargs.get("use_auth_token", None), - "trust_remote_code": trust_remote_code, - } - model_kwargs = kwargs.get("model_kwargs", {}) - tokenizer = kwargs.get("tokenizer", None) - - if tokenizer is None and trust_remote_code: - # For models not yet supported by the transformers library, we must set `trust_remote_code=True` within - # the underlying pipeline to ensure the model's successful loading. However, this does not guarantee the - # tokenizer will be loaded alongside. Therefore, we need to add additional logic here to manually load the - # tokenizer and pass it to transformers' pipeline. - # Otherwise, calling `self.pipe.tokenizer.model_max_length` will return an error. - tokenizer = self._prepare_tokenizer(model, hub_kwargs, model_kwargs) - - pipeline_kwargs = { - "task": kwargs.get("task", None), - "model": model, - "config": kwargs.get("config", None), - "tokenizer": tokenizer, - "feature_extractor": kwargs.get("feature_extractor", None), - "device_map": device_map, - "device": device, - "torch_dtype": torch_dtype, - "model_kwargs": model_kwargs, - "pipeline_class": kwargs.get("pipeline_class", None), - "use_fast": kwargs.get("use_fast", True), - **hub_kwargs, - } - return pipeline_kwargs - - def invoke(self, *args, **kwargs): - """ - It takes a prompt and returns a list of generated texts using the local Hugging Face transformers model - :return: A list of generated texts. - - Note: Only kwargs relevant to Text2TextGenerationPipeline and TextGenerationPipeline are passed to - Hugging Face as model_input_kwargs. Other kwargs are ignored. - """ - output: List[Dict[str, str]] = [] - stop_words = kwargs.pop("stop_words", None) - top_k = kwargs.pop("top_k", None) - # either stream is True (will use default handler) or stream_handler is provided for custom handler - stream = kwargs.get("stream", self.stream) - stream_handler = kwargs.get("stream_handler", self.stream_handler) - stream = stream or stream_handler is not None - if kwargs and "prompt" in kwargs: - prompt = kwargs.pop("prompt") - - # Consider only Text2TextGenerationPipeline and TextGenerationPipeline relevant, ignore others - # For more details refer to Hugging Face Text2TextGenerationPipeline and TextGenerationPipeline - # documentation - model_input_kwargs = { - key: kwargs[key] - for key in [ - "return_tensors", - "return_text", - "return_full_text", - "clean_up_tokenization_spaces", - "truncation", - "generation_kwargs", - "max_new_tokens", - "num_beams", - "do_sample", - "num_return_sequences", - "max_length", - ] - if key in kwargs - } - generation_kwargs = model_input_kwargs.pop("generation_kwargs", self.generation_kwargs) - if isinstance(generation_kwargs, dict): - model_input_kwargs.update(generation_kwargs) - elif isinstance(generation_kwargs, GenerationConfig): - gen_dict = generation_kwargs.to_diff_dict() - gen_dict.pop("transformers_version", None) - model_input_kwargs.update(gen_dict) - - is_text_generation = self.task_name == "text-generation" - # Prefer return_full_text is False for text-generation (unless explicitly set) - # Thus only generated text is returned (excluding prompt) - if is_text_generation and "return_full_text" not in model_input_kwargs: - model_input_kwargs["return_full_text"] = False - if stop_words: - sw = StopWordsCriteria(tokenizer=self.pipe.tokenizer, stop_words=stop_words, device=self.pipe.device) - model_input_kwargs["stopping_criteria"] = StoppingCriteriaList([sw]) - if top_k: - model_input_kwargs["num_return_sequences"] = top_k - if "num_beams" not in model_input_kwargs or model_input_kwargs["num_beams"] < top_k: - if "num_beams" in model_input_kwargs: - logger.warning("num_beams should not be less than top_k, hence setting it to %s", top_k) - model_input_kwargs["num_beams"] = top_k - # max_new_tokens is used for text-generation and max_length for text2text-generation - if is_text_generation: - model_input_kwargs["max_new_tokens"] = model_input_kwargs.pop("max_length", self.max_length) - else: - model_input_kwargs["max_length"] = model_input_kwargs.pop("max_length", self.max_length) - - if stream: - stream_handler: TokenStreamingHandler = stream_handler or DefaultTokenStreamingHandler() - model_input_kwargs["streamer"] = HFTokenStreamingHandler(self.pipe.tokenizer, stream_handler) - - output = self.pipe(prompt, **model_input_kwargs) - generated_texts = [o["generated_text"] for o in output if "generated_text" in o] - - if stop_words: - # Although HF generates text until stop words are encountered unfortunately it includes the stop word - # We want to exclude it to be consistent with other invocation layers - for idx, _ in enumerate(generated_texts): - for stop_word in stop_words: - generated_texts[idx] = generated_texts[idx].replace(stop_word, "").rstrip() - return generated_texts - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - """Ensure that the length of the prompt and answer is within the max tokens limit of the model. - If needed, truncate the prompt text so that it fits within the limit. - - :param prompt: Prompt text to be sent to the generative model. - """ - model_max_length = self.pipe.tokenizer.model_max_length - tokenized_prompt = self.pipe.tokenizer.tokenize(prompt) - n_prompt_tokens = len(tokenized_prompt) - n_answer_tokens = self.max_length - if (n_prompt_tokens + n_answer_tokens) <= model_max_length: - return prompt - - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens so that the prompt length and " - "answer length (%s tokens) fit within the max token limit (%s tokens). " - "Shorten the prompt to prevent it from being cut off", - n_prompt_tokens, - max(0, model_max_length - n_answer_tokens), - n_answer_tokens, - model_max_length, - ) - - decoded_string = self.pipe.tokenizer.convert_tokens_to_string( - tokenized_prompt[: model_max_length - n_answer_tokens] - ) - return decoded_string - - def _extract_torch_dtype(self, **kwargs) -> Optional["torch.dtype"]: - torch_dtype_resolved = None - torch_dtype = kwargs.get("torch_dtype", None) - if torch_dtype is not None: - if isinstance(torch_dtype, str): - if "torch." in torch_dtype: - torch_dtype_resolved = getattr(torch, torch_dtype.strip("torch.")) - elif torch_dtype == "auto": - torch_dtype_resolved = torch_dtype - else: - raise ValueError( - f"torch_dtype should be a torch.dtype, a string with 'torch.' prefix or the string 'auto', got {torch_dtype}" - ) - elif isinstance(torch_dtype, torch.dtype): - torch_dtype_resolved = torch_dtype - else: - raise ValueError(f"Invalid torch_dtype value {torch_dtype}") - return torch_dtype_resolved - - def _prepare_tokenizer( - self, model: Union[str, "PreTrainedModel"], hub_kwargs: Dict, model_kwargs: Optional[Dict] = None - ) -> Union["PreTrainedTokenizer", "PreTrainedTokenizerFast", None]: - """ - This method prepares the tokenizer before passing it to transformers' pipeline, so that the instantiated pipeline - object has a working tokenizer. - - It checks whether the pipeline method in the transformers library will load the tokenizer. - - If yes, None will be returned, because in this case, the pipeline is intelligent enough to load the tokenizer by itself. - - If not, we will load the tokenizer and an tokenizer instance is returned. - - :param model: The name or path of the underlying model. - :hub_kwargs: Keyword argument related to hugging face hub, including revision, trust_remote_code and use_auth_token. - :model_kwargs: Keyword arguments passed to the underlying model. - """ - - if isinstance(model, str): - model_config = AutoConfig.from_pretrained(model, **hub_kwargs, **model_kwargs) - else: - model_config = model.config - model = model_config._name_or_path - # the will_load_tokenizer logic corresponds to this line in transformers library - # https://github.com/huggingface/transformers/blob/05cda5df3405e6a2ee4ecf8f7e1b2300ebda472e/src/transformers/pipelines/__init__.py#L805 - will_load_tokenizer = type(model_config) in TOKENIZER_MAPPING or model_config.tokenizer_class is not None - if not will_load_tokenizer: - logger.warning( - "The transformers library doesn't know which tokenizer class should be " - "loaded for the model %s. Therefore, the tokenizer will be loaded in Haystack's " - "invocation layer and then passed to the underlying pipeline. Alternatively, you could " - "pass `tokenizer_class` to `model_kwargs` to workaround this, if your tokenizer is supported " - "by the transformers library.", - model, - ) - tokenizer = AutoTokenizer.from_pretrained(model, **hub_kwargs, **model_kwargs) - else: - tokenizer = None - return tokenizer - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - task_name: Optional[str] = kwargs.get("task_name", None) - if os.path.exists(model_name_or_path): - return True - - try: - task_name = task_name or get_task(model_name_or_path, use_auth_token=kwargs.get("use_auth_token", None)) - except RuntimeError: - # This will fail for all non-HF models - return False - # if we are using an api_key it could be HF inference point - using_api_key = bool(kwargs.get("api_key", None)) - return not using_api_key and task_name in ["text2text-generation", "text-generation"] diff --git a/haystack/nodes/prompt/invocation_layer/hugging_face_inference.py b/haystack/nodes/prompt/invocation_layer/hugging_face_inference.py deleted file mode 100644 index 9fd7989b3f..0000000000 --- a/haystack/nodes/prompt/invocation_layer/hugging_face_inference.py +++ /dev/null @@ -1,296 +0,0 @@ -import json -import os -from typing import Optional, Dict, Union, List, Any, Callable -import logging - -import requests -import sseclient - -from haystack.environment import HAYSTACK_REMOTE_API_TIMEOUT_SEC, HAYSTACK_REMOTE_API_MAX_RETRIES -from haystack.errors import ( - HuggingFaceInferenceLimitError, - HuggingFaceInferenceUnauthorizedError, - HuggingFaceInferenceError, -) -from haystack.nodes.prompt.invocation_layer import ( - PromptModelInvocationLayer, - TokenStreamingHandler, - DefaultTokenStreamingHandler, -) -from haystack.nodes.prompt.invocation_layer.handlers import DefaultPromptHandler -from haystack.nodes.prompt.invocation_layer.utils import get_task -from haystack.utils import request_with_retry - -logger = logging.getLogger(__name__) -HF_TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) -HF_RETRIES = int(os.environ.get(HAYSTACK_REMOTE_API_MAX_RETRIES, 5)) - - -class HFInferenceEndpointInvocationLayer(PromptModelInvocationLayer): - """ - A PromptModelInvocationLayer that invokes Hugging Face remote Inference Endpoint and API Inference to prompt the model. - For more details see Hugging Face Inference API [documentation](https://huggingface.co/docs/api-inference/index) - and Hugging Face Inference Endpoints [documentation](https://huggingface.co/inference-endpoints) - - The Inference API is free to use, and rate limited. If you need an inference solution for production, you can use - Inference Endpoints service. - - See documentation for more details: https://huggingface.co/docs/inference-endpoints - - """ - - def __init__(self, api_key: str, model_name_or_path: str, max_length: Optional[int] = 100, **kwargs): - """ - Creates an instance of HFInferenceEndpointInvocationLayer - :param model_name_or_path: can be either: - a) Hugging Face Inference model name (i.e. google/flan-t5-xxl) - b) Hugging Face Inference Endpoint URL (i.e. e.g. https://.us-east-1.aws.endpoints.huggingface.cloud) - :param max_length: The maximum length of the output text. - :param api_key: The Hugging Face API token. You’ll need to provide your user token which can - be found in your Hugging Face account [settings](https://huggingface.co/settings/tokens) - """ - - super().__init__(model_name_or_path) - self.prompt_preprocessors: Dict[str, Callable] = {} - valid_api_key = isinstance(api_key, str) and api_key - if not valid_api_key: - raise ValueError( - f"api_key {api_key} must be a valid Hugging Face token. " - f"Your token is available in your Hugging Face settings page." - ) - self.api_key = api_key - self.max_length = max_length - - # See https://huggingface.co/docs/api-inference/detailed_parameters#text-generation-task - # for a list of supported parameters - self.model_input_kwargs = { - key: kwargs[key] - for key in [ - "best_of", - "details", - "do_sample", - "max_new_tokens", - "max_time", - "model_max_length", - "num_return_sequences", - "repetition_penalty", - "return_full_text", - "seed", - "stream", - "stream_handler", - "temperature", - "top_k", - "top_p", - "truncate", - "typical_p", - "watermark", - ] - if key in kwargs - } - self.prompt_preprocessors["oasst"] = lambda prompt: f"<|prompter|>{prompt}<|endoftext|><|assistant|>" - - # we pop the model_max_length from the model_input_kwargs as it is not sent to the model - # but used to truncate the prompt if needed - model_max_length = self.model_input_kwargs.pop("model_max_length", 1024) - - if HFInferenceEndpointInvocationLayer.is_inference_endpoint(model_name_or_path): - # as we are using the deployed HF inference endpoint, we don't know the model name - # we'll use gpt2 BPE tokenizer for prompt length calculation - self.prompt_handler = DefaultPromptHandler( - model_name_or_path="gpt2", model_max_length=model_max_length, max_length=self.max_length or 100 - ) - else: - self.prompt_handler = DefaultPromptHandler( - model_name_or_path=model_name_or_path, - model_max_length=model_max_length, - max_length=self.max_length or 100, - ) - - def preprocess_prompt(self, prompt: str): - for key, prompt_preprocessor in self.prompt_preprocessors.items(): - if key in self.model_name_or_path: - return prompt_preprocessor(prompt) - return prompt - - @property - def url(self) -> str: - if HFInferenceEndpointInvocationLayer.is_inference_endpoint(self.model_name_or_path): - # Inference Endpoint URL - # i.e. https://o3x2xh3o4m47mxny.us-east-1.aws.endpoints.huggingface.cloud - url = self.model_name_or_path - - else: - url = f"https://api-inference.huggingface.co/models/{self.model_name_or_path}" - return url - - @property - def headers(self) -> Dict[str, str]: - return {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"} - - def invoke(self, *args, **kwargs): - """ - Invokes a prompt on the model. It takes in a prompt and returns a list of responses using a REST invocation. - :return: The responses are being returned. - """ - prompt = kwargs.get("prompt") - if not prompt: - raise ValueError( - f"No prompt provided. Model {self.model_name_or_path} requires prompt." - f"Make sure to provide prompt in kwargs." - ) - prompt = self.preprocess_prompt(prompt) - stop_words = kwargs.pop("stop_words", None) or [] - kwargs_with_defaults = self.model_input_kwargs - - if "max_new_tokens" not in kwargs_with_defaults: - kwargs_with_defaults["max_new_tokens"] = self.max_length - kwargs_with_defaults.update(kwargs) - - # either stream is True (will use default handler) or stream_handler is provided - stream = ( - kwargs_with_defaults.get("stream", False) or kwargs_with_defaults.get("stream_handler", None) is not None - ) - - # see https://huggingface.co/docs/api-inference/detailed_parameters#text-generation-task - params = { - "best_of": kwargs_with_defaults.get("best_of", None), - "details": kwargs_with_defaults.get("details", True), - "do_sample": kwargs_with_defaults.get("do_sample", False), - "max_new_tokens": kwargs_with_defaults.get("max_new_tokens", self.max_length), - "max_time": kwargs_with_defaults.get("max_time", None), - "num_return_sequences": kwargs_with_defaults.get("num_return_sequences", None), - "repetition_penalty": kwargs_with_defaults.get("repetition_penalty", None), - "return_full_text": kwargs_with_defaults.get("return_full_text", False), - "seed": kwargs_with_defaults.get("seed", None), - "stop": kwargs_with_defaults.get("stop", stop_words), - "temperature": kwargs_with_defaults.get("temperature", None), - "top_k": kwargs_with_defaults.get("top_k", None), - "top_p": kwargs_with_defaults.get("top_p", None), - "truncate": kwargs_with_defaults.get("truncate", None), - "typical_p": kwargs_with_defaults.get("typical_p", None), - "watermark": kwargs_with_defaults.get("watermark", False), - } - response: requests.Response = self._post( - data={"inputs": prompt, "parameters": params, "stream": stream}, stream=stream - ) - if stream: - handler: TokenStreamingHandler = kwargs_with_defaults.pop("stream_handler", DefaultTokenStreamingHandler()) - generated_texts = self._process_streaming_response(response, handler, stop_words) - else: - output = json.loads(response.text) - generated_texts = [o["generated_text"] for o in output if "generated_text" in o] - return generated_texts - - def _process_streaming_response( - self, response: requests.Response, stream_handler: TokenStreamingHandler, stop_words: List[str] - ) -> List[str]: - """ - Stream the response and invoke the stream_handler on each token. - - :param response: The response object from the server. - :param stream_handler: The handler to invoke on each token. - :param stop_words: The stop words to ignore. - """ - client = sseclient.SSEClient(response) # type: ignore # requests.Response behaves like a generator but the typing does not reflect it - tokens: List[str] = [] - try: - for event in client.events(): - if event.data != TokenStreamingHandler.DONE_MARKER: - event_data = json.loads(event.data) - token: Optional[str] = self._extract_token(event_data) - # if valid token and not a stop words (we don't want to return stop words) - if token and token.strip() not in stop_words: - tokens.append(stream_handler(token, event_data=event_data)) - finally: - client.close() - return ["".join(tokens)] # return a list of strings just like non-streaming - - def _extract_token(self, event_data: Dict[str, Any]) -> Optional[str]: - """ - Extract the token from the event data. If the token is a special token, return None. - param event_data: Event data from the streaming response. - """ - # extract token from event data and only consider non-special tokens - return event_data["token"]["text"] if not event_data["token"]["special"] else None - - def _post( - self, - data: Dict[str, Any], - stream: bool = False, - attempts: int = HF_RETRIES, - status_codes_to_retry: Optional[List[int]] = None, - timeout: float = HF_TIMEOUT, - ) -> requests.Response: - """ - Post data to the HF inference model. It takes in a prompt and returns a list of responses using a REST invocation. - :param data: The data to be sent to the model. - :param stream: Whether to stream the response. - :param attempts: The number of attempts to make. - :param status_codes_to_retry: The status codes to retry on. - :param timeout: The timeout for the request. - :return: The responses are being returned. - """ - response: requests.Response - if status_codes_to_retry is None: - status_codes_to_retry = [429] - try: - response = request_with_retry( - method="POST", - status_codes_to_retry=status_codes_to_retry, - attempts=attempts, - url=self.url, - headers=self.headers, - json=data, - timeout=timeout, - stream=stream, - ) - except requests.HTTPError as err: - res = err.response - if res.status_code == 429: # type: ignore[union-attr] - raise HuggingFaceInferenceLimitError(f"API rate limit exceeded: {res.text}") # type: ignore[union-attr] - if res.status_code == 401: # type: ignore[union-attr] - raise HuggingFaceInferenceUnauthorizedError(f"API key is invalid: {res.text}") # type: ignore[union-attr] - - raise HuggingFaceInferenceError( - f"HuggingFace Inference returned an error.\nStatus code: {res.status_code}\nResponse body: {res.text}", # type: ignore[union-attr] - status_code=res.status_code, # type: ignore[union-attr] - ) - return response - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - # the prompt for this model will be of the type str - resize_info = self.prompt_handler(prompt) # type: ignore - if resize_info["prompt_length"] != resize_info["new_prompt_length"]: - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens so that the prompt length and " - "answer length (%s tokens) fit within the max token limit (%s tokens). " - "Shorten the prompt to prevent it from being cut off.", - resize_info["prompt_length"], - max(0, resize_info["model_max_length"] - resize_info["max_length"]), # type: ignore - resize_info["max_length"], - resize_info["model_max_length"], - ) - return str(resize_info["resized_prompt"]) - - @staticmethod - def is_inference_endpoint(model_name_or_path: str) -> bool: - return model_name_or_path is not None and all( - token in model_name_or_path for token in ["https://", "endpoints"] - ) - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - if cls.is_inference_endpoint(model_name_or_path): - return True - else: - # Check if the model is an HF inference API - task_name: Optional[str] = None - is_inference_api = False - try: - task_name = get_task(model_name_or_path, use_auth_token=kwargs.get("use_auth_token", None)) - is_inference_api = bool(kwargs.get("api_key", None)) - except RuntimeError: - # This will fail for all non-HF models - return False - - return is_inference_api and task_name in ["text2text-generation", "text-generation"] diff --git a/haystack/nodes/prompt/invocation_layer/open_ai.py b/haystack/nodes/prompt/invocation_layer/open_ai.py deleted file mode 100644 index 825da26234..0000000000 --- a/haystack/nodes/prompt/invocation_layer/open_ai.py +++ /dev/null @@ -1,278 +0,0 @@ -from typing import List, Union, Dict, Optional, cast, Any -import json -import logging - -import sseclient - -from haystack.errors import OpenAIError -from haystack.nodes.prompt.invocation_layer.utils import has_azure_parameters -from haystack.utils.openai_utils import ( - _openai_text_completion_tokenization_details, - load_openai_tokenizer, - _check_openai_finish_reason, - check_openai_async_policy_violation, - check_openai_policy_violation, - openai_async_request, - openai_request, -) -from haystack.nodes.prompt.invocation_layer.base import PromptModelInvocationLayer -from haystack.nodes.prompt.invocation_layer.handlers import TokenStreamingHandler, DefaultTokenStreamingHandler - -logger = logging.getLogger(__name__) - - -class OpenAIInvocationLayer(PromptModelInvocationLayer): - """ - PromptModelInvocationLayer implementation for OpenAI's GPT-3 InstructGPT models. Invocations are made using REST API. - See [OpenAI GPT-3](https://platform.openai.com/docs/models/gpt-3) for more details. - - Note: kwargs other than init parameter names are ignored to enable reflective construction of the class - as many variants of PromptModelInvocationLayer are possible and they may have different parameters. - """ - - def __init__( - self, - api_key: str, - model_name_or_path: str = "text-davinci-003", - max_length: Optional[int] = 100, - api_base: str = "https://api.openai.com/v1", - openai_organization: Optional[str] = None, - timeout: Optional[float] = None, - **kwargs, - ): - """ - Creates an instance of OpenAIInvocationLayer for OpenAI's GPT-3 InstructGPT models. - - :param model_name_or_path: The name or path of the underlying model. - :param max_length: The maximum number of tokens the output text can have. - :param api_key: The OpenAI API key. - :param api_base: The OpenAI API Base url, defaults to `https://api.openai.com/v1`. - :param openai_organization: The OpenAI-Organization ID, defaults to `None`. For more details, see see OpenAI - [documentation](https://platform.openai.com/docs/api-reference/requesting-organization). - :param kwargs: Additional keyword arguments passed to the underlying model. Due to reflective construction of - all PromptModelInvocationLayer instances, this instance of OpenAIInvocationLayer might receive some unrelated - kwargs. Only the kwargs relevant to OpenAIInvocationLayer are considered. The list of OpenAI-relevant - kwargs includes: suffix, temperature, top_p, presence_penalty, frequency_penalty, best_of, n, max_tokens, - logit_bias, stop, echo, and logprobs. For more details about these kwargs, see OpenAI - [documentation](https://platform.openai.com/docs/api-reference/completions/create). - Note: additional model argument moderate_content will filter input and generated answers for potentially - sensitive content using the [OpenAI Moderation API](https://platform.openai.com/docs/guides/moderation) - if set. If the input or answers are flagged, an empty list is returned in place of the answers. - """ - super().__init__(model_name_or_path) - if not isinstance(api_key, str) or len(api_key) == 0: - raise OpenAIError( - f"api_key {api_key} must be a valid OpenAI key. Visit https://openai.com/api/ to get one." - ) - self.api_key = api_key - self.api_base = api_base - self.openai_organization = openai_organization - self.timeout = timeout - - # 16 is the default length for answers from OpenAI shown in the docs - # here, https://platform.openai.com/docs/api-reference/completions/create. - # max_length must be set otherwise OpenAIInvocationLayer._ensure_token_limit will fail. - self.max_length = max_length or 16 - - # Due to reflective construction of all invocation layers we might receive some - # unknown kwargs, so we need to take only the relevant. - # For more details refer to OpenAI documentation - self.model_input_kwargs = { - key: kwargs[key] - for key in [ - "suffix", - "max_tokens", - "temperature", - "top_p", - "n", - "logprobs", - "echo", - "stop", - "presence_penalty", - "frequency_penalty", - "best_of", - "logit_bias", - "stream", - "stream_handler", - "moderate_content", - ] - if key in kwargs - } - - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details( - model_name=self.model_name_or_path - ) - self.max_tokens_limit = max_tokens_limit - self._tokenizer = load_openai_tokenizer(tokenizer_name=tokenizer_name) - - @property - def url(self) -> str: - return f"{self.api_base}/completions" - - @property - def headers(self) -> Dict[str, str]: - headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"} - if self.openai_organization: - headers["OpenAI-Organization"] = self.openai_organization - return headers - - def _prepare_invoke(self, *args, **kwargs): - prompt = kwargs.get("prompt") - if not prompt: - raise ValueError( - f"No prompt provided. Model {self.model_name_or_path} requires prompt." - f"Make sure to provide prompt in kwargs." - ) - # either stream is True (will use default handler) or stream_handler is provided - kwargs_with_defaults = self.model_input_kwargs - if kwargs: - # we use keyword stop_words but OpenAI uses stop - if "stop_words" in kwargs: - kwargs["stop"] = kwargs.pop("stop_words") - if "top_k" in kwargs: - top_k = kwargs.pop("top_k") - kwargs["n"] = top_k - kwargs["best_of"] = top_k - kwargs_with_defaults.update(kwargs) - stream = ( - kwargs_with_defaults.get("stream", False) or kwargs_with_defaults.get("stream_handler", None) is not None - ) - moderation = kwargs_with_defaults.get("moderate_content", False) - base_payload = { # payload common to all OpenAI models - "model": self.model_name_or_path, - "max_tokens": kwargs_with_defaults.get("max_tokens", self.max_length), - "temperature": kwargs_with_defaults.get("temperature", 0.7), - "top_p": kwargs_with_defaults.get("top_p", 1), - "n": kwargs_with_defaults.get("n", 1), - "stream": stream, - "stop": kwargs_with_defaults.get("stop", None), - "presence_penalty": kwargs_with_defaults.get("presence_penalty", 0), - "frequency_penalty": kwargs_with_defaults.get("frequency_penalty", 0), - "logit_bias": kwargs_with_defaults.get("logit_bias", {}), - } - - return (prompt, base_payload, kwargs_with_defaults, stream, moderation) - - def invoke(self, *args, **kwargs): - """ - Invokes a prompt on the model. Based on the model, it takes in a prompt (or either a prompt or a list of messages) - and returns a list of responses using a REST invocation. - - :return: The responses are being returned. - - Note: Only kwargs relevant to OpenAI are passed to OpenAI rest API. Others kwargs are ignored. - For more details, see OpenAI [documentation](https://platform.openai.com/docs/api-reference/completions/create). - """ - prompt, base_payload, kwargs_with_defaults, stream, moderation = self._prepare_invoke(*args, **kwargs) - - if moderation and check_openai_policy_violation(input=prompt, headers=self.headers): - logger.info("Prompt '%s' will not be sent to OpenAI due to potential policy violation.", prompt) - return [] - - extra_payload = { - "prompt": prompt, - "suffix": kwargs_with_defaults.get("suffix", None), - "logprobs": kwargs_with_defaults.get("logprobs", None), - "echo": kwargs_with_defaults.get("echo", False), - "best_of": kwargs_with_defaults.get("best_of", 1), - } - payload = {**base_payload, **extra_payload} - if not stream: - res = openai_request(url=self.url, headers=self.headers, payload=payload) - _check_openai_finish_reason(result=res, payload=payload) - responses = [ans["text"].strip() for ans in res["choices"]] - else: - response = openai_request( - url=self.url, headers=self.headers, payload=payload, read_response=False, stream=True - ) - handler: TokenStreamingHandler = kwargs_with_defaults.pop("stream_handler", DefaultTokenStreamingHandler()) - responses = self._process_streaming_response(response=response, stream_handler=handler) - - if moderation and check_openai_policy_violation(input=responses, headers=self.headers): - logger.info("Response '%s' will not be returned due to potential policy violation.", responses) - return [] - - return responses - - async def ainvoke(self, *args, **kwargs): - """ - asyncio version of the `invoke` method. - """ - prompt, base_payload, kwargs_with_defaults, stream, moderation = self._prepare_invoke(*args, **kwargs) - if moderation and await check_openai_async_policy_violation(input=prompt, headers=self.headers): - logger.info("Prompt '%s' will not be sent to OpenAI due to potential policy violation.", prompt) - return [] - - extra_payload = { - "prompt": prompt, - "suffix": kwargs_with_defaults.get("suffix", None), - "logprobs": kwargs_with_defaults.get("logprobs", None), - "echo": kwargs_with_defaults.get("echo", False), - "best_of": kwargs_with_defaults.get("best_of", 1), - } - payload = {**base_payload, **extra_payload} - if not stream: - res = await openai_async_request(url=self.url, headers=self.headers, payload=payload) - _check_openai_finish_reason(result=res, payload=payload) - responses = [ans["text"].strip() for ans in res["choices"]] - else: - response = await openai_async_request( - url=self.url, headers=self.headers, payload=payload, read_response=False, stream=True - ) - handler: TokenStreamingHandler = kwargs_with_defaults.pop("stream_handler", DefaultTokenStreamingHandler()) - responses = self._process_streaming_response(response=response, stream_handler=handler) - - if moderation and await check_openai_async_policy_violation(input=responses, headers=self.headers): - logger.info("Response '%s' will not be returned due to potential policy violation.", responses) - return [] - - return responses - - def _process_streaming_response(self, response, stream_handler: TokenStreamingHandler): - client = sseclient.SSEClient(response) - tokens: List[str] = [] - try: - for event in client.events(): - if event.data != TokenStreamingHandler.DONE_MARKER: - event_data = json.loads(event.data) - token: str = self._extract_token(event_data) - if token: - tokens.append(stream_handler(token, event_data=event_data["choices"])) - finally: - client.close() - return ["".join(tokens)] # return a list of strings just like non-streaming - - def _extract_token(self, event_data: Dict[str, Any]): - return event_data["choices"][0]["text"] - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - """Ensure that the length of the prompt and answer is within the max tokens limit of the model. - If needed, truncate the prompt text so that it fits within the limit. - - :param prompt: Prompt text to be sent to the generative model. - """ - n_prompt_tokens = len(self._tokenizer.encode(cast(str, prompt))) - n_answer_tokens = self.max_length - if (n_prompt_tokens + n_answer_tokens) <= self.max_tokens_limit: - return prompt - - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens so that the prompt length and " - "answer length (%s tokens) fit within the max token limit (%s tokens). " - "Reduce the length of the prompt to prevent it from being cut off.", - n_prompt_tokens, - self.max_tokens_limit - n_answer_tokens, - n_answer_tokens, - self.max_tokens_limit, - ) - - tokenized_payload = self._tokenizer.encode(prompt) - decoded_string = self._tokenizer.decode(tokenized_payload[: self.max_tokens_limit - n_answer_tokens]) - return decoded_string - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - valid_model = model_name_or_path in ["ada", "babbage", "davinci", "curie", "gpt-3.5-turbo-instruct"] or any( - m in model_name_or_path for m in ["-ada-", "-babbage-", "-davinci-", "-curie-"] - ) - return valid_model and not has_azure_parameters(**kwargs) diff --git a/haystack/nodes/prompt/invocation_layer/sagemaker_base.py b/haystack/nodes/prompt/invocation_layer/sagemaker_base.py deleted file mode 100644 index b18e0f1f6f..0000000000 --- a/haystack/nodes/prompt/invocation_layer/sagemaker_base.py +++ /dev/null @@ -1,154 +0,0 @@ -import json -import logging -from abc import abstractmethod, ABC -from typing import Dict, Union, List, Any - - -from haystack.errors import AWSConfigurationError, SageMakerConfigurationError -from haystack.lazy_imports import LazyImport -from haystack.nodes.prompt.invocation_layer.aws_base import AWSBaseInvocationLayer -from haystack.nodes.prompt.invocation_layer.handlers import DefaultPromptHandler - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[aws]'") as boto3_import: - import boto3 - from botocore.exceptions import ClientError - - -class SageMakerBaseInvocationLayer(AWSBaseInvocationLayer, ABC): - """ - Base class for SageMaker based invocation layers. - """ - - def __init__(self, model_name_or_path: str, max_length: int = 100, **kwargs): - super().__init__(model_name_or_path, **kwargs) - self.max_length = max_length - - # We pop the model_max_length as it is not sent to the model - # but used to truncate the prompt if needed - model_max_length = kwargs.get("model_max_length", 1024) - - # Truncate prompt if prompt tokens > model_max_length-max_length - # (max_length is the length of the generated text) - # It is hard to determine which tokenizer to use for the SageMaker model - # so we use GPT2 tokenizer which will likely provide good token count approximation - self.prompt_handler = DefaultPromptHandler( - model_name_or_path="gpt2", model_max_length=model_max_length, max_length=self.max_length or 100 - ) - - @classmethod - @abstractmethod - def get_test_payload(cls) -> Dict[str, Any]: - """ - Return test payload for the model. - """ - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - # the prompt for this model will be of the type str - if isinstance(prompt, List): - raise ValueError("SageMaker invocation layer doesn't support a dictionary as prompt, only a string.") - - resize_info = self.prompt_handler(prompt) - if resize_info["prompt_length"] != resize_info["new_prompt_length"]: - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens so that the prompt length and " - "answer length (%s tokens) fit within the max token limit (%s tokens). " - "Shorten the prompt to prevent it from being cut off.", - resize_info["prompt_length"], - max(0, resize_info["model_max_length"] - resize_info["max_length"]), # type: ignore - resize_info["max_length"], - resize_info["model_max_length"], - ) - return str(resize_info["resized_prompt"]) - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - """ - Checks whether a model_name_or_path passed down (e.g. via PromptNode) is supported by this class. - - :param model_name_or_path: The model_name_or_path to check. - """ - if cls.aws_configured(**kwargs): - # attempt to create a session with the provided credentials - try: - session = cls.get_aws_session(**kwargs) - except AWSConfigurationError as e: - raise SageMakerConfigurationError(message=e.message) from e - # is endpoint in service? - cls.check_endpoint_in_service(session, model_name_or_path) - - test_payload = cls.get_test_payload() - # send test payload to endpoint to see if it's supported - supported = cls.check_model_input_format(session, model_name_or_path, test_payload, **kwargs) - return supported - return False - - @classmethod - def check_endpoint_in_service(cls, session: "boto3.Session", endpoint: str): - """ - Checks if the SageMaker endpoint exists and is in service. - :param session: The boto3 session. - :param endpoint: The endpoint to check. - """ - boto3_import.check() - client = None - try: - client = session.client("sagemaker") - response = client.describe_endpoint(EndpointName=endpoint) - endpoint_status = response["EndpointStatus"] if "EndpointStatus" in response else None - if endpoint_status and endpoint_status.strip() != "InService": - raise SageMakerConfigurationError( - f"SageMaker endpoint {endpoint} exists but is not in service. " - f"Please make sure that the endpoint is in state 'InService'." - ) - except ClientError as e: - raise SageMakerConfigurationError( - f"Could not connect to {endpoint} Sagemaker endpoint. " - f"Please make sure that the endpoint exists and is accessible." - ) from e - finally: - if client: - client.close() - - @classmethod - def format_custom_attributes(cls, attributes: dict) -> str: - """ - Formats the custom attributes for the SageMaker endpoint. - :param attributes: The custom attributes to format. - :return: The formatted custom attributes. - """ - if attributes: - return ";".join(f"{k}={str(v).lower() if isinstance(v, bool) else str(v)}" for k, v in attributes.items()) - return "" - - @classmethod - def check_model_input_format(cls, session: "boto3.Session", endpoint: str, test_payload: Any, **kwargs): - """ - Checks if the SageMaker endpoint supports the test_payload model input format. - :param session: The boto3 session. - :param endpoint: The endpoint to hit - :param test_payload: The payload to send to the endpoint - :return: True if the endpoint supports the test_payload model input format, False otherwise. - """ - boto3_import.check() - custom_attributes = kwargs.get("aws_custom_attributes", None) - custom_attributes = SageMakerBaseInvocationLayer.format_custom_attributes(custom_attributes) - client = None - try: - client = session.client("sagemaker-runtime") - client.invoke_endpoint( - EndpointName=endpoint, - Body=json.dumps(test_payload), - ContentType="application/json", - Accept="application/json", - CustomAttributes=custom_attributes, - ) - except ClientError: - # raised if the endpoint doesn't support the test_payload model input format - return False - finally: - if client: - client.close() - return True diff --git a/haystack/nodes/prompt/invocation_layer/sagemaker_hf_infer.py b/haystack/nodes/prompt/invocation_layer/sagemaker_hf_infer.py deleted file mode 100644 index 263d765a12..0000000000 --- a/haystack/nodes/prompt/invocation_layer/sagemaker_hf_infer.py +++ /dev/null @@ -1,267 +0,0 @@ -import json -import logging -from typing import Optional, Dict, List, Any - -import requests - -from haystack.errors import SageMakerInferenceError, SageMakerConfigurationError, SageMakerModelNotReadyError -from haystack.nodes.prompt.invocation_layer.sagemaker_base import SageMakerBaseInvocationLayer - -logger = logging.getLogger(__name__) - - -class SageMakerHFInferenceInvocationLayer(SageMakerBaseInvocationLayer): - """ - SageMaker HuggingFace Inference Invocation Layer - - SageMakerHFInferenceInvocationLayer enables the use of Large Language Models (LLMs) hosted on a SageMaker Inference - Endpoint via PromptNode. It supports text-generation and text2text-generation models from HuggingFace, which are - running on the SageMaker Inference Endpoint. - - As of June 23, this layer has been confirmed to support the following SageMaker deployed models: - - MPT - - Dolly V2 - - Flan-U2 - - Flan-T5 - - RedPajama - - Open Llama - - GPT-J-6B - - GPT NEO - - BloomZ - - For guidance on how to deploy such a model to SageMaker, refer to - the [SageMaker JumpStart foundation models documentation](https://docs.aws.amazon.com/sagemaker/latest/dg/jumpstart-foundation-models-use.html) - and follow the instructions provided there. - - Technical Note: - - This layer is designed for models that anticipate an input format composed of the following keys/values: - {'text_inputs': 'prompt_text', **(params or {})} - The text_inputs key represents the prompt text, with all additional parameters for the model being added at - the same dictionary level as text_inputs. - - - **Example** - - ```python - from haystack.nodes import PromptNode - - # Pass sagemaker endpoint name and authentication details - pn = PromptNode(model_name_or_path="jumpstart-dft-hf-textgeneration-dolly-v2-3b-bf16", - model_kwargs={"aws_profile_name": "my_aws_profile_name", "aws_region_name": "eu-central-1"}) - res = pn("what is the meaning of life?") - print(res) - ``` - - **Example using AWS env variables** - ```python - import os - from haystack.nodes import PromptNode - - # We can also configure Sagemaker via AWS environment variables without AWS profile name - pn = PromptNode(model_name_or_path="jumpstart-dft-hf-textgeneration-dolly-v2-3b-bf16", max_length=128, - model_kwargs={"aws_access_key_id": os.getenv("AWS_ACCESS_KEY_ID"), - "aws_secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"), - "aws_session_token": os.getenv("AWS_SESSION_TOKEN"), - "aws_region_name": "us-east-1"}) - - response = pn("Tell me more about Berlin, be elaborate") - print(response) - ``` - - Of course, in both examples your endpoints, region names and other settings will be different. - You can find it in the SageMaker AWS console. - """ - - def __init__( - self, - model_name_or_path: str, - max_length: int = 100, - aws_access_key_id: Optional[str] = None, - aws_secret_access_key: Optional[str] = None, - aws_session_token: Optional[str] = None, - aws_region_name: Optional[str] = None, - aws_profile_name: Optional[str] = None, - **kwargs, - ): - """ - Instantiates the session with SageMaker using IAM based authentication via boto3. - - :param model_name_or_path: The name for SageMaker Model Endpoint. - :param max_length: The maximum length of the output text. - :param aws_access_key_id: AWS access key ID. - :param aws_secret_access_key: AWS secret access key. - :param aws_session_token: AWS session token. - :param aws_region_name: AWS region name. - :param aws_profile_name: AWS profile name. - """ - super().__init__(model_name_or_path, max_length=max_length, **kwargs) - try: - session = self.get_aws_session( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token, - aws_region_name=aws_region_name, - aws_profile_name=aws_profile_name, - ) - self.client = session.client("sagemaker-runtime") - except Exception as e: - raise SageMakerInferenceError( - f"Could not connect to SageMaker Inference Endpoint {model_name_or_path}." - f"Make sure the Endpoint exists and AWS environment is configured." - ) from e - - self.model_input_kwargs = { - key: kwargs[key] - for key in [ - "max_length", - "max_time", - "num_return_sequences", - "num_beams", - "no_repeat_ngram_size", - "temperature", - "early_stopping", - "do_sample", - "top_k", - "top_p", - "seed", - "return_full_text", - ] - if key in kwargs - } - - # As of June 23, SageMaker does not support streaming responses. - # However, even though it's not provided, users may attempt to use streaming responses. - # Use stream and stream_handler for warning and future use - self.stream_handler = kwargs.get("stream_handler", None) - self.stream = kwargs.get("stream", False) - - def invoke(self, *args, **kwargs) -> List[str]: - """ - Sends the prompt to the remote model and returns the generated response(s). - You can pass all parameters supported by the SageMaker model - here via **kwargs (e.g. "temperature", "do_sample" ...). - - :return: The generated responses from the model as a list of strings. - """ - - prompt = kwargs.get("prompt") - if not prompt: - raise ValueError( - f"No prompt provided. Model {self.model_name_or_path} requires prompt." - f"Make sure to provide prompt in kwargs." - ) - - stream = kwargs.get("stream", self.stream) - stream_handler = kwargs.get("stream_handler", self.stream_handler) - streaming_requested = stream or stream_handler is not None - if streaming_requested: - raise SageMakerConfigurationError("SageMaker model response streaming is not supported yet") - - stop_words = kwargs.pop("stop_words", None) # doesn't tolerate empty list - kwargs_with_defaults = self.model_input_kwargs - kwargs_with_defaults.update(kwargs) - - # these parameters were valid in June 23, make sure to check the Sagemaker docs for updates - default_params = { - "max_length": self.max_length, - "max_time": None, - "num_return_sequences": None, - "num_beams": None, - "no_repeat_ngram_size": None, - "temperature": None, - "early_stopping": None, - "do_sample": None, - "top_k": None, - "top_p": None, - "seed": None, - "stopping_criteria": stop_words, - "return_full_text": None, # not used by all models (e.g. MPT, Flan) - } - - # put the param in the params if it's in kwargs and not None (e.g. it is actually defined) - # endpoint doesn't tolerate None values, send only the params that are defined - params = { - param: kwargs_with_defaults.get(param, default) - for param, default in default_params.items() - if param in kwargs_with_defaults or default is not None - } - generated_texts = self._post(prompt=prompt, params=params) - return generated_texts - - def _post(self, prompt: str, params: Optional[Dict[str, Any]] = None) -> List[str]: - """ - Post data to the SageMaker inference model. It takes in a prompt and returns a list of responses using model invocation. - :param prompt: The prompt text to be sent to the model. - :param params: The parameters to be sent to the Hugging Face model (see https://huggingface.co/docs/api-inference/detailed_parameters#text-generation-task) - :return: The generated responses as a list of strings. - """ - - try: - body = {"text_inputs": prompt, **(params or {})} - response = self.client.invoke_endpoint( - EndpointName=self.model_name_or_path, - Body=json.dumps(body), - ContentType="application/json", - Accept="application/json", - ) - response_json = response.get("Body").read().decode("utf-8") - output = json.loads(response_json) - return self._extract_response(output) - except requests.HTTPError as err: - res = err.response - if res.status_code == 429: # type: ignore[union-attr] - raise SageMakerModelNotReadyError(f"Model not ready: {res.text}") # type: ignore[union-attr] - raise SageMakerInferenceError( - f"SageMaker Inference returned an error.\nStatus code: {res.status_code}\nResponse body: {res.text}", # type: ignore[union-attr] - status_code=res.status_code, # type: ignore[union-attr] - ) - - def _extract_response(self, json_response: Any) -> List[str]: - """ - Extracts generated list of texts from the JSON response. - :param json_response: The JSON response to process. - :return: A list of generated texts. - """ - generated_texts = [] - for response in self._unwrap_response(json_response): - for key in ["generated_texts", "generated_text"]: - raw_response = response.get(key) - if raw_response: - if isinstance(raw_response, list): - generated_texts.extend(raw_response) - else: - generated_texts.append(raw_response) - return generated_texts - - def _unwrap_response(self, response: Any): - """ - Recursively unwrap the JSON response to get to the dictionary level where the generated text is. - - If the response is a list, it recursively calls this method for each sublist. - If the response is a dict and contains either "generated_text" or "generated_texts" key, - it yields the dictionary. - - :param response: The response to process. - :yield: dictionary containing either "generated_text" or "generated_texts" key with a - string or list of strings as value. - """ - if isinstance(response, list): - for sublist in response: - yield from self._unwrap_response(sublist) - elif isinstance(response, dict) and ("generated_text" in response or "generated_texts" in response): - yield response - - @classmethod - def get_test_payload(cls) -> Dict[str, str]: - """ - Returns a payload used for testing if the current endpoint supports the JSON payload format used by - this class. - - As of June 23, Sagemaker endpoints support the format where the payload is a JSON object with: - "text_inputs" used as the key and the prompt as the value. All other parameters are passed as key/value - pairs on the same level. See _post method for more details. - - :return: A payload used for testing if the current endpoint is working. - """ - return {"text_inputs": "Hello world!"} diff --git a/haystack/nodes/prompt/invocation_layer/sagemaker_hf_text_gen.py b/haystack/nodes/prompt/invocation_layer/sagemaker_hf_text_gen.py deleted file mode 100644 index 0ac51f0654..0000000000 --- a/haystack/nodes/prompt/invocation_layer/sagemaker_hf_text_gen.py +++ /dev/null @@ -1,222 +0,0 @@ -import json -import logging -from typing import Optional, Dict, List, Any - -import requests - -from haystack.errors import SageMakerModelNotReadyError, SageMakerInferenceError, SageMakerConfigurationError -from haystack.nodes.prompt.invocation_layer.sagemaker_base import SageMakerBaseInvocationLayer - -logger = logging.getLogger(__name__) - - -class SageMakerHFTextGenerationInvocationLayer(SageMakerBaseInvocationLayer): - """ - SageMaker HuggingFace TextGeneration Invocation Layer - - - SageMakerHFTextGenerationInvocationLayer enables the use of Large Language Models (LLMs) hosted on a SageMaker - Inference Endpoint via PromptNode. It supports text-generation from HuggingFace, which are running on the - SageMaker Inference Endpoint. - - For guidance on how to deploy such a model to SageMaker, refer to - the [SageMaker JumpStart foundation models documentation](https://docs.aws.amazon.com/sagemaker/latest/dg/jumpstart-foundation-models-use.html) - and follow the instructions provided there. - - As of June 23, this layer has been confirmed to support the following SageMaker deployed models: - - Falcon models - - Technical Note: - This layer is designed for models that anticipate an input format composed of the following keys/values: - {'inputs': 'prompt_text', 'parameters': params} where 'inputs' represents the prompt and 'parameters' the - parameters for the model. - - - **Example** - - ```python - from haystack.nodes import PromptNode - - # Pass sagemaker endpoint name and authentication details - pn = PromptNode(model_name_or_path="falcon-40b-my-sagemaker-inference-endpoint, - model_kwargs={"aws_profile_name": "my_aws_profile_name", "aws_region_name": "eu-central-1"}) - res = pn("what is the meaning of life?") - print(res) - ``` - - **Example using AWS env variables** - ```python - import os - from haystack.nodes import PromptNode - - # We can also configure Sagemaker via AWS environment variables without AWS profile name - pn = PromptNode(model_name_or_path="hf-llm-falcon-7b-instruct-bf16-2023-06-22-16-22-19-811", max_length=256, - model_kwargs={"aws_access_key_id": os.getenv("AWS_ACCESS_KEY_ID"), - "aws_secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"), - "aws_session_token": os.getenv("AWS_SESSION_TOKEN"), - "aws_region_name": "us-east-1"}) - - response = pn("Tell me more about Berlin, be elaborate") - print(response) - ``` - - Of course, in both examples your endpoints, region names and other settings will be different. - You can find it in the SageMaker AWS console. - """ - - def __init__( - self, - model_name_or_path: str, - max_length: int = 100, - aws_access_key_id: Optional[str] = None, - aws_secret_access_key: Optional[str] = None, - aws_session_token: Optional[str] = None, - aws_region_name: Optional[str] = None, - aws_profile_name: Optional[str] = None, - **kwargs, - ): - """ - Instantiates the session with SageMaker using IAM based authentication via boto3. - - :param model_name_or_path: The name for SageMaker Model Endpoint. - :param max_length: The maximum length of the output text. - :param aws_access_key_id: AWS access key ID. - :param aws_secret_access_key: AWS secret access key. - :param aws_session_token: AWS session token. - :param aws_region_name: AWS region name. - :param aws_profile_name: AWS profile name. - """ - super().__init__(model_name_or_path, max_length=max_length, **kwargs) - try: - session = self.get_aws_session( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token, - aws_region_name=aws_region_name, - aws_profile_name=aws_profile_name, - ) - self.client = session.client("sagemaker-runtime") - except Exception as e: - raise SageMakerInferenceError( - f"Could not connect to SageMaker Inference Endpoint {model_name_or_path}." - f"Make sure the Endpoint exists and AWS environment is configured." - ) from e - - # for a list of supported parameters - # see https://huggingface.co/blog/sagemaker-huggingface-llm#4-run-inference-and-chat-with-our-model - self.model_input_kwargs = { - key: kwargs[key] - for key in [ - "best_of", - "details", - "do_sample", - "max_new_tokens", - "repetition_penalty", - "return_full_text", - "seed", - "temperature", - "top_k", - "top_p", - "truncate", - "typical_p", - "watermark", - ] - if key in kwargs - } - - # As of June 23, SageMaker does not support streaming responses. - # However, even though it's not provided, users may attempt to use streaming responses. - # Use stream and stream_handler for warning and future use - self.stream_handler = kwargs.get("stream_handler", None) - self.stream = kwargs.get("stream", False) - - def invoke(self, *args, **kwargs) -> List[str]: - """ - Sends the prompt to the remote model and returns the generated response(s). - You can pass all parameters supported by the Huggingface Transformers `generate` method - here via **kwargs (e.g. "temperature", "stop" ...). - - :return: The generated responses from the model as a list of strings. - """ - prompt = kwargs.get("prompt") - if not prompt: - raise ValueError( - f"No prompt provided. Model {self.model_name_or_path} requires prompt." - f"Make sure to provide prompt in kwargs." - ) - - stream = kwargs.get("stream", self.stream) - stream_handler = kwargs.get("stream_handler", self.stream_handler) - streaming_requested = stream or stream_handler is not None - if streaming_requested: - raise SageMakerConfigurationError("SageMaker model response streaming is not supported yet") - - stop_words = kwargs.pop("stop_words", None) or [] - kwargs_with_defaults = self.model_input_kwargs - kwargs_with_defaults.update(kwargs) - - # For the list of supported parameters and the docs - # see https://huggingface.co/blog/sagemaker-huggingface-llm#4-run-inference-and-chat-with-our-model - # these parameters were valid in June 23, make sure to check the docs for updates - params = { - "best_of": kwargs_with_defaults.get("best_of", None), - "details": kwargs_with_defaults.get("details", False), - "do_sample": kwargs_with_defaults.get("do_sample", False), - "max_new_tokens": kwargs_with_defaults.get("max_new_tokens", self.max_length), - "repetition_penalty": kwargs_with_defaults.get("repetition_penalty", None), - "return_full_text": kwargs_with_defaults.get("return_full_text", False), - "seed": kwargs_with_defaults.get("seed", None), - "stop": kwargs_with_defaults.get("stop", stop_words), - "temperature": kwargs_with_defaults.get("temperature", 1.0), - "top_k": kwargs_with_defaults.get("top_k", None), - "top_p": kwargs_with_defaults.get("top_p", None), - "truncate": kwargs_with_defaults.get("truncate", None), - "typical_p": kwargs_with_defaults.get("typical_p", None), - "watermark": kwargs_with_defaults.get("watermark", False), - } - generated_texts = self._post(prompt=prompt, params=params) - return generated_texts - - def _post(self, prompt: str, params: Optional[Dict[str, Any]] = None) -> List[str]: - """ - Post data to the SageMaker inference model. It takes in a prompt and returns a list of responses using model invocation. - :param prompt: The prompt text to be sent to the model. - :param params: The parameters to be sent to the Hugging Face model (see https://huggingface.co/docs/api-inference/detailed_parameters#text-generation-task) - :return: The generated responses as a list of strings. - """ - - try: - body = {"inputs": prompt, "parameters": params} - response = self.client.invoke_endpoint( - EndpointName=self.model_name_or_path, - Body=json.dumps(body), - ContentType="application/json", - Accept="application/json", - ) - response_json = response.get("Body").read().decode("utf-8") - output = json.loads(response_json) - generated_texts = [o["generated_text"] for o in output if "generated_text" in o] - return generated_texts - except requests.HTTPError as err: - res = err.response - if res.status_code == 429: # type: ignore[union-attr] - raise SageMakerModelNotReadyError(f"Model not ready: {res.text}") from err # type: ignore[union-attr] - raise SageMakerInferenceError( - f"SageMaker Inference returned an error.\nStatus code: {res.status_code}\nResponse body: {res.text}", # type: ignore[union-attr] - status_code=res.status_code, # type: ignore[union-attr] - ) from err - - @classmethod - def get_test_payload(cls) -> Dict[str, Any]: - """ - Returns a payload used for testing if the current endpoint supports the JSON payload format used by - this class. - - As of June 23, Sagemaker endpoints support the JSON payload format from the - https://github.com/huggingface/text-generation-inference project. At the time of writing this docstring, - only Falcon models were deployed using this format. See python client implementation from the - https://github.com/huggingface/text-generation-inference for more details. - - :return: A payload used for testing if the current endpoint is working. - """ - return {"inputs": "Hello world", "parameters": {}} diff --git a/haystack/nodes/prompt/invocation_layer/sagemaker_meta.py b/haystack/nodes/prompt/invocation_layer/sagemaker_meta.py deleted file mode 100644 index e77912adce..0000000000 --- a/haystack/nodes/prompt/invocation_layer/sagemaker_meta.py +++ /dev/null @@ -1,330 +0,0 @@ -import json -import logging -from typing import Optional, Dict, List, Any, Union - -import requests - -from haystack.errors import ( - AWSConfigurationError, - SageMakerModelNotReadyError, - SageMakerInferenceError, - SageMakerConfigurationError, -) -from haystack.nodes.prompt.invocation_layer.sagemaker_base import SageMakerBaseInvocationLayer - -logger = logging.getLogger(__name__) - - -class SageMakerMetaInvocationLayer(SageMakerBaseInvocationLayer): - """ - SageMaker Meta Invocation Layer - - - SageMakerMetaInvocationLayer enables the use of Meta Large Language Models (LLMs) hosted on a SageMaker - Inference Endpoint via PromptNode. It primarily focuses on LLama-2 models and it supports both the chat and - instruction following models. Other Meta models have not been tested. - - For guidance on how to deploy such a model to SageMaker, refer to - the [SageMaker JumpStart foundation models documentation](https://docs.aws.amazon.com/sagemaker/latest/dg/jumpstart-foundation-models-use.html) - and follow the instructions provided there. - - As of July 24, this layer has been confirmed to support the following SageMaker deployed models: - - Llama-2 models - - Technical Note: - This layer is designed for models that anticipate an input format composed of the following keys/values: - {'inputs': 'prompt_text', 'parameters': params} where 'inputs' represents the prompt and 'parameters' the - parameters for the model. - - - **Examples** - - ```python - from haystack.nodes import PromptNode - - # Pass sagemaker endpoint name and authentication details - pn = PromptNode(model_name_or_path="llama-2-7b", - model_kwargs={"aws_profile_name": "my_aws_profile_name"}) - res = pn("Berlin is the capital of") - print(res) - ``` - - **Example using AWS env variables** - ```python - import os - from haystack.nodes import PromptNode - - # We can also configure Sagemaker via AWS environment variables without AWS profile name - pn = PromptNode(model_name_or_path="llama-2-7b", max_length=512, - model_kwargs={"aws_access_key_id": os.getenv("AWS_ACCESS_KEY_ID"), - "aws_secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"), - "aws_session_token": os.getenv("AWS_SESSION_TOKEN"), - "aws_region_name": "us-east-1"}) - - response = pn("The secret for a good life is") - print(response) - ``` - - LLama-2 also supports chat format. - **Example using chat format** - ```python - from haystack.nodes.prompt import PromptNode - pn = PromptNode(model_name_or_path="llama-2-7b-chat", max_length=512, model_kwargs={"aws_profile_name": "default", - "aws_custom_attributes": {"accept_eula": True}}) - pn_input = [[{"role": "user", "content": "what is the recipe of mayonnaise?"}]] - response = pn(pn_input) - print(response) - ``` - - Note that in the chat examples we can also include multiple turns between the user and the assistant. See the - Llama-2 chat documentation for more details. - - **Example using chat format with multiple turns** - ```python - from haystack.nodes.prompt import PromptNode - pn = PromptNode(model_name_or_path="llama-2-7b-chat", max_length=512, model_kwargs={"aws_profile_name": "default", - "aws_custom_attributes": {"accept_eula": True}}) - pn_input = [[ - {"role": "user", "content": "I am going to Paris, what should I see?"}, - {"role": "assistant", "content": "Paris, the capital of France, is known for its stunning architecture, art museums, historical landmarks, and romantic atmosphere. Here are some of the top attractions to see in Paris:\n - 1. The Eiffel Tower: The iconic Eiffel Tower is one of the most recognizable landmarks in the world and offers breathtaking views of the city.\n - 2. The Louvre Museum: The Louvre is one of the world's largest and most famous museums, housing an impressive collection of art and artifacts, including the Mona Lisa.\n - 3. Notre-Dame Cathedral: This beautiful cathedral is one of the most famous landmarks in Paris and is known for its Gothic architecture and stunning stained glass windows.\n - These are just a few of the many attractions that Paris has to offer. With so much to see and do, it's no wonder that Paris is one of the most popular tourist destinations in the world.",}, - {"role": "user", "content": "What is so great about #1?"}]] - response = pn(pn_input) - print(response) - ``` - - - - Llama-2 models support the following inference payload parameters: - - max_new_tokens: Model generates text until the output length (excluding the input context length) reaches - max_new_tokens. If specified, it must be a positive integer. - temperature: Controls the randomness in the output. Higher temperature results in output sequence with - low-probability words and lower temperature results in output sequence with high-probability words. - If temperature -> 0, it results in greedy decoding. If specified, it must be a positive float. - top_p: In each step of text generation, sample from the smallest possible set of words with cumulative - probability top_p. If specified, it must be a float between 0 and 1. - return_full_text: If True, input text will be part of the output generated text. If specified, it must be - boolean. The default value for it is False. - - Of course, in both examples your endpoints, region names and other settings will be different. - You can find it in the SageMaker AWS console. - """ - - def __init__( - self, - model_name_or_path: str, - max_length: int = 100, - aws_access_key_id: Optional[str] = None, - aws_secret_access_key: Optional[str] = None, - aws_session_token: Optional[str] = None, - aws_region_name: Optional[str] = None, - aws_profile_name: Optional[str] = None, - **kwargs, - ): - """ - Instantiates the session with SageMaker using IAM based authentication via boto3. - - :param model_name_or_path: The name for SageMaker Model Endpoint. - :param max_length: The maximum length of the output text. - :param aws_access_key_id: AWS access key ID. - :param aws_secret_access_key: AWS secret access key. - :param aws_session_token: AWS session token. - :param aws_region_name: AWS region name. - :param aws_profile_name: AWS profile name. - """ - # We set the default max_length to 4096 as this is the context window size supported by the LLama-2 model - kwargs.setdefault("model_max_length", 4096) - super().__init__(model_name_or_path, max_length=max_length, **kwargs) - try: - session = self.get_aws_session( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token, - aws_region_name=aws_region_name, - aws_profile_name=aws_profile_name, - ) - self.client = session.client("sagemaker-runtime") - except Exception as e: - raise SageMakerInferenceError( - f"Could not connect to SageMaker Inference Endpoint {model_name_or_path}." - f"Make sure the Endpoint exists and AWS environment is configured." - ) from e - - # save the kwargs for the model invocation - self.model_input_kwargs = kwargs - - # As of July 24, SageMaker Meta layer does not support streaming responses. - # However, even though it's not provided, users may attempt to use streaming responses. - # Use stream and stream_handler for warning and future use - self.stream_handler = kwargs.get("stream_handler", None) - self.stream = kwargs.get("stream", False) - - def invoke(self, *args, **kwargs) -> List[str]: - """ - Sends the prompt to the remote model and returns the generated response(s). - - :return: The generated responses from the model as a list of strings. - """ - prompt: Any = kwargs.get("prompt") - if not prompt or not isinstance(prompt, (str, list)): - raise ValueError( - f"No valid prompt provided. Model {self.model_name_or_path} requires a valid prompt." - f"Make sure to provide a prompt in the format that the model expects." - ) - - if not (isinstance(prompt, str) or self.is_proper_chat_conversation_format(prompt)): - raise ValueError( - f"The prompt format is different than what the model expects. " - f"The model {self.model_name_or_path} requires either a string or messages in the specific chat format. " - f"For more details, see https://github.com/facebookresearch/llama/blob/main/llama/generation.py#L213)." - ) - - stream = kwargs.get("stream", self.stream) - stream_handler = kwargs.get("stream_handler", self.stream_handler) - streaming_requested = stream or stream_handler is not None - if streaming_requested: - raise SageMakerConfigurationError("SageMaker model response streaming is not supported yet") - - kwargs_with_defaults = self.model_input_kwargs - kwargs_with_defaults.update(kwargs) - - default_params = { - "max_new_tokens": self.max_length, - "return_full_text": None, - "temperature": None, - "top_p": None, - } - # put the param in the params if it's in kwargs and not None (e.g. it is actually defined) - # endpoint doesn't tolerate None values, send only the params that are defined - params = { - param: kwargs_with_defaults.get(param, default) - for param, default in default_params.items() - if param in kwargs_with_defaults or default is not None - } - generated_texts = self._post(prompt=prompt, params=params) - return generated_texts - - def _post(self, prompt: Any, params: Optional[Dict[str, Any]] = None) -> List[str]: - """ - Post data to the SageMaker inference model. It takes in a prompt and returns a list of responses using model - invocation. - :param prompt: The prompt text/messages to be sent to the model. - :param params: The parameters to be sent to the Meta model. - :return: The generated responses as a list of strings. - """ - custom_attributes = SageMakerBaseInvocationLayer.format_custom_attributes( - self.model_input_kwargs.get("aws_custom_attributes", {}) - ) - try: - body = {"inputs": prompt, "parameters": params} - response = self.client.invoke_endpoint( - EndpointName=self.model_name_or_path, - Body=json.dumps(body), - ContentType="application/json", - Accept="application/json", - CustomAttributes=custom_attributes, - ) - response_json = response.get("Body").read().decode("utf-8") - output = json.loads(response_json) - generated_texts = [o["generation"] for o in output if "generation" in o] - return generated_texts - except requests.HTTPError as err: - res = err.response - if res.status_code == 429: # type: ignore[union-attr] - raise SageMakerModelNotReadyError(f"Model not ready: {res.text}") from err # type: ignore[union-attr] - raise SageMakerInferenceError( - f"SageMaker Inference returned an error.\nStatus code: {res.status_code}\nResponse body: {res.text}", # type: ignore[union-attr] - status_code=res.status_code, # type: ignore[union-attr] - ) from err - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - # the prompt for this model will be of the type str - if isinstance(prompt, str): - return super()._ensure_token_limit(prompt) - else: - # TODO: implement truncation for the chat format - return prompt - - def _is_proper_chat_message_format(self, chat_message: Dict[str, str]) -> bool: - """ - Checks whether a chat message is in the proper format. - :param chat_message: The chat message to be checked. - :return: True if the chat message is in the proper format, False otherwise. - """ - allowed_roles = {"user", "assistant", "system"} - return ( - isinstance(chat_message, dict) - and "role" in chat_message - and "content" in chat_message - and chat_message["role"] in allowed_roles - ) - - def is_proper_chat_conversation_format(self, prompt: List[Any]) -> bool: - """ - Checks whether a chat conversation is in the proper format. - :param prompt: The chat conversation to be checked. - :return: True if the chat conversation is in the proper format, False otherwise. - """ - if not isinstance(prompt, list) or len(prompt) == 0: - return False - - return all( - isinstance(message_list, list) - and all(self._is_proper_chat_message_format(chat_message) for chat_message in message_list) - for message_list in prompt - ) - - @classmethod - def get_test_payload(cls) -> Dict[str, Any]: - """ - Return test payload for the model. - """ - # implement the abstract method to fulfill the contract, but it won't be used - # because we override the supports method to check support - # for the chat and instruction following format manually - return {} - - @classmethod - def supports(cls, model_name_or_path: str, **kwargs) -> bool: - """ - Checks whether a model_name_or_path passed down (e.g. via PromptNode) is supported by this class. - - :param model_name_or_path: The model_name_or_path to check. - """ - accept_eula = False - if "aws_custom_attributes" in kwargs and isinstance(kwargs["aws_custom_attributes"], dict): - accept_eula = kwargs["aws_custom_attributes"].get("accept_eula", False) - if cls.aws_configured(**kwargs) and accept_eula: - # attempt to create a session with the provided credentials - try: - session = cls.get_aws_session(**kwargs) - except AWSConfigurationError as e: - raise SageMakerConfigurationError(message=e.message) from e - # is endpoint in service? - cls.check_endpoint_in_service(session, model_name_or_path) - - # let's test both formats as we want to support both chat and instruction following models: - # 1. instruction following format - # send test payload to endpoint to see if it's supported - instruction_test_payload: Dict[str, Any] = { - "inputs": "Hello world", - # don't remove max_new_tokens param, if we don't specify it, the model will generate 4k tokens - "parameters": {"max_new_tokens": 10}, - } - supported = cls.check_model_input_format(session, model_name_or_path, instruction_test_payload, **kwargs) - if supported: - return True - - # 2. chat format - chat_test_payload: Dict[str, Any] = { - "inputs": [[{"role": "user", "content": "what is the recipe of mayonnaise?"}]], - # don't remove max_new_tokens param, if we don't specify it, the model will generate 4k tokens - "parameters": {"max_new_tokens": 10}, - } - supported = cls.check_model_input_format(session, model_name_or_path, chat_test_payload, **kwargs) - return supported - return False diff --git a/haystack/nodes/prompt/invocation_layer/utils.py b/haystack/nodes/prompt/invocation_layer/utils.py deleted file mode 100644 index 7016486c61..0000000000 --- a/haystack/nodes/prompt/invocation_layer/utils.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Optional, Union - -from huggingface_hub import model_info - - -def has_azure_parameters(**kwargs) -> bool: - azure_params = ["azure_base_url", "azure_deployment_name"] - return any(kwargs.get(param) for param in azure_params) - - -def get_task(model: str, use_auth_token: Optional[Union[str, bool]] = None, timeout: float = 3.0) -> Optional[str]: - """ - Retrieve the task (pipeline tag) associated with a given model. - - Simplified version of transformers.pipelines.get_task with support for timeouts - """ - try: - return model_info(model, token=use_auth_token, timeout=timeout).pipeline_tag - except Exception as e: - raise RuntimeError(f"The task for {model} couldn't be found!") from e diff --git a/haystack/nodes/prompt/prompt_model.py b/haystack/nodes/prompt/prompt_model.py deleted file mode 100644 index 47ce1ee987..0000000000 --- a/haystack/nodes/prompt/prompt_model.py +++ /dev/null @@ -1,167 +0,0 @@ -import inspect -import logging -from typing import Any, Dict, List, Optional, Tuple, Type, Union, overload - -from haystack.nodes.base import BaseComponent -from haystack.nodes.prompt.invocation_layer import PromptModelInvocationLayer -from haystack.schema import Document, MultiLabel -from haystack.lazy_imports import LazyImport - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_import: - import torch - - -logger = logging.getLogger(__name__) - - -class PromptModel(BaseComponent): - """ - The PromptModel class is a component that uses a pre-trained model to perform tasks defined in a prompt. Out of - the box, it supports model invocation layers for: - - Hugging Face transformers (all text2text-generation and text-generation models) - - OpenAI InstructGPT models - - Azure OpenAI InstructGPT models - - Although it's possible to use PromptModel to make prompt invocations on the underlying model, use - PromptNode to interact with the model. PromptModel instances are a way for multiple - PromptNode instances to use a single PromptNode, and thus save computational resources. - - For more details, refer to [PromptModels](https://docs.haystack.deepset.ai/docs/prompt_node#models). - """ - - outgoing_edges = 1 - - def __init__( - self, - model_name_or_path: str = "google/flan-t5-base", - max_length: Optional[int] = 100, - api_key: Optional[str] = None, - timeout: Optional[float] = None, - use_auth_token: Optional[Union[str, bool]] = None, - use_gpu: Optional[bool] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - invocation_layer_class: Optional[Type[PromptModelInvocationLayer]] = None, - model_kwargs: Optional[Dict] = None, - ): - """ - Creates an instance of PromptModel. - - :param model_name_or_path: The name or path of the underlying model. - :param max_length: The maximum number of tokens the output text generated by the model can have. - :param api_key: The API key to use for the model. - :param use_auth_token: The Hugging Face token to use. - :param use_gpu: Whether to use GPU or not. - :param devices: The devices to use where the model is loaded. - :param invocation_layer_class: The custom invocation layer class to use. If None, known invocation layers are used. - :param model_kwargs: Additional keyword arguments passed to the underlying model. - - Note that Azure OpenAI InstructGPT models require two additional parameters: azure_base_url (The URL for the - Azure OpenAI API endpoint, usually in the form `https://.openai.azure.com') and - azure_deployment_name (the name of the Azure OpenAI API deployment). You should add these parameters - in the `model_kwargs` dictionary. - """ - super().__init__() - self.model_name_or_path = model_name_or_path - self.max_length = max_length - self.api_key = api_key - self.timeout = timeout - self.use_auth_token = use_auth_token - self.use_gpu = use_gpu - self.devices = devices - - self.model_kwargs = model_kwargs if model_kwargs else {} - self.model_invocation_layer = self.create_invocation_layer(invocation_layer_class=invocation_layer_class) - - def create_invocation_layer( - self, invocation_layer_class: Optional[Type[PromptModelInvocationLayer]] - ) -> PromptModelInvocationLayer: - kwargs = { - "api_key": self.api_key, - "timeout": self.timeout, - "use_auth_token": self.use_auth_token, - "use_gpu": self.use_gpu, - "devices": self.devices, - } - all_kwargs = {**self.model_kwargs, **kwargs} - - if invocation_layer_class: - return invocation_layer_class( - model_name_or_path=self.model_name_or_path, max_length=self.max_length, **all_kwargs - ) - - for invocation_layer in PromptModelInvocationLayer.invocation_layer_providers: - if inspect.isabstract(invocation_layer): - continue - if invocation_layer.supports(self.model_name_or_path, **all_kwargs): - return invocation_layer( - model_name_or_path=self.model_name_or_path, max_length=self.max_length, **all_kwargs - ) - raise ValueError( - f"Model {self.model_name_or_path} is not supported - no matching invocation layer found." - f" Currently supported invocation layers are: {PromptModelInvocationLayer.invocation_layer_providers}" - f" You can implement and provide custom invocation layer for {self.model_name_or_path} by subclassing " - "PromptModelInvocationLayer." - f" Also please ensure you are authorised to load the model {self.model_name_or_path} and you are " - "logged-in into the huggingface cli." - ) - - def invoke(self, prompt: Union[str, List[str], List[Dict[str, str]]], **kwargs) -> List[str]: - """ - Takes in a prompt and returns a list of responses using the underlying invocation layer. - - :param prompt: The prompt to use for the invocation. It can be a single prompt or a list of prompts. - :param kwargs: Additional keyword arguments to pass to the invocation layer. - :return: A list of model-generated responses for the prompt or prompts. - """ - output = self.model_invocation_layer.invoke(prompt=prompt, **kwargs) - return output - - async def ainvoke(self, prompt: Union[str, List[str], List[Dict[str, str]]], **kwargs) -> List[str]: - """ - Drop-in replacement asyncio version of the `invoke` method, see there for documentation. - """ - if hasattr(self.model_invocation_layer, "ainvoke"): - return await self.model_invocation_layer.ainvoke(prompt=prompt, **kwargs) - - # The underlying invocation layer doesn't support asyncio - return self.model_invocation_layer.invoke(prompt=prompt, **kwargs) - - @overload - def _ensure_token_limit(self, prompt: str) -> str: - ... - - @overload - def _ensure_token_limit(self, prompt: List[Dict[str, str]]) -> List[Dict[str, str]]: - ... - - def _ensure_token_limit(self, prompt: Union[str, List[Dict[str, str]]]) -> Union[str, List[Dict[str, str]]]: - """Ensure that length of the prompt and answer is within the maximum token length of the PromptModel. - - :param prompt: Prompt text to be sent to the generative model. - """ - return self.model_invocation_layer._ensure_token_limit(prompt=prompt) - - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - ) -> Tuple[Dict, str]: - raise NotImplementedError("This method should never be implemented in the derived class") - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - raise NotImplementedError("This method should never be implemented in the derived class") - - def __repr__(self): - return "{}({!r})".format(self.__class__.__name__, self.__dict__) diff --git a/haystack/nodes/prompt/prompt_node.py b/haystack/nodes/prompt/prompt_node.py deleted file mode 100644 index 92ec069acb..0000000000 --- a/haystack/nodes/prompt/prompt_node.py +++ /dev/null @@ -1,558 +0,0 @@ -from collections import defaultdict -import copy -import logging -from typing import Dict, List, Optional, Tuple, Union, Any - -from haystack.nodes.base import BaseComponent -from haystack.schema import Document, MultiLabel -from haystack.telemetry import send_event -from haystack.nodes.prompt.prompt_model import PromptModel -from haystack.nodes.prompt.prompt_template import PromptTemplate -from haystack.lazy_imports import LazyImport - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_import: - import torch - - -logger = logging.getLogger(__name__) - - -class PromptNode(BaseComponent): - """ - The PromptNode class is the central abstraction in Haystack's large language model (LLM) support. PromptNode - supports multiple NLP tasks out of the box. You can use it to perform tasks such as - summarization, question answering, question generation, and more, using a single, unified model within the Haystack - framework. - - One of the benefits of PromptNode is that you can use it to define and add additional prompt templates - the model supports. Defining additional prompt templates makes it possible to extend the model's capabilities - and use it for a broader range of NLP tasks in Haystack. Prompt engineers define templates - for each NLP task and register them with PromptNode. The burden of defining templates for each task rests on - the prompt engineers, not the users. - - Using an instance of the PromptModel class, you can create multiple PromptNodes that share the same model, saving - the memory and time required to load the model multiple times. - - PromptNode also supports multiple model invocation layers: - - Hugging Face transformers (all text2text-generation models) - - OpenAI InstructGPT models - - Azure OpenAI InstructGPT models - - But you're not limited to the models listed above, as you can register - additional custom model invocation layers. - - We recommend using LLMs fine-tuned on a collection of datasets phrased as instructions, otherwise we find that the - LLM does not "follow" prompt instructions well. The list of instruction-following models increases every month, - and the current list includes: Flan, OpenAI InstructGPT, opt-iml, bloomz, and mt0 models. - - For more details, see [PromptNode](https://docs.haystack.deepset.ai/docs/prompt_node). - """ - - outgoing_edges: int = 1 - - def __init__( - self, - model_name_or_path: Union[str, PromptModel] = "google/flan-t5-base", - default_prompt_template: Optional[Union[str, PromptTemplate]] = None, - output_variable: Optional[str] = None, - max_length: Optional[int] = 100, - api_key: Optional[str] = None, - timeout: Optional[float] = None, - use_auth_token: Optional[Union[str, bool]] = None, - use_gpu: Optional[bool] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - stop_words: Optional[List[str]] = None, - top_k: int = 1, - debug: Optional[bool] = False, - model_kwargs: Optional[Dict] = None, - ): - """ - Creates a PromptNode instance. - - :param model_name_or_path: The name of the model to use or an instance of the PromptModel. - :param default_prompt_template: The default prompt template to use for the model. - :param output_variable: The name of the output variable in which you want to store the inference results. - If not set, PromptNode uses PromptTemplate's output_variable. If PromptTemplate's output_variable is not set, the default name is `results`. - :param max_length: The maximum number of tokens the generated text output can have. - :param api_key: The API key to use for the model. - :param use_auth_token: The authentication token to use for the model. - :param use_gpu: Whether to use GPU or not. - :param devices: The devices to use for the model. - :param top_k: The number of independently generated texts to return per prompt. For example, if you set top_k=3, the model will generate three answers to the query. - :param stop_words: Stops text generation if any of the stop words is generated. - :param model_kwargs: Additional keyword arguments passed when loading the model specified in `model_name_or_path`. - :param debug: Whether to include the used prompts as debug information in the output under the key _debug. - - Note that Azure OpenAI InstructGPT models require two additional parameters: azure_base_url (the URL for the - Azure OpenAI API endpoint, usually in the form `https://.openai.azure.com') and - azure_deployment_name (the name of the Azure OpenAI API deployment). - You should specify these parameters in the `model_kwargs` dictionary. - - """ - send_event( - event_name="PromptNode", - event_properties={ - "llm.model_name_or_path": model_name_or_path, - "llm.default_prompt_template": default_prompt_template, - }, - ) - super().__init__() - - # If we don't set _default_template here Pylint fails with error W0201 because it can't see that - # it's set in default_prompt_template, so we set it explicitly to None to avoid it failing - self._default_template = None - self.default_prompt_template = default_prompt_template - self.output_variable: Optional[str] = output_variable - self.model_name_or_path: Union[str, PromptModel] = model_name_or_path - self.prompt_model: PromptModel - self.stop_words: Optional[List[str]] = stop_words - self.top_k: int = top_k - self.debug = debug - - if isinstance(model_name_or_path, str): - self.prompt_model = PromptModel( - model_name_or_path=model_name_or_path, - max_length=max_length, - api_key=api_key, - timeout=timeout, - use_auth_token=use_auth_token, - use_gpu=use_gpu, - devices=devices, - model_kwargs=model_kwargs, - ) - elif isinstance(model_name_or_path, PromptModel): - self.prompt_model = model_name_or_path - else: - raise ValueError("model_name_or_path must be either a string or a PromptModel object") - - def __call__(self, *args, **kwargs) -> List[Any]: - """ - This method is invoked when the component is called directly, for example: - ```python - PromptNode pn = ... - sa = pn.set_default_prompt_template("sentiment-analysis") - sa(documents=[Document("I am in love and I feel great!")]) - ``` - """ - if "prompt_template" in kwargs: - prompt_template = kwargs["prompt_template"] - kwargs.pop("prompt_template") - return self.prompt(prompt_template, *args, **kwargs) - else: - return self.prompt(self.default_prompt_template, *args, **kwargs) - - def prompt(self, prompt_template: Optional[Union[str, PromptTemplate]], *args, **kwargs) -> List[Any]: - """ - Prompts the model and represents the central API for the PromptNode. It takes a prompt template, - a list of non-keyword and keyword arguments, and returns a list of strings - the responses from the underlying model. - - If you specify the optional prompt_template parameter, it takes precedence over the default PromptTemplate for this PromptNode. - - :param prompt_template: The name or object of the optional PromptTemplate to use. - :return: A list of strings as model responses. - """ - results = [] - # we pop the prompt_collector kwarg to avoid passing it to the model - prompt_collector: List[Union[str, List[Dict[str, str]]]] = kwargs.pop("prompt_collector", []) - - # kwargs override model kwargs - kwargs = {**self._prepare_model_kwargs(), **kwargs} - template_to_fill = self.get_prompt_template(prompt_template) - if template_to_fill: - # prompt template used, yield prompts from inputs args - for prompt in template_to_fill.fill(*args, **kwargs): - kwargs_copy = template_to_fill.remove_template_params(copy.copy(kwargs)) - # and pass the prepared prompt and kwargs copy to the model - prompt = self.prompt_model._ensure_token_limit(prompt) - prompt_collector.append(prompt) - logger.debug("Prompt being sent to LLM with prompt %s and kwargs %s", prompt, kwargs_copy) - output = self.prompt_model.invoke(prompt, **kwargs_copy) - results.extend(output) - - kwargs["prompts"] = prompt_collector - results = template_to_fill.post_process(results, **kwargs) - else: - # straightforward prompt, no templates used - for prompt in list(args): - kwargs_copy = copy.copy(kwargs) - prompt = self.prompt_model._ensure_token_limit(prompt) - prompt_collector.append(prompt) - logger.debug("Prompt being sent to LLM with prompt %s and kwargs %s ", prompt, kwargs_copy) - output = self.prompt_model.invoke(prompt, **kwargs_copy) - results.extend(output) - return results - - @property - def default_prompt_template(self): - return self._default_template - - @default_prompt_template.setter - def default_prompt_template(self, prompt_template: Union[str, PromptTemplate, None]): - """ - Sets the default prompt template for the node. - :param prompt_template: The prompt template to be set as default. - :return: The current PromptNode object. - """ - self._default_template = self.get_prompt_template(prompt_template) - - def get_prompt_template(self, prompt_template: Union[str, PromptTemplate, None] = None) -> Optional[PromptTemplate]: - """ - Resolves a prompt template. - - :param prompt_template: The prompt template to be resolved. You can choose between the following types: - - None: Returns the default prompt template. - - PromptTemplate: Returns the given prompt template object. - - str: Parses the string depending on its content: - - prompt template name: Returns the prompt template registered with the given name. - - prompt template yaml: Returns a prompt template specified by the given YAML. - - prompt text: Returns a copy of the default prompt template with the given prompt text. - - :return: The prompt template object. - """ - # None means we're asking for the default prompt template - prompt_template = prompt_template or self._default_template - if prompt_template is None: - return None - - # PromptTemplate instances simply go through - if isinstance(prompt_template, PromptTemplate): - return prompt_template - - output_parser = None - if self.default_prompt_template: - output_parser = self.default_prompt_template.output_parser - return PromptTemplate(prompt_template, output_parser=output_parser) - - def prompt_template_params(self, prompt_template: str) -> List[str]: - """ - Returns the list of parameters for a prompt template. - :param prompt_template: The name of the prompt template. - :return: The list of parameters for the prompt template. - """ - template = self.get_prompt_template(prompt_template) - if template: - return list(template.prompt_params) - return [] - - def _prepare( # type: ignore - self, query, file_paths, labels, documents, meta, invocation_context, prompt_template, generation_kwargs - ) -> Dict: - """ - Prepare prompt invocation. - """ - invocation_context = invocation_context or {} - - if query and "query" not in invocation_context: - invocation_context["query"] = query - - if file_paths and "file_paths" not in invocation_context: - invocation_context["file_paths"] = file_paths - - if labels and "labels" not in invocation_context: - invocation_context["labels"] = labels - - if documents and "documents" not in invocation_context: - invocation_context["documents"] = documents - - if meta and "meta" not in invocation_context: - invocation_context["meta"] = meta - - if "prompt_template" not in invocation_context: - invocation_context["prompt_template"] = self.get_prompt_template(prompt_template) - - if generation_kwargs: - invocation_context.update(generation_kwargs) - - return invocation_context - - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - invocation_context: Optional[Dict[str, Any]] = None, - prompt_template: Optional[Union[str, PromptTemplate]] = None, - generation_kwargs: Optional[Dict[str, Any]] = None, - ) -> Tuple[Dict, str]: - """ - Runs the PromptNode on these input parameters. Returns the output of the prompt model. - The parameters `query`, `file_paths`, `labels`, `documents`, and `meta` are added to the invocation context - before invoking the prompt model. PromptNode uses these variables only if they are present as - parameters in the PromptTemplate. - - :param query: The PromptNode usually ignores the query, unless it's used as a parameter in the - prompt template. - :param file_paths: The PromptNode usually ignores the file paths, unless they're used as a parameter - in the prompt template. - :param labels: The PromptNode usually ignores the labels, unless they're used as a parameter in the - prompt template. - :param documents: The documents to be used for the prompt. - :param meta: PromptNode usually ignores meta information, unless it's used as a parameter in the - PromptTemplate. - :param invocation_context: The invocation context to be used for the prompt. - :param prompt_template: The prompt template to use. You can choose between the following types: - - None: Use the default prompt template. - - PromptTemplate: Use the given prompt template object. - - str: Parses the string depending on its content: - - prompt template name: Uses the prompt template registered with the given name. - - prompt template yaml: Uses the prompt template specified by the given YAML. - - prompt text: Uses a copy of the default prompt template with the given prompt text. - :param generation_kwargs: The generation_kwargs are used to customize text generation for the underlying pipeline. - """ - # prompt_collector is an empty list, it's passed to the PromptNode that will fill it with the rendered prompts, - # so that they can be returned by `run()` as part of the pipeline's debug output. - prompt_collector: List[str] = [] - - invocation_context = self._prepare( - query, file_paths, labels, documents, meta, invocation_context, prompt_template, generation_kwargs - ) - - results = self(**invocation_context, prompt_collector=prompt_collector) - - prompt_template_resolved: PromptTemplate = invocation_context.pop("prompt_template") - - try: - output_variable = self.output_variable or prompt_template_resolved.output_variable or "results" - except: - output_variable = "results" - - invocation_context[output_variable] = results - invocation_context["prompts"] = prompt_collector - final_result: Dict[str, Any] = {output_variable: results, "invocation_context": invocation_context} - - if self.debug: - final_result["_debug"] = {"prompts_used": prompt_collector} - - return final_result, "output_1" - - async def _aprompt(self, prompt_template: Optional[Union[str, PromptTemplate]], *args, **kwargs): - """ - Async version of the actual prompt invocation. - """ - results = [] - # we pop the prompt_collector kwarg to avoid passing it to the model - prompt_collector: List[Union[str, List[Dict[str, str]]]] = kwargs.pop("prompt_collector", []) - - # kwargs override model kwargs - kwargs = {**self._prepare_model_kwargs(), **kwargs} - template_to_fill = self.get_prompt_template(prompt_template) - if template_to_fill: - # prompt template used, yield prompts from inputs args - for prompt in template_to_fill.fill(*args, **kwargs): - kwargs_copy = template_to_fill.remove_template_params(copy.copy(kwargs)) - # and pass the prepared prompt and kwargs copy to the model - prompt = self.prompt_model._ensure_token_limit(prompt) - prompt_collector.append(prompt) - logger.debug("Prompt being sent to LLM with prompt %s and kwargs %s", prompt, kwargs_copy) - output = await self.prompt_model.ainvoke(prompt, **kwargs_copy) - results.extend(output) - - kwargs["prompts"] = prompt_collector - results = template_to_fill.post_process(results, **kwargs) - else: - # straightforward prompt, no templates used - for prompt in list(args): - kwargs_copy = copy.copy(kwargs) - prompt = self.prompt_model._ensure_token_limit(prompt) - prompt_collector.append(prompt) - logger.debug("Prompt being sent to LLM with prompt %s and kwargs %s ", prompt, kwargs_copy) - output = await self.prompt_model.ainvoke(prompt, **kwargs_copy) - results.extend(output) - return results - - async def arun( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - invocation_context: Optional[Dict[str, Any]] = None, - prompt_template: Optional[Union[str, PromptTemplate]] = None, - generation_kwargs: Optional[Dict[str, Any]] = None, - ) -> Tuple[Dict, str]: - """ - Drop-in replacement asyncio version of the `run` method, see there for documentation. - """ - prompt_collector: List[str] = [] - - invocation_context = self._prepare( - query, file_paths, labels, documents, meta, invocation_context, prompt_template, generation_kwargs - ) - - # Let's skip the call to __call__, because all it does is injecting a prompt template - # if there isn't any, while we know for sure it'll be in `invocation_context`. - results = await self._aprompt(prompt_collector=prompt_collector, **invocation_context) - - prompt_template_resolved: PromptTemplate = invocation_context.pop("prompt_template") - - try: - output_variable = self.output_variable or prompt_template_resolved.output_variable or "results" - except: - output_variable = "results" - - invocation_context[output_variable] = results - invocation_context["prompts"] = prompt_collector - final_result: Dict[str, Any] = {output_variable: results, "invocation_context": invocation_context} - - if self.debug: - final_result["_debug"] = {"prompts_used": prompt_collector} - - return final_result, "output_1" - - def run_batch( # type: ignore - self, - queries: Optional[List[str]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - invocation_contexts: Optional[List[Dict[str, Any]]] = None, - prompt_templates: Optional[List[Union[str, PromptTemplate]]] = None, - ): - """ - Runs PromptNode in batch mode. - - - If you provide a list containing a single query (or invocation context)... - - ... and a single list of Documents, the query is applied to each Document individually. - - ... and a list of lists of Documents, the query is applied to each list of Documents and the results - are aggregated per Document list. - - - If you provide a list of multiple queries (or multiple invocation contexts)... - - ... and a single list of Documents, each query (or invocation context) is applied to each Document individually. - - ... and a list of lists of Documents, each query (or invocation context) is applied to its corresponding list of Documents - and the results are aggregated per query-Document pair. - - - If you provide no Documents, then each query (or invocation context) is applied directly to the PromptTemplate. - - :param queries: List of queries. - :param documents: Single list of Documents or list of lists of Documents in which to search for the answers. - :param invocation_contexts: List of invocation contexts. - :param prompt_templates: The prompt templates to use. You can choose between the following types: - - None: Use the default prompt template. - - PromptTemplate: Use the given prompt template object. - - str: Parses the string depending on its content: - - prompt template name: Uses the prompt template registered with the given name. - - prompt template yaml: Uuses the prompt template specified by the given YAML. - - prompt text: Uses a copy of the default prompt template with the given prompt text. - """ - inputs = PromptNode._flatten_inputs(queries, documents, invocation_contexts, prompt_templates) - all_results: Dict[str, List] = defaultdict(list) - for query, docs, invocation_context, prompt_template in zip( - inputs["queries"], inputs["documents"], inputs["invocation_contexts"], inputs["prompt_templates"] - ): - prompt_template = self.get_prompt_template(self.default_prompt_template) - output_variable = self.output_variable or prompt_template.output_variable or "results" - results = self.run( - query=query, documents=docs, invocation_context=invocation_context, prompt_template=prompt_template - )[0] - all_results[output_variable].append(results[output_variable]) - all_results["invocation_contexts"].append(results["invocation_context"]) - if self.debug: - all_results["_debug"].append(results["_debug"]) - return all_results, "output_1" - - def _prepare_model_kwargs(self): - # these are the parameters from PromptNode level - # that are passed to the prompt model invocation layer - return {"stop_words": self.stop_words, "top_k": self.top_k} - - @staticmethod - def _flatten_inputs( - queries: Optional[List[str]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - invocation_contexts: Optional[List[Dict[str, Any]]] = None, - prompt_templates: Optional[List[Union[str, PromptTemplate]]] = None, - ) -> Dict[str, List]: - """Flatten and copy the queries, documents, and invocation contexts into lists of equal length. - - - If you provide a list containing a single query (or invocation context)... - - ... and a single list of Documents, the query is applied to each Document individually. - - ... and a list of lists of Documents, the query is applied to each list of Documents and the results - are aggregated per Document list. - - - If you provide a list of multiple queries (or multiple invocation contexts)... - - ... and a single list of Documents, each query (or invocation context) is applied to each Document individually. - - ... and a list of lists of Documents, each query (or invocation context) is applied to its corresponding list of Documents - and the results are aggregated per query-Document pair. - - - If you provide no Documents, then each query (or invocation context) is applied to the PromptTemplate. - - :param queries: List of queries. - :param documents: Single list of Documents or list of lists of Documents in which to search for the answers. - :param invocation_contexts: List of invocation contexts. - """ - # Check that queries, and invocation_contexts are of the same length if provided - input_queries: List[Any] - input_invocation_contexts: List[Any] - input_prompt_templates: List[Any] - if queries is not None and invocation_contexts is not None: - if len(queries) != len(invocation_contexts): - raise ValueError("The input variables queries and invocation_contexts should have the same length.") - input_queries = queries - input_invocation_contexts = invocation_contexts - elif queries is not None and invocation_contexts is None: - input_queries = queries - input_invocation_contexts = [None] * len(queries) - elif queries is None and invocation_contexts is not None: - input_queries = [None] * len(invocation_contexts) - input_invocation_contexts = invocation_contexts - else: - input_queries = [None] - input_invocation_contexts = [None] - - if prompt_templates is not None: - if len(prompt_templates) != len(input_queries): - raise ValueError("The input variables prompt_templates and queries should have the same length.") - input_prompt_templates = prompt_templates - else: - input_prompt_templates = [None] * len(input_queries) - - multi_docs_list = isinstance(documents, list) and len(documents) > 0 and isinstance(documents[0], list) - single_docs_list = isinstance(documents, list) and len(documents) > 0 and isinstance(documents[0], Document) - - # Docs case 1: single list of Documents - # -> apply each query (and invocation_contexts) to all Documents - inputs: Dict[str, List] = defaultdict(list) - if documents is not None: - if single_docs_list: - for query, invocation_context, prompt_template in zip( - input_queries, input_invocation_contexts, input_prompt_templates - ): - for doc in documents: - inputs["queries"].append(query) - inputs["invocation_contexts"].append(invocation_context) - inputs["documents"].append([doc]) - inputs["prompt_templates"].append(prompt_template) - # Docs case 2: list of lists of Documents - # -> apply each query (and invocation_context) to corresponding list of Documents, - # if queries contains only one query, apply it to each list of Documents - elif multi_docs_list: - total_queries = input_queries.copy() - total_invocation_contexts = input_invocation_contexts.copy() - total_prompt_templates = input_prompt_templates.copy() - if len(total_queries) == 1 and len(total_invocation_contexts) == 1 and len(total_prompt_templates) == 1: - total_queries = input_queries * len(documents) - total_invocation_contexts = input_invocation_contexts * len(documents) - total_prompt_templates = input_prompt_templates * len(documents) - if ( - len(total_queries) != len(documents) - or len(total_invocation_contexts) != len(documents) - or len(total_prompt_templates) != len(documents) - ): - raise ValueError("Number of queries must be equal to number of provided Document lists.") - for query, invocation_context, prompt_template, cur_docs in zip( - total_queries, total_invocation_contexts, total_prompt_templates, documents - ): - inputs["queries"].append(query) - inputs["invocation_contexts"].append(invocation_context) - inputs["documents"].append(cur_docs) - inputs["prompt_templates"].append(prompt_template) - elif queries is not None or invocation_contexts is not None or prompt_templates is not None: - for query, invocation_context, prompt_template in zip( - input_queries, input_invocation_contexts, input_prompt_templates - ): - inputs["queries"].append(query) - inputs["invocation_contexts"].append(invocation_context) - inputs["documents"].append([None]) - inputs["prompt_templates"].append(prompt_template) - return inputs diff --git a/haystack/nodes/prompt/prompt_template.py b/haystack/nodes/prompt/prompt_template.py deleted file mode 100644 index f90ccc17ad..0000000000 --- a/haystack/nodes/prompt/prompt_template.py +++ /dev/null @@ -1,596 +0,0 @@ -from typing import Optional, List, Union, Tuple, Dict, Iterator, Any -import logging -import re -import os -import ast -import json -import warnings -from pathlib import Path -from abc import ABC -from uuid import uuid4 - -import yaml -from platformdirs import user_data_dir -import tenacity -import prompthub -from requests import HTTPError, RequestException, JSONDecodeError - -from haystack.errors import NodeError -from haystack.environment import HAYSTACK_PROMPT_TEMPLATE_ALLOWED_FUNCTIONS -from haystack.nodes.base import BaseComponent -from haystack.nodes.prompt.shapers import ( # pylint: disable=unused-import - BaseOutputParser, - AnswerParser, - to_strings, - current_datetime, - join, # used as shaping function - format_document, - format_answer, - format_string, -) -from haystack.schema import Document, MultiLabel -from haystack.environment import ( - HAYSTACK_REMOTE_API_TIMEOUT_SEC, - HAYSTACK_REMOTE_API_BACKOFF_SEC, - HAYSTACK_REMOTE_API_MAX_RETRIES, -) - -logger = logging.getLogger(__name__) - -PROMPT_TEMPLATE_ALLOWED_FUNCTIONS = json.loads( - os.environ.get( - HAYSTACK_PROMPT_TEMPLATE_ALLOWED_FUNCTIONS, - '["join", "to_strings", "replace", "enumerate", "str", "current_datetime"]', - ) -) -PROMPT_TEMPLATE_SPECIAL_CHAR_ALIAS = {"new_line": "\n", "tab": "\t", "double_quote": '"', "carriage_return": "\r"} -PROMPT_TEMPLATE_STRIPS = ["'", '"'] -PROMPT_TEMPLATE_STR_REPLACE = {'"': "'"} - -PROMPTHUB_TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30.0)) -PROMPTHUB_BACKOFF = float(os.environ.get(HAYSTACK_REMOTE_API_BACKOFF_SEC, 10.0)) -PROMPTHUB_MAX_RETRIES = int(os.environ.get(HAYSTACK_REMOTE_API_MAX_RETRIES, 5)) - -PROMPTHUB_CACHE_PATH = os.environ.get( - "PROMPTHUB_CACHE_PATH", Path(user_data_dir("haystack", "deepset")) / "prompthub_cache" -) - - -############################################################################# -# This templates were hardcoded in the prompt_template module. When adding -# support for PromptHub integration we decided to remove them with the PR -# that added the integration: https://github.com/deepset-ai/haystack/pull/4879/ -# -# That PR also changed the PromptNode API forcing the user to change how -# they use the node. -# -# After some discussion we deemed the change to be too breaking for existing -# use cases and which steps would have been necessary to migrate to the -# new API in case someone was using an hardcoded template we decided to -# bring them back. -# -# So for the time being this must live here, no new template must be added -# to this dictionary. -############################################################################# - - -LEGACY_DEFAULT_TEMPLATES: Dict[str, Dict] = { - # DO NOT ADD ANY NEW TEMPLATE IN HERE! - "question-answering": { - "prompt": "Given the context please answer the question. Context: {join(documents)}; Question: " - "{query}; Answer:", - "output_parser": AnswerParser(), - }, - "question-answering-per-document": { - "prompt": "Given the context please answer the question. Context: {documents}; Question: " "{query}; Answer:", - "output_parser": AnswerParser(), - }, - "question-answering-with-references": { - "prompt": "Create a concise and informative answer (no more than 50 words) for a given question " - "based solely on the given documents. You must only use information from the given documents. " - "Use an unbiased and journalistic tone. Do not repeat text. Cite the documents using Document[number] notation. " - "If multiple documents contain the answer, cite those documents like ‘as stated in Document[number], Document[number], etc.’. " - "If the documents do not contain the answer to the question, say that ‘answering is not possible given the available information.’\n" - "{join(documents, delimiter=new_line, pattern=new_line+'Document[$idx]: $content', str_replace={new_line: ' ', '[': '(', ']': ')'})} \n Question: {query}; Answer: ", - "output_parser": AnswerParser(reference_pattern=r"Document\[(\d+)\]"), - }, - "question-answering-with-document-scores": { - "prompt": "Answer the following question using the paragraphs below as sources. " - "An answer should be short, a few words at most.\n" - "Paragraphs:\n{documents}\n" - "Question: {query}\n\n" - "Instructions: Consider all the paragraphs above and their corresponding scores to generate " - "the answer. While a single paragraph may have a high score, it's important to consider all " - "paragraphs for the same answer candidate to answer accurately.\n\n" - "After having considered all possibilities, the final answer is:\n" - }, - "question-generation": {"prompt": "Given the context please generate a question. Context: {documents}; Question:"}, - "conditioned-question-generation": { - "prompt": "Please come up with a question for the given context and the answer. " - "Context: {documents}; Answer: {answers}; Question:" - }, - "summarization": {"prompt": "Summarize this document: {documents} Summary:"}, - "question-answering-check": { - "prompt": "Does the following context contain the answer to the question? " - "Context: {documents}; Question: {query}; Please answer yes or no! Answer:", - "output_parser": AnswerParser(), - }, - "sentiment-analysis": { - "prompt": "Please give a sentiment for this context. Answer with positive, " - "negative or neutral. Context: {documents}; Answer:" - }, - "multiple-choice-question-answering": { - "prompt": "Question:{query} ; Choose the most suitable option to answer the above question. " - "Options: {options}; Answer:", - "output_parser": AnswerParser(), - }, - "topic-classification": {"prompt": "Categories: {options}; What category best describes: {documents}; Answer:"}, - "language-detection": { - "prompt": "Detect the language in the following context and answer with the " - "name of the language. Context: {documents}; Answer:" - }, - "translation": { - "prompt": "Translate the following context to {target_language}. Context: {documents}; Translation:" - }, - "zero-shot-react": { - "prompt": "You are a helpful and knowledgeable agent. To achieve your goal of answering complex questions " - "correctly, you have access to the following tools:\n\n" - "{tool_names_with_descriptions}\n\n" - "To answer questions, you'll need to go through multiple steps involving step-by-step thinking and " - "selecting appropriate tools and their inputs; tools will respond with observations. When you are ready " - "for a final answer, respond with the `Final Answer:`\n\n" - "Use the following format:\n\n" - "Question: the question to be answered\n" - "Thought: Reason if you have the final answer. If yes, answer the question. If not, find out the missing information needed to answer it.\n" - "Tool: pick one of {tool_names} \n" - "Tool Input: the input for the tool\n" - "Observation: the tool will respond with the result\n" - "...\n" - "Final Answer: the final answer to the question, make it short (1-5 words)\n\n" - "Thought, Tool, Tool Input, and Observation steps can be repeated multiple times, but sometimes we can find an answer in the first pass\n" - "---\n\n" - "Question: {query}\n" - "Thought: Let's think step-by-step, I first need to {transcript}" - }, - "conversational-agent": { - "prompt": "In the following conversation, a human user interacts with an AI Agent. The human user poses questions, and the AI Agent goes through several steps to provide well-informed answers.\n" - "If the AI Agent knows the answer, the response begins with `Final Answer:` on a new line.\n" - "If the AI Agent is uncertain or concerned that the information may be outdated or inaccurate, it must use the available tools to find the most up-to-date information. The AI has access to these tools:\n" - "{tool_names_with_descriptions}\n" - "The following is the previous conversation between a human and an AI:\n" - "{memory}\n" - "AI Agent responses must start with one of the following:\n" - "Thought: [AI Agent's reasoning process]\n" - "Tool: [{tool_names}] (on a new line) Tool Input: [input for the selected tool WITHOUT quotation marks and on a new line] (These must always be provided together and on separate lines.)\n" - "Final Answer: [final answer to the human user's question]\n" - "When selecting a tool, the AI Agent must provide both the `Tool:` and `Tool Input:` pair in the same response, but on separate lines. `Observation:` marks the beginning of a tool's result, and the AI Agent trusts these results.\n" - "The AI Agent should not ask the human user for additional information, clarification, or context.\n" - "If the AI Agent cannot find a specific answer after exhausting available tools and approaches, it answers with Final Answer: inconclusive\n" - "Question: {query}\n" - "Thought:\n" - "{transcript}\n" - }, - "conversational-summary": { - "prompt": "Condense the following chat transcript by shortening and summarizing the content without losing important information:\n{chat_transcript}\nCondensed Transcript:" - }, - "conversational-agent-without-tools": { - "prompt": "The following is a conversation between a human and an AI.\n{memory}\nHuman: {query}\nAI:" - }, - # DO NOT ADD ANY NEW TEMPLATE IN HERE! -} - - -class PromptNotFoundError(Exception): - ... - - -class BasePromptTemplate(BaseComponent): - outgoing_edges = 1 - - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - ) -> Tuple[Dict, str]: - raise NotImplementedError("This method should never be implemented in the derived class") - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - raise NotImplementedError("This method should never be implemented in the derived class") - - -class PromptTemplateValidationError(NodeError): - """ - The error raised when a PromptTemplate is invalid. - """ - - pass - - -class _ValidationVisitor(ast.NodeVisitor): - """ - This class is used to validate the prompt text for a PromptTemplate. - It checks that the prompt text is a valid f-string and that it only uses allowed functions. - Useful information extracted from the AST is stored in the class attributes (for example, `prompt_params` and `used_functions`). - """ - - def __init__(self, prompt_template_name: str): - self.used_names: List[str] = [] - self.comprehension_targets: List[str] = [] - self.used_functions: List[str] = [] - self.prompt_template_name = prompt_template_name - - @property - def prompt_params(self) -> List[str]: - """ - The names of the variables used in the prompt text. - For example, for the prompt text `f"Hello {name}"`, the prompt_params is `["name"]`. - """ - return list(set(self.used_names) - set(self.used_functions) - set(self.comprehension_targets)) - - def visit_Name(self, node: ast.Name) -> None: - """ - Stores the name of the variable used in the prompt text. This also includes function and method names. - For example, for the prompt text `f"Hello {func(name)}"`, the used_names are `["func", "name"]`. - """ - self.used_names.append(node.id) - - def visit_comprehension(self, node: ast.comprehension) -> None: - """ - Stores the name of the variable used in comprehensions. - For example, for the prompt text `f"Hello {[name for name in names]}"`, the comprehension_targets is `["name"]`. - """ - super().generic_visit(node) - if isinstance(node.target, ast.Name): - self.comprehension_targets.append(node.target.id) - elif isinstance(node.target, ast.Tuple): - self.comprehension_targets.extend([elt.id for elt in node.target.elts if isinstance(elt, ast.Name)]) - - def visit_Call(self, node: ast.Call) -> None: - """ - Stores the name of functions and methods used in the prompt text and validates that only allowed functions are used. - For example, for the prompt text `f"Hello {func(name)}"`, the used_functions is `["func"]`. - - raises: PromptTemplateValidationError if the prompt text contains an invalid function. - """ - super().generic_visit(node) - if isinstance(node.func, ast.Name) and node.func.id in PROMPT_TEMPLATE_ALLOWED_FUNCTIONS: - # functions: func(args, kwargs) - self.used_functions.append(node.func.id) - elif isinstance(node.func, ast.Attribute) and node.func.attr in PROMPT_TEMPLATE_ALLOWED_FUNCTIONS: - # methods: instance.method(args, kwargs) - self.used_functions.append(node.func.attr) - else: - raise PromptTemplateValidationError( - f"Invalid function in prompt text for prompt template {self.prompt_template_name}. " - f"Allowed functions are {PROMPT_TEMPLATE_ALLOWED_FUNCTIONS}." - ) - - -class _FstringParamsTransformer(ast.NodeTransformer): - """ - Transforms an AST for f-strings into a format the PromptTemplate can use. - It replaces all f-string expressions with a unique ID and stores the corresponding expressions in a dictionary. - - You can evaluate the stored expressions using the `eval` function given the `prompt_params` (see _ValidatorVisitor). - PromptTemplate determines the number of prompts to generate and renders them using the evaluated expressions. - """ - - def __init__(self): - self.prompt_params_functions: Dict[str, ast.Expression] = {} - - def visit_FormattedValue(self, node: ast.FormattedValue) -> Optional[ast.AST]: - """ - Replaces the f-string expression with a unique ID and stores the corresponding expression in a dictionary. - If the expression is the raw `documents` variable, it is encapsulated into a call to `documents_to_strings` - to ensure that the documents get rendered correctly. - """ - super().generic_visit(node) - - # Keep special char variables as is. They are available via globals. - if isinstance(node.value, ast.Name) and node.value.id in PROMPT_TEMPLATE_SPECIAL_CHAR_ALIAS: - return node - - id = uuid4().hex - if isinstance(node.value, ast.Name) and node.value.id in ["documents", "answers"]: - call = ast.Call(func=ast.Name(id="to_strings", ctx=ast.Load()), args=[node.value], keywords=[]) - self.prompt_params_functions[id] = ast.fix_missing_locations(ast.Expression(body=call)) - else: - self.prompt_params_functions[id] = ast.fix_missing_locations(ast.Expression(body=node.value)) - return ast.FormattedValue( - value=ast.Name(id=id, ctx=ast.Load()), conversion=node.conversion, format_spec=node.format_spec - ) - - -@tenacity.retry( - reraise=True, - retry=tenacity.retry_if_exception_type((HTTPError, RequestException, JSONDecodeError)), - wait=tenacity.wait_exponential(multiplier=PROMPTHUB_BACKOFF), - stop=tenacity.stop_after_attempt(PROMPTHUB_MAX_RETRIES), -) -def fetch_from_prompthub(name: str) -> prompthub.Prompt: - """ - Looks for the given prompt in the PromptHub. - - :param name: the name of the prompt on the Hub. - :returns: the Prompt object. - """ - try: - prompt_data: prompthub.Prompt = prompthub.fetch(name, timeout=PROMPTHUB_TIMEOUT) - except HTTPError as http_error: - if http_error.response.status_code != 404: # type: ignore[union-attr] - raise http_error - raise PromptNotFoundError(f"Prompt template named '{name}' not available in the Prompt Hub.") - return prompt_data - - -def cache_prompt(data: prompthub.Prompt): - """ - Saves the prompt to the cache. Helps avoiding naming mismatches in the cache folder. - - :param data: the prompthub.Prompt object from PromptHub. - """ - path = Path(PROMPTHUB_CACHE_PATH) / f"{data.name}.yml" - path.parent.mkdir(parents=True, exist_ok=True) - data.to_yaml(path) - - -class PromptTemplate(BasePromptTemplate, ABC): - """ - PromptTemplate is a template for the prompt you feed to the model to instruct it what to do. For example, if you want the model to perform sentiment analysis, you simply tell it to do that in a prompt. Here's what a prompt template may look like: - - ```python - PromptTemplate("Give a sentiment for this context. Answer with positive, negative or neutral. Context: {documents}; Answer:") - ``` - - Optionally, you can declare prompt parameters using f-string syntax in the PromptTemplate. Prompt parameters are input parameters that need to be filled in - the prompt_text for the model to perform the task. For example, in the template above, there's one prompt parameter, `documents`. - - You declare prompt parameters by adding variables to the prompt text. These variables should be in the format: `{variable}`. In the template above, the variable is `{documents}`. - - At runtime, the variables you declared in prompt text are filled in with the arguments passed to the `fill()` method of the PromptTemplate. So in the example above, the `{documents}` variable will be filled with the Documents whose sentiment you want the model to analyze. - - Note that other than strict f-string syntax, you can safely use the following backslash characters in the text parts of the prompt text: `\n`, `\t`, `\r`. - In f-string expressions, use `new_line`, `tab`, `carriage_return` instead. - Double quotes (`"`) are automatically replaced with single quotes (`'`) in the prompt text. If you want to use double quotes in the prompt text, use `{double_quote}` instead. - - For more details on how to use PromptTemplate, see - [PromptTemplates](https://docs.haystack.deepset.ai/docs/prompt_node#prompttemplates). - """ - - def __init__(self, prompt: str, output_parser: Optional[Union[BaseOutputParser, Dict[str, Any]]] = None): - """ - Creates a PromptTemplate instance. - - :param prompt: The name of the prompt template on the PromptHub (for example, "sentiment-analysis", - "question-generation"), a Path to a local file, or the text of a new prompt, including its parameters. - :param output_parser: A parser that applied to the model output. - For example, to convert the model output to an Answer object, you can use `AnswerParser`. - Instead of BaseOutputParser instances, you can also pass dictionaries defining the output parsers. For example: - ``` - output_parser={"type": "AnswerParser", "params": {"pattern": "Answer: (.*)"}}, - ``` - """ - super().__init__() - name, prompt_text = "", "" - - if prompt in LEGACY_DEFAULT_TEMPLATES: - name = prompt - prompt_text, output_parser = self._load_from_legacy_template(prompt) - - # if it looks like a prompt template name - elif re.fullmatch(r"[-a-zA-Z0-9_/]+", prompt): - name = prompt - prompt_text = self._load_from_prompthub(prompt) - - # if it's a path to a YAML file - elif len(prompt) < 255 and Path(prompt).exists(): - name, prompt_text = self._load_from_file(prompt) - - # Otherwise it's a on-the-fly prompt text - else: - prompt_text = prompt - name = "custom-at-query-time" - - # use case when PromptTemplate is loaded from a YAML file, we need to start and end the prompt text with quotes - for strip in PROMPT_TEMPLATE_STRIPS: - prompt_text = prompt_text.strip(strip) - replacements = { - **{v: "{" + k + "}" for k, v in PROMPT_TEMPLATE_SPECIAL_CHAR_ALIAS.items()}, - **PROMPT_TEMPLATE_STR_REPLACE, - } - for old, new in replacements.items(): - prompt_text = prompt_text.replace(old, new) - - self._ast_expression = ast.parse(f'f"{prompt_text}"', mode="eval") - - ast_validator = _ValidationVisitor(prompt_template_name=name) - ast_validator.visit(self._ast_expression) - - ast_transformer = _FstringParamsTransformer() - self._ast_expression = ast.fix_missing_locations(ast_transformer.visit(self._ast_expression)) - self._prompt_params_functions = ast_transformer.prompt_params_functions - self._used_functions = ast_validator.used_functions - - self.name = name - self.prompt_text = prompt_text - self.prompt_params: List[str] = sorted( - param for param in ast_validator.prompt_params if param not in PROMPT_TEMPLATE_SPECIAL_CHAR_ALIAS - ) - self.globals = { - **{k: v for k, v in globals().items() if k in PROMPT_TEMPLATE_ALLOWED_FUNCTIONS}, - **PROMPT_TEMPLATE_SPECIAL_CHAR_ALIAS, - } - self.output_parser: Optional[BaseOutputParser] = None - if isinstance(output_parser, BaseOutputParser): - self.output_parser = output_parser - elif isinstance(output_parser, dict): - output_parser_type = output_parser["type"] - output_parser_params = output_parser.get("params", {}) - self.output_parser = BaseComponent._create_instance(output_parser_type, output_parser_params) - - def _load_from_legacy_template(self, name: str) -> Tuple[str, Any]: - warnings.warn( - f"You're using a legacy prompt template '{name}', " - "we strongly suggest you use prompts from the official Haystack PromptHub: " - "https://prompthub.deepset.ai/" - ) - prompt_text = LEGACY_DEFAULT_TEMPLATES[name]["prompt"] - output_parser = LEGACY_DEFAULT_TEMPLATES[name].get("output_parser") - return prompt_text, output_parser - - def _load_from_prompthub(self, name: str) -> str: - prompt_path = Path(PROMPTHUB_CACHE_PATH) / f"{name}.yml" - if Path(prompt_path).exists(): - return self._load_from_file(prompt_path)[1] - try: - data = fetch_from_prompthub(name) - if os.environ.get("PROMPTHUB_CACHE_ENABLED", "true").lower() not in ("0", "false", "f"): - cache_prompt(data) - - except HTTPError as http_error: - if http_error.response.status_code != 404: # type: ignore[union-attr] - raise http_error - raise PromptNotFoundError(f"Prompt template named '{name}' not available in the Prompt Hub.") - return data.text - - def _load_from_file(self, path: Union[Path, str]) -> Tuple[str, str]: - with open(path, "r", encoding="utf-8") as yaml_file: - prompt_template_parsed = yaml.safe_load(yaml_file.read()) - if not isinstance(prompt_template_parsed, dict): - raise ValueError("The prompt loaded is not a prompt YAML file.") - name = prompt_template_parsed["name"] - prompt_text = prompt_template_parsed["text"] - return name, prompt_text - - @property - def output_variable(self) -> Optional[str]: - return self.output_parser.output_variable if self.output_parser else None - - def prepare(self, *args, **kwargs) -> Dict[str, Any]: - """ - Prepares and verifies the PromtpTemplate with input parameters. - - :param args: Non-keyword arguments to fill the parameters in the prompt text of a PromptTemplate. - :param kwargs: Keyword arguments to fill the parameters in the prompt text of a PromptTemplate. - :return: A dictionary with the prompt text and the prompt parameters. - """ - params_dict = {} - # attempt to resolve args first - if args: - if len(args) != len(self.prompt_params): - logger.warning( - "For %s, expected %s arguments, instead got %s arguments %s", - self.name, - self.prompt_params, - len(args), - args, - ) - for prompt_param, arg in zip(self.prompt_params, args): - params_dict[prompt_param] = [arg] if isinstance(arg, str) else arg - # then attempt to resolve kwargs - if kwargs: - for param in self.prompt_params: - if param in kwargs: - params_dict[param] = kwargs[param] - - if "documents" in self.prompt_params and "documents" not in params_dict: - params_dict["documents"] = [] - logger.warning( - "Expected prompt parameter 'documents' to be provided but it is missing. " - "Continuing with an empty list of documents." - ) - - if not set(self.prompt_params).issubset(params_dict.keys()): - available_params = {*params_dict.keys(), *kwargs.keys()} - provided = set(self.prompt_params).intersection(available_params) - message = f"only {list(provided)}" if provided else "none of these parameters" - raise ValueError( - f"Expected prompt parameters {self.prompt_params} to be provided but got " - f"{message}. Make sure to provide all template parameters." - ) - - template_dict = {"_at_least_one_prompt": True} - for id, call in self._prompt_params_functions.items(): - template_dict[id] = eval( # pylint: disable=eval-used - compile(call, filename="", mode="eval"), self.globals, params_dict - ) - - return template_dict - - def post_process(self, prompt_output: List[str], **kwargs) -> List[Any]: - """ - Post-processes the output of the PromptTemplate. - :param args: Non-keyword arguments to use for post-processing the prompt output. - :param kwargs: Keyword arguments to use for post-processing the prompt output. - :return: A dictionary with the post-processed output. - """ - if self.output_parser: - invocation_context = kwargs - invocation_context["results"] = prompt_output - self.output_parser.run(invocation_context=invocation_context) - return invocation_context[self.output_parser.outputs[0]] - else: - return prompt_output - - def fill(self, *args, **kwargs) -> Iterator[str]: - """ - Fills the parameters defined in the prompt text with the arguments passed to it and returns the iterator prompt text. - - You can pass non-keyword (args) or keyword (kwargs) arguments to this method. If you pass non-keyword arguments, their order must match the left-to-right - order of appearance of the parameters in the prompt text. For example, if the prompt text is: - `Come up with a question for the given context and the answer. Context: {documents}; - Answer: {answers}; Question:`, then the first non-keyword argument fills the `{documents}` variable - and the second non-keyword argument fills the `{answers}` variable. - - If you pass keyword arguments, the order of the arguments doesn't matter. Variables in the - prompt text are filled with the corresponding keyword argument. - - :param args: Non-keyword arguments to fill the parameters in the prompt text. Their order must match the order of appearance of the parameters in the prompt text. - :param kwargs: Keyword arguments to fill the parameters in the prompt text. - :return: An iterator of prompt texts. - """ - template_dict = self.prepare(*args, **kwargs) - - # the prompt context values should all be lists, as they will be split as one - prompt_context_copy = {k: v if isinstance(v, list) else [v] for k, v in template_dict.items()} - max_len = max(len(v) for v in prompt_context_copy.values()) - if max_len > 1: - for key, value in prompt_context_copy.items(): - if len(value) == 1: - prompt_context_copy[key] = value * max_len - - for prompt_context_values in zip(*prompt_context_copy.values()): - template_input = {key: prompt_context_values[idx] for idx, key in enumerate(prompt_context_copy.keys())} - prompt_prepared: str = eval( # pylint: disable=eval-used - compile(self._ast_expression, filename="", mode="eval"), self.globals, template_input - ) - yield prompt_prepared - - def remove_template_params(self, kwargs: Dict[str, Any]) -> Dict[str, Any]: - """ - Removes template parameters from kwargs. - - :param kwargs: Keyword arguments to remove template parameters from. - :return: A modified dictionary with the template parameters removed. - """ - if kwargs: - for param in self.prompt_params: - kwargs.pop(param, None) - return kwargs - else: - return {} - - def __repr__(self): - return f"PromptTemplate(name={self.name}, prompt_text={self.prompt_text}, prompt_params={self.prompt_params})" diff --git a/haystack/nodes/prompt/shapers.py b/haystack/nodes/prompt/shapers.py deleted file mode 100644 index 265f571272..0000000000 --- a/haystack/nodes/prompt/shapers.py +++ /dev/null @@ -1,65 +0,0 @@ -from typing import Optional, List, Union - -from haystack.schema import Answer, Document - -from haystack.nodes.other.shaper import ( # pylint: disable=unused-import - Shaper, - current_datetime, # used as shaping function - join_documents_to_string as join, # used as shaping function - format_document, - format_answer, - format_string, -) - - -def to_strings(items: List[Union[str, Document, Answer]], pattern=None, str_replace=None) -> List[str]: - results = [] - for idx, item in enumerate(items, start=1): - if isinstance(item, str): - results.append(format_string(item, str_replace=str_replace)) - elif isinstance(item, Document): - results.append(format_document(document=item, pattern=pattern, str_replace=str_replace, idx=idx)) - elif isinstance(item, Answer): - results.append(format_answer(answer=item, pattern=pattern, str_replace=str_replace, idx=idx)) - else: - raise ValueError(f"Unsupported item type: {type(item)}") - return results - - -class BaseOutputParser(Shaper): - """ - An output parser in `PromptTemplate` defines how to parse the model output and convert it into Haystack primitives (answers, documents, or labels). - BaseOutputParser is the base class for output parser implementations. - """ - - @property - def output_variable(self) -> Optional[str]: - return self.outputs[0] - - -class AnswerParser(BaseOutputParser): - """ - Parses the model output to extract the answer into a proper `Answer` object using regex patterns. - AnswerParser adds the `document_ids` of the documents used to generate the answer and the prompts used to the `Answer` object. - You can pass a `reference_pattern` to extract the document_ids of the answer from the model output. - """ - - def __init__(self, pattern: Optional[str] = None, reference_pattern: Optional[str] = None): - """ - :param pattern: The regex pattern to use for parsing the answer. - Examples: - `[^\\n]+$` finds "this is an answer" in string "this is an argument.\nthis is an answer". - `Answer: (.*)` finds "this is an answer" in string "this is an argument. Answer: this is an answer". - If not specified, the whole string is used as the answer. If specified, the first group of the regex is used as the answer. If there is no group, the whole match is used as the answer. - :param reference_pattern: The regex pattern to use for parsing the document references. - Example: `\\[(\\d+)\\]` finds "1" in string "this is an answer[1]". - If None, no parsing is done and all documents are referenced. - """ - self.pattern = pattern - self.reference_pattern = reference_pattern - super().__init__( - func="strings_to_answers", - inputs={"strings": "results"}, - outputs=["answers"], - params={"pattern": pattern, "reference_pattern": reference_pattern}, - ) diff --git a/haystack/nodes/query_classifier/__init__.py b/haystack/nodes/query_classifier/__init__.py deleted file mode 100644 index e0ddf2e563..0000000000 --- a/haystack/nodes/query_classifier/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.query_classifier.base import BaseQueryClassifier -from haystack.nodes.query_classifier.transformers import TransformersQueryClassifier diff --git a/haystack/nodes/query_classifier/base.py b/haystack/nodes/query_classifier/base.py deleted file mode 100644 index 0d12790c28..0000000000 --- a/haystack/nodes/query_classifier/base.py +++ /dev/null @@ -1,20 +0,0 @@ -from abc import abstractmethod -from typing import List, Optional - -from haystack.nodes.base import BaseComponent - - -class BaseQueryClassifier(BaseComponent): - """ - Abstract class for Query Classifiers - """ - - outgoing_edges = 2 - - @abstractmethod - def run(self, query: str): # type: ignore - pass - - @abstractmethod - def run_batch(self, queries: List[str], batch_size: Optional[int] = None): # type: ignore - pass diff --git a/haystack/nodes/query_classifier/transformers.py b/haystack/nodes/query_classifier/transformers.py deleted file mode 100644 index 1369589608..0000000000 --- a/haystack/nodes/query_classifier/transformers.py +++ /dev/null @@ -1,192 +0,0 @@ -import logging -from pathlib import Path -from typing import Union, List, Optional, Dict, Any - -from tqdm import tqdm - -from haystack.nodes.query_classifier.base import BaseQueryClassifier -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import pipeline - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - from haystack.utils.torch_utils import ListDataset - - -DEFAULT_LABELS = ["LABEL_1", "LABEL_0"] - - -class TransformersQueryClassifier(BaseQueryClassifier): - """ - A node to classify an incoming query into categories using a transformer model. - Depending on the result, the query flows to a different branch in your pipeline and the further processing - can be customized. You can define this by connecting the further pipeline to `output_1`, `output_2`, ..., `output_n` - from this node. - This node also supports zero-shot-classification. - - Example: - ```python - { - pipe = Pipeline() - pipe.add_node(component=TransformersQueryClassifier(), name="QueryClassifier", inputs=["Query"]) - pipe.add_node(component=bm25_retriever, name="BM25Retriever", inputs=["QueryClassifier.output_2"]) - pipe.add_node(component=dpr_retriever, name="DPRRetriever", inputs=["QueryClassifier.output_1"]) - - # Keyword queries will use the BM25Retriever - pipe.run("kubernetes aws") - - # Semantic queries (questions, statements, sentences ...) will leverage the DPR retriever - pipe.run("How to manage kubernetes on aws") - - ``` - - Models: - - Pass your own `Transformer` classification/zero-shot-classification model from file/huggingface or use one of the following - pretrained ones hosted on Huggingface: - 1) Keywords vs. Questions/Statements (Default) - model_name_or_path="shahrukhx01/bert-mini-finetune-question-detection" - output_1 => question/statement - output_2 => keyword query - [Readme](https://ext-models-haystack.s3.eu-central-1.amazonaws.com/gradboost_query_classifier_2022/readme.txt) - - - 2) Questions vs. Statements - `model_name_or_path`="shahrukhx01/question-vs-statement-classifier" - output_1 => question - output_2 => statement - [Readme](https://ext-models-haystack.s3.eu-central-1.amazonaws.com/gradboost_query_classifier_statements_2022/readme.txt) - - - See also the [tutorial](https://haystack.deepset.ai/tutorials/pipelines) on pipelines. - """ - - def __init__( - self, - model_name_or_path: Union[Path, str] = "shahrukhx01/bert-mini-finetune-question-detection", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - use_gpu: bool = True, - task: str = "text-classification", - labels: Optional[List[str]] = None, - batch_size: int = 16, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - :param model_name_or_path: Directory of a saved model or the name of a public model, for example 'shahrukhx01/bert-mini-finetune-question-detection'. - See [Hugging Face models](https://huggingface.co/models) for a full list of available models. - :param model_version: The version of the model to use from the Hugging Face model hub. This can be a tag name, a branch name, or a commit hash. - :param tokenizer: The name of the tokenizer (usually the same as model). - :param use_gpu: Whether to use GPU (if available). - :param task: Specifies the type of classification. Possible values: 'text-classification' or 'zero-shot-classification'. - :param labels: If the task is 'text-classification' and an ordered list of labels is provided, the first label corresponds to output_1, - the second label to output_2, and so on. The labels must match the model labels; only the order can differ. - If the task is 'zero-shot-classification', these are the candidate labels. - :param batch_size: The number of queries to be processed at a time. - :param progress_bar: Whether to show a progress bar. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - """ - torch_and_transformers_import.check() - - if labels is None: - labels = DEFAULT_LABELS - super().__init__() - resolved_devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(resolved_devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - resolved_devices[0], - ) - - self.model = pipeline( - task=task, - model=model_name_or_path, - tokenizer=tokenizer, - device=resolved_devices[0], - revision=model_version, - token=use_auth_token, - ) - - self.labels = labels - if task == "text-classification": - labels_from_model = list(self.model.model.config.id2label.values()) - if set(labels) != set(labels_from_model): - raise ValueError( - f"For text-classification, the provided labels must match the model labels; only the order can differ.\n" - f"Provided labels: {labels}\n" - f"Model labels: {labels_from_model}" - ) - if task not in ["text-classification", "zero-shot-classification"]: - raise ValueError( - f"Task not supported: {task}.\n" - f"Possible task values are: 'text-classification' or 'zero-shot-classification'" - ) - self.task = task - self.batch_size = batch_size - self.progress_bar = progress_bar - - @classmethod - def _calculate_outgoing_edges(cls, component_params: Dict[str, Any]) -> int: - labels = component_params.get("labels", DEFAULT_LABELS) - if labels is None or len(labels) == 0: - raise ValueError("The labels must be provided") - return len(labels) - - def _get_edge_number_from_label(self, label): - return self.labels.index(label) + 1 - - def run(self, query: str): # type: ignore - if self.task == "zero-shot-classification": - prediction = self.model([query], candidate_labels=self.labels, truncation=True) - label = prediction[0]["labels"][0] - elif self.task == "text-classification": - prediction = self.model([query], truncation=True) - label = prediction[0]["label"] - return {}, f"output_{self._get_edge_number_from_label(label)}" - - def run_batch(self, queries: List[str], batch_size: Optional[int] = None): # type: ignore - # HF pb hack https://discuss.huggingface.co/t/progress-bar-for-hf-pipelines/20498/2 - queries_dataset = ListDataset(queries) - if batch_size is None: - batch_size = self.batch_size - all_predictions = [] - if self.task == "zero-shot-classification": - for predictions in tqdm( - self.model(queries_dataset, candidate_labels=self.labels, truncation=True, batch_size=batch_size), - disable=not self.progress_bar, - desc="Classifying queries", - ): - all_predictions.extend([predictions]) - elif self.task == "text-classification": - for predictions in tqdm( - self.model(queries_dataset, truncation=True, batch_size=batch_size), - disable=not self.progress_bar, - desc="Classifying queries", - ): - all_predictions.extend([predictions]) - results = {f"output_{self._get_edge_number_from_label(label)}": {"queries": []} for label in self.labels} # type: ignore - for query, prediction in zip(queries, all_predictions): - if self.task == "zero-shot-classification": - label = prediction["labels"][0] - elif self.task == "text-classification": - label = prediction["label"] - results[f"output_{self._get_edge_number_from_label(label)}"]["queries"].append(query) - - return results, "split" diff --git a/haystack/nodes/question_generator/__init__.py b/haystack/nodes/question_generator/__init__.py deleted file mode 100644 index 46758d1308..0000000000 --- a/haystack/nodes/question_generator/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from haystack.nodes.question_generator.question_generator import QuestionGenerator diff --git a/haystack/nodes/question_generator/question_generator.py b/haystack/nodes/question_generator/question_generator.py deleted file mode 100644 index ba54eccc5e..0000000000 --- a/haystack/nodes/question_generator/question_generator.py +++ /dev/null @@ -1,300 +0,0 @@ -import logging -from typing import List, Union, Optional, Iterator -import itertools - -from tqdm import tqdm - -from haystack.errors import HaystackError -from haystack.schema import Document -from haystack.nodes.base import BaseComponent -from haystack.nodes.preprocessor import PreProcessor -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import AutoModelForSeq2SeqLM - from transformers import AutoTokenizer - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class QuestionGenerator(BaseComponent): - """ - The QuestionGenerator takes only a document as input and outputs questions that it thinks this document can answer. In the current implementation, it splits input texts into chunks of 50 words - with a 10 word overlap. This is because the default model `valhalla/t5-base-e2e-qg` seems to generate only - about 3 questions per passage, regardless of length. - - Our approach prioritizes the creation of more questions - over processing efficiency (T5 can digest much more than 50 words at once). The returned questions - generally come in an order dictated by the order of their answers, this means early questions in the list generally - come from earlier in the document. - """ - - outgoing_edges = 1 - - def __init__( - self, - model_name_or_path: str = "valhalla/t5-base-e2e-qg", - model_version: Optional[str] = None, - num_beams: int = 4, - max_length: int = 256, - no_repeat_ngram_size: int = 3, - length_penalty: float = 1.5, - early_stopping: bool = True, - split_length: int = 50, - split_overlap: int = 10, - use_gpu: bool = True, - prompt: str = "generate questions:", - num_queries_per_doc: int = 1, - sep_token: str = "", - batch_size: int = 16, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Uses the valhalla/t5-base-e2e-qg model by default. This class supports any question generation model that is implemented as a Seq2SeqLM in Hugging Face Transformers. - Note that this style of question generation (where the only input - is a document) is sometimes referred to as end-to-end question generation. Answer-supervised question - generation is not currently supported. - - :param model_name_or_path: Directory of a saved model or the name of a public model, for example "valhalla/t5-base-e2e-qg". - See [Hugging Face models](https://huggingface.co/models) for a full list of available models. - :param model_version: The version of the model to use from the Hugging Face model hub. Can be a tag name, a branch name, or a commit hash. - :param num_beams: The number of beams for beam search. `1` means no beam search. - :param max_length: The maximum number of characters the generated text can have. - :param no_repeat_ngram_size: If set to a number larger than 0, all ngrams whose size equals this number can only occur once. For example, if you set it to `3`, all 3-grams can appear once. - :param length_penalty: Encourages the model to generate longer or shorter texts, depending on the value you specify. Values greater than 0.0 promote longer sequences, while values less than 0.0 promote shorter sequences. Used with text generation based on beams. - :param early_stopping: Defines the stopping condition for beam search. - `True` means the model stops generating text after reaching the `num_beams`. - `False` means the model stops generating text only if it's unlikely to find better candidates. - :param split_length: Determines the length of the split (a chunk of a document). Used by `num_queries_per_doc`. - :param split_overlap: Configures the amount of overlap between two adjacent documents after a split. Setting it to a positive number enables sliding window approach. - :param use_gpu: Whether to use GPU or the CPU. Falls back on CPU if no GPU is available. - :param prompt: Contains the prompt with instructions for the model. - :param batch_size: Number of documents to process at a time. - :param num_queries_per_doc: Number of questions to generate per document. However, this is actually a number - of questions to generate per split in the document where the `split_length` determines - the length of the split and the `split_overlap` determines the overlap between splits. - Therefore, this parameter is multiplied by the resulting number of splits to get the - total number of questions generated per document. This value is capped at 3. - :param sep_token: A special token that separates two sentences in the same output. - :param progress_bar: Whether to show a tqdm progress bar or not. - :param use_auth_token: The API token used to download private models from Hugging Face. - If set to `True`, the token generated when running - `transformers-cli login` (stored in ~/.huggingface) is used. - For more information, see [Hugging Face](https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained). - :param devices: List of torch devices (for example cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects or strings is supported (for example - [torch.device('cuda:0'), "mps", "cuda:1"]). If you specify `use_gpu=False`, the devices - parameter is not used and a single CPU device is used for inference. - - """ - torch_and_transformers_import.check() - super().__init__() - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - self.model = AutoModelForSeq2SeqLM.from_pretrained( - model_name_or_path, revision=model_version, use_auth_token=use_auth_token - ) - self.model.to(str(self.devices[0])) - self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_auth_token=use_auth_token) - self.num_beams = num_beams - self.max_length = max_length - self.no_repeat_ngram_size = no_repeat_ngram_size - self.length_penalty = length_penalty - self.early_stopping = early_stopping - self.split_length = split_length - self.split_overlap = split_overlap - self.preprocessor = PreProcessor() - self.prompt = prompt - self.num_queries_per_doc = min(num_queries_per_doc, 3) - self.batch_size = batch_size - self.sep_token = self.tokenizer.sep_token or sep_token - self.progress_bar = progress_bar - - def run(self, documents: List[Document]): # type: ignore - generated_questions = [] - for d in documents: - questions = self.generate(d.content) - curr_dict = {"document_id": d.id, "document_sample": d.content[:200], "questions": questions} - generated_questions.append(curr_dict) - output = {"generated_questions": generated_questions, "documents": documents} - return output, "output_1" - - def run_batch(self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None): # type: ignore - generated_questions = [] - if isinstance(documents[0], Document): - questions = self.generate_batch( - texts=[d.content for d in documents if isinstance(d, Document)], batch_size=batch_size - ) - questions_iterator = questions # type: ignore - documents_iterator = documents - else: - questions = self.generate_batch( - texts=[[d.content for d in doc_list] for doc_list in documents if isinstance(doc_list, list)], - batch_size=batch_size, - ) - questions_iterator = itertools.chain.from_iterable(questions) # type: ignore - documents_iterator = itertools.chain.from_iterable(documents) # type: ignore - for cur_questions, doc in zip(questions_iterator, documents_iterator): - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - curr_dict = {"document_id": doc.id, "document_sample": doc.content[:200], "questions": cur_questions} - generated_questions.append(curr_dict) - output = {"generated_questions": generated_questions, "documents": documents} - return output, "output_1" - - def generate(self, text: str) -> List[str]: - # Performing splitting because T5 has a max input length - # Also currently, it seems that it only generates about 3 questions for the beginning section of text - split_texts_docs = self.preprocessor.split( - document={"content": text}, - split_by="word", - split_respect_sentence_boundary=False, - split_overlap=self.split_overlap, - split_length=self.split_length, - ) - split_texts = [ - f"{self.prompt} {text.content}" if self.prompt not in text.content else text.content - for text in split_texts_docs - ] - tokenized = self.tokenizer(split_texts, return_tensors="pt", padding=True) - input_ids = tokenized["input_ids"].to(self.devices[0]) - # Necessary if padding is enabled so the model won't attend pad tokens - attention_mask = tokenized["attention_mask"].to(self.devices[0]) - tokens_output = self.model.generate( - input_ids=input_ids, - attention_mask=attention_mask, - num_beams=self.num_beams, - max_length=self.max_length, - no_repeat_ngram_size=self.no_repeat_ngram_size, - length_penalty=self.length_penalty, - early_stopping=self.early_stopping, - num_return_sequences=self.num_queries_per_doc, - ) - - string_output = self.tokenizer.batch_decode(tokens_output, skip_special_tokens=True) - - ret = [] - for split in string_output: - for question in split.split(self.sep_token): - question = question.strip() - if question and question not in ret: - ret.append(question) - - return ret - - def generate_batch( - self, texts: Union[List[str], List[List[str]]], batch_size: Optional[int] = None - ) -> Union[List[List[str]], List[List[List[str]]]]: - """ - Generates questions for a list of strings or a list of lists of strings. - - :param texts: List of str or list of list of str. - :param batch_size: Number of texts to process at a time. - """ - - if batch_size is None: - batch_size = self.batch_size - - if isinstance(texts[0], str): - single_doc_list = True - number_of_docs = [1 for text_list in texts] - text_iterator = texts - else: - single_doc_list = False - number_of_docs = [len(text_list) for text_list in texts] - text_iterator = itertools.chain.from_iterable(texts) # type: ignore - - split_texts_docs = [ - self.preprocessor.split( - document={"content": text}, - split_by="word", - split_respect_sentence_boundary=False, - split_overlap=self.split_overlap, - split_length=self.split_length, - ) - for text in text_iterator - ] - split_texts = [[doc.content for doc in split if isinstance(doc.content, str)] for split in split_texts_docs] - number_of_splits = [len(split) for split in split_texts] - flat_split_texts = [ - f"{self.prompt} {text}" if self.prompt not in text else text - for text in itertools.chain.from_iterable(split_texts) - ] - - batches = self._get_batches(flat_split_texts, batch_size=batch_size) - all_string_outputs = [] - pb = tqdm(total=len(flat_split_texts), disable=not self.progress_bar, desc="Generating questions") - for batch in batches: - tokenized = self.tokenizer(batch, return_tensors="pt", padding=True) - input_ids = tokenized["input_ids"].to(self.devices[0]) - # Necessary if padding is enabled so the model won't attend pad tokens - attention_mask = tokenized["attention_mask"].to(self.devices[0]) - tokens_output = self.model.generate( - input_ids=input_ids, - attention_mask=attention_mask, - num_beams=self.num_beams, - max_length=self.max_length, - no_repeat_ngram_size=self.no_repeat_ngram_size, - length_penalty=self.length_penalty, - early_stopping=self.early_stopping, - num_return_sequences=self.num_queries_per_doc, - ) - - string_output = self.tokenizer.batch_decode(tokens_output, skip_special_tokens=True) - all_string_outputs.extend(string_output) - pb.update(len(batch)) - pb.close() - # Group predictions together by split - grouped_predictions_split = [] - left_idx = 0 - right_idx = 0 - for number in number_of_splits: - right_idx = left_idx + number * self.num_queries_per_doc - grouped_predictions_split.append(all_string_outputs[left_idx:right_idx]) - left_idx = right_idx - # Group predictions together by doc list - grouped_predictions_doc_list = [] - left_idx = 0 - right_idx = 0 - for number in number_of_docs: - right_idx = left_idx + number - grouped_predictions_doc_list.append(grouped_predictions_split[left_idx:right_idx]) - left_idx = right_idx - - results = [] - for group in grouped_predictions_doc_list: - group_preds = [] - for doc in group: - doc_preds = [] - for split in doc: - for question in split.split(self.sep_token): - question = question.strip() - if question and question not in doc_preds: - doc_preds.append(question) - group_preds.append(doc_preds) - if single_doc_list: - results.append(group_preds[0]) - else: - results.append(group_preds) - - return results - - @staticmethod - def _get_batches(texts: List[str], batch_size: Optional[int]) -> Iterator[List[str]]: - if batch_size is None: - yield texts - return - else: - for index in range(0, len(texts), batch_size): - yield texts[index : index + batch_size] diff --git a/haystack/nodes/ranker/__init__.py b/haystack/nodes/ranker/__init__.py deleted file mode 100644 index 1c3b7dbcee..0000000000 --- a/haystack/nodes/ranker/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from haystack.nodes.ranker.base import BaseRanker -from haystack.nodes.ranker.sentence_transformers import SentenceTransformersRanker -from haystack.nodes.ranker.cohere import CohereRanker -from haystack.nodes.ranker.lost_in_the_middle import LostInTheMiddleRanker -from haystack.nodes.ranker.diversity import DiversityRanker -from haystack.nodes.ranker.recentness_ranker import RecentnessRanker diff --git a/haystack/nodes/ranker/base.py b/haystack/nodes/ranker/base.py deleted file mode 100644 index a2a84bcb28..0000000000 --- a/haystack/nodes/ranker/base.py +++ /dev/null @@ -1,171 +0,0 @@ -from typing import List, Optional, Union - -import logging -from abc import abstractmethod -from functools import wraps -from time import perf_counter -from copy import deepcopy - -from haystack.schema import Document -from haystack.nodes.base import BaseComponent - - -logger = logging.getLogger(__name__) - - -class BaseRanker(BaseComponent): - return_no_answers: bool - outgoing_edges = 1 - query_count = 0 - query_time = 0 - - @abstractmethod - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None): - pass - - @abstractmethod - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - pass - - def _add_meta_fields_to_docs( - self, documents: List[Document], embed_meta_fields: Optional[List[str]] = None - ) -> List[Document]: - """ - Concatenates specified metadata fields with the text representations. - - :param documents: List of documents to add metadata to. - :param embed_meta_fields: Concatenate the provided meta fields and into the text passage that is then used in - reranking. - :return: List of documents with metadata. - """ - if not embed_meta_fields: - return documents - - docs_with_meta = [] - for doc in documents: - doc = deepcopy(doc) - # Gather all relevant metadata fields - meta_data_fields = [] - for key in embed_meta_fields: - if key in doc.meta and doc.meta[key]: - if isinstance(doc.meta[key], list): - meta_data_fields.extend(list(doc.meta[key])) - else: - meta_data_fields.append(doc.meta[key]) - # Convert to type string (e.g. for ints or floats) - meta_data_fields = [str(field) for field in meta_data_fields] - doc.content = "\n".join(meta_data_fields + [doc.content]) - docs_with_meta.append(doc) - return docs_with_meta - - def run(self, query: str, documents: List[Document], top_k: Optional[int] = None): # type: ignore - """ - :param query: Query string. - :param documents: List of Documents to process. - :param top_k: The maximum number of Documents to return. - """ - self.query_count += 1 - if documents: - predict = self.timing(self.predict, "query_time") - results = predict(query=query, documents=documents, top_k=top_k) - else: - results = [] - - document_ids = [doc.id for doc in results] - logger.debug("Retrieved documents with IDs: %s", document_ids) - output = {"documents": results} - - return output, "output_1" - - def run_batch( # type: ignore - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ): - """ - :param queries: List of query strings. - :param documents: List of list of Documents to process. - :param top_k: The maximum number of answers to return. - :param batch_size: Number of Documents to process at a time. - """ - self.query_count = +len(queries) - predict_batch = self.timing(self.predict_batch, "query_time") - results = predict_batch(queries=queries, documents=documents, top_k=top_k, batch_size=batch_size) - - for doc_list in results: - document_ids = [doc.id for doc in doc_list] - logger.debug("Ranked documents with IDs: %s", document_ids) - - output = {"documents": results} - - return output, "output_1" - - def timing(self, fn, attr_name): - """Wrapper method used to time functions.""" - - @wraps(fn) - def wrapper(*args, **kwargs): - if attr_name not in self.__dict__: - self.__dict__[attr_name] = 0 - tic = perf_counter() - ret = fn(*args, **kwargs) - toc = perf_counter() - self.__dict__[attr_name] += toc - tic - return ret - - return wrapper - - def print_time(self): - print("Ranker (Speed)") - print("---------------") - if not self.query_count: - print("No querying performed via Retriever.run()") - else: - print(f"Queries Performed: {self.query_count}") - print(f"Query time: {self.query_time}s") - print(f"{self.query_time / self.query_count} seconds per query") - - def eval( - self, - label_index: str = "label", - doc_index: str = "eval_document", - label_origin: str = "gold_label", - top_k: int = 10, - open_domain: bool = False, - return_preds: bool = False, - ) -> dict: - """ - Performs evaluation of the Ranker. - Ranker is evaluated in the same way as a Retriever based on whether it finds the correct document given the query string and at which - position in the ranking of documents the correct document is. - - Returns a dict containing the following metrics: - - - "recall": Proportion of questions for which correct document is among retrieved documents - - "mrr": Mean of reciprocal rank. Rewards retrievers that give relevant documents a higher rank. - Only considers the highest ranked relevant document. - - "map": Mean of average precision for each question. Rewards retrievers that give relevant - documents a higher rank. Considers all retrieved relevant documents. If ``open_domain=True``, - average precision is normalized by the number of retrieved relevant documents per query. - If ``open_domain=False``, average precision is normalized by the number of all relevant documents - per query. - - :param label_index: Index/Table in DocumentStore where labeled questions are stored - :param doc_index: Index/Table in DocumentStore where documents that are used for evaluation are stored - :param top_k: How many documents to return per query - :param open_domain: If ``True``, retrieval will be evaluated by checking if the answer string to a question is - contained in the retrieved docs (common approach in open-domain QA). - If ``False``, retrieval uses a stricter evaluation that checks if the retrieved document ids - are within ids explicitly stated in the labels. - :param return_preds: Whether to add predictions in the returned dictionary. If True, the returned dictionary - contains the keys "predictions" and "metrics". - """ - raise NotImplementedError diff --git a/haystack/nodes/ranker/cohere.py b/haystack/nodes/ranker/cohere.py deleted file mode 100644 index f3c084f29a..0000000000 --- a/haystack/nodes/ranker/cohere.py +++ /dev/null @@ -1,232 +0,0 @@ -import json -import os -from typing import Optional, Dict, Union, List, Any -import logging - -import requests - -from haystack.environment import HAYSTACK_REMOTE_API_TIMEOUT_SEC, HAYSTACK_REMOTE_API_MAX_RETRIES -from haystack.errors import CohereInferenceLimitError, CohereUnauthorizedError, CohereError -from haystack.utils import request_with_retry - -from haystack.errors import HaystackError -from haystack.schema import Document -from haystack.nodes.ranker.base import BaseRanker - - -logger = logging.getLogger(__name__) - - -TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) -RETRIES = int(os.environ.get(HAYSTACK_REMOTE_API_MAX_RETRIES, 5)) - - -class CohereRanker(BaseRanker): - """ - You can use re-ranking on top of a Retriever to boost the performance for document search. - This is particularly useful if the Retriever has a high recall but is bad in sorting the documents by relevance. - - Cohere models are trained with a context length of 512 tokens - the model takes into account both the input - from the query and document. If your query is larger than 256 tokens, it will be truncated to the first 256 tokens. - - Cohere breaks down a query-document pair into 512 token chunks. For example, if your query is 50 tokens and your - document is 1024 tokens, your document will be broken into the following chunks: - ```bash - relevance_score_1 = - relevance_score_2 = - relevance_score_3 = - relevance_score = max(relevance_score_1, relevance_score_2, relevance_score_3) - ``` - - Find more best practices for reranking in the [Cohere documentation](https://docs.cohere.com/docs/reranking-best-practices). - """ - - def __init__( - self, - api_key: str, - model_name_or_path: str, - top_k: int = 10, - max_chunks_per_doc: Optional[int] = None, - embed_meta_fields: Optional[List[str]] = None, - ): - """ - Creates an instance of CohereInvocationLayer for the specified Cohere model. - - :param api_key: Cohere API key. - :param model_name_or_path: Cohere model name. Check the list of supported models in the [Cohere documentation](https://docs.cohere.com/docs/models). - :param top_k: The maximum number of documents to return. - :param max_chunks_per_doc: If your document exceeds 512 tokens, this determines the maximum number of - chunks a document can be split into. If None, the default of 10 is used. - For example, if your document is 6000 tokens, with the default of 10, the document will be split into 10 - chunks each of 512 tokens and the last 880 tokens will be disregarded. - :param embed_meta_fields: Concatenate the provided meta fields and into the text passage that is then used in - reranking. The original documents are returned so the concatenated metadata is not included in the returned documents. - """ - super().__init__() - valid_api_key = isinstance(api_key, str) and api_key - if not valid_api_key: - raise ValueError( - f"api_key {api_key} must be a valid Cohere token. " - f"Your token is available in your Cohere settings page." - ) - # See model info at https://docs.cohere.com/docs/models - # supported models are rerank-english-v2.0, rerank-multilingual-v2.0 - valid_model_name_or_path = isinstance(model_name_or_path, str) and model_name_or_path - if not valid_model_name_or_path: - raise ValueError(f"model_name_or_path {model_name_or_path} must be a valid Cohere model name") - self.model_name_or_path = model_name_or_path - self.api_key = api_key - self.top_k = top_k - self.max_chunks_per_doc = max_chunks_per_doc - self.embed_meta_fields = embed_meta_fields - - @property - def url(self) -> str: - return "https://api.cohere.ai/v1/rerank" - - @property - def headers(self) -> Dict[str, str]: - return { - "Authorization": f"Bearer {self.api_key}", - "Content-Type": "application/json", - "Request-Source": "python-sdk", - } - - def _post( - self, - data: Dict[str, Any], - attempts: int = RETRIES, - status_codes_to_retry: Optional[List[int]] = None, - timeout: float = TIMEOUT, - ) -> requests.Response: - """ - Post data to the Cohere re-ranker model. It takes in a query and a list of documents and returns a response - using a REST invocation. - - :param data: The data to be sent to the model. - :param attempts: The number of attempts to make. - :param status_codes_to_retry: The status codes to retry on. - :param timeout: The timeout for the request. - :return: The response from the model as a requests.Response object. - """ - response: requests.Response - if status_codes_to_retry is None: - status_codes_to_retry = [429] - try: - response = request_with_retry( - method="POST", - status_codes_to_retry=status_codes_to_retry, - attempts=attempts, - url=self.url, - headers=self.headers, - json=data, - timeout=timeout, - ) - except requests.HTTPError as err: - res = err.response - if res.status_code == 429: # type: ignore[union-attr] - raise CohereInferenceLimitError(f"API rate limit exceeded: {res.text}") # type: ignore[union-attr] - if res.status_code == 401: # type: ignore[union-attr] - raise CohereUnauthorizedError(f"API key is invalid: {res.text}") # type: ignore[union-attr] - - raise CohereError( - f"Cohere model returned an error.\nStatus code: {res.status_code}\nResponse body: {res.text}", # type: ignore[union-attr] - status_code=res.status_code, # type: ignore[union-attr] - ) - return response - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None) -> List[Document]: - """ - Use the Cohere Reranker to re-rank the supplied list of documents based on the query. - - :param query: The query string. - :param documents: List of Document to be re-ranked. - :param top_k: The maximum number of documents to return. - """ - if top_k is None: - top_k = self.top_k - - # See https://docs.cohere.com/reference/rerank-1 - docs_with_meta_fields = self._add_meta_fields_to_docs( - documents=documents, embed_meta_fields=self.embed_meta_fields - ) - cohere_docs = [{"text": d.content} for d in docs_with_meta_fields] - if len(cohere_docs) > 1000: - logger.warning( - "The Cohere reranking endpoint only supports 1000 documents. " - "The number of documents has been truncated to 1000 from %s.", - len(cohere_docs), - ) - cohere_docs = cohere_docs[:1000] - - params = { - "model": self.model_name_or_path, - "query": query, - "documents": cohere_docs, - "top_n": None, # By passing None we return all documents and use top_k to truncate later - "return_documents": False, - "max_chunks_per_doc": self.max_chunks_per_doc, - } - response = self._post(params) - output = json.loads(response.text) - - indices = [o["index"] for o in output["results"]] - scores = [o["relevance_score"] for o in output["results"]] - sorted_docs = [] - for idx, score in zip(indices, scores): - doc = documents[idx] - doc.score = score - sorted_docs.append(documents[idx]) - - return sorted_docs[:top_k] - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - """ - Use Cohere Reranking endpoint to re-rank the supplied lists of Documents. - - Returns a lists of Documents sorted by (descending) similarity with the corresponding queries. - - - If you provide a list containing a single query... - - - ... and a single list of Documents, the single list of Documents will be re-ranked based on the - supplied query. - - ... and a list of lists of Documents, each list of Documents will be re-ranked individually based on the - supplied query. - - - If you provide a list of multiple queries... - - - ... you need to provide a list of lists of Documents. Each list of Documents will be re-ranked based on - its corresponding query. - - :param queries: List of queries. - :param documents: Single list of Documents or list of lists of Documents to be reranked. - :param top_k: The maximum number of documents to return per Document list. - :param batch_size: Not relevant. - """ - if top_k is None: - top_k = self.top_k - - if len(documents) > 0 and isinstance(documents[0], Document): - # Docs case 1: single list of Documents -> rerank single list of Documents based on single query - if len(queries) != 1: - raise HaystackError("Number of queries must be 1 if a single list of Documents is provided.") - return self.predict(query=queries[0], documents=documents, top_k=top_k) # type: ignore - else: - # Docs case 2: list of lists of Documents -> rerank each list of Documents based on corresponding query - # If queries contains a single query, apply it to each list of Documents - if len(queries) == 1: - queries = queries * len(documents) - if len(queries) != len(documents): - raise HaystackError("Number of queries must be equal to number of provided Document lists.") - - results = [] - for query, cur_docs in zip(queries, documents): - assert isinstance(cur_docs, list) - results.append(self.predict(query=query, documents=cur_docs, top_k=top_k)) # type: ignore - return results diff --git a/haystack/nodes/ranker/diversity.py b/haystack/nodes/ranker/diversity.py deleted file mode 100644 index bd684d17de..0000000000 --- a/haystack/nodes/ranker/diversity.py +++ /dev/null @@ -1,153 +0,0 @@ -import logging -from pathlib import Path -from typing import List, Literal, Optional, Union - -from haystack.nodes.ranker.base import BaseRanker -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - -logger = logging.getLogger(__name__) - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from sentence_transformers import SentenceTransformer - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class DiversityRanker(BaseRanker): - """ - Implements a document ranking algorithm that orders documents in such a way as to maximize the overall diversity - of the documents. - """ - - def __init__( - self, - model_name_or_path: Union[str, Path] = "all-MiniLM-L6-v2", - top_k: Optional[int] = None, - use_gpu: Optional[bool] = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - similarity: Literal["dot_product", "cosine"] = "dot_product", - ): - """ - Initialize a DiversityRanker. - - :param model_name_or_path: Path to a pretrained sentence-transformers model. - :param top_k: The maximum number of documents to return. - :param use_gpu: Whether to use GPU (if available). If no GPUs are available, it falls back on a CPU. - :param devices: List of torch devices (for example, cuda:0, cpu, mps) to limit inference to specific devices. - :param similarity: Whether to use dot product or cosine similarity. Can be set to "dot_product" (default) or "cosine". - """ - torch_and_transformers_import.check() - super().__init__() - self.top_k = top_k - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=True) - self.model = SentenceTransformer(model_name_or_path, device=str(self.devices[0])) - self.similarity = similarity - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None) -> List[Document]: - """ - Rank the documents based on their diversity and return the top_k documents. - - :param query: The query. - :param documents: A list of Document objects that should be ranked. - :param top_k: The maximum number of documents to return. - - :return: A list of top_k documents ranked based on diversity. - """ - if query is None or len(query) == 0: - raise ValueError("Query is empty") - if documents is None or len(documents) == 0: - raise ValueError("No documents to choose from") - - top_k = top_k or self.top_k - diversity_sorted = self.greedy_diversity_order(query=query, documents=documents) - return diversity_sorted[:top_k] - - def greedy_diversity_order(self, query: str, documents: List[Document]) -> List[Document]: - """ - Orders the given list of documents to maximize diversity. The algorithm first calculates embeddings for - each document and the query. It starts by selecting the document that is semantically closest to the query. - Then, for each remaining document, it selects the one that, on average, is least similar to the already - selected documents. This process continues until all documents are selected, resulting in a list where - each subsequent document contributes the most to the overall diversity of the selected set. - - :param query: The search query. - :param documents: The list of Document objects to be ranked. - - :return: A list of documents ordered to maximize diversity. - """ - - # Calculate embeddings - doc_embeddings: torch.Tensor = self.model.encode([d.content for d in documents], convert_to_tensor=True) - query_embedding: torch.Tensor = self.model.encode([query], convert_to_tensor=True) - - if self.similarity == "dot_product": - doc_embeddings /= torch.norm(doc_embeddings, p=2, dim=-1).unsqueeze(-1) - query_embedding /= torch.norm(query_embedding, p=2, dim=-1).unsqueeze(-1) - - n = len(documents) - selected: List[int] = [] - - # Compute the similarity vector between the query and documents - query_doc_sim: torch.Tensor = query_embedding @ doc_embeddings.T - - # Start with the document with the highest similarity to the query - selected.append(int(torch.argmax(query_doc_sim).item())) - - selected_sum = doc_embeddings[selected[0]] / n - - while len(selected) < n: - # Compute mean of dot products of all selected documents and all other documents - similarities = selected_sum @ doc_embeddings.T - # Mask documents that are already selected - similarities[selected] = torch.inf - # Select the document with the lowest total similarity score - index_unselected = int(torch.argmin(similarities).item()) - - selected.append(index_unselected) - # It's enough just to add to the selected vectors because dot product is distributive - # It's divided by n for numerical stability - selected_sum += doc_embeddings[index_unselected] / n - - ranked_docs: List[Document] = [documents[i] for i in selected] - - return ranked_docs - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[float] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - """ - Rank the documents based on their diversity and return the top_k documents. - - :param queries: The queries. - :param documents: A list (or a list of lists) of Document objects that should be ranked. - :param top_k: The maximum number of documents to return. - :param batch_size: The number of documents to process in one batch. - - :return: A list (or a list of lists) of top_k documents ranked based on diversity. - """ - if queries is None or len(queries) == 0: - raise ValueError("No queries to choose from") - if documents is None or len(documents) == 0: - raise ValueError("No documents to choose from") - if len(documents) > 0 and isinstance(documents[0], Document): - # Docs case 1: single list of Documents -> rerank single list of Documents based on single query - if len(queries) != 1: - raise ValueError("Number of queries must be 1 if a single list of Documents is provided.") - return self.predict(query=queries[0], documents=documents, top_k=top_k) # type: ignore - else: - # Docs case 2: list of lists of Documents -> rerank each list of Documents based on corresponding query - # If queries contains a single query, apply it to each list of Documents - if len(queries) == 1: - queries = queries * len(documents) - if len(queries) != len(documents): - raise ValueError("Number of queries must be equal to number of provided Document lists.") - - results = [] - for query, cur_docs in zip(queries, documents): - results.append(self.predict(query=query, documents=cur_docs, top_k=top_k)) # type: ignore - return results diff --git a/haystack/nodes/ranker/lost_in_the_middle.py b/haystack/nodes/ranker/lost_in_the_middle.py deleted file mode 100644 index 1ffbe5bcd3..0000000000 --- a/haystack/nodes/ranker/lost_in_the_middle.py +++ /dev/null @@ -1,133 +0,0 @@ -from typing import Optional, Union, List -import logging - -from haystack.schema import Document -from haystack.nodes.ranker.base import BaseRanker - -logger = logging.getLogger(__name__) - - -class LostInTheMiddleRanker(BaseRanker): - """ - The LostInTheMiddleRanker implements a ranker that reorders documents based on the "lost in the middle" order. - "Lost in the Middle: How Language Models Use Long Contexts" paper by Liu et al. aims to lay out paragraphs into LLM - context so that the relevant paragraphs are at the beginning or end of the input context, while the least relevant - information is in the middle of the context. - - See https://arxiv.org/abs/2307.03172 for more details. - """ - - def __init__(self, word_count_threshold: Optional[int] = None, top_k: Optional[int] = None): - """ - Creates an instance of LostInTheMiddleRanker. - - If 'word_count_threshold' is specified, this ranker includes all documents up until the point where adding - another document would exceed the 'word_count_threshold'. The last document that causes the threshold to - be breached will be included in the resulting list of documents, but all subsequent documents will be - discarded. - - :param word_count_threshold: The maximum total number of words across all documents selected by the ranker. - :param top_k: The maximum number of documents to return. - """ - super().__init__() - if isinstance(word_count_threshold, int) and word_count_threshold <= 0: - raise ValueError( - f"Invalid value for word_count_threshold: {word_count_threshold}. " - f"word_count_threshold must be a positive integer." - ) - self.word_count_threshold = word_count_threshold - self.top_k = top_k - - def reorder_documents(self, documents: List[Document]) -> List[Document]: - """ - Ranks documents based on the "lost in the middle" order. Assumes that all documents are ordered by relevance. - - :param documents: List of Documents to merge. - :return: Documents in the "lost in the middle" order. - """ - - # Return empty list if no documents are provided - if not documents: - return [] - - # If there's only one document, return it as is - if len(documents) == 1: - return documents - - # Raise an error if any document is not textual - if any(not doc.content_type == "text" for doc in documents): - raise ValueError("Some provided documents are not textual; LostInTheMiddleRanker can process only text.") - - # Initialize word count and indices for the "lost in the middle" order - word_count = 0 - document_index = list(range(len(documents))) - lost_in_the_middle_indices = [0] - - # If word count threshold is set, calculate word count for the first document - if self.word_count_threshold: - word_count = len(documents[0].content.split()) - - # If the first document already meets the word count threshold, return it - if word_count >= self.word_count_threshold: - return [documents[0]] - - # Start from the second document and create "lost in the middle" order - for doc_idx in document_index[1:]: - # Calculate the index at which the current document should be inserted - insertion_index = len(lost_in_the_middle_indices) // 2 + len(lost_in_the_middle_indices) % 2 - - # Insert the document index at the calculated position - lost_in_the_middle_indices.insert(insertion_index, doc_idx) - - # If word count threshold is set, calculate the total word count - if self.word_count_threshold: - word_count += len(documents[doc_idx].content.split()) - - # If the total word count meets the threshold, stop processing further documents - if word_count >= self.word_count_threshold: - break - - # Return the documents in the "lost in the middle" order - return [documents[idx] for idx in lost_in_the_middle_indices] - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None) -> List[Document]: - """ - Reranks documents based on the "lost in the middle" order. - - :param query: The query to reorder documents for (ignored). - :param documents: List of Documents to reorder. - :param top_k: The number of documents to return. - - :return: The reordered documents. - """ - top_k = top_k or self.top_k - documents_to_reorder = documents[:top_k] if top_k else documents - ranked_docs = self.reorder_documents(documents=documents_to_reorder) - return ranked_docs - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - """ - Reranks batch of documents based on the "lost in the middle" order. - - :param queries: The queries to reorder documents for (ignored). - :param documents: List of Documents to reorder. - :param top_k: The number of documents to return. - :param batch_size: The number of queries to process in one batch (ignored). - - :return: The reordered documents. - """ - if len(documents) > 0 and isinstance(documents[0], Document): - return self.predict(query="", documents=documents, top_k=top_k) # type: ignore - else: - # Docs case 2: list of lists of Documents -> rerank each list of Documents - results = [] - for cur_docs in documents: - assert isinstance(cur_docs, list) - results.append(self.predict(query="", documents=cur_docs, top_k=top_k)) - return results diff --git a/haystack/nodes/ranker/recentness_ranker.py b/haystack/nodes/ranker/recentness_ranker.py deleted file mode 100644 index ff7149993d..0000000000 --- a/haystack/nodes/ranker/recentness_ranker.py +++ /dev/null @@ -1,189 +0,0 @@ -import logging -import warnings -from collections import defaultdict -from typing import List, Union, Optional, Dict, Literal - -from dateutil.parser import parse, ParserError -from haystack.errors import NodeError - -from haystack.nodes.ranker.base import BaseRanker -from haystack.schema import Document - -logger = logging.getLogger(__name__) - - -class RecentnessRanker(BaseRanker): - outgoing_edges = 1 - - def __init__( - self, - date_meta_field: str, - weight: float = 0.5, - top_k: Optional[int] = None, - ranking_mode: Literal["reciprocal_rank_fusion", "score"] = "reciprocal_rank_fusion", - ): - """ - This Node is used to rerank retrieved documents based on their age. Newer documents will rank higher. - The importance of recentness is parametrized through the weight parameter. - - :param date_meta_field: Identifier pointing to the date field in the metadata. - This is a required parameter, since we need dates for sorting. - :param weight: in range [0,1]. - 0 disables sorting by age. - 0.5 content and age have the same impact. - 1 means sorting only by age, most recent comes first. - :param top_k: (optional) How many documents to return. If not provided, all documents will be returned. - It can make sense to have large top-k values from the initial retrievers and filter docs down in the - RecentnessRanker with this top_k parameter. - :param ranking_mode: The mode used to combine retriever and recentness. Possible values are 'reciprocal_rank_fusion' (default) and 'score'. - Make sure to use 'score' mode only with retrievers/rankers that give back OK score in range [0,1]. - """ - - super().__init__() - self.date_meta_field = date_meta_field - self.weight = weight - self.top_k = top_k - self.ranking_mode = ranking_mode - - if self.weight < 0 or self.weight > 1: - raise NodeError( - """ - Param needs to be in range [0,1] but was set to '{}'.\n - '0' disables sorting by recency, '0.5' gives equal weight to previous relevance scores and recency, and '1' ranks by recency only.\n - Please change param when initializing the RecentnessRanker. - """.format( - self.weight - ) - ) - - # pylint: disable=arguments-differ - def predict( # type: ignore - self, query: str, documents: List[Document], top_k: Optional[int] = None - ) -> List[Document]: - """ - This method is used to rank a list of documents based on their age and relevance by: - 1. Adjusting the relevance score from the previous node (or, for RRF, calculating it from scratch, then adjusting) based on the chosen weight in initial parameters. - 2. Sorting the documents based on their age in the metadata, calculating the recentness score, adjusting it by weight as well. - 3. Returning top-k documents (or all, if top-k not provided) in the documents dictionary sorted by final score (relevance score + recentness score). - - :param query: Not used in practice (so can be left blank), as this ranker does not perform sorting based on semantic closeness of documents to the query. - :param documents: Documents provided for ranking. - :param top_k: (optional) How many documents to return at the end. If not provided, all documents will be returned, sorted by relevance and recentness (adjusted by weight). - """ - - try: - sorted_by_date = sorted(documents, reverse=True, key=lambda x: parse(x.meta[self.date_meta_field])) - except KeyError: - raise NodeError( - """ - Param was set to '{}', but document(s) {} do not contain this metadata key.\n - Please double-check the names of existing metadata fields of your documents \n - and set to the name of the field that contains dates. - """.format( - self.date_meta_field, - ",".join([doc.id for doc in documents if self.date_meta_field not in doc.meta]), - ) - ) - - except ParserError: - logger.error( - """ - Could not parse date information for dates: %s\n - Continuing without sorting by date. - """, - " - ".join([doc.meta.get(self.date_meta_field, "identifier wrong") for doc in documents]), - ) - - return documents - - # merge scores for documents sorted both by content and by date. - # If ranking mode is set to 'reciprocal_rank_fusion', then that is used to combine previous ranking with recency ranking. - # If ranking mode is set to 'score', then documents will be assigned a recency score in [0,1] and will be re-ranked based on both their recency score and their pre-existing relevance score. - scores_map: Dict = defaultdict(int) - if self.ranking_mode not in ["reciprocal_rank_fusion", "score"]: - raise NodeError( - """ - Param needs to be 'reciprocal_rank_fusion' or 'score' but was set to '{}'. \n - Please change the when initializing the RecentnessRanker. - """.format( - self.ranking_mode - ) - ) - - for i, doc in enumerate(documents): - if self.ranking_mode == "reciprocal_rank_fusion": - scores_map[doc.id] += self._calculate_rrf(rank=i) * (1 - self.weight) - elif self.ranking_mode == "score": - score = float(0) - if doc.score is None: - warnings.warn("The score was not provided; defaulting to 0") - elif doc.score < 0 or doc.score > 1: - warnings.warn( - "The score {} for document {} is outside the [0,1] range; defaulting to 0".format( - doc.score, doc.id - ) - ) - else: - score = doc.score - - scores_map[doc.id] += score * (1 - self.weight) - - for i, doc in enumerate(sorted_by_date): - if self.ranking_mode == "reciprocal_rank_fusion": - scores_map[doc.id] += self._calculate_rrf(rank=i) * self.weight - elif self.ranking_mode == "score": - scores_map[doc.id] += self._calc_recentness_score(rank=i, amount=len(sorted_by_date)) * self.weight - - top_k = top_k or self.top_k or len(documents) - - for doc in documents: - doc.score = scores_map[doc.id] - - return sorted(documents, key=lambda doc: doc.score if doc.score is not None else -1, reverse=True)[:top_k] - - # pylint: disable=arguments-differ - def predict_batch( # type: ignore - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - """ - This method is used to rank A) a list or B) a list of lists (in case the previous node is JoinDocuments) of documents based on their age and relevance. - In case A, the predict method defined earlier is applied to the provided list. - In case B, predict method is applied to each individual list in the list of lists provided, then the results are returned as list of lists. - - :param queries: Not used in practice (so can be left blank), as this ranker does not perform sorting based on semantic closeness of documents to the query. - :param documents: Documents provided for ranking in a list or a list of lists. - :param top_k: (optional) How many documents to return at the end (per list). If not provided, all documents will be returned, sorted by relevance and recentness (adjusted by weight). - :param batch_size: Not used in practice, so can be left blank. - """ - - if isinstance(documents[0], Document): - return self.predict("", documents=documents, top_k=top_k) # type: ignore - nested_docs = [] - for docs in documents: - results = self.predict("", documents=docs, top_k=top_k) # type: ignore - nested_docs.append(results) - - return nested_docs - - @staticmethod - def _calculate_rrf(rank: int, k: int = 61) -> float: - """ - Calculates the reciprocal rank fusion. The constant K is set to 61 (60 was suggested by the original paper, - plus 1 as python lists are 0-based and the paper [https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf] used 1-based ranking). - """ - return 1 / (k + rank) - - @staticmethod - def _calc_recentness_score(rank: int, amount: int) -> float: - """ - Calculate recentness score as a linear score between most recent and oldest document. - This linear scaling is useful to - a) reduce the effect of outliers and - b) create recentness scoress that are meaningfully distributed in [0,1], - similar to scores coming from a retriever/ranker. - """ - return (amount - rank) / amount diff --git a/haystack/nodes/ranker/sentence_transformers.py b/haystack/nodes/ranker/sentence_transformers.py deleted file mode 100644 index 17d82055e5..0000000000 --- a/haystack/nodes/ranker/sentence_transformers.py +++ /dev/null @@ -1,326 +0,0 @@ -from typing import List, Optional, Union, Tuple, Iterator, Any -import logging -from pathlib import Path - -from tqdm import tqdm - -from haystack.errors import HaystackError -from haystack.schema import Document -from haystack.nodes.ranker.base import BaseRanker -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from torch.nn import DataParallel - from transformers import AutoModelForSequenceClassification, AutoTokenizer - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class SentenceTransformersRanker(BaseRanker): - """ - Sentence Transformer based pre-trained Cross-Encoder model for Document Re-ranking (https://huggingface.co/cross-encoder). - Re-Ranking can be used on top of a retriever to boost the performance for document search. - This is particularly useful if the retriever has a high recall but is bad in sorting the documents by relevance. - - SentenceTransformerRanker handles Cross-Encoder models - - use a single logit as similarity score e.g. cross-encoder/ms-marco-MiniLM-L-12-v2 - - use two output logits (no_answer, has_answer) e.g. deepset/gbert-base-germandpr-reranking - https://www.sbert.net/docs/pretrained-models/ce-msmarco.html#usage-with-transformers - - With a SentenceTransformersRanker, you can: - - directly get predictions via predict() - - Usage example: - - ```python - retriever = BM25Retriever(document_store=document_store) - ranker = SentenceTransformersRanker(model_name_or_path="cross-encoder/ms-marco-MiniLM-L-12-v2") - p = Pipeline() - p.add_node(component=retriever, name="Retriever", inputs=["Query"]) - p.add_node(component=ranker, name="Ranker", inputs=["ESRetriever"]) - ``` - """ - - def __init__( - self, - model_name_or_path: Union[str, Path], - model_version: Optional[str] = None, - top_k: int = 10, - use_gpu: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - batch_size: int = 16, - scale_score: bool = True, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - embed_meta_fields: Optional[List[str]] = None, - ): - """ - :param model_name_or_path: Directory of a saved model or the name of a public model e.g. - 'cross-encoder/ms-marco-MiniLM-L-12-v2'. - See https://huggingface.co/cross-encoder for full list of available models - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param top_k: The maximum number of documents to return - :param use_gpu: Whether to use all available GPUs or the CPU. Falls back on CPU if no GPU is available. - :param batch_size: Number of documents to process at a time. - :param scale_score: The raw predictions will be transformed using a Sigmoid activation function in case the model - only predicts a single label. For multi-label predictions, no scaling is applied. Set this - to False if you do not want any scaling of the raw predictions. - :param progress_bar: Whether to show a progress bar while processing the documents. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :param embed_meta_fields: Concatenate the provided meta fields and into the text passage that is then used in - reranking. The original documents are returned so the concatenated metadata is not included in the returned documents. - """ - torch_and_transformers_import.check() - super().__init__() - - self.top_k = top_k - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=True) - - self.progress_bar = progress_bar - self.transformer_model = AutoModelForSequenceClassification.from_pretrained( - pretrained_model_name_or_path=model_name_or_path, revision=model_version, use_auth_token=use_auth_token - ) - self.transformer_model.to(str(self.devices[0])) - self.transformer_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=model_name_or_path, revision=model_version, use_auth_token=use_auth_token - ) - self.transformer_model.eval() - - # we use sigmoid activation function to scale the score in case there is only a single label - # we do not apply any scaling when scale_score is set to False - num_labels = self.transformer_model.num_labels - self.activation_function: torch.nn.Module - if num_labels == 1 and scale_score: - self.activation_function = torch.nn.Sigmoid() - else: - self.activation_function = torch.nn.Identity() - - if len(self.devices) > 1: - self.model = DataParallel(self.transformer_model, device_ids=self.devices) - - self.batch_size = batch_size - self.embed_meta_fields = embed_meta_fields - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None) -> List[Document]: - """ - Use loaded ranker model to re-rank the supplied list of Document. - - Returns list of Document sorted by (desc.) similarity with the query. - - :param query: Query string - :param documents: List of Document to be re-ranked - :param top_k: The maximum number of documents to return - :return: List of Document - """ - if top_k is None: - top_k = self.top_k - - docs_with_meta_fields = self._add_meta_fields_to_docs( - documents=documents, embed_meta_fields=self.embed_meta_fields - ) - docs = [doc.content for doc in docs_with_meta_fields] - features = self.transformer_tokenizer( - [query for _ in documents], docs, padding=True, truncation=True, return_tensors="pt" - ).to(self.devices[0]) - - # SentenceTransformerRanker uses: - # 1. the logit as similarity score/answerable classification - # 2. the logits as answerable classification (no_answer / has_answer) - # https://www.sbert.net/docs/pretrained-models/ce-msmarco.html#usage-with-transformers - with torch.inference_mode(): - similarity_scores = self.transformer_model(**features).logits - - logits_dim = similarity_scores.shape[1] # [batch_size, logits_dim] - sorted_scores_and_documents = sorted( - zip(similarity_scores, documents), - key=lambda similarity_document_tuple: - # assume the last element in logits represents the `has_answer` label - similarity_document_tuple[0][-1] if logits_dim >= 2 else similarity_document_tuple[0], - reverse=True, - ) - - # add normalized scores to documents - sorted_documents = self._add_scores_to_documents(sorted_scores_and_documents[:top_k], logits_dim) - - return sorted_documents - - def _add_scores_to_documents( - self, sorted_scores_and_documents: List[Tuple[Any, Document]], logits_dim: int - ) -> List[Document]: - """ - Normalize and add scores to retrieved result documents. - - :param sorted_scores_and_documents: List of score, Document Tuples. - :param logits_dim: Dimensionality of the returned scores. - """ - sorted_documents = [] - for raw_score, doc in sorted_scores_and_documents: - if logits_dim >= 2: - score = self.activation_function(raw_score)[-1] - else: - score = self.activation_function(raw_score)[0] - - doc.score = score.detach().cpu().numpy().tolist() - sorted_documents.append(doc) - - return sorted_documents - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - """ - Use loaded ranker model to re-rank the supplied lists of Documents. - - Returns lists of Documents sorted by (desc.) similarity with the corresponding queries. - - - - If you provide a list containing a single query... - - - ... and a single list of Documents, the single list of Documents will be re-ranked based on the - supplied query. - - ... and a list of lists of Documents, each list of Documents will be re-ranked individually based on the - supplied query. - - - - If you provide a list of multiple queries... - - - ... you need to provide a list of lists of Documents. Each list of Documents will be re-ranked based on - its corresponding query. - - :param queries: Single query string or list of queries - :param documents: Single list of Documents or list of lists of Documents to be reranked. - :param top_k: The maximum number of documents to return per Document list. - :param batch_size: Number of Documents to process at a time. - """ - if top_k is None: - top_k = self.top_k - - if batch_size is None: - batch_size = self.batch_size - - number_of_docs, all_queries, all_docs, single_list_of_docs = self._preprocess_batch_queries_and_docs( - queries=queries, documents=documents - ) - all_docs_with_meta_fields = self._add_meta_fields_to_docs( - documents=all_docs, embed_meta_fields=self.embed_meta_fields - ) - - batches = self._get_batches(all_queries=all_queries, all_docs=all_docs_with_meta_fields, batch_size=batch_size) - pb = tqdm(total=len(all_docs_with_meta_fields), disable=not self.progress_bar, desc="Ranking") - preds = [] - for cur_queries, cur_docs in batches: - features = self.transformer_tokenizer( - cur_queries, [doc.content for doc in cur_docs], padding=True, truncation=True, return_tensors="pt" - ).to(self.devices[0]) - - with torch.inference_mode(): - similarity_scores = self.transformer_model(**features).logits - preds.extend(similarity_scores) - pb.update(len(cur_docs)) - pb.close() - - logits_dim = similarity_scores.shape[1] # [batch_size, logits_dim] - if single_list_of_docs: - sorted_scores_and_documents = sorted( - zip(preds, documents), - key=lambda similarity_document_tuple: - # assume the last element in logits represents the `has_answer` label - similarity_document_tuple[0][-1] if logits_dim >= 2 else similarity_document_tuple[0], - reverse=True, - ) - - # is this step needed? - sorted_documents = [(score, doc) for score, doc in sorted_scores_and_documents if isinstance(doc, Document)] - sorted_documents_with_scores = self._add_scores_to_documents(sorted_documents[:top_k], logits_dim) - - return sorted_documents_with_scores - else: - # Group predictions together - grouped_predictions = [] - left_idx = 0 - for number in number_of_docs: - right_idx = left_idx + number - grouped_predictions.append(preds[left_idx:right_idx]) - left_idx = right_idx - - result = [] - for pred_group, doc_group in zip(grouped_predictions, documents): - sorted_scores_and_documents = sorted( - zip(pred_group, doc_group), # type: ignore - key=lambda similarity_document_tuple: - # assume the last element in logits represents the `has_answer` label - similarity_document_tuple[0][-1] if logits_dim >= 2 else similarity_document_tuple[0], - reverse=True, - ) - - # rank documents according to scores - sorted_documents = [ - (score, doc) for score, doc in sorted_scores_and_documents if isinstance(doc, Document) - ] - sorted_documents_with_scores = self._add_scores_to_documents(sorted_documents[:top_k], logits_dim) - - result.append(sorted_documents_with_scores) - - return result - - def _preprocess_batch_queries_and_docs( - self, queries: List[str], documents: Union[List[Document], List[List[Document]]] - ) -> Tuple[List[int], List[str], List[Document], bool]: - number_of_docs = [] - all_queries = [] - all_docs: List[Document] = [] - single_list_of_docs = False - - # Docs case 1: single list of Documents -> rerank single list of Documents based on single query - if len(documents) > 0 and isinstance(documents[0], Document): - if len(queries) != 1: - raise HaystackError("Number of queries must be 1 if a single list of Documents is provided.") - query = queries[0] - number_of_docs = [len(documents)] - all_queries = [query] * len(documents) - all_docs = documents # type: ignore - single_list_of_docs = True - - # Docs case 2: list of lists of Documents -> rerank each list of Documents based on corresponding query - # If queries contains a single query, apply it to each list of Documents - if len(documents) > 0 and isinstance(documents[0], list): - if len(queries) == 1: - queries = queries * len(documents) - if len(queries) != len(documents): - raise HaystackError("Number of queries must be equal to number of provided Document lists.") - for query, cur_docs in zip(queries, documents): - if not isinstance(cur_docs, list): - raise HaystackError(f"cur_docs was of type {type(cur_docs)}, but expected a list of Documents.") - number_of_docs.append(len(cur_docs)) - all_queries.extend([query] * len(cur_docs)) - all_docs.extend(cur_docs) - - return number_of_docs, all_queries, all_docs, single_list_of_docs - - @staticmethod - def _get_batches( - all_queries: List[str], all_docs: List[Document], batch_size: Optional[int] - ) -> Iterator[Tuple[List[str], List[Document]]]: - if batch_size is None: - yield all_queries, all_docs - return - else: - for index in range(0, len(all_queries), batch_size): - yield all_queries[index : index + batch_size], all_docs[index : index + batch_size] diff --git a/haystack/nodes/reader/__init__.py b/haystack/nodes/reader/__init__.py deleted file mode 100644 index 0d80527e0f..0000000000 --- a/haystack/nodes/reader/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from haystack.nodes.reader.base import BaseReader -from haystack.nodes.reader.farm import FARMReader -from haystack.nodes.reader.transformers import TransformersReader -from haystack.nodes.reader.table import TableReader, RCIReader diff --git a/haystack/nodes/reader/base.py b/haystack/nodes/reader/base.py deleted file mode 100644 index 840cf72ec3..0000000000 --- a/haystack/nodes/reader/base.py +++ /dev/null @@ -1,256 +0,0 @@ -from typing import List, Optional, Sequence, Tuple, Union -import itertools -import logging - -from abc import abstractmethod -from copy import deepcopy -from functools import wraps -from time import perf_counter - -import numpy as np - -from haystack.schema import Document, Answer, Span, MultiLabel -from haystack.nodes.base import BaseComponent -from haystack.utils.scipy_utils import expit - - -logger = logging.getLogger(__name__) - - -class BaseReader(BaseComponent): - return_no_answers: bool - outgoing_edges = 1 - query_count = 0 - query_time = 0 - - @abstractmethod - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None): - pass - - @abstractmethod - def predict_batch( - self, queries: List[str], documents: Union[List[Document], List[List[Document]]], top_k: Optional[int] = None - ): - pass - - @staticmethod - def _calc_no_answer( - no_ans_gaps: Sequence[float], best_score_answer: float, use_confidence_scores: bool = True - ) -> Tuple[Answer, float]: - # "no answer" scores and positive answers scores are difficult to compare, because - # + a positive answer score is related to one specific document - # - a "no answer" score is related to all input documents - # Thus we compute the "no answer" score relative to the best possible answer and adjust it by - # the most significant difference between scores. - # Most significant difference: a model switching from predicting an answer to "no answer" (or vice versa). - # No_ans_gap is a list of this most significant difference per document - - # If there is not even one predicted answer, we return a no_answer with score 1.0 - if best_score_answer == 0 and len(no_ans_gaps) == 0: - no_ans_score = 1024.0 - no_ans_score_scaled = 1.0 - max_no_ans_gap = 1024.0 - else: - no_ans_gap_array = np.array(no_ans_gaps) - max_no_ans_gap = np.max(no_ans_gap_array) - # case 1: all passages "no answer" as top score - # max_no_ans_gap is negative, so it increases best pos score - # case 2: at least one passage predicts an answer (positive no_ans_gap) - no_ans_score = best_score_answer - max_no_ans_gap - no_ans_score_scaled = float(expit(np.asarray(no_ans_score) / 8)) - - no_ans_prediction = Answer( - answer="", - type="extractive", - score=no_ans_score_scaled - if use_confidence_scores - else no_ans_score, # just a pseudo prob for now or old score, - context=None, - offsets_in_context=[Span(start=0, end=0)], - offsets_in_document=[Span(start=0, end=0)], - document_ids=None, - meta=None, - ) - - return no_ans_prediction, max_no_ans_gap - - @staticmethod - def add_doc_meta_data_to_answer(documents: List[Document], answer): - # Add corresponding document_name and more meta data, if the answer contains the document_id - if answer.meta is None: - answer.meta = {} - # get meta from doc - meta_from_doc = {} - if answer.document_ids: - for doc in documents: - if doc.id in answer.document_ids: - meta_from_doc = deepcopy(doc.meta) - break - # append to "own" meta - answer.meta.update(meta_from_doc) - return answer - - def run(self, query: str, documents: List[Document], top_k: Optional[int] = None, labels: Optional[MultiLabel] = None, add_isolated_node_eval: bool = False): # type: ignore - """ - :param query: Query string. - :param documents: List of Documents in which Reader looks for answers. - :param top_k: The maximum number of answers to return. - :param labels: Labels to be used for evaluation. - :param add_isolated_node_eval: If True, the reader will be evaluated in isolation (i.e. without a retriever). - """ - self.query_count += 1 - predict = self.timing(self.predict, "query_time") - # Remove empty text documents before making predictions - documents = [d for d in documents if not isinstance(d.content, str) or d.content.strip() != ""] - if documents: - results = predict(query=query, documents=documents, top_k=top_k) - else: - if hasattr(self, "return_no_answers") and self.return_no_answers: - no_ans_prediction = Answer( - answer="", - type="extractive", - score=1.0 - if hasattr(self, "use_confidence_scores") and self.use_confidence_scores - else 1024.0, # just a pseudo prob for now or old score, - context=None, - offsets_in_context=[Span(start=0, end=0)], - offsets_in_document=[Span(start=0, end=0)], - document_ids=None, - meta=None, - ) - results = {"answers": [no_ans_prediction]} - else: - results = {"answers": []} - - # Add corresponding document_name and more meta data, if an answer contains the document_id - results["answers"] = [ - BaseReader.add_doc_meta_data_to_answer(documents=documents, answer=answer) for answer in results["answers"] - ] - - # run evaluation with labels as node inputs - if add_isolated_node_eval and labels is not None: - # This dict comprehension deduplicates same Documents in a MultiLabel based on their Document ID and - # filters out empty documents - relevant_documents = list( - { - label.document.id: label.document - for label in labels.labels - if not isinstance(label.document.content, str) or label.document.content.strip() != "" - }.values() - ) - results_label_input = predict(query=query, documents=relevant_documents, top_k=top_k) - - # Add corresponding document_name and more meta data, if an answer contains the document_id - results["answers_isolated"] = [ - BaseReader.add_doc_meta_data_to_answer(documents=documents, answer=answer) - for answer in results_label_input["answers"] - ] - - return results, "output_1" - - def run_batch( # type: ignore - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - labels: Optional[List[MultiLabel]] = None, - add_isolated_node_eval: bool = False, - ): - """ - :param queries: List of query strings. - :param documents: List of lists of Document in which Reader looks for answers. - :param top_k: The maximum number of answers to return. - :param labels: Labels to be used for evaluation. - :param add_isolated_node_eval: If True, the reader will be evaluated in isolation (i.e. without a retriever). - """ - self.query_count += len(queries) - - # Remove empty documents before making predictions - if len(documents) > 0: - if isinstance(documents[0], Document): - documents = [d for d in documents if not isinstance(d.content, str) or d.content.strip() != ""] # type: ignore[union-attr, assignment] - else: - documents = [[d for d in docs_per_query if not isinstance(d.content, str) or d.content.strip() != ""] for docs_per_query in documents] # type: ignore[union-attr] - - if not documents: - return {"answers": []}, "output_1" - - predict_batch = self.timing(self.predict_batch, "query_time") - - results = predict_batch(queries=queries, documents=documents, top_k=top_k, batch_size=batch_size) - - # Add corresponding document_name and more meta data, if an answer contains the document_id - answer_iterator = itertools.chain.from_iterable(results["answers"]) - if isinstance(documents[0], Document): - answer_iterator = itertools.chain.from_iterable(itertools.chain.from_iterable(results["answers"])) - flattened_documents = [] - for doc_list in documents: - if isinstance(doc_list, list): - flattened_documents.extend(doc_list) - else: - flattened_documents.append(doc_list) - - for answer in answer_iterator: - BaseReader.add_doc_meta_data_to_answer(documents=flattened_documents, answer=answer) - - # run evaluation with labels as node inputs - if add_isolated_node_eval and labels is not None: - relevant_documents = [] - for labelx in labels: - # This dict comprehension deduplicates same Documents in a MultiLabel based on their Document ID - # and filters out empty documents - relevant_docs_labelx = list( - { - label.document.id: label.document - for label in labelx.labels - if not isinstance(label.document.content, str) or label.document.content.strip() != "" - }.values() - ) - relevant_documents.append(relevant_docs_labelx) - results_label_input = predict_batch(queries=queries, documents=relevant_documents, top_k=top_k) - - # Add corresponding document_name and more meta data, if an answer contains the document_id - answer_iterator = itertools.chain.from_iterable(results_label_input["answers"]) - if isinstance(documents[0], Document) and isinstance(queries, list): - answer_iterator = itertools.chain.from_iterable( - itertools.chain.from_iterable(results_label_input["answers"]) - ) - flattened_documents = [] - for doc_list in documents: - if isinstance(doc_list, list): - flattened_documents.extend(doc_list) - else: - flattened_documents.append(doc_list) - - for answer in answer_iterator: - BaseReader.add_doc_meta_data_to_answer(documents=flattened_documents, answer=answer) - - results["answers_isolated"] = results_label_input["answers"] - - return results, "output_1" - - def timing(self, fn, attr_name): - """Wrapper method used to time functions.""" - - @wraps(fn) - def wrapper(*args, **kwargs): - if attr_name not in self.__dict__: - self.__dict__[attr_name] = 0 - tic = perf_counter() - ret = fn(*args, **kwargs) - toc = perf_counter() - self.__dict__[attr_name] += toc - tic - return ret - - return wrapper - - def print_time(self): - print("Reader (Speed)") - print("---------------") - if not self.query_count: - print("No querying performed via Retriever.run()") - else: - print(f"Queries Performed: {self.query_count}") - print(f"Query time: {self.query_time}s") - print(f"{self.query_time / self.query_count} seconds per query") diff --git a/haystack/nodes/reader/farm.py b/haystack/nodes/reader/farm.py deleted file mode 100644 index 94847339d1..0000000000 --- a/haystack/nodes/reader/farm.py +++ /dev/null @@ -1,1475 +0,0 @@ -# pylint: disable=ungrouped-imports - -from typing import List, Optional, Dict, Any, Union, Callable, Tuple - -import logging -import multiprocessing -from pathlib import Path -from collections import defaultdict -import os -import tempfile -from time import perf_counter - -from huggingface_hub import create_repo, HfFolder, Repository - -from haystack.errors import HaystackError -from haystack.schema import Document, Answer, Span -from haystack.document_stores.base import BaseDocumentStore -from haystack.nodes.reader.base import BaseReader -from haystack.utils import get_batches_from_generator -from haystack.utils.early_stopping import EarlyStopping -from haystack.telemetry import send_event -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from haystack.modeling.data_handler.data_silo import DataSilo, DistillationDataSilo - from haystack.modeling.data_handler.processor import SquadProcessor, Processor - from haystack.modeling.data_handler.dataloader import NamedDataLoader - from haystack.modeling.data_handler.inputs import QAInput, Question - from haystack.modeling.infer import QAInferencer - from haystack.modeling.model.optimization import initialize_optimizer - from haystack.modeling.model.predictions import QAPred, QACandidate - from haystack.modeling.model.adaptive_model import AdaptiveModel - from haystack.modeling.training import Trainer, DistillationTrainer, TinyBERTDistillationTrainer - from haystack.modeling.evaluation import Evaluator - from haystack.modeling.utils import set_all_seeds, initialize_device_settings - - -class FARMReader(BaseReader): - """ - Transformer based model for extractive Question Answering using the FARM framework (https://github.com/deepset-ai/FARM). - While the underlying model can vary (BERT, Roberta, DistilBERT, ...), the interface remains the same. - - With a FARMReader, you can: - - - directly get predictions via predict() - - fine-tune the model on QA data via train() - """ - - def __init__( - self, - model_name_or_path: str, - model_version: Optional[str] = None, - context_window_size: int = 150, - batch_size: int = 50, - use_gpu: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - no_ans_boost: float = 0.0, - return_no_answer: bool = False, - top_k: int = 10, - top_k_per_candidate: int = 3, - top_k_per_sample: int = 1, - num_processes: Optional[int] = None, - max_seq_len: int = 256, - doc_stride: int = 128, - progress_bar: bool = True, - duplicate_filtering: int = 0, - use_confidence_scores: bool = True, - confidence_threshold: Optional[float] = None, - proxies: Optional[Dict[str, str]] = None, - local_files_only=False, - force_download=False, - use_auth_token: Optional[Union[str, bool]] = None, - max_query_length: int = 64, - preprocessing_batch_size: Optional[int] = None, - ): - """ - :param model_name_or_path: Directory of a saved model or the name of a public model e.g. 'bert-base-cased', - 'deepset/bert-base-cased-squad2', 'deepset/bert-base-cased-squad2', 'distilbert-base-uncased-distilled-squad'. - See https://huggingface.co/models for full list of available models. - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param context_window_size: The size, in characters, of the window around the answer span that is used when - displaying the context around the answer. - :param batch_size: Number of samples the model receives in one batch for inference. - Memory consumption is much lower in inference mode. Recommendation: Increase the batch size - to a value so only a single batch is used. - :param use_gpu: Whether to use GPUs or the CPU. Falls back on CPU if no GPU is available. - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :param no_ans_boost: How much the no_answer logit is boosted/increased. - If set to 0 (default), the no_answer logit is not changed. - If a negative number, there is a lower chance of "no_answer" being predicted. - If a positive number, there is an increased chance of "no_answer" - :param return_no_answer: Whether to include no_answer predictions in the results. - :param top_k: The maximum number of answers to return - :param top_k_per_candidate: How many answers to extract for each candidate doc that is coming from the retriever (might be a long text). - Note that this is not the number of "final answers" you will receive - (see `top_k` in FARMReader.predict() or Finder.get_answers() for that) - and that FARM includes no_answer in the sorted list of predictions. - :param top_k_per_sample: How many answers to extract from each small text passage that the model can process at once - (one "candidate doc" is usually split into many smaller "passages"). - You usually want a very small value here, as it slows down inference - and you don't gain much of quality by having multiple answers from one passage. - Note that this is not the number of "final answers" you will receive - (see `top_k` in FARMReader.predict() or Finder.get_answers() for that) - and that FARM includes no_answer in the sorted list of predictions. - :param num_processes: The number of processes for `multiprocessing.Pool`. Set to value of 0 to disable - multiprocessing. Set to None to let Inferencer determine optimum number. If you - want to debug the Language Model, you might need to disable multiprocessing! - :param max_seq_len: Max sequence length of one input text for the model - :param doc_stride: Length of striding window for splitting long texts (used if ``len(text) > max_seq_len``) - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param duplicate_filtering: Answers are filtered based on their position. Both start and end position of the answers are considered. - The higher the value, answers that are more apart are filtered out. 0 corresponds to exact duplicates. -1 turns off duplicate removal. - :param use_confidence_scores: Determines the type of score that is used for ranking a predicted answer. - `True` => a scaled confidence / relevance score between [0, 1]. - This score can also be further calibrated on your dataset via self.eval() - (see https://docs.haystack.deepset.ai/docs/reader#confidence-scores). - `False` => an unscaled, raw score [-inf, +inf] which is the sum of start and end logit - from the model for the predicted span. - Using confidence scores can change the ranking of no_answer compared to using the - unscaled raw scores. - :param confidence_threshold: Filters out predictions below confidence_threshold. Value should be between 0 and 1. Disabled by default. - :param proxies: Dict of proxy servers to use for downloading external models. Example: {'http': 'some.proxy:1234', 'http://hostname': 'my.proxy:3111'} - :param local_files_only: Whether to force checking for local files only (and forbid downloads) - :param force_download: Whether to force a (re-)download even if the model exists locally in the cache. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param max_query_length: Maximum length of the question in number of tokens. - :param preprocessing_batch_size: Number of query-document pairs to be preprocessed (= tokenized, put into - tensors, etc.) at once. If `None` (default), all query-document pairs are - preprocessed at once. - """ - torch_and_transformers_import.check() - - super().__init__() - - self.devices, self.n_gpu = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=True) - self.return_no_answers = return_no_answer - self.top_k = top_k - self.top_k_per_candidate = top_k_per_candidate - self.inferencer = QAInferencer.load( - model_name_or_path, - batch_size=batch_size, - gpu=self.n_gpu > 0, - task_type="question_answering", - max_seq_len=max_seq_len, - doc_stride=doc_stride, - num_processes=num_processes, - revision=model_version, - disable_tqdm=not progress_bar, - strict=False, - proxies=proxies, - local_files_only=local_files_only, - force_download=force_download, - devices=self.devices, # type: ignore [arg-type] - use_auth_token=use_auth_token, - max_query_length=max_query_length, - ) - self.inferencer.model.prediction_heads[0].context_window_size = context_window_size - self.inferencer.model.prediction_heads[0].no_ans_boost = no_ans_boost - self.inferencer.model.prediction_heads[0].n_best = top_k_per_candidate + 1 # including possible no_answer - self.inferencer.model.prediction_heads[0].n_best_per_sample = top_k_per_sample - self.inferencer.model.prediction_heads[0].duplicate_filtering = duplicate_filtering - self.inferencer.model.prediction_heads[0].use_confidence_scores_for_ranking = use_confidence_scores - self.max_seq_len = max_seq_len - self.doc_stride = doc_stride - self.max_query_length = max_query_length - self.progress_bar = progress_bar - self.use_confidence_scores = use_confidence_scores - self.confidence_threshold = confidence_threshold - self.model_name_or_path = model_name_or_path # Used in distillation, see DistillationDataSilo._get_checksum() - self.preprocessing_batch_size = preprocessing_batch_size - - def _training_procedure( - self, - data_dir: str, - train_filename: str, - dev_filename: Optional[str] = None, - test_filename: Optional[str] = None, - use_gpu: Optional[bool] = None, - devices: Optional[List["torch.device"]] = None, - batch_size: int = 10, - n_epochs: int = 2, - learning_rate: float = 1e-5, - max_seq_len: Optional[int] = None, - warmup_proportion: float = 0.2, - dev_split: float = 0, - evaluate_every: int = 300, - save_dir: Optional[str] = None, - num_processes: Optional[int] = None, - use_amp: bool = False, - checkpoint_root_dir: Path = Path("model_checkpoints"), - checkpoint_every: Optional[int] = None, - checkpoints_to_keep: int = 3, - teacher_model: Optional["FARMReader"] = None, - teacher_batch_size: Optional[int] = None, - caching: bool = False, - cache_path: Path = Path("cache/data_silo"), - distillation_loss_weight: float = 0.5, - distillation_loss: Union[str, Callable[["torch.Tensor", "torch.Tensor"], "torch.Tensor"]] = "kl_div", - temperature: float = 1.0, - tinybert: bool = False, - processor: Optional["Processor"] = None, - grad_acc_steps: int = 1, - early_stopping: Optional["EarlyStopping"] = None, - distributed: bool = False, - doc_stride: Optional[int] = None, - max_query_length: Optional[int] = None, - ): - if devices is None: - devices = [] - if dev_filename: - dev_split = 0 - - if num_processes is None: - num_processes = multiprocessing.cpu_count() - 1 or 1 - - set_all_seeds(seed=42) - - # For these variables, by default, we use the value set when initializing the FARMReader. - # These can also be manually set when train() is called if you want a different value at train vs inference - if devices is None: - devices = self.devices - if max_seq_len is None: - max_seq_len = self.max_seq_len - if doc_stride is None: - doc_stride = self.doc_stride - if max_query_length is None: - max_query_length = self.max_query_length - - devices, n_gpu = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) # type: ignore [arg-type] - - if not save_dir: - save_dir = f"./saved_models/{self.inferencer.model.language_model.name}" - if tinybert: - save_dir += "_tinybert_stage_1" - - # 1. Create a DataProcessor that handles all the conversion from raw text into a pytorch Dataset - label_list = ["start_token", "end_token"] - metric = "squad" - if processor is None: - processor = SquadProcessor( - tokenizer=self.inferencer.processor.tokenizer, - max_seq_len=max_seq_len, - max_query_length=max_query_length, - doc_stride=doc_stride, - label_list=label_list, - metric=metric, - train_filename=train_filename, - dev_filename=dev_filename, - dev_split=dev_split, - test_filename=test_filename, - data_dir=Path(data_dir), - ) - data_silo: DataSilo - - # 2. Create a DataSilo that loads several datasets (train/dev/test), provides DataLoaders for them - # and calculates a few descriptive statistics of our datasets - if ( - teacher_model and not tinybert - ): # checks if teacher model is passed as parameter, in that case assume model distillation is used - data_silo = DistillationDataSilo( - teacher_model, - teacher_batch_size or batch_size, - device=devices[0], - processor=processor, - batch_size=batch_size, - distributed=distributed, - max_processes=num_processes, - caching=caching, - cache_path=cache_path, - ) - else: # caching would need too much memory for tinybert distillation so in that case we use the default data silo - data_silo = DataSilo( - processor=processor, - batch_size=batch_size, - distributed=distributed, - max_processes=num_processes, - caching=caching, - cache_path=cache_path, - ) - - # 3. Create an optimizer and pass the already initialized model - model, optimizer, lr_schedule = initialize_optimizer( - model=self.inferencer.model, - learning_rate=learning_rate, - schedule_opts={"name": "LinearWarmup", "warmup_proportion": warmup_proportion}, - n_batches=len(data_silo.loaders["train"]), - n_epochs=n_epochs, - device=devices[0], - grad_acc_steps=grad_acc_steps, - distributed=distributed, - ) - # 4. Feed everything to the Trainer, which keeps care of growing our model and evaluates it from time to time - if tinybert: - if not teacher_model: - raise ValueError("TinyBERT distillation requires a teacher model.") - trainer = TinyBERTDistillationTrainer.create_or_load_checkpoint( - model=model, - teacher_model=teacher_model.inferencer.model, # teacher needs to be passed as teacher outputs aren't cached - optimizer=optimizer, - data_silo=data_silo, - epochs=n_epochs, - n_gpu=n_gpu, - lr_schedule=lr_schedule, - evaluate_every=evaluate_every, - device=devices[0], - use_amp=use_amp, - disable_tqdm=not self.progress_bar, - checkpoint_root_dir=Path(checkpoint_root_dir), - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - grad_acc_steps=grad_acc_steps, - early_stopping=early_stopping, - ) - - elif ( - teacher_model - ): # checks again if teacher model is passed as parameter, in that case assume model distillation is used - trainer = DistillationTrainer.create_or_load_checkpoint( - model=model, - optimizer=optimizer, - data_silo=data_silo, - epochs=n_epochs, - n_gpu=n_gpu, - lr_schedule=lr_schedule, - evaluate_every=evaluate_every, - device=devices[0], - use_amp=use_amp, - disable_tqdm=not self.progress_bar, - checkpoint_root_dir=Path(checkpoint_root_dir), - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - distillation_loss=distillation_loss, - distillation_loss_weight=distillation_loss_weight, - temperature=temperature, - grad_acc_steps=grad_acc_steps, - early_stopping=early_stopping, - ) - else: - trainer = Trainer.create_or_load_checkpoint( - model=model, - optimizer=optimizer, - data_silo=data_silo, - epochs=n_epochs, - n_gpu=n_gpu, - lr_schedule=lr_schedule, - evaluate_every=evaluate_every, - device=devices[0], - use_amp=use_amp, - disable_tqdm=not self.progress_bar, - checkpoint_root_dir=Path(checkpoint_root_dir), - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - grad_acc_steps=grad_acc_steps, - early_stopping=early_stopping, - ) - - # 5. Let it grow! - self.inferencer.model = trainer.train() - self.save(Path(save_dir)) - - def train( - self, - data_dir: str, - train_filename: str, - dev_filename: Optional[str] = None, - test_filename: Optional[str] = None, - use_gpu: Optional[bool] = None, - devices: Optional[List["torch.device"]] = None, - batch_size: int = 10, - n_epochs: int = 2, - learning_rate: float = 1e-5, - max_seq_len: Optional[int] = None, - warmup_proportion: float = 0.2, - dev_split: float = 0, - evaluate_every: int = 300, - save_dir: Optional[str] = None, - num_processes: Optional[int] = None, - use_amp: bool = False, - checkpoint_root_dir: Path = Path("model_checkpoints"), - checkpoint_every: Optional[int] = None, - checkpoints_to_keep: int = 3, - caching: bool = False, - cache_path: Path = Path("cache/data_silo"), - grad_acc_steps: int = 1, - early_stopping: Optional[EarlyStopping] = None, - max_query_length: Optional[int] = None, - ): - """ - Fine-tune a model on a QA dataset. Options: - - Take a plain language model (e.g. `bert-base-cased`) and train it for QA (e.g. on SQuAD data) - - Take a QA model (e.g. `deepset/bert-base-cased-squad2`) and fine-tune it for your domain (e.g. using your labels collected via the haystack annotation tool) - - Checkpoints can be stored via setting `checkpoint_every` to a custom number of steps. - If any checkpoints are stored, a subsequent run of train() will resume training from the latest available checkpoint. - - Note that when performing training with this function, long documents are split into chunks. - If a chunk doesn't contain the answer to the question, it is treated as a no-answer sample. - - :param data_dir: Path to directory containing your training data in SQuAD style - :param train_filename: Filename of training data - :param dev_filename: Filename of dev / eval data - :param test_filename: Filename of test data - :param dev_split: Instead of specifying a dev_filename, you can also specify a ratio (e.g. 0.1) here - that gets split off from training data for eval. - :param use_gpu: Whether to use GPU (if available) - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :param batch_size: Number of samples the model receives in one batch for training - :param n_epochs: Number of iterations on the whole training data set - :param learning_rate: Learning rate of the optimizer - :param max_seq_len: Maximum text length (in tokens). Everything longer gets cut down. - :param warmup_proportion: Proportion of training steps until maximum learning rate is reached. - Until that point LR is increasing linearly. After that it's decreasing again linearly. - Options for different schedules are available in FARM. - :param evaluate_every: Evaluate the model every X steps on the hold-out eval dataset. - Note that the evaluation report is logged at evaluation level INFO while Haystack's default is WARNING. - :param save_dir: Path to store the final model - :param num_processes: The number of processes for `multiprocessing.Pool` during preprocessing. - Set to value of 1 to disable multiprocessing. When set to 1, you cannot split away a dev set from train set. - Set to None to use all CPU cores minus one. - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param checkpoint_root_dir: The Path of a directory where all train checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoint_every: Save a train checkpoint after this many steps of training. - :param checkpoints_to_keep: The maximum number of train checkpoints to save. - :param caching: Whether or not to use caching for the preprocessed dataset. - :param cache_path: The Path to cache the preprocessed dataset. - :param grad_acc_steps: The number of steps to accumulate gradients for before performing a backward pass. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - :param max_query_length: Maximum length of the question in number of tokens. - :return: None - """ - send_event(event_name="Training", event_properties={"class": self.__class__.__name__, "function_name": "train"}) - return self._training_procedure( - data_dir=data_dir, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - use_gpu=use_gpu, - devices=devices, - batch_size=batch_size, - n_epochs=n_epochs, - learning_rate=learning_rate, - max_seq_len=max_seq_len, - warmup_proportion=warmup_proportion, - dev_split=dev_split, - evaluate_every=evaluate_every, - save_dir=save_dir, - num_processes=num_processes, - use_amp=use_amp, - checkpoint_root_dir=checkpoint_root_dir, - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - caching=caching, - cache_path=cache_path, - grad_acc_steps=grad_acc_steps, - early_stopping=early_stopping, - max_query_length=max_query_length, - distributed=False, - ) - - def distil_prediction_layer_from( - self, - teacher_model: "FARMReader", - data_dir: str, - train_filename: str, - dev_filename: Optional[str] = None, - test_filename: Optional[str] = None, - use_gpu: Optional[bool] = None, - devices: Optional[List["torch.device"]] = None, - batch_size: int = 10, - teacher_batch_size: Optional[int] = None, - n_epochs: int = 2, - learning_rate: float = 3e-5, - max_seq_len: Optional[int] = None, - warmup_proportion: float = 0.2, - dev_split: float = 0, - evaluate_every: int = 300, - save_dir: Optional[str] = None, - num_processes: Optional[int] = None, - use_amp: bool = False, - checkpoint_root_dir: Path = Path("model_checkpoints"), - checkpoint_every: Optional[int] = None, - checkpoints_to_keep: int = 3, - caching: bool = False, - cache_path: Path = Path("cache/data_silo"), - distillation_loss_weight: float = 0.5, - distillation_loss: Union[str, Callable[["torch.Tensor", "torch.Tensor"], "torch.Tensor"]] = "kl_div", - temperature: float = 1.0, - processor: Optional["Processor"] = None, - grad_acc_steps: int = 1, - early_stopping: Optional["EarlyStopping"] = None, - ): - """ - Fine-tune a model on a QA dataset using logit-based distillation. You need to provide a teacher model that is already finetuned on the dataset - and a student model that will be trained using the teacher's logits. The idea of this is to increase the accuracy of a lightweight student model. - using a more complex teacher. - Originally proposed in: https://arxiv.org/pdf/1503.02531.pdf - This can also be considered as the second stage of distillation finetuning as described in the TinyBERT paper: - https://arxiv.org/pdf/1909.10351.pdf - **Example** - ```python - student = FARMReader(model_name_or_path="prajjwal1/bert-medium") - teacher = FARMReader(model_name_or_path="deepset/bert-large-uncased-whole-word-masking-squad2") - student.distil_prediction_layer_from(teacher, data_dir="squad2", train_filename="train.json", test_filename="dev.json", - learning_rate=3e-5, distillation_loss_weight=1.0, temperature=5) - ``` - - Checkpoints can be stored via setting `checkpoint_every` to a custom number of steps. - If any checkpoints are stored, a subsequent run of train() will resume training from the latest available checkpoint. - - :param teacher_model: Model whose logits will be used to improve accuracy - :param data_dir: Path to directory containing your training data in SQuAD style - :param train_filename: Filename of training data - :param dev_filename: Filename of dev / eval data - :param test_filename: Filename of test data - :param dev_split: Instead of specifying a dev_filename, you can also specify a ratio (e.g. 0.1) here - that gets split off from training data for eval. - :param use_gpu: Whether to use GPU (if available) - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :param batch_size: Number of samples the student model receives in one batch for training - :param teacher_batch_size: Number of samples the teacher model receives in one batch for distillation - :param n_epochs: Number of iterations on the whole training data set - :param learning_rate: Learning rate of the optimizer - :param max_seq_len: Maximum text length (in tokens). Everything longer gets cut down. - :param warmup_proportion: Proportion of training steps until maximum learning rate is reached. - Until that point LR is increasing linearly. After that it's decreasing again linearly. - Options for different schedules are available in FARM. - :param evaluate_every: Evaluate the model every X steps on the hold-out eval dataset - :param save_dir: Path to store the final model - :param num_processes: The number of processes for `multiprocessing.Pool` during preprocessing. - Set to value of 1 to disable multiprocessing. When set to 1, you cannot split away a dev set from train set. - Set to None to use all CPU cores minus one. - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param checkpoint_root_dir: the Path of directory where all train checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoint_every: save a train checkpoint after this many steps of training. - :param checkpoints_to_keep: maximum number of train checkpoints to save. - :param caching: whether or not to use caching for preprocessed dataset and teacher logits - :param cache_path: Path to cache the preprocessed dataset and teacher logits - :param distillation_loss_weight: The weight of the distillation loss. A higher weight means the teacher outputs are more important. - :param distillation_loss: Specifies how teacher and model logits should be compared. Can either be a string ("mse" for mean squared error or "kl_div" for kl divergence loss) or a callable loss function (needs to have named parameters student_logits and teacher_logits) - :param temperature: The temperature for distillation. A higher temperature will result in less certainty of teacher outputs. A lower temperature means more certainty. A temperature of 1.0 does not change the certainty of the model. - :param processor: The processor to use for preprocessing. If None, the default SquadProcessor is used. - :param grad_acc_steps: The number of steps to accumulate gradients for before performing a backward pass. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - :return: None - """ - send_event( - event_name="Training", - event_properties={"class": self.__class__.__name__, "function_name": "distil_prediction_layer_from"}, - ) - return self._training_procedure( - data_dir=data_dir, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - use_gpu=use_gpu, - devices=devices, - batch_size=batch_size, - n_epochs=n_epochs, - learning_rate=learning_rate, - max_seq_len=max_seq_len, - warmup_proportion=warmup_proportion, - dev_split=dev_split, - evaluate_every=evaluate_every, - save_dir=save_dir, - num_processes=num_processes, - use_amp=use_amp, - checkpoint_root_dir=checkpoint_root_dir, - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - teacher_model=teacher_model, - teacher_batch_size=teacher_batch_size, - caching=caching, - cache_path=cache_path, - distillation_loss_weight=distillation_loss_weight, - distillation_loss=distillation_loss, - temperature=temperature, - processor=processor, - grad_acc_steps=grad_acc_steps, - early_stopping=early_stopping, - distributed=False, - ) - - def distil_intermediate_layers_from( - self, - teacher_model: "FARMReader", - data_dir: str, - train_filename: str, - dev_filename: Optional[str] = None, - test_filename: Optional[str] = None, - use_gpu: Optional[bool] = None, - devices: Optional[List["torch.device"]] = None, - batch_size: int = 10, - teacher_batch_size: Optional[int] = None, - n_epochs: int = 5, - learning_rate: float = 5e-5, - max_seq_len: Optional[int] = None, - warmup_proportion: float = 0.2, - dev_split: float = 0, - evaluate_every: int = 300, - save_dir: Optional[str] = None, - num_processes: Optional[int] = None, - use_amp: bool = False, - checkpoint_root_dir: Path = Path("model_checkpoints"), - checkpoint_every: Optional[int] = None, - checkpoints_to_keep: int = 3, - caching: bool = False, - cache_path: Path = Path("cache/data_silo"), - distillation_loss: Union[str, Callable[["torch.Tensor", "torch.Tensor"], "torch.Tensor"]] = "mse", - distillation_loss_weight: float = 0.5, - temperature: float = 1.0, - processor: Optional["Processor"] = None, - grad_acc_steps: int = 1, - early_stopping: Optional["EarlyStopping"] = None, - ): - """ - The first stage of distillation finetuning as described in the TinyBERT paper: - https://arxiv.org/pdf/1909.10351.pdf - **Example** - ```python - student = FARMReader(model_name_or_path="prajjwal1/bert-medium") - teacher = FARMReader(model_name_or_path="huawei-noah/TinyBERT_General_6L_768D") - student.distil_intermediate_layers_from(teacher, data_dir="squad2", train_filename="train.json", test_filename="dev.json", - learning_rate=3e-5, distillation_loss_weight=1.0, temperature=5) - ``` - - Checkpoints can be stored via setting `checkpoint_every` to a custom number of steps. - If any checkpoints are stored, a subsequent run of train() will resume training from the latest available checkpoint. - - :param teacher_model: Model whose logits will be used to improve accuracy - :param data_dir: Path to directory containing your training data in SQuAD style - :param train_filename: Filename of training data. To best follow the original paper, this should be an augmented version of the training data created using the augment_squad.py script - :param dev_filename: Filename of dev / eval data - :param test_filename: Filename of test data - :param dev_split: Instead of specifying a dev_filename, you can also specify a ratio (e.g. 0.1) here - that gets split off from training data for eval. - :param use_gpu: Whether to use GPU (if available) - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - :param batch_size: Number of samples the student model receives in one batch for training - :param teacher_batch_size: Number of samples the teacher model receives in one batch for distillation. - :param n_epochs: Number of iterations on the whole training data set - :param learning_rate: Learning rate of the optimizer - :param max_seq_len: Maximum text length (in tokens). Everything longer gets cut down. - :param warmup_proportion: Proportion of training steps until maximum learning rate is reached. - Until that point LR is increasing linearly. After that it's decreasing again linearly. - Options for different schedules are available in FARM. - :param evaluate_every: Evaluate the model every X steps on the hold-out eval dataset - :param save_dir: Path to store the final model - :param num_processes: The number of processes for `multiprocessing.Pool` during preprocessing. - Set to value of 1 to disable multiprocessing. When set to 1, you cannot split away a dev set from train set. - Set to None to use all CPU cores minus one. - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param checkpoint_root_dir: the Path of directory where all train checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoint_every: save a train checkpoint after this many steps of training. - :param checkpoints_to_keep: maximum number of train checkpoints to save. - :param caching: whether or not to use caching for preprocessed dataset and teacher logits - :param cache_path: Path to cache the preprocessed dataset and teacher logits - :param distillation_loss: Specifies how teacher and model logits should be compared. Can either be a string ("mse" for mean squared error or "kl_div" for kl divergence loss) or a callable loss function (needs to have named parameters student_logits and teacher_logits) - :param distillation_loss_weight: The weight of the distillation loss. A higher weight means the teacher outputs are more important. - :param temperature: The temperature for distillation. A higher temperature will result in less certainty of teacher outputs. A lower temperature means more certainty. A temperature of 1.0 does not change the certainty of the model. - :param processor: The processor to use for preprocessing. If None, the default SquadProcessor is used. - :param grad_acc_steps: The number of steps to accumulate gradients for before performing a backward pass. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - :return: None - """ - send_event( - event_name="Training", - event_properties={"class": self.__class__.__name__, "function_name": "distil_intermediate_layers_from"}, - ) - return self._training_procedure( - data_dir=data_dir, - train_filename=train_filename, - dev_filename=dev_filename, - test_filename=test_filename, - use_gpu=use_gpu, - devices=devices, - batch_size=batch_size, - n_epochs=n_epochs, - learning_rate=learning_rate, - max_seq_len=max_seq_len, - warmup_proportion=warmup_proportion, - dev_split=dev_split, - evaluate_every=evaluate_every, - save_dir=save_dir, - num_processes=num_processes, - use_amp=use_amp, - checkpoint_root_dir=checkpoint_root_dir, - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - teacher_model=teacher_model, - teacher_batch_size=teacher_batch_size, - caching=caching, - cache_path=cache_path, - distillation_loss=distillation_loss, - distillation_loss_weight=distillation_loss_weight, - temperature=temperature, - tinybert=True, - processor=processor, - grad_acc_steps=grad_acc_steps, - early_stopping=early_stopping, - distributed=False, - ) - - def update_parameters( - self, - context_window_size: Optional[int] = None, - no_ans_boost: Optional[float] = None, - return_no_answer: Optional[bool] = None, - max_seq_len: Optional[int] = None, - doc_stride: Optional[int] = None, - ): - """ - Hot update parameters of a loaded Reader. It may not to be safe when processing concurrent requests. - """ - if no_ans_boost is not None: - self.inferencer.model.prediction_heads[0].no_ans_boost = no_ans_boost - if return_no_answer is not None: - self.return_no_answers = return_no_answer - if doc_stride is not None: - self.inferencer.processor.doc_stride = doc_stride - if context_window_size is not None: - self.inferencer.model.prediction_heads[0].context_window_size = context_window_size - if max_seq_len is not None: - self.inferencer.processor.max_seq_len = max_seq_len - self.max_seq_len = max_seq_len - - def save(self, directory: Path): - """ - Saves the Reader model so that it can be reused at a later point in time. - - :param directory: Directory where the Reader model should be saved - """ - logger.info("Saving reader model to %s", directory) - self.inferencer.model.save(directory) - self.inferencer.processor.save(directory) - - def save_to_remote( - self, repo_id: str, private: bool = False, commit_message: str = "Add new model to Hugging Face." - ): - """ - Saves the Reader model to Hugging Face Model Hub with the given model_name. For this to work: - - Be logged in to Hugging Face on your machine via transformers-cli - - Have git lfs installed (https://packagecloud.io/github/git-lfs/install), you can test it by git lfs --version - - :param repo_id: A namespace (user or an organization) and a repo name separated by a '/' of the model you want to save to Hugging Face - :param private: Set to true to make the model repository private - :param commit_message: Commit message while saving to Hugging Face - """ - # Note: This function was inspired by the save_to_hub function in the sentence-transformers repo (https://github.com/UKPLab/sentence-transformers/) - # Especially for git-lfs tracking. - - token = HfFolder.get_token() - if token is None: - raise ValueError( - "To save this reader model to Hugging Face, make sure you login to the hub on this computer by typing `transformers-cli login`." - ) - - repo_url = create_repo(token=token, repo_id=repo_id, private=private, repo_type=None, exist_ok=True) - - transformer_models = self.inferencer.model.convert_to_transformers() - - with tempfile.TemporaryDirectory() as tmp_dir: - repo = Repository(tmp_dir, clone_from=repo_url) - - self.inferencer.processor.tokenizer.save_pretrained(tmp_dir) - - # convert_to_transformers (above) creates one model per prediction head. - # As the FarmReader models only have one head (QA) we go with this. - transformer_models[0].save_pretrained(tmp_dir) - - large_files = [] - for root, _, files in os.walk(tmp_dir): - for filename in files: - file_path = os.path.join(root, filename) - rel_path = os.path.relpath(file_path, tmp_dir) - - if os.path.getsize(file_path) > (5 * 1024 * 1024): - large_files.append(rel_path) - - if len(large_files) > 0: - logger.info("Track files with git lfs: %s", ", ".join(large_files)) - repo.lfs_track(large_files) - - logger.info("Push model to the hub. This might take a while") - commit_url = repo.push_to_hub(commit_message=commit_message) - - return commit_url - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ): - """ - Use loaded QA model to find answers for the queries in the Documents. - - - If you provide a list containing a single query... - - - ... and a single list of Documents, the query will be applied to each Document individually. - - ... and a list of lists of Documents, the query will be applied to each list of Documents and the Answers - will be aggregated per Document list. - - - If you provide a list of multiple queries... - - - ... and a single list of Documents, each query will be applied to each Document individually. - - ... and a list of lists of Documents, each query will be applied to its corresponding list of Documents - and the Answers will be aggregated per query-Document pair. - - :param queries: Single query or list of queries. - :param documents: Related documents (e.g. coming from a retriever) that the answer shall be conditioned on. - Can be a single list of Documents or a list of lists of Documents. - :param top_k: Number of returned answers per query. - :param batch_size: Number of query-document pairs to be processed at a time. - """ - if top_k is None: - top_k = self.top_k - - inputs, number_of_docs, single_doc_list = self._preprocess_batch_queries_and_docs( - queries=queries, documents=documents - ) - - if batch_size is not None: - self.inferencer.batch_size = batch_size - # Make predictions on all document-query pairs - predictions = [] - for input_batch in get_batches_from_generator(inputs, self.preprocessing_batch_size): - cur_predictions = self.inferencer.inference_from_objects( - objects=input_batch, return_json=False, multiprocessing_chunksize=10 - ) - predictions.extend(cur_predictions) - - # Group predictions together - grouped_predictions = [] - left_idx = 0 - for number in number_of_docs: - right_idx = left_idx + number - grouped_predictions.append(predictions[left_idx:right_idx]) - left_idx = right_idx - - results: Dict = {"queries": queries, "answers": [], "no_ans_gaps": []} - for group in grouped_predictions: - answers, max_no_ans_gap = self._extract_answers_of_predictions(group, top_k) - results["answers"].append(answers) - results["no_ans_gaps"].append(max_no_ans_gap) - - # Group answers by question in case of multiple queries and single doc list - if single_doc_list and len(queries) > 1: - answers_per_query = int(len(results["answers"]) / len(queries)) - answers = [] - for i in range(0, len(results["answers"]), answers_per_query): - answer_group = results["answers"][i : i + answers_per_query] - answers.append(answer_group) - results["answers"] = answers - - return results - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None): - """ - Use loaded QA model to find answers for a query in the supplied list of Document. - - Returns dictionaries containing answers sorted by (desc.) score. - Example: - - ```python - { - 'query': 'Who is the father of Arya Stark?', - 'answers':[Answer( - 'answer': 'Eddard,', - 'context': "She travels with her father, Eddard, to King's Landing when he is", - 'score': 0.9787139466668613, - 'offsets_in_document': [Span(start=29, end=35], - 'offsets_in_context': [Span(start=347, end=353], - 'document_id': '88d1ed769d003939d3a0d28034464ab2' - ),... - ] - } - ``` - - :param query: Query string - :param documents: List of Document in which to search for the answer - :param top_k: The maximum number of answers to return - :return: Dict containing query and answers - """ - if top_k is None: - top_k = self.top_k - # convert input to FARM format - inputs = [] - for doc in documents: - cur = QAInput(doc_text=doc.content, questions=Question(text=query, uid=doc.id)) - inputs.append(cur) - - # get answers from QA model - # TODO: Need fix in FARM's `to_dict` function of `QAInput` class - predictions = [] - for input_batch in get_batches_from_generator(inputs, self.preprocessing_batch_size): - cur_predictions = self.inferencer.inference_from_objects( - objects=input_batch, return_json=False, multiprocessing_chunksize=1 - ) - predictions.extend(cur_predictions) - # Deduplicate same answers resulting from Document split overlap - predictions = self._deduplicate_predictions(predictions, documents) - # assemble answers from all the different documents & format them. - answers, max_no_ans_gap = self._extract_answers_of_predictions(predictions, top_k) - # TODO: potentially simplify return here to List[Answer] and handle no_ans_gap differently - result = {"query": query, "no_ans_gap": max_no_ans_gap, "answers": answers} - - return result - - def eval_on_file( - self, - data_dir: Union[Path, str], - test_filename: str, - device: Optional[Union[str, "torch.device"]] = None, - calibrate_conf_scores: bool = False, - ): - """ - Performs evaluation on a SQuAD-formatted file. - Returns a dict containing the following metrics: - - "EM": exact match score - - "f1": F1-Score - - "top_n_accuracy": Proportion of predicted answers that overlap with correct answer - - :param data_dir: The directory in which the test set can be found - :param test_filename: The name of the file containing the test data in SQuAD format. - :param device: The device on which the tensors should be processed. - Choose from torch.device("cpu") and torch.device("cuda") (or simply "cpu" or "cuda") - or use the Reader's device by default. - :param calibrate_conf_scores: Whether to calibrate the temperature for scaling of the confidence scores. - """ - logger.warning( - "FARMReader.eval_on_file() uses a slightly different evaluation approach than `Pipeline.eval()`:\n" - "- instead of giving you full control over which labels to use, this method always returns three types of metrics: combined (no suffix), text_answer ('_text_answer' suffix) and no_answer ('_no_answer' suffix) metrics.\n" - "- instead of comparing predictions with labels on a string level, this method compares them on a token-ID level. This makes it unable to do any string normalization (e.g. normalize whitespaces) beforehand.\n" - "Hence, results might slightly differ from those of `Pipeline.eval()`\n." - "If you are just about starting to evaluate your model consider using `Pipeline.eval()` instead." - ) - send_event( - event_name="Evaluation", - event_properties={"class": self.__class__.__name__, "function_name": "eval_on_file"}, - ) - if device is None: - device = self.devices[0] - else: - device = torch.device(device) - - eval_processor = SquadProcessor( - tokenizer=self.inferencer.processor.tokenizer, - max_seq_len=self.inferencer.processor.max_seq_len, - label_list=self.inferencer.processor.tasks["question_answering"]["label_list"], - metric=self.inferencer.processor.tasks["question_answering"]["metric"], - train_filename=None, - dev_filename=None, - dev_split=0, - test_filename=test_filename, - data_dir=Path(data_dir), - ) - - data_silo = DataSilo(processor=eval_processor, batch_size=self.inferencer.batch_size, distributed=False) - data_loader = data_silo.get_data_loader("test") - - evaluator = Evaluator(data_loader=data_loader, tasks=eval_processor.tasks, device=device) - - eval_results = evaluator.eval( - self.inferencer.model, - calibrate_conf_scores=calibrate_conf_scores, - use_confidence_scores_for_ranking=self.use_confidence_scores, - ) - results = { - "EM": eval_results[0]["EM"] * 100, - "f1": eval_results[0]["f1"] * 100, - "top_n_accuracy": eval_results[0]["top_n_accuracy"] * 100, - "top_n": self.inferencer.model.prediction_heads[0].n_best, - "EM_text_answer": eval_results[0]["EM_text_answer"] * 100, - "f1_text_answer": eval_results[0]["f1_text_answer"] * 100, - "top_n_accuracy_text_answer": eval_results[0]["top_n_accuracy_text_answer"] * 100, - "top_n_EM_text_answer": eval_results[0]["top_n_EM_text_answer"] * 100, - "top_n_f1_text_answer": eval_results[0]["top_n_f1_text_answer"] * 100, - "Total_text_answer": eval_results[0]["Total_text_answer"], - "EM_no_answer": eval_results[0]["EM_no_answer"] * 100, - "f1_no_answer": eval_results[0]["f1_no_answer"] * 100, - "top_n_accuracy_no_answer": eval_results[0]["top_n_accuracy_no_answer"] * 100, - "Total_no_answer": eval_results[0]["Total_no_answer"], - } - return results - - def eval( - self, - document_store: BaseDocumentStore, - device: Optional[Union[str, "torch.device"]] = None, - label_index: str = "label", - doc_index: str = "eval_document", - label_origin: str = "gold-label", - calibrate_conf_scores: bool = False, - ): - """ - Performs evaluation on evaluation documents in the DocumentStore. - Returns a dict containing the following metrics: - - "EM": Proportion of exact matches of predicted answers with their corresponding correct answers - - "f1": Average overlap between predicted answers and their corresponding correct answers - - "top_n_accuracy": Proportion of predicted answers that overlap with correct answer - - :param document_store: DocumentStore containing the evaluation documents - :param device: The device on which the tensors should be processed. - Choose from torch.device("cpu") and torch.device("cuda") (or simply "cpu" or "cuda") - or use the Reader's device by default. - :param label_index: Index/Table name where labeled questions are stored - :param doc_index: Index/Table name where documents that are used for evaluation are stored - :param label_origin: Field name where the gold labels are stored - :param calibrate_conf_scores: Whether to calibrate the temperature for scaling of the confidence scores. - """ - logger.warning( - "FARMReader.eval() uses a slightly different evaluation approach than `Pipeline.eval()`:\n" - "- instead of giving you full control over which labels to use, this method always returns three types of metrics: combined (no suffix), text_answer ('_text_answer' suffix) and no_answer ('_no_answer' suffix) metrics.\n" - "- instead of comparing predictions with labels on a string level, this method compares them on a token-ID level. This makes it unable to do any string normalization (e.g. normalize whitespaces) beforehand.\n" - "Hence, results might slightly differ from those of `Pipeline.eval()`\n." - "If you are just about starting to evaluate your model consider using `Pipeline.eval()` instead." - ) - send_event( - event_name="Evaluation", event_properties={"class": self.__class__.__name__, "function_name": "eval"} - ) - if device is None: - device = self.devices[0] - else: - device = torch.device(device) - - if self.top_k_per_candidate != 4: - logger.info( - "Performing Evaluation using top_k_per_candidate = %s \n" - "and consequently, QuestionAnsweringPredictionHead.n_best = {self.top_k_per_candidate + 1}. \n" - "This deviates from FARM's default where QuestionAnsweringPredictionHead.n_best = 5", - self.top_k_per_candidate, - ) - - # extract all questions for evaluation - filters: Dict = {"origin": [label_origin]} - - labels = document_store.get_all_labels(index=label_index, filters=filters) - - # Aggregate all answer labels per question - aggregated_per_doc = defaultdict(list) - for label in labels: - if not label.document.id: - logger.error("Label does not contain a document id") - continue - if label.document.content_type == "table": - logger.warning( - "Label with a table document is not compatible with the FARMReader. Skipping label with id %s.", - label.id, - ) - continue - aggregated_per_doc[label.document.id].append(label) - - # Create squad style dicts - d: Dict[str, Any] = {} - all_doc_ids = [x.id for x in document_store.get_all_documents(doc_index)] - for doc_id in all_doc_ids: - doc = document_store.get_document_by_id(doc_id, index=doc_index) - if not doc: - logger.error("Document with the ID '%s' is not present in the document store.", doc_id) - continue - d[str(doc_id)] = {"context": doc.content} - # get all questions / answers - # TODO check if we can simplify this by using MultiLabel - aggregated_per_question: Dict[tuple, Any] = defaultdict(list) - - if doc_id in aggregated_per_doc: - for label in aggregated_per_doc[doc_id]: - aggregation_key = (doc_id, label.query) - if label.answer is None: - logger.error("Label.answer was None, but Answer object was expected: %s", label) - continue - if label.answer.offsets_in_document is None: - logger.error( - "Label.answer.offsets_in_document was None, but Span object was expected: %s ", label - ) - continue - # add to existing answers - # TODO offsets (whole block) - if aggregation_key in aggregated_per_question.keys(): - if label.no_answer: - continue - - # Hack to fix problem where duplicate questions are merged by doc_store processing creating a QA example with 8 annotations > 6 annotation max - if len(aggregated_per_question[aggregation_key]["answers"]) >= 6: - logger.warning( - "Answers in this sample are being dropped because it has more than 6 answers. " - "(doc_id: %s, question: %s, label_id: %s)", - doc_id, - label.query, - label.id, - ) - continue - aggregated_per_question[aggregation_key]["answers"].append( - {"text": label.answer.answer, "answer_start": label.answer.offsets_in_document[0].start} # type: ignore [union-attr] - ) - aggregated_per_question[aggregation_key]["is_impossible"] = False - # create new one - else: - # We don't need to create an answer dict if is_impossible / no_answer - if label.no_answer is True: - aggregated_per_question[aggregation_key] = { - "id": str(hash(str(doc_id) + label.query)), - "question": label.query, - "answers": [], - "is_impossible": True, - } - else: - aggregated_per_question[aggregation_key] = { - "id": str(hash(str(doc_id) + label.query)), - "question": label.query, - "answers": [ - { - "text": label.answer.answer, - "answer_start": label.answer.offsets_in_document[0].start, # type: ignore [union-attr] - } - ], - "is_impossible": False, - } - - # Get rid of the question key again (after we aggregated we don't need it anymore) - d[str(doc_id)]["qas"] = list(aggregated_per_question.values()) - - # Convert input format for FARM - farm_input = list(d.values()) - n_queries = len([y for x in farm_input for y in x["qas"]]) - - # Create DataLoader that can be passed to the Evaluator - tic = perf_counter() - indices = range(len(farm_input)) - dataset, tensor_names, _ = self.inferencer.processor.dataset_from_dicts(farm_input, indices=indices) - data_loader = NamedDataLoader(dataset=dataset, batch_size=self.inferencer.batch_size, tensor_names=tensor_names) - - evaluator = Evaluator(data_loader=data_loader, tasks=self.inferencer.processor.tasks, device=device) - - eval_results = evaluator.eval( - self.inferencer.model, - calibrate_conf_scores=calibrate_conf_scores, - use_confidence_scores_for_ranking=self.use_confidence_scores, - ) - toc = perf_counter() - reader_time = toc - tic - results = { - "EM": eval_results[0]["EM"] * 100, - "f1": eval_results[0]["f1"] * 100, - "top_n_accuracy": eval_results[0]["top_n_accuracy"] * 100, - "top_n": self.inferencer.model.prediction_heads[0].n_best, - "reader_time": reader_time, - "seconds_per_query": reader_time / n_queries, - "EM_text_answer": eval_results[0]["EM_text_answer"] * 100, - "f1_text_answer": eval_results[0]["f1_text_answer"] * 100, - "top_n_accuracy_text_answer": eval_results[0]["top_n_accuracy_text_answer"] * 100, - "top_n_EM_text_answer": eval_results[0]["top_n_EM_text_answer"] * 100, - "top_n_f1_text_answer": eval_results[0]["top_n_f1_text_answer"] * 100, - "Total_text_answer": eval_results[0]["Total_text_answer"], - "EM_no_answer": eval_results[0]["EM_no_answer"] * 100, - "f1_no_answer": eval_results[0]["f1_no_answer"] * 100, - "top_n_accuracy_no_answer": eval_results[0]["top_n_accuracy_no_answer"] * 100, - "Total_no_answer": eval_results[0]["Total_no_answer"], - } - return results - - def _extract_answers_of_predictions(self, predictions: List["QAPred"], top_k: Optional[int] = None): - # Assemble answers from all the different documents and format them. - # For the 'no answer' option, we collect all no_ans_gaps and decide how likely - # a no answer is based on all no_ans_gaps values across all documents - answers: List[Answer] = [] - no_ans_gaps = [] - best_score_answer = 0 - - for pred in predictions: - answers_per_document = [] - no_ans_gaps.append(pred.no_answer_gap) - for ans in pred.prediction: - # skip 'no answers' here - if self._check_no_answer(ans): - pass - else: - cur = Answer( - answer=ans.answer, - type="extractive", - score=ans.confidence if self.use_confidence_scores else ans.score, - context=ans.context_window, - document_ids=[pred.id], - offsets_in_context=[ - Span( - start=ans.offset_answer_start - ans.offset_context_window_start, - end=ans.offset_answer_end - ans.offset_context_window_start, - ) - ], - offsets_in_document=[Span(start=ans.offset_answer_start, end=ans.offset_answer_end)], - ) - - answers_per_document.append(cur) - - if ans.score > best_score_answer: - best_score_answer = ans.score - - # Only take n best candidates. Answers coming back from FARM are sorted with decreasing relevance - answers += answers_per_document[: self.top_k_per_candidate] - - # calculate the score for predicting 'no answer', relative to our best positive answer score - no_ans_prediction, max_no_ans_gap = self._calc_no_answer( - no_ans_gaps, best_score_answer, self.use_confidence_scores - ) - if self.return_no_answers: - answers.append(no_ans_prediction) - - # sort answers by score (descending) and select top-k - answers = sorted(answers, reverse=True) - answers = answers[:top_k] - - # apply confidence based filtering if enabled - if self.confidence_threshold is not None: - answers = [ans for ans in answers if ans.score is not None and ans.score >= self.confidence_threshold] - - return answers, max_no_ans_gap - - def _preprocess_batch_queries_and_docs( - self, queries: List[str], documents: Union[List[Document], List[List[Document]]] - ) -> Tuple[List["QAInput"], List[int], bool]: - # Convert input to FARM format - inputs = [] - number_of_docs = [] - single_doc_list = False - - # Docs case 1: single list of Documents -> apply each query to all Documents - if len(documents) > 0 and isinstance(documents[0], Document): - single_doc_list = True - for query in queries: - for doc in documents: - number_of_docs.append(1) - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - cur = QAInput(doc_text=doc.content, questions=Question(text=query, uid=doc.id)) - inputs.append(cur) - - # Docs case 2: list of lists of Documents -> apply each query to corresponding list of Documents, if queries - # contains only one query, apply it to each list of Documents - elif len(documents) > 0 and isinstance(documents[0], list): - single_doc_list = False - if len(queries) == 1: - queries = queries * len(documents) - if len(queries) != len(documents): - raise HaystackError("Number of queries must be equal to number of provided Document lists.") - for query, cur_docs in zip(queries, documents): - if not isinstance(cur_docs, list): - raise HaystackError(f"cur_docs was of type {type(cur_docs)}, but expected a list of Documents.") - number_of_docs.append(len(cur_docs)) - for doc in cur_docs: - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - cur = QAInput(doc_text=doc.content, questions=Question(text=query, uid=doc.id)) - inputs.append(cur) - - return inputs, number_of_docs, single_doc_list - - def _deduplicate_predictions(self, predictions: List["QAPred"], documents: List[Document]) -> List["QAPred"]: - overlapping_docs = self._identify_overlapping_docs(documents) - if not overlapping_docs: - return predictions - - preds_per_doc = {pred.id: pred for pred in predictions} - for pred in predictions: - # Check if current Document overlaps with Documents of other preds and continue if not - if pred.id not in overlapping_docs: - continue - - relevant_overlaps = overlapping_docs[pred.id] - for ans_idx in reversed(range(len(pred.prediction))): - ans = pred.prediction[ans_idx] - if ans.answer_type != "span": - continue - - for overlap in relevant_overlaps: - # Check if answer offsets are within the overlap - if not self._qa_cand_in_overlap(ans, overlap): - continue - - # Check if predictions from overlapping Document are within the overlap - overlapping_doc_pred = preds_per_doc[overlap["doc_id"]] - cur_doc_overlap = [ol for ol in overlapping_docs[overlap["doc_id"]] if ol["doc_id"] == pred.id][0] - for pot_dupl_ans_idx in reversed(range(len(overlapping_doc_pred.prediction))): - pot_dupl_ans = overlapping_doc_pred.prediction[pot_dupl_ans_idx] - if pot_dupl_ans.answer_type != "span": - continue - if not self._qa_cand_in_overlap(pot_dupl_ans, cur_doc_overlap): - continue - - # Check if ans and pot_dupl_ans are duplicates - if self._is_duplicate_answer(ans, overlap, pot_dupl_ans, cur_doc_overlap): - # Discard the duplicate with lower score - if ans.confidence < pot_dupl_ans.confidence: - pred.prediction.pop(ans_idx) - else: - overlapping_doc_pred.prediction.pop(pot_dupl_ans_idx) - - return predictions - - @staticmethod - def _is_duplicate_answer( - ans: "QACandidate", ans_overlap: Dict, pot_dupl_ans: "QACandidate", pot_dupl_ans_overlap: Dict - ) -> bool: - answer_start_in_overlap = ans.offset_answer_start - ans_overlap["range"][0] - answer_end_in_overlap = ans.offset_answer_end - ans_overlap["range"][0] - - pot_dupl_ans_start_in_overlap = pot_dupl_ans.offset_answer_start - pot_dupl_ans_overlap["range"][0] - pot_dupl_ans_end_in_overlap = pot_dupl_ans.offset_answer_end - pot_dupl_ans_overlap["range"][0] - - return ( - answer_start_in_overlap == pot_dupl_ans_start_in_overlap - and answer_end_in_overlap == pot_dupl_ans_end_in_overlap - ) - - @staticmethod - def _qa_cand_in_overlap(cand: "QACandidate", overlap: Dict) -> bool: - if cand.offset_answer_start < overlap["range"][0] or cand.offset_answer_end > overlap["range"][1]: - return False - return True - - @staticmethod - def _identify_overlapping_docs(documents: List[Document]) -> Dict[str, List]: - docs_by_ids = {doc.id: doc for doc in documents} - overlapping_docs = {} - for doc in documents: - if "_split_overlap" not in doc.meta: - continue - current_overlaps = [overlap for overlap in doc.meta["_split_overlap"] if overlap["doc_id"] in docs_by_ids] - if current_overlaps: - overlapping_docs[doc.id] = current_overlaps - - return overlapping_docs - - def calibrate_confidence_scores( - self, - document_store: BaseDocumentStore, - device: Optional[Union[str, "torch.device"]] = None, - label_index: str = "label", - doc_index: str = "eval_document", - label_origin: str = "gold_label", - ): - """ - Calibrates confidence scores on evaluation documents in the DocumentStore. - - :param document_store: DocumentStore containing the evaluation documents - :param device: The device on which the tensors should be processed. - Choose from torch.device("cpu") and torch.device("cuda") (or simply "cpu" or "cuda") - or use the Reader's device by default. - :param label_index: Index/Table name where labeled questions are stored - :param doc_index: Index/Table name where documents that are used for evaluation are stored - :param label_origin: Field name where the gold labels are stored - """ - if device is None: - device = self.devices[0] - self.eval( - document_store=document_store, - device=device, - label_index=label_index, - doc_index=doc_index, - label_origin=label_origin, - calibrate_conf_scores=True, - ) - - @staticmethod - def _check_no_answer(c: "QACandidate"): - # check for correct value in "answer" - if c.offset_answer_start == 0 and c.offset_answer_end == 0 and c.answer != "no_answer": - logger.error("Invalid 'no_answer': Got a prediction for position 0, but answer string is not 'no_answer'") - return c.answer == "no_answer" - - def predict_on_texts(self, question: str, texts: List[str], top_k: Optional[int] = None): - """ - Use loaded QA model to find answers for a question in the supplied list of Document. - Returns dictionaries containing answers sorted by (desc.) score. - Example: - - ```python - { - 'question': 'Who is the father of Arya Stark?', - 'answers':[ - {'answer': 'Eddard,', - 'context': " She travels with her father, Eddard, to King's Landing when he is ", - 'offset_answer_start': 147, - 'offset_answer_end': 154, - 'score': 0.9787139466668613, - 'document_id': '1337' - },... - ] - } - ``` - - :param question: Question string - :param texts: A list of Document texts as a string type - :param top_k: The maximum number of answers to return - :return: Dict containing question and answers - """ - documents = [] - for text in texts: - documents.append(Document(content=text)) - predictions = self.predict(question, documents, top_k) - return predictions - - @classmethod - def convert_to_onnx( - cls, - model_name: str, - output_path: Path, - convert_to_float16: bool = False, - quantize: bool = False, - task_type: str = "question_answering", - opset_version: int = 11, - ): - """ - Convert a PyTorch BERT model to ONNX format and write to ./onnx-export dir. The converted ONNX model - can be loaded with in the `FARMReader` using the export path as `model_name_or_path` param. - - Usage: - - `from haystack.reader.farm import FARMReader - from pathlib import Path - onnx_model_path = Path("roberta-onnx-model") - FARMReader.convert_to_onnx(model_name="deepset/bert-base-cased-squad2", output_path=onnx_model_path) - reader = FARMReader(onnx_model_path)` - - :param model_name: transformers model name - :param output_path: Path to output the converted model - :param convert_to_float16: Many models use float32 precision by default. With the half precision of float16, - inference is faster on Nvidia GPUs with Tensor core like T4 or V100. On older GPUs, - float32 could still be be more performant. - :param quantize: convert floating point number to integers - :param task_type: Type of task for the model. Available options: "question_answering" or "embeddings". - :param opset_version: ONNX opset version - """ - AdaptiveModel.convert_to_onnx( - model_name=model_name, - output_path=output_path, - task_type=task_type, - convert_to_float16=convert_to_float16, - quantize=quantize, - opset_version=opset_version, - ) diff --git a/haystack/nodes/reader/table.py b/haystack/nodes/reader/table.py deleted file mode 100644 index ddbd2720a7..0000000000 --- a/haystack/nodes/reader/table.py +++ /dev/null @@ -1,947 +0,0 @@ -from typing import List, Optional, Tuple, Dict, Union, Literal - -import logging -import itertools -from statistics import mean -import numpy as np -import pandas as pd -from quantulum3 import parser - -from haystack.errors import HaystackError -from haystack.schema import Document, Answer, TableCell, Span -from haystack.nodes.reader.base import BaseReader -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -TableQuestionAnsweringPipeline = object -TapasPreTrainedModel = object -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import ( # type: ignore - TapasTokenizer, - TapasForQuestionAnswering, - AutoTokenizer, - AutoModelForSequenceClassification, - BatchEncoding, - TapasModel, - TapasConfig, - TableQuestionAnsweringPipeline, - ) - from transformers.models.tapas.modeling_tapas import TapasPreTrainedModel # type: ignore - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class TableReader(BaseReader): - """ - Transformer-based model for extractive Question Answering on Tables with TaPas - using the HuggingFace's transformers framework (https://github.com/huggingface/transformers). - With this reader, you can directly get predictions via predict() - - Example: - ```python - from haystack import Document - from haystack.nodes import TableReader - import pandas as pd - - table_reader = TableReader(model_name_or_path="google/tapas-base-finetuned-wtq") - data = { - "actors": ["brad pitt", "leonardo di caprio", "george clooney"], - "age": ["57", "46", "60"], - "number of movies": ["87", "53", "69"], - "date of birth": ["7 february 1967", "10 june 1996", "28 november 1967"], - } - table = pd.DataFrame(data) - document = Document(content=table, content_type="table") - query = "When was DiCaprio born?" - prediction = table_reader.predict(query=query, documents=[document]) - answer = prediction["answers"][0].answer # "10 june 1996" - ``` - """ - - def __init__( - self, - model_name_or_path: str = "google/tapas-base-finetuned-wtq", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - use_gpu: bool = True, - top_k: int = 10, - top_k_per_candidate: int = 3, - return_no_answer: bool = False, - max_seq_len: int = 256, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Load a TableQA model from Transformers. - Available models include: - - - ``'google/tapas-base-finetuned-wtq`'`` - - ``'google/tapas-base-finetuned-wikisql-supervised``' - - ``'deepset/tapas-large-nq-hn-reader'`` - - ``'deepset/tapas-large-nq-reader'`` - - See https://huggingface.co/models?pipeline_tag=table-question-answering - for full list of available TableQA models. - - The nq-reader models are able to provide confidence scores, but cannot handle questions that need aggregation - over multiple cells. The returned answers are sorted first by a general table score and then by answer span - scores. - All the other models can handle aggregation questions, but don't provide reasonable confidence scores. - - :param model_name_or_path: Directory of a saved model or the name of a public model e.g. - See https://huggingface.co/models?pipeline_tag=table-question-answering for full list of available models. - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, - or commit hash. - :param tokenizer: Name of the tokenizer (usually the same as model) - :param use_gpu: Whether to use GPU or CPU. Falls back on CPU if no GPU is available. - :param top_k: The maximum number of answers to return. - :param top_k_per_candidate: How many answers to extract for each candidate table that is coming from - the retriever. - :param return_no_answer: Whether to include no_answer predictions in the results. - This option only has an effect when using the deepset/tapas-large-nq-hn-reader and deepset/tapas-large-nq-reader models. - :param max_seq_len: Max sequence length of one input table for the model. If the number of tokens of - query + table exceed max_seq_len, the table will be truncated by removing rows until the - input size fits the model. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - """ - torch_and_transformers_import.check() - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - config = TapasConfig.from_pretrained(model_name_or_path, use_auth_token=use_auth_token) - self.table_encoder: Union[_TapasEncoder, _TapasScoredEncoder] - if config.architectures[0] == "TapasForQuestionAnswering": - self.table_encoder = _TapasEncoder( - device=self.devices[0], - model_name_or_path=model_name_or_path, - model_version=model_version, - tokenizer=tokenizer, - max_seq_len=max_seq_len, - use_auth_token=use_auth_token, - ) - elif config.architectures[0] == "TapasForScoredQA": - self.table_encoder = _TapasScoredEncoder( - device=self.devices[0], - model_name_or_path=model_name_or_path, - model_version=model_version, - tokenizer=tokenizer, - top_k_per_candidate=top_k_per_candidate, - return_no_answer=return_no_answer, - max_seq_len=max_seq_len, - use_auth_token=use_auth_token, - ) - else: - logger.error( - "Unrecognized model architecture %s. Only the architectures TapasForQuestionAnswering and TapasForScoredQA are supported", - config.architectures[0], - ) - self.table_encoder.model.to(str(self.devices[0])) - - self.top_k = top_k - self.top_k_per_candidate = top_k_per_candidate - self.max_seq_len = max_seq_len - self.return_no_answer = return_no_answer - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None) -> Dict: - """ - Use loaded TableQA model to find answers for a query in the supplied list of Documents - of content_type ``'table'``. - - Returns dictionary containing query and list of Answer objects sorted by (desc.) score. - WARNING: The answer scores are not reliable, as they are always extremely high, even if - a question cannot be answered by a given table. - - :param query: Query string - :param documents: List of Document in which to search for the answer. Documents should be - of content_type ``'table'``. - :param top_k: The maximum number of answers to return - :return: Dict containing query and answers - """ - if top_k is None: - top_k = self.top_k - return self.table_encoder.predict(query=query, documents=documents, top_k=top_k) - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ): - """ - Use loaded TableQA model to find answers for the supplied queries in the supplied Documents - of content_type ``'table'``. - - Returns dictionary containing query and list of Answer objects sorted by (descending) score. - WARNING: The answer scores are not reliable, as they are always extremely high, even if - a question cannot be answered by a given table. - - - If you provide a list containing a single query... - - ... and a single list of Documents, the query will be applied to each Document individually. - - ... and a list of lists of Documents, the query will be applied to each list of Documents and the Answers - will be aggregated per Document list. - - - If you provide a list of multiple queries... - - ... and a single list of Documents, each query will be applied to each Document individually. - - ... and a list of lists of Documents, each query will be applied to its corresponding list of Documents - and the Answers will be aggregated per query-Document pair. - - :param queries: Single query string or list of queries. - :param documents: Single list of Documents or list of lists of Documents in which to search for the answers. - Documents should be of content_type ``'table'``. - :param top_k: The maximum number of answers to return per query. - :param batch_size: Not applicable. - """ - if top_k is None: - top_k = self.top_k - - single_doc_list = bool(len(documents) > 0 and isinstance(documents[0], Document)) - - inputs = _flatten_inputs(queries, documents) - results: Dict = self.table_encoder.predict_batch( - queries=inputs["queries"], documents=inputs["docs"], top_k=top_k - ) - - # Group answers by question in case of multiple queries and single doc list - if single_doc_list and len(queries) > 1: - num_docs_per_query = int(len(results["answers"]) / len(queries)) - answers = [] - for i in range(0, len(results["answers"]), num_docs_per_query): - answer_group = results["answers"][i : i + num_docs_per_query] - answers.append(answer_group) - results["answers"] = answers - - return results - - -class _TapasEncoder: - def __init__( - self, - device: "torch.device", - model_name_or_path: str = "google/tapas-base-finetuned-wtq", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - max_seq_len: int = 256, - use_auth_token: Optional[Union[str, bool]] = None, - ): - self.model = TapasForQuestionAnswering.from_pretrained( - model_name_or_path, revision=model_version, use_auth_token=use_auth_token - ) - if tokenizer is None: - self.tokenizer = TapasTokenizer.from_pretrained( - model_name_or_path, use_auth_token=use_auth_token, model_max_length=max_seq_len - ) - else: - self.tokenizer = TapasTokenizer.from_pretrained( - tokenizer, use_auth_token=use_auth_token, model_max_length=max_seq_len - ) - self.max_seq_len = max_seq_len - self.device = device - self.pipeline = _TableQuestionAnsweringPipeline( # type: ignore - task="table-question-answering", - model=self.model, - tokenizer=self.tokenizer, - framework="pt", - batch_size=1, # batch_size of 1 only works currently b/c of issue with HuggingFace pipeline logic and the return type of TableQuestionAnsweringPipeline._forward - device=self.device, - ) - - def predict(self, query: str, documents: List[Document], top_k: int) -> Dict: - table_documents = _check_documents(documents) - if len(table_documents) == 0: - return {"query": query, "answers": []} - - # Create list of all data points - pipeline_inputs = [] - for document in table_documents: - table: pd.DataFrame = document.content - pipeline_inputs.append({"query": query, "table": table.astype(str)}) - - # Run the pipeline - answers = self.pipeline(pipeline_inputs, sequential=False, padding=True, truncation=True) # type: ignore - - # Unpack batched answers - if isinstance(answers[0], list): - answers = list(itertools.chain.from_iterable(answers)) - for ans, doc in zip(answers, table_documents): - if ans is not None: - ans.document_ids = [doc.id] - - # Remove no_answers from the answers list - answers = [ans for ans in answers if ans is not None] - - answers = sorted(answers, reverse=True) - results = {"query": query, "answers": answers[:top_k]} - return results - - def predict_batch(self, queries: List[str], documents: List[List[Document]], top_k: int): - results: Dict = {"queries": queries, "answers": []} - for query, docs in zip(queries, documents): - preds = self.predict(query=query, documents=docs, top_k=top_k) - results["answers"].append(preds["answers"]) - return results - - -class _TableQuestionAnsweringPipeline(TableQuestionAnsweringPipeline): # pylint: disable=useless-object-inheritance - """Modified from transformers TableQuestionAnsweringPipeline.postprocess to return Haystack Answer objects.""" - - def _calculate_answer_score( - self, logits: "torch.Tensor", inputs: Dict, answer_coordinates: List[List[Tuple[int, int]]] - ) -> List[Optional[np.ndarray]]: - """Calculate the answer scores given the `logits`, `input`, and `answer_coordinates`.""" - token_probabilities = torch.sigmoid(logits) * inputs["attention_mask"] - - token_types = [ - "segment_ids", - "column_ids", - "row_ids", - "prev_labels", - "column_ranks", - "inv_column_ranks", - "numeric_relations", - ] - segment_ids = inputs["token_type_ids"][:, :, token_types.index("segment_ids")] - row_ids = inputs["token_type_ids"][:, :, token_types.index("row_ids")] - column_ids = inputs["token_type_ids"][:, :, token_types.index("column_ids")] - - batch_size = logits.shape[0] - answer_scores: List[Optional[np.ndarray]] = [] - for i in range(batch_size): - # It is possible that a list within answer_coordinates is empty. This happens if no answer cells are found - # for a single table so we set the score to None. - if len(answer_coordinates[i]) == 0: - answer_scores.append(None) - else: - cell_coords_to_prob = self.tokenizer._get_mean_cell_probs( # type: ignore - token_probabilities[i].tolist(), - segment_ids[i].tolist(), - row_ids[i].tolist(), - column_ids[i].tolist(), - ) - # _get_mean_cell_probs indexes cells by (col, row). DataFrames are, however, indexed by (row, col). - all_cell_probabilities = {(row, col): prob for (col, row), prob in cell_coords_to_prob.items()} - answer_cell_probabilities = [all_cell_probabilities[coord] for coord in answer_coordinates[i]] - if len(answer_cell_probabilities) == 0: - answer_scores.append(None) - else: - answer_scores.append(np.mean(answer_cell_probabilities)) - - return answer_scores - - @staticmethod - def _aggregate_answers(agg_operator: Literal["COUNT", "SUM", "AVERAGE"], answer_cells: List[str]) -> str: - if agg_operator == "COUNT": - return str(len(answer_cells)) - - # No aggregation needed as only one cell selected as answer_cells - if len(answer_cells) == 1: - return answer_cells[0] - # Return empty string if model did not select any cell as answer - if len(answer_cells) == 0: - return "" - - # Parse answer cells in order to aggregate numerical values - parsed_answer_cells = [parser.parse(cell) for cell in answer_cells] - # Check if all cells contain at least one numerical value and that all values share the same unit - try: - if all(parsed_answer_cells) and all( - cell[0].unit.name == parsed_answer_cells[0][0].unit.name for cell in parsed_answer_cells - ): - numerical_values = [cell[0].value for cell in parsed_answer_cells] - unit = parsed_answer_cells[0][0].unit.symbols[0] if parsed_answer_cells[0][0].unit.symbols else "" - - if agg_operator == "SUM": - answer_value = sum(numerical_values) - elif agg_operator == "AVERAGE": - answer_value = mean(numerical_values) - else: - raise ValueError("unknown aggregator") - - return f"{answer_value}{' ' + unit if unit else ''}" - - except ValueError as e: - if "unknown aggregator" in str(e): - pass - - # Not all selected answer cells contain a numerical value or answer cells don't share the same unit - return f"{agg_operator} > {', '.join(answer_cells)}" - - def postprocess(self, model_outputs): - inputs = model_outputs["model_inputs"] - table = model_outputs["table"] - string_table = table.astype(str) - outputs = model_outputs["outputs"] - if self.type == "tapas": - if self.aggregate: - logits, logits_agg = outputs[:2] - copy_logits = logits.clone() - predictions = self.tokenizer.convert_logits_to_predictions( - inputs, copy_logits, logits_agg, cell_classification_threshold=0.5 - ) - answer_coordinates_batch, agg_predictions = predictions - aggregators = {i: self.model.config.aggregation_labels[pred] for i, pred in enumerate(agg_predictions)} - else: - logits = outputs[0] - copy_logits = logits.clone() - predictions = self.tokenizer.convert_logits_to_predictions( - inputs, copy_logits, cell_classification_threshold=0.5 - ) - answer_coordinates_batch = predictions[0] - aggregators = {} - answer_scores = self._calculate_answer_score(logits, inputs, answer_coordinates_batch) - answers = [] - for index, ans_coordinates_per_table in enumerate(answer_coordinates_batch): - if len(ans_coordinates_per_table) > 0: - cells = [string_table.iat[coordinate] for coordinate in ans_coordinates_per_table] - aggregator = aggregators.get(index, "") # type: ignore - if aggregator == "NONE": - answer_str = ", ".join(cells) - else: - answer_str = self._aggregate_answers(aggregator, cells) - current_score = answer_scores[index] - answer_offsets = _calculate_answer_offsets(ans_coordinates_per_table) - answer = Answer( - answer=answer_str, - type="extractive", - score=current_score, - context=string_table, - offsets_in_document=answer_offsets, - offsets_in_context=answer_offsets, - meta={"aggregation_operator": aggregator, "answer_cells": cells}, - ) - answers.append(answer) - else: - # If there is no answer then we use None to keep track of it. - answers.append(None) - else: - raise NotImplementedError("Only TAPAS models are supported") - - return answers - - -class _TapasScoredEncoder: - def __init__( - self, - device: "torch.device", - model_name_or_path: str = "deepset/tapas-large-nq-hn-reader", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - top_k_per_candidate: int = 3, - return_no_answer: bool = False, - max_seq_len: int = 256, - use_auth_token: Optional[Union[str, bool]] = None, - ): - self.model = self._TapasForScoredQA.from_pretrained( # type: ignore - model_name_or_path, revision=model_version, use_auth_token=use_auth_token - ) - if tokenizer is None: - self.tokenizer = TapasTokenizer.from_pretrained(model_name_or_path, use_auth_token=use_auth_token) - else: - self.tokenizer = TapasTokenizer.from_pretrained(tokenizer, use_auth_token=use_auth_token) - self.max_seq_len = max_seq_len - self.device = device - self.top_k_per_candidate = top_k_per_candidate - self.return_no_answer = return_no_answer - - def _predict_tapas_scored(self, inputs: "BatchEncoding", document: Document) -> Tuple[List[Answer], float]: - orig_table: pd.DataFrame = document.content - string_table = orig_table.astype(str) - - # Forward pass through model - with torch.inference_mode(): - outputs = self.model.tapas(**inputs) - table_score = self.model.classifier(outputs.pooler_output) - - # Get general table score - table_score_softmax = torch.nn.functional.softmax(table_score, dim=1) - table_relevancy_prob = table_score_softmax[0][1].item() - no_answer_score = table_score_softmax[0][0].item() - - # Get possible answer spans - token_types = [ - "segment_ids", - "column_ids", - "row_ids", - "prev_labels", - "column_ranks", - "inv_column_ranks", - "numeric_relations", - ] - row_ids: List[int] = inputs.token_type_ids[:, :, token_types.index("row_ids")].tolist()[0] - column_ids: List[int] = inputs.token_type_ids[:, :, token_types.index("column_ids")].tolist()[0] - - possible_answer_spans: List[ - Tuple[int, int, int, int] - ] = [] # List of tuples: (row_idx, col_idx, start_token, end_token) - current_start_token_idx = -1 - current_column_id = -1 - for token_idx, (row_id, column_id) in enumerate(zip(row_ids, column_ids)): - if row_id == 0 or column_id == 0: - continue - # Beginning of new cell - if column_id != current_column_id: - if current_start_token_idx != -1: - possible_answer_spans.append( - ( - row_ids[current_start_token_idx] - 1, - column_ids[current_start_token_idx] - 1, - current_start_token_idx, - token_idx - 1, - ) - ) - current_start_token_idx = token_idx - current_column_id = column_id - possible_answer_spans.append( - ( - row_ids[current_start_token_idx] - 1, - column_ids[current_start_token_idx] - 1, - current_start_token_idx, - len(row_ids) - 1, - ) - ) - - # Concat logits of start token and end token of possible answer spans - sequence_output = outputs.last_hidden_state - concatenated_logits = [] - for possible_span in possible_answer_spans: - start_token_logits = sequence_output[0, possible_span[2], :] - end_token_logits = sequence_output[0, possible_span[3], :] - concatenated_logits.append(torch.cat((start_token_logits, end_token_logits))) - concatenated_logit_tensors = torch.unsqueeze(torch.stack(concatenated_logits), dim=0) - - # Calculate score for each possible span - span_logits = ( - torch.einsum("bsj,j->bs", concatenated_logit_tensors, self.model.span_output_weights) - + self.model.span_output_bias - ) - span_logits_softmax = torch.nn.functional.softmax(span_logits, dim=1) - - top_k_answer_spans = torch.topk(span_logits[0], min(self.top_k_per_candidate, len(possible_answer_spans))) - - answers = [] - for answer_span_idx in top_k_answer_spans.indices: - current_answer_span = possible_answer_spans[answer_span_idx] - answer_str = string_table.iat[current_answer_span[:2]] - answer_offsets: Union[List[Span], List[TableCell]] - answer_offsets = _calculate_answer_offsets([current_answer_span[:2]]) - # As the general table score is more important for the final score, it is double weighted. - current_score = ((2 * table_relevancy_prob) + span_logits_softmax[0, answer_span_idx].item()) / 3 - - answers.append( - Answer( - answer=answer_str, - type="extractive", - score=current_score, - context=string_table, - offsets_in_document=answer_offsets, - offsets_in_context=answer_offsets, - document_ids=[document.id], - meta={"aggregation_operator": "NONE", "answer_cells": string_table.iat[current_answer_span[:2]]}, - ) - ) - - return answers, no_answer_score - - def predict(self, query: str, documents: List[Document], top_k: int) -> Dict: - answers = [] - no_answer_score = 1.0 - table_documents = _check_documents(documents) - for document in table_documents: - table: pd.DataFrame = document.content - table = table.astype(str) - model_inputs = self.tokenizer( - table=table, queries=query, max_length=self.max_seq_len, return_tensors="pt", truncation=True - ) - model_inputs.to(self.device) - - current_answers, current_no_answer_score = self._predict_tapas_scored(model_inputs, document) - answers.extend(current_answers) - if current_no_answer_score < no_answer_score: - no_answer_score = current_no_answer_score - - if self.return_no_answer: - offsets_in_context = None - offsets_in_document = None - answers.append( - Answer( - answer="", - type="extractive", - score=no_answer_score, - context=None, - offsets_in_context=offsets_in_context, - offsets_in_document=offsets_in_document, - document_ids=None, - meta=None, - ) - ) - - answers = sorted(answers, reverse=True) - results = {"query": query, "answers": answers[:top_k]} - return results - - def predict_batch(self, queries: List[str], documents: List[List[Document]], top_k: int): - results: Dict = {"queries": queries, "answers": []} - for query, docs in zip(queries, documents): - preds = self.predict(query=query, documents=docs, top_k=top_k) - results["answers"].append(preds["answers"]) - return results - - class _TapasForScoredQA(TapasPreTrainedModel): # pylint: disable=useless-object-inheritance - def __init__(self, config): - super().__init__(config) - - # base model - self.tapas = TapasModel(config) - - # dropout (only used when training) - self.dropout = torch.nn.Dropout(config.hidden_dropout_prob) - - # answer selection head - self.span_output_weights = torch.nn.Parameter(torch.zeros(2 * config.hidden_size)) - self.span_output_bias = torch.nn.Parameter(torch.zeros([])) - - # table scoring head - self.classifier = torch.nn.Linear(config.hidden_size, 2) - - # Initialize weights - self.init_weights() - - -class RCIReader(BaseReader): - """ - Table Reader model based on Glass et al. (2021)'s Row-Column-Intersection model. - See the original paper for more details: - Glass, Michael, et al. (2021): "Capturing Row and Column Semantics in Transformer Based Question Answering over Tables" - (https://aclanthology.org/2021.naacl-main.96/) - - Each row and each column is given a score with regard to the query by two separate models. The score of each cell - is then calculated as the sum of the corresponding row score and column score. Accordingly, the predicted answer is - the cell with the highest score. - - Pros and Cons of RCIReader compared to TableReader: - + Provides meaningful confidence scores - + Allows larger tables as input - - Does not support aggregation over table cells - - Slower - """ - - def __init__( - self, - row_model_name_or_path: str = "michaelrglass/albert-base-rci-wikisql-row", - column_model_name_or_path: str = "michaelrglass/albert-base-rci-wikisql-col", - row_model_version: Optional[str] = None, - column_model_version: Optional[str] = None, - row_tokenizer: Optional[str] = None, - column_tokenizer: Optional[str] = None, - use_gpu: bool = True, - top_k: int = 10, - max_seq_len: int = 256, - use_auth_token: Optional[Union[str, bool]] = None, - ): - """ - Load an RCI model from Transformers. - Available models include: - - - ``'michaelrglass/albert-base-rci-wikisql-row'`` + ``'michaelrglass/albert-base-rci-wikisql-col'`` - - ``'michaelrglass/albert-base-rci-wtq-row'`` + ``'michaelrglass/albert-base-rci-wtq-col'`` - - - - :param row_model_name_or_path: Directory of a saved row scoring model or the name of a public model - :param column_model_name_or_path: Directory of a saved column scoring model or the name of a public model - :param row_model_version: The version of row model to use from the HuggingFace model hub. - Can be tag name, branch name, or commit hash. - :param column_model_version: The version of column model to use from the HuggingFace model hub. - Can be tag name, branch name, or commit hash. - :param row_tokenizer: Name of the tokenizer for the row model (usually the same as model) - :param column_tokenizer: Name of the tokenizer for the column model (usually the same as model) - :param use_gpu: Whether to use GPU or CPU. Falls back on CPU if no GPU is available. - :param top_k: The maximum number of answers to return - :param max_seq_len: Max sequence length of one input table for the model. If the number of tokens of - query + table exceed max_seq_len, the table will be truncated by removing rows until the - input size fits the model. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - torch_and_transformers_import.check() - super().__init__() - - self.devices, _ = initialize_device_settings(use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - self.row_model = AutoModelForSequenceClassification.from_pretrained( - row_model_name_or_path, revision=row_model_version, use_auth_token=use_auth_token - ) - self.column_model = AutoModelForSequenceClassification.from_pretrained( - row_model_name_or_path, revision=column_model_version, use_auth_token=use_auth_token - ) - self.row_model.to(str(self.devices[0])) - self.column_model.to(str(self.devices[0])) - - if row_tokenizer is None: - try: - self.row_tokenizer = AutoTokenizer.from_pretrained( - row_model_name_or_path, use_auth_token=use_auth_token - ) - # The existing RCI models on the model hub don't come with tokenizer vocab files. - except TypeError: - self.row_tokenizer = AutoTokenizer.from_pretrained("albert-base-v2", use_auth_token=use_auth_token) - else: - self.row_tokenizer = AutoTokenizer.from_pretrained(row_tokenizer, use_auth_token=use_auth_token) - - if column_tokenizer is None: - try: - self.column_tokenizer = AutoTokenizer.from_pretrained( - column_model_name_or_path, use_auth_token=use_auth_token - ) - # The existing RCI models on the model hub don't come with tokenizer vocab files. - except TypeError: - self.column_tokenizer = AutoTokenizer.from_pretrained("albert-base-v2", use_auth_token=use_auth_token) - else: - self.column_tokenizer = AutoTokenizer.from_pretrained(column_tokenizer, use_auth_token=use_auth_token) - - self.top_k = top_k - self.max_seq_len = max_seq_len - self.return_no_answers = False - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None) -> Dict: - """ - Use loaded RCI models to find answers for a query in the supplied list of Documents - of content_type ``'table'``. - - Returns dictionary containing query and list of Answer objects sorted by (desc.) score. - The existing RCI models on the HF model hub don"t allow aggregation, therefore, the answer will always be - composed of a single cell. - - :param query: Query string - :param documents: List of Document in which to search for the answer. Documents should be - of content_type ``'table'``. - :param top_k: The maximum number of answers to return - :return: Dict containing query and answers - """ - if top_k is None: - top_k = self.top_k - - answers = [] - table_documents = _check_documents(documents) - for document in table_documents: - # Create row and column representations - table: pd.DataFrame = document.content - string_table = table.astype(str) - row_reps, column_reps = self._create_row_column_representations(string_table) - - # Get row logits - row_inputs = self.row_tokenizer( - [(query, row_rep) for row_rep in row_reps], - max_length=self.max_seq_len, - return_tensors="pt", - add_special_tokens=True, - truncation=True, - padding=True, - ) - row_inputs.to(self.devices[0]) - with torch.inference_mode(): - row_outputs = self.row_model(**row_inputs) - row_logits = row_outputs[0].detach().cpu().numpy()[:, 1] - - # Get column logits - column_inputs = self.column_tokenizer( - [(query, column_rep) for column_rep in column_reps], - max_length=self.max_seq_len, - return_tensors="pt", - add_special_tokens=True, - truncation=True, - padding=True, - ) - column_inputs.to(self.devices[0]) - with torch.inference_mode(): - column_outputs = self.column_model(**column_inputs) - column_logits = column_outputs[0].detach().cpu().numpy()[:, 1] - - # Calculate cell scores - current_answers: List[Answer] = [] - cell_scores_table: List[List[float]] = [] - for row_idx, row_score in enumerate(row_logits): - cell_scores_table.append([]) - for col_idx, col_score in enumerate(column_logits): - current_cell_score = float(row_score + col_score) - cell_scores_table[-1].append(current_cell_score) - - answer_str = string_table.iloc[row_idx, col_idx] - answer_offsets: Union[List[Span], List[TableCell]] - answer_offsets = [TableCell(row=row_idx, col=col_idx)] - current_answers.append( - Answer( - answer=answer_str, - type="extractive", - score=current_cell_score, - context=string_table, - offsets_in_document=answer_offsets, - offsets_in_context=answer_offsets, - document_ids=[document.id], - ) - ) - - # Add cell scores to Answers' meta to be able to use as heatmap - for answer in current_answers: - answer.meta = {"table_scores": cell_scores_table} - answers.extend(current_answers) - - # Sort answers by score and select top-k answers - answers = sorted(answers, reverse=True) - answers = answers[:top_k] - - results = {"query": query, "answers": answers} - - return results - - @staticmethod - def _create_row_column_representations(table: pd.DataFrame) -> Tuple[List[str], List[str]]: - row_reps = [] - column_reps = [] - columns = table.columns - - for _, row in table.iterrows(): - current_row_rep = " * ".join([header + " : " + cell for header, cell in zip(columns, row)]) - row_reps.append(current_row_rep) - - for col_name in columns: - current_column_rep = f"{col_name} * " - current_column_rep += " * ".join(table[col_name]) - column_reps.append(current_column_rep) - - return row_reps, column_reps - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ): - if top_k is None: - top_k = self.top_k - - single_doc_list = bool(len(documents) > 0 and isinstance(documents[0], Document)) - - inputs = _flatten_inputs(queries, documents) - - results: Dict[str, List] = {"queries": inputs["queries"], "answers": []} - for query, docs in zip(inputs["queries"], inputs["docs"]): - preds = self.predict(query=query, documents=docs, top_k=top_k) - results["answers"].append(preds["answers"]) - - # Group answers by question in case of multiple queries and single doc list - if single_doc_list and len(queries) > 1: - num_docs_per_query = int(len(results["answers"]) / len(queries)) - answers = [] - for i in range(0, len(results["answers"]), num_docs_per_query): - answer_group = results["answers"][i : i + num_docs_per_query] - answers.append(answer_group) - results["answers"] = answers - - return results - - -def _calculate_answer_offsets(answer_coordinates: List[Tuple[int, int]]) -> List[TableCell]: - """ - Calculates the answer cell offsets of the linearized table based on the answer cell coordinates. - - :param answer_coordinates: List of answer coordinates. - """ - answer_offsets = [] - for coord in answer_coordinates: - answer_offsets.append(TableCell(row=coord[0], col=coord[1])) - return answer_offsets - - -def _check_documents(documents: List[Document]) -> List[Document]: - """ - Check that the content type of all `documents` is of type 'table' otherwise remove that document from the list. - - :param documents: List of documents to be checked. - """ - table_documents = [] - for document in documents: - if document.content_type != "table": - logger.warning("Skipping document with id '%s' in TableReader as it is not of type table.", document.id) - continue - - table: pd.DataFrame = document.content - if table.shape[0] == 0: - logger.warning( - "Skipping document with id '%s' in TableReader as it does not contain any rows.", document.id - ) - continue - - table_documents.append(document) - return table_documents - - -def _flatten_inputs(queries: List[str], documents: Union[List[Document], List[List[Document]]]) -> Dict[str, List]: - """Flatten (and copy) the queries and documents into lists of equal length. - - - If you provide a list containing a single query... - - ... and a single list of Documents, the query will be applied to each Document individually. - - ... and a list of lists of Documents, the query will be applied to each list of Documents and the Answers - will be aggregated per Document list. - - - If you provide a list of multiple queries... - - ... and a single list of Documents, each query will be applied to each Document individually. - - ... and a list of lists of Documents, each query will be applied to its corresponding list of Documents - and the Answers will be aggregated per query-Document pair. - - :param queries: Single query string or list of queries. - :param documents: Single list of Documents or list of lists of Documents in which to search for the answers. - Documents should be of content_type ``'table'``. - """ - # Docs case 1: single list of Documents -> apply each query to all Documents - inputs: Dict[str, List] = {"queries": [], "docs": []} - if len(documents) > 0 and isinstance(documents[0], Document): - for query in queries: - for doc in documents: - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - inputs["queries"].append(query) - inputs["docs"].append([doc]) - - # Docs case 2: list of lists of Documents -> apply each query to corresponding list of Documents, if queries - # contains only one query, apply it to each list of Documents - elif len(documents) > 0 and isinstance(documents[0], list): - total_queries = queries.copy() - if len(total_queries) == 1: - total_queries = queries * len(documents) - if len(total_queries) != len(documents): - raise HaystackError("Number of queries must be equal to number of provided Document lists.") - for query, cur_docs in zip(total_queries, documents): - if not isinstance(cur_docs, list): - raise HaystackError(f"cur_docs was of type {type(cur_docs)}, but expected a list of Documents.") - inputs["queries"].append(query) - inputs["docs"].append(cur_docs) - return inputs diff --git a/haystack/nodes/reader/transformers.py b/haystack/nodes/reader/transformers.py deleted file mode 100644 index 9ec8644629..0000000000 --- a/haystack/nodes/reader/transformers.py +++ /dev/null @@ -1,380 +0,0 @@ -from typing import List, Optional, Union, Dict, Any, Tuple - -import logging -import itertools - -from haystack.errors import HaystackError -from haystack.schema import Document, Answer, Span -from haystack.nodes.reader.base import BaseReader -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import pipeline - from transformers.data.processors.squad import SquadExample - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class TransformersReader(BaseReader): - """ - Transformer based model for extractive Question Answering using the HuggingFace's transformers framework - (https://github.com/huggingface/transformers). - While the underlying model can vary (BERT, Roberta, DistilBERT ...), the interface remains the same. - With this reader, you can directly get predictions via predict() - """ - - def __init__( - self, - model_name_or_path: str = "distilbert-base-uncased-distilled-squad", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - context_window_size: int = 70, - use_gpu: bool = True, - top_k: int = 10, - top_k_per_candidate: int = 3, - return_no_answers: bool = False, - max_seq_len: int = 256, - doc_stride: int = 128, - batch_size: int = 16, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Load a QA model from Transformers. - Available models include: - - - ``'distilbert-base-uncased-distilled-squad`'`` - - ``'bert-large-cased-whole-word-masking-finetuned-squad``' - - ``'bert-large-uncased-whole-word-masking-finetuned-squad``' - - See https://huggingface.co/models for full list of available QA models - - :param model_name_or_path: Directory of a saved model or the name of a public model e.g. 'bert-base-cased', - 'deepset/bert-base-cased-squad2', 'deepset/bert-base-cased-squad2', 'distilbert-base-uncased-distilled-squad'. - See https://huggingface.co/models for full list of available models. - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param tokenizer: Name of the tokenizer (usually the same as model) - :param context_window_size: Num of chars (before and after the answer) to return as "context" for each answer. - The context usually helps users to understand if the answer really makes sense. - :param use_gpu: Whether to use GPU (if available). - :param top_k: The maximum number of answers to return - :param top_k_per_candidate: How many answers to extract for each candidate doc that is coming from the retriever (might be a long text). - Note that this is not the number of "final answers" you will receive - (see `top_k` in TransformersReader.predict() or Finder.get_answers() for that) - and that no_answer can be included in the sorted list of predictions. - :param return_no_answers: If True, the HuggingFace Transformers model could return a "no_answer" (i.e. when there is an unanswerable question) - If False, it cannot return a "no_answer". Note that `no_answer_boost` is unfortunately not available with TransformersReader. - If you would like to set no_answer_boost, use a `FARMReader`. - :param max_seq_len: max sequence length of one input text for the model - :param doc_stride: length of striding window for splitting long texts (used if len(text) > max_seq_len) - :param batch_size: Number of documents to process at a time. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - """ - torch_and_transformers_import.check() - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - self.model = pipeline( - "question-answering", - model=model_name_or_path, - tokenizer=tokenizer, - device=self.devices[0], - revision=model_version, - use_auth_token=use_auth_token, - ) - self.context_window_size = context_window_size - self.top_k = top_k - self.top_k_per_candidate = top_k_per_candidate - self.return_no_answers = return_no_answers - self.max_seq_len = max_seq_len - self.doc_stride = doc_stride - self.batch_size = batch_size - - # TODO context_window_size behaviour different from behavior in FARMReader - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None): - """ - Use loaded QA model to find answers for a query in the supplied list of Document. - - Returns dictionaries containing answers sorted by (desc.) score. - Example: - - ```python - { - 'query': 'Who is the father of Arya Stark?', - 'answers':[ - {'answer': 'Eddard,', - 'context': " She travels with her father, Eddard, to King's Landing when he is ", - 'offset_answer_start': 147, - 'offset_answer_end': 154, - 'score': 0.9787139466668613, - 'document_id': '1337' - },... - ] - } - ``` - - :param query: Query string - :param documents: List of Document in which to search for the answer - :param top_k: The maximum number of answers to return - :return: Dict containing query and answers - """ - if top_k is None: - top_k = self.top_k - - inputs = [] - all_docs = {} - for doc in documents: - cur = self.model.create_sample(question=query, context=doc.content) - cur.doc_id = doc.id - all_docs[doc.id] = doc - inputs.append(cur) - - predictions = self.model( - inputs, - top_k=self.top_k_per_candidate, - handle_impossible_answer=self.return_no_answers, - max_seq_len=self.max_seq_len, - doc_stride=self.doc_stride, - ) - # Transformers gives different output depending on top_k_per_candidate and number of inputs - if isinstance(predictions, dict): - predictions = [[predictions]] - elif len(inputs) == 1: - predictions = [predictions] - else: - predictions = [p if isinstance(p, list) else [p] for p in predictions] - - # Add Document ID to predictions to be able to construct Answer objects - for preds_for_single_doc, inp in zip(predictions, inputs): - cur_doc_id = inp.doc_id - for pred in preds_for_single_doc: - pred["doc_id"] = cur_doc_id - predictions = list(itertools.chain.from_iterable(predictions)) - - answers, _ = self._extract_answers_of_predictions(predictions, all_docs, top_k) - - results = {"query": query, "answers": answers} - return results - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ): - """ - Use loaded QA model to find answers for the queries in the Documents. - - - If you provide a list containing a single query... - - - ... and a single list of Documents, the query will be applied to each Document individually. - - ... and a list of lists of Documents, the query will be applied to each list of Documents and the Answers - will be aggregated per Document list. - - - If you provide a list of multiple queries... - - - ... and a single list of Documents, each query will be applied to each Document individually. - - ... and a list of lists of Documents, each query will be applied to its corresponding list of Documents - and the Answers will be aggregated per query-Document pair. - - :param queries: Single query or list of queries. - :param documents: Related documents (e.g. coming from a retriever) that the answer shall be conditioned on. - Can be a single list of Documents or a list of lists of Documents. - :param top_k: Number of returned answers per query. - :param batch_size: Number of query-document pairs to be processed at a time. - """ - if top_k is None: - top_k = self.top_k - - if batch_size is None: - batch_size = self.batch_size - - inputs, number_of_docs, all_docs, single_doc_list = self._preprocess_batch_queries_and_docs( - queries=queries, documents=documents - ) - - # Inference - predictions = self.model( - inputs, - top_k=self.top_k_per_candidate, - handle_impossible_answer=self.return_no_answers, - max_seq_len=self.max_seq_len, - doc_stride=self.doc_stride, - batch_size=batch_size, - ) - - # Transformers flattens lists of length 1. This restores the original list structure. - if isinstance(predictions, dict): - predictions = [[predictions]] - elif len(inputs) == 1: - predictions = [predictions] - else: - predictions = [p if isinstance(p, list) else [p] for p in predictions] - - # Group predictions together - grouped_predictions = [] - grouped_inputs = [] - left_idx = 0 - for number in number_of_docs: - right_idx = left_idx + number - grouped_predictions.append(predictions[left_idx:right_idx]) - grouped_inputs.append(inputs[left_idx:right_idx]) - left_idx = right_idx - - results: Dict = {"queries": queries, "answers": [], "no_ans_gaps": []} - for grouped_pred, grouped_inp in zip(grouped_predictions, grouped_inputs): - # Add Document ID to predictions to be able to construct Answer objects - for preds_for_single_doc, inp in zip(grouped_pred, grouped_inp): - for pred in preds_for_single_doc: - cur_doc_id = inp.doc_id - pred["doc_id"] = cur_doc_id - if len(grouped_pred) == 0: - group = [] - elif isinstance(grouped_pred[0], list): - group = list(itertools.chain.from_iterable(grouped_pred)) - answers, max_no_ans_gap = self._extract_answers_of_predictions(group, all_docs, top_k) - results["answers"].append(answers) - results["no_ans_gaps"].append(max_no_ans_gap) - - # Group answers by question in case of list of queries and single doc list - if single_doc_list and len(queries) > 1: - answers_per_query = int(len(results["answers"]) / len(queries)) - answers = [] - for i in range(0, len(results["answers"]), answers_per_query): - answer_group = results["answers"][i : i + answers_per_query] - answers.append(answer_group) - results["answers"] = answers - - return results - - def _extract_answers_of_predictions( - self, predictions: List[Dict[str, Any]], docs: Dict[str, Document], top_k: int - ) -> Tuple[List[Answer], float]: - answers = [] - no_ans_gaps = [] - best_overall_score = 0 - - if len(predictions) > 0: - cur_doc_id = predictions[0]["doc_id"] - cur_doc = docs[cur_doc_id] - no_ans_doc_score = 0 - best_doc_score = 0 - - # TODO add no answer bias on haystack side after getting "no answer" scores from transformers - for pred in predictions: - # Update best_overall_score based on best_doc_score of predictions of previous Document - # + add no_ans_gap for previous Document + update cur_doc - if cur_doc_id != pred["doc_id"]: - if best_doc_score > best_overall_score: - best_overall_score = best_doc_score - no_ans_gaps.append(no_ans_doc_score - best_doc_score) - cur_doc_id = pred["doc_id"] - cur_doc = docs[cur_doc_id] - no_ans_doc_score = 0 - best_doc_score = 0 - if pred["answer"]: - if pred["score"] > best_doc_score: - best_doc_score = pred["score"] - context_start = max(0, pred["start"] - self.context_window_size) - context_end = min(len(cur_doc.content), pred["end"] + self.context_window_size) - answers.append( - Answer( - answer=pred["answer"], - type="extractive", - score=pred["score"], - context=cur_doc.content[context_start:context_end], - offsets_in_document=[Span(start=pred["start"], end=pred["end"])], - offsets_in_context=[Span(start=pred["start"] - context_start, end=pred["end"] - context_start)], - document_ids=[cur_doc.id], - meta=cur_doc.meta, - ) - ) - # "no answer" prediction - else: - no_ans_doc_score = pred["score"] - - # Update best_overall_score based on best_doc_score of predictions of last Document - # + add no_ans_gap for last Document - if best_doc_score > best_overall_score: - best_overall_score = best_doc_score - - if len(predictions) > 0: - no_ans_gaps.append(no_ans_doc_score - best_doc_score) - - # Calculate the score for predicting "no answer", relative to our best positive answer score - no_ans_prediction, max_no_ans_gap = self._calc_no_answer(no_ans_gaps, best_overall_score) - - if self.return_no_answers: - answers.append(no_ans_prediction) - # Sort answers by score and select top-k - answers = sorted(answers, reverse=True) - answers = answers[:top_k] - - return answers, max_no_ans_gap - - def _preprocess_batch_queries_and_docs( - self, queries: List[str], documents: Union[List[Document], List[List[Document]]] - ) -> Tuple[List["SquadExample"], List[int], Dict[str, Document], bool]: - # Convert input to transformers format - inputs = [] - number_of_docs = [] - all_docs = {} - single_doc_list = False - - # Docs case 1: single list of Documents -> apply each query to all Documents - if len(documents) > 0 and isinstance(documents[0], Document): - single_doc_list = True - for query in queries: - for doc in documents: - number_of_docs.append(1) - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - cur = self.model.create_sample(question=query, context=doc.content) - cur.doc_id = doc.id - all_docs[doc.id] = doc - inputs.append(cur) - - # Docs case 2: list of lists of Documents -> apply each query to corresponding list of Documents, if queries - # contains only one query, apply it to each list of Documents - elif len(documents) > 0 and isinstance(documents[0], list): - single_doc_list = False - if len(queries) == 1: - queries = queries * len(documents) - if len(queries) != len(documents): - raise HaystackError("Number of queries must be equal to number of provided Document lists.") - for query, cur_docs in zip(queries, documents): - if not isinstance(cur_docs, list): - raise HaystackError(f"cur_docs was of type {type(cur_docs)}, but expected a list of Documents.") - number_of_docs.append(len(cur_docs)) - for doc in cur_docs: - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - cur = self.model.create_sample(question=query, context=doc.content) - cur.doc_id = doc.id - all_docs[doc.id] = doc - inputs.append(cur) - - return inputs, number_of_docs, all_docs, single_doc_list diff --git a/haystack/nodes/retriever/__init__.py b/haystack/nodes/retriever/__init__.py deleted file mode 100644 index cbdf89547c..0000000000 --- a/haystack/nodes/retriever/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from haystack.nodes.retriever.base import BaseRetriever -from haystack.nodes.retriever.dense import ( - DensePassageRetriever, - DenseRetriever, - EmbeddingRetriever, - MultihopEmbeddingRetriever, - TableTextRetriever, -) -from haystack.nodes.retriever.multimodal import MultiModalRetriever -from haystack.nodes.retriever.sparse import BM25Retriever, FilterRetriever, TfidfRetriever -from haystack.nodes.retriever.link_content import LinkContentFetcher -from haystack.nodes.retriever.web import WebRetriever diff --git a/haystack/nodes/retriever/_base_embedding_encoder.py b/haystack/nodes/retriever/_base_embedding_encoder.py deleted file mode 100644 index 4af4d339ca..0000000000 --- a/haystack/nodes/retriever/_base_embedding_encoder.py +++ /dev/null @@ -1,102 +0,0 @@ -import logging -from abc import abstractmethod -from pathlib import Path -from typing import Any, Dict, List, Optional, Union - -import numpy as np - -from haystack.document_stores.base import BaseDocumentStore -from haystack.schema import Document - -logger = logging.getLogger(__name__) - - -class _BaseEmbeddingEncoder: - @abstractmethod - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - pass - - @abstractmethod - def embed_documents(self, docs: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of documents. - - :param docs: List of documents to embed. - :return: Embeddings, one per input document, shape: (documents, embedding_dim) - """ - pass - - def train( - self, - training_data: List[Dict[str, Any]], - learning_rate: float = 2e-5, - n_epochs: int = 1, - num_warmup_steps: Optional[int] = None, - batch_size: int = 16, - ): - """ - Trains or adapts the underlying embedding model. - - Each training data example is a dictionary with the following keys: - - * question: The question string. - * pos_doc: Positive document string (the document containing the answer). - * neg_doc: Negative document string (the document that doesn't contain the answer). - * score: The score margin the answer must fall within. - - - :param training_data: The training data in a dictionary format. Required. - :type training_data: List[Dict[str, Any]] - :param learning_rate: The speed at which the model learns. Required. We recommend that you leave the default `2e-5` value. - :type learning_rate: float - :param n_epochs: The number of epochs (complete passes of the training data through the algorithm) that you want the model to go through. Required. - :type n_epochs: int - :param num_warmup_steps: The number of warmup steps for the model. Warmup steps are epochs when the learning rate is very low. You can use them at the beginning of the training to prevent early overfitting of your model. Required. - :type num_warmup_steps: int - :param batch_size: The batch size to use for the training. Optional. The default values is 16. - :type batch_size: int (optional) - """ - pass - - def save(self, save_dir: Union[Path, str]): - """ - Save the model to the directory you specify. - - :param save_dir: The directory where the model is saved. Required. - :type save_dir: Union[Path, str] - """ - pass - - def _check_docstore_similarity_function(self, document_store: BaseDocumentStore, model_name: str): - """ - Check that document_store uses a similarity function - compatible with the embedding model - """ - if "sentence-transformers" in model_name.lower(): - model_similarity = None - if "-cos-" in model_name.lower(): - model_similarity = "cosine" - elif "-dot-" in model_name.lower(): - model_similarity = "dot_product" - - if model_similarity is not None and document_store.similarity != model_similarity: - logger.warning( - "You seem to be using %s model with the %s function instead of the recommended %s. " - "This can be set when initializing the DocumentStore", - model_name, - document_store.similarity, - model_similarity, - ) - elif "dpr" in model_name.lower() and document_store.similarity != "dot_product": - logger.warning( - "You seem to be using a DPR model with the %s function. " - "We recommend using dot_product instead. " - "This can be set when initializing the DocumentStore", - document_store.similarity, - ) diff --git a/haystack/nodes/retriever/_embedding_encoder.py b/haystack/nodes/retriever/_embedding_encoder.py deleted file mode 100644 index d07e7ab1b8..0000000000 --- a/haystack/nodes/retriever/_embedding_encoder.py +++ /dev/null @@ -1,444 +0,0 @@ -# pylint: disable=ungrouped-imports - -import json -import logging -import os -from pathlib import Path -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union, Literal -from tenacity import retry, retry_if_exception_type, wait_exponential, stop_after_attempt - -import numpy as np -import requests -from tqdm import tqdm - -from haystack.environment import ( - HAYSTACK_REMOTE_API_BACKOFF_SEC, - HAYSTACK_REMOTE_API_MAX_RETRIES, - HAYSTACK_REMOTE_API_TIMEOUT_SEC, -) -from haystack.errors import CohereError, CohereUnauthorizedError -from haystack.nodes.retriever._openai_encoder import _OpenAIEmbeddingEncoder -from haystack.schema import Document -from haystack.telemetry import send_event -from haystack.lazy_imports import LazyImport - -from ._base_embedding_encoder import _BaseEmbeddingEncoder - -if TYPE_CHECKING: - from haystack.nodes.retriever import EmbeddingRetriever - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from sentence_transformers import InputExample, SentenceTransformer - from torch.utils.data import DataLoader - from torch.utils.data.sampler import SequentialSampler - from transformers import AutoModel, AutoTokenizer - from haystack.modeling.data_handler.dataloader import NamedDataLoader - from haystack.modeling.data_handler.dataset import convert_features_to_dataset, flatten_rename - from haystack.modeling.infer import Inferencer - from haystack.nodes.retriever._losses import _TRAINING_LOSSES - - -COHERE_TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) -COHERE_BACKOFF = int(os.environ.get(HAYSTACK_REMOTE_API_BACKOFF_SEC, 10)) -COHERE_MAX_RETRIES = int(os.environ.get(HAYSTACK_REMOTE_API_MAX_RETRIES, 5)) -COHERE_EMBEDDING_MODELS = [ - "small", - "large", - "multilingual-22-12", - "embed-english-v2.0", - "embed-english-light-v2.0", - "embed-multilingual-v2.0", -] - - -class _DefaultEmbeddingEncoder(_BaseEmbeddingEncoder): - def __init__(self, retriever: "EmbeddingRetriever"): - self.embedding_model = Inferencer.load( - retriever.embedding_model, - revision=retriever.model_version, - task_type="embeddings", - extraction_strategy=retriever.pooling_strategy, - extraction_layer=retriever.emb_extraction_layer, - gpu=retriever.use_gpu, - batch_size=retriever.batch_size, - max_seq_len=retriever.max_seq_len, - num_processes=0, - use_auth_token=retriever.use_auth_token, - ) - torch_and_transformers_import.check() - if retriever.document_store: - self._check_docstore_similarity_function( - document_store=retriever.document_store, model_name=retriever.embedding_model - ) - - def embed(self, texts: Union[List[List[str]], List[str], str]) -> np.ndarray: - # TODO: FARM's `sample_to_features_text` need to fix following warning - - # tokenization_utils.py:460: FutureWarning: `is_pretokenized` is deprecated and will be removed in a future version, use `is_split_into_words` instead. - emb = self.embedding_model.inference_from_dicts(dicts=[{"text": t} for t in texts]) - emb = np.stack([r["vec"] for r in emb]) - return emb - - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - return self.embed(queries) - - def embed_documents(self, docs: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of documents. - - :param docs: List of documents to embed. - :return: Embeddings, one per input document, shape: (documents, embedding_dim) - """ - passages = [d.content for d in docs] - return self.embed(passages) - - def train( - self, - training_data: List[Dict[str, Any]], - learning_rate: float = 2e-5, - n_epochs: int = 1, - num_warmup_steps: Optional[int] = None, - batch_size: int = 16, - train_loss: Literal["mnrl", "margin_mse"] = "mnrl", - num_workers: int = 0, - use_amp: bool = False, - **kwargs, - ): - raise NotImplementedError( - "You can't train this retriever. You can only use the `train` method with sentence-transformers EmbeddingRetrievers." - ) - - def save(self, save_dir: Union[Path, str]): - raise NotImplementedError( - "You can't save your record as `save` only works for sentence-transformers EmbeddingRetrievers." - ) - - -class _SentenceTransformersEmbeddingEncoder(_BaseEmbeddingEncoder): - def __init__(self, retriever: "EmbeddingRetriever"): - # pretrained embedding models coming from: https://github.com/UKPLab/sentence-transformers#pretrained-models - # e.g. 'roberta-base-nli-stsb-mean-tokens' - torch_and_transformers_import.check() - self.embedding_model = SentenceTransformer( - retriever.embedding_model, device=str(retriever.devices[0]), use_auth_token=retriever.use_auth_token - ) - self.batch_size = retriever.batch_size - self.embedding_model.max_seq_length = retriever.max_seq_len - self.show_progress_bar = retriever.progress_bar - if retriever.document_store: - self._check_docstore_similarity_function( - document_store=retriever.document_store, model_name=retriever.embedding_model - ) - - def embed(self, texts: Union[List[str], str]) -> np.ndarray: - # texts can be a list of strings - # get back list of numpy embedding vectors - emb = self.embedding_model.encode( - texts, batch_size=self.batch_size, show_progress_bar=self.show_progress_bar, convert_to_numpy=True - ) - return emb - - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - return self.embed(queries) - - def embed_documents(self, docs: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of documents. - - :param docs: List of documents to embed. - :return: Embeddings, one per input document, shape: (documents, embedding_dim) - """ - passages = [d.content for d in docs] - return self.embed(passages) - - def train( - self, - training_data: List[Dict[str, Any]], - learning_rate: float = 2e-5, - n_epochs: int = 1, - num_warmup_steps: Optional[int] = None, - batch_size: Optional[int] = 16, - train_loss: Literal["mnrl", "margin_mse"] = "mnrl", - num_workers: int = 0, - use_amp: bool = False, - **kwargs, - ): - """ - Trains the underlying Sentence Transformer model. - - Each training data example is a dictionary with the following keys: - - * question: The question string. - * pos_doc: Positive document string (the document containing the answer). - * neg_doc: Negative document string (the document that doesn't contain the answer). - * score: The score margin the answer must fall within. - - :param training_data: The training data in a dictionary format. - :param learning_rate: The learning rate of the optimizer. - :param n_epochs: The number of iterations on the whole training data set you want to train for. - :param num_warmup_steps: Behavior depends on the scheduler. For WarmupLinear (default), the learning rate is - increased from 0 up to the maximal learning rate. After these many training steps, the learning rate is - decreased linearly back to zero. - :param batch_size: The batch size to use for the training. The default value is 16. - :param train_loss: Specify the training loss to use to fit the Sentence-Transformers model. Possible options are - "mnrl" (Multiple Negatives Ranking Loss) and "margin_mse". - :param num_workers: The number of subprocesses to use for the Pytorch DataLoader. - :param use_amp: Use Automatic Mixed Precision (AMP). - :param kwargs: Additional training keyword arguments to pass to the `SentenceTransformer.fit` function. Please - reference the Sentence-Transformers [documentation](https://www.sbert.net/docs/training/overview.html#sentence_transformers.SentenceTransformer.fit) - for a full list of keyword arguments. - """ - send_event(event_name="Training", event_properties={"class": self.__class__.__name__, "function_name": "train"}) - - if train_loss not in _TRAINING_LOSSES: - raise ValueError(f"Unrecognized train_loss {train_loss}. Should be one of: {_TRAINING_LOSSES.keys()}") - - st_loss = _TRAINING_LOSSES[train_loss] - - train_examples = [] - for train_i in training_data: - missing_attrs = st_loss.required_attrs.difference(set(train_i.keys())) - if len(missing_attrs) > 0: - raise ValueError( - f"Some training examples don't contain the fields {missing_attrs} which are necessary when using the '{train_loss}' loss." - ) - - texts = [train_i["question"], train_i["pos_doc"]] - if "neg_doc" in train_i: - texts.append(train_i["neg_doc"]) - - if "score" in train_i: - train_examples.append(InputExample(texts=texts, label=train_i["score"])) - else: - train_examples.append(InputExample(texts=texts)) - - logger.info("Training/adapting %s with %s examples", self.embedding_model, len(train_examples)) - train_dataloader = DataLoader( - train_examples, # type: ignore [var-annotated, arg-type] - batch_size=batch_size, - drop_last=True, - shuffle=True, - num_workers=num_workers, - ) - train_loss = st_loss.loss(self.embedding_model) - - # Tune the model - self.embedding_model.fit( - train_objectives=[(train_dataloader, train_loss)], - epochs=n_epochs, - optimizer_params={"lr": learning_rate}, - warmup_steps=int(len(train_dataloader) * 0.1) if num_warmup_steps is None else num_warmup_steps, - use_amp=use_amp, - **kwargs, - ) - - def save(self, save_dir: Union[Path, str]): - self.embedding_model.save(path=str(save_dir)) - - -class _RetribertEmbeddingEncoder(_BaseEmbeddingEncoder): - def __init__(self, retriever: "EmbeddingRetriever"): - torch_and_transformers_import.check() - - self.progress_bar = retriever.progress_bar - self.batch_size = retriever.batch_size - self.max_length = retriever.max_seq_len - self.embedding_tokenizer = AutoTokenizer.from_pretrained( - retriever.embedding_model, use_auth_token=retriever.use_auth_token - ) - self.embedding_model = AutoModel.from_pretrained( - retriever.embedding_model, use_auth_token=retriever.use_auth_token - ).to(str(retriever.devices[0])) - - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - query_text = [{"text": q} for q in queries] - dataloader = self._create_dataloader(query_text) - - embeddings: List[np.ndarray] = [] - disable_tqdm = True if len(dataloader) == 1 else not self.progress_bar - - for batch in tqdm(dataloader, desc="Creating Embeddings", unit=" Batches", disable=disable_tqdm): - batch = {key: batch[key].to(self.embedding_model.device) for key in batch} - with torch.inference_mode(): - q_reps = ( - self.embedding_model.embed_questions( - input_ids=batch["input_ids"], attention_mask=batch["padding_mask"] - ) - .cpu() - .numpy() - ) - embeddings.append(q_reps) - - return np.concatenate(embeddings) - - def embed_documents(self, docs: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of documents. - - :param docs: List of documents to embed. - :return: Embeddings, one per input document, shape: (documents, embedding_dim) - """ - doc_text = [{"text": d.content} for d in docs] - dataloader = self._create_dataloader(doc_text) - - embeddings: List[np.ndarray] = [] - disable_tqdm = True if len(dataloader) == 1 else not self.progress_bar - - for batch in tqdm(dataloader, desc="Creating Embeddings", unit=" Batches", disable=disable_tqdm): - batch = {key: batch[key].to(self.embedding_model.device) for key in batch} - with torch.inference_mode(): - q_reps = ( - self.embedding_model.embed_answers( - input_ids=batch["input_ids"], attention_mask=batch["padding_mask"] - ) - .cpu() - .numpy() - ) - embeddings.append(q_reps) - - return np.concatenate(embeddings) - - def _create_dataloader(self, text_to_encode: List[dict]) -> "NamedDataLoader": - dataset, tensor_names = self.dataset_from_dicts(text_to_encode) - dataloader = NamedDataLoader( - dataset=dataset, sampler=SequentialSampler(dataset), batch_size=self.batch_size, tensor_names=tensor_names - ) - return dataloader - - def dataset_from_dicts(self, dicts: List[dict]): - texts = [x["text"] for x in dicts] - tokenized_batch = self.embedding_tokenizer( - texts, - return_token_type_ids=True, - return_attention_mask=True, - max_length=self.max_length, - truncation=True, - padding=True, - ) - - features_flat = flatten_rename( - tokenized_batch, - ["input_ids", "token_type_ids", "attention_mask"], - ["input_ids", "segment_ids", "padding_mask"], - ) - dataset, tensornames = convert_features_to_dataset(features=features_flat) - return dataset, tensornames - - def train( - self, - training_data: List[Dict[str, Any]], - learning_rate: float = 2e-5, - n_epochs: int = 1, - num_warmup_steps: Optional[int] = None, - batch_size: int = 16, - train_loss: Literal["mnrl", "margin_mse"] = "mnrl", - num_workers: int = 0, - use_amp: bool = False, - **kwargs, - ): - raise NotImplementedError( - "You can't train this retriever. You can only use the `train` method with sentence-transformers EmbeddingRetrievers." - ) - - def save(self, save_dir: Union[Path, str]): - raise NotImplementedError( - "You can't save your record as `save` only works for sentence-transformers EmbeddingRetrievers." - ) - - -class _CohereEmbeddingEncoder(_BaseEmbeddingEncoder): - def __init__(self, retriever: "EmbeddingRetriever"): - torch_and_transformers_import.check() - - # See https://docs.cohere.com/reference/embed for more details - # Cohere has a max seq length of 4096 tokens and a max batch size of 96 - self.max_seq_len = min(4096, retriever.max_seq_len) - self.url = "https://api.cohere.ai/embed" - self.api_key = retriever.api_key - self.batch_size = min(96, retriever.batch_size) - self.progress_bar = retriever.progress_bar - self.model: str = next( - (m for m in COHERE_EMBEDDING_MODELS if m in retriever.embedding_model), "multilingual-22-12" - ) - - @retry( - retry=retry_if_exception_type(CohereError), - wait=wait_exponential(multiplier=COHERE_BACKOFF), - stop=stop_after_attempt(COHERE_MAX_RETRIES), - ) - def embed(self, model: str, text: List[str]) -> np.ndarray: - payload = {"model": model, "texts": text, "truncate": "END"} - headers = {"Authorization": f"BEARER {self.api_key}", "Content-Type": "application/json"} - response = requests.request("POST", self.url, headers=headers, data=json.dumps(payload), timeout=COHERE_TIMEOUT) - res = json.loads(response.text) - if response.status_code == 401: - raise CohereUnauthorizedError(f"Invalid Cohere API key. {response.text}") - if response.status_code != 200: - raise CohereError(response.text, status_code=response.status_code) - generated_embeddings = list(res["embeddings"]) - return np.array(generated_embeddings) - - def embed_batch(self, text: List[str]) -> np.ndarray: - all_embeddings = [] - for i in tqdm( - range(0, len(text), self.batch_size), disable=not self.progress_bar, desc="Calculating embeddings" - ): - batch = text[i : i + self.batch_size] - generated_embeddings = self.embed(self.model, batch) - all_embeddings.append(generated_embeddings) - return np.concatenate(all_embeddings) - - def embed_queries(self, queries: List[str]) -> np.ndarray: - return self.embed_batch(queries) - - def embed_documents(self, docs: List[Document]) -> np.ndarray: - return self.embed_batch([d.content for d in docs]) - - def train( - self, - training_data: List[Dict[str, Any]], - learning_rate: float = 2e-5, - n_epochs: int = 1, - num_warmup_steps: Optional[int] = None, - batch_size: int = 16, - train_loss: Literal["mnrl", "margin_mse"] = "mnrl", - num_workers: int = 0, - use_amp: bool = False, - **kwargs, - ): - raise NotImplementedError(f"Training is not implemented for {self.__class__}") - - def save(self, save_dir: Union[Path, str]): - raise NotImplementedError(f"Saving is not implemented for {self.__class__}") - - -_EMBEDDING_ENCODERS: Dict[str, Callable] = { - "farm": _DefaultEmbeddingEncoder, - "transformers": _DefaultEmbeddingEncoder, - "sentence_transformers": _SentenceTransformersEmbeddingEncoder, - "retribert": _RetribertEmbeddingEncoder, - "openai": _OpenAIEmbeddingEncoder, - "cohere": _CohereEmbeddingEncoder, -} diff --git a/haystack/nodes/retriever/_losses.py b/haystack/nodes/retriever/_losses.py deleted file mode 100644 index 6fbe1b0ea4..0000000000 --- a/haystack/nodes/retriever/_losses.py +++ /dev/null @@ -1,12 +0,0 @@ -from collections import namedtuple -from typing import Dict - -from sentence_transformers import losses - - -SentenceTransformerLoss = namedtuple("SentenceTransformerLoss", "loss required_attrs") - -_TRAINING_LOSSES: Dict[str, SentenceTransformerLoss] = { - "mnrl": SentenceTransformerLoss(losses.MultipleNegativesRankingLoss, {"question", "pos_doc"}), - "margin_mse": SentenceTransformerLoss(losses.MarginMSELoss, {"question", "pos_doc", "neg_doc", "score"}), -} diff --git a/haystack/nodes/retriever/_openai_encoder.py b/haystack/nodes/retriever/_openai_encoder.py deleted file mode 100644 index 4af3cd1fa8..0000000000 --- a/haystack/nodes/retriever/_openai_encoder.py +++ /dev/null @@ -1,160 +0,0 @@ -import logging -import os -from concurrent.futures import ThreadPoolExecutor -from multiprocessing import cpu_count -from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Union - -import numpy as np -import tiktoken -from tqdm import tqdm - -from haystack.environment import HAYSTACK_REMOTE_API_TIMEOUT_SEC -from haystack.nodes.retriever._base_embedding_encoder import _BaseEmbeddingEncoder -from haystack.schema import Document -from haystack.utils.openai_utils import load_openai_tokenizer, openai_request -from haystack.telemetry import send_event - -if TYPE_CHECKING: - from haystack.nodes.retriever import EmbeddingRetriever - -logger = logging.getLogger(__name__) - -OPENAI_TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) - - -class _OpenAIEmbeddingEncoder(_BaseEmbeddingEncoder): - def __init__(self, retriever: "EmbeddingRetriever"): - send_event("OpenAIEmbeddingEncoder initialized", event_properties={"model": retriever.embedding_model}) - # See https://platform.openai.com/docs/guides/embeddings and - # https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/embeddings?tabs=console for more details - self.using_azure = ( - retriever.azure_deployment_name is not None - and retriever.azure_base_url is not None - and retriever.api_version is not None - ) - - if self.using_azure: - self.url = f"{retriever.azure_base_url}/openai/deployments/{retriever.azure_deployment_name}/embeddings?api-version={retriever.api_version}" - else: - self.url = f"{retriever.api_base}/embeddings" - - self.api_key = retriever.api_key - self.openai_organization = retriever.openai_organization - self.batch_size = min(64, retriever.batch_size) - self.progress_bar = retriever.progress_bar - model_class: str = next( - (m for m in ["ada", "babbage", "davinci", "curie"] if m in retriever.embedding_model), "babbage" - ) - - tokenizer = self._setup_encoding_models(model_class, retriever.embedding_model, retriever.max_seq_len) - self._tokenizer = load_openai_tokenizer(tokenizer_name=tokenizer) - - def _setup_encoding_models(self, model_class: str, model_name: str, max_seq_len: int): - """ - Setup the encoding models for the retriever. - """ - - tokenizer_name = "gpt2" - # new generation of embedding models (December 2022), we need to specify the full name - if model_name.endswith("-002"): - self.query_encoder_model = model_name - self.doc_encoder_model = model_name - self.max_seq_len = min(8191, max_seq_len) - try: - tokenizer_name = tiktoken.encoding_name_for_model(model_name) - except KeyError: - tokenizer_name = "cl100k_base" - else: - self.query_encoder_model = f"text-search-{model_class}-query-001" - self.doc_encoder_model = f"text-search-{model_class}-doc-001" - self.max_seq_len = min(2046, max_seq_len) - - return tokenizer_name - - def _ensure_text_limit(self, text: str) -> str: - """ - Ensure that length of the text is within the maximum length of the model. - OpenAI v1 embedding models have a limit of 2046 tokens, and v2 models have a limit of 8191 tokens. - """ - n_tokens = len(self._tokenizer.encode(text)) - if n_tokens <= self.max_seq_len: - return text - - logger.warning( - "The prompt has been truncated from %s tokens to %s tokens to fit within the max token limit." - " Reduce the length of the prompt to prevent it from being cut off.", - n_tokens, - self.max_seq_len, - ) - - tokenized_payload = self._tokenizer.encode(text) - decoded_string = self._tokenizer.decode(tokenized_payload[: self.max_seq_len]) - - return decoded_string - - def embed(self, model: str, text: List[str]) -> np.ndarray: - if self.api_key is None: - raise ValueError( - f"{'Azure ' if self.using_azure else ''}OpenAI API key is not set. You can set it via the `api_key` parameter of the EmbeddingRetriever." - ) - - generated_embeddings: List[Any] = [] - - headers: Dict[str, str] = {"Content-Type": "application/json"} - - def azure_get_embedding(input: str): - headers["api-key"] = str(self.api_key) - azure_payload: Dict[str, str] = {"input": input} - res = openai_request(url=self.url, headers=headers, payload=azure_payload, timeout=OPENAI_TIMEOUT) - return res["data"][0]["embedding"] - - if self.using_azure: - thread_count = cpu_count() if len(text) > cpu_count() else len(text) - with ThreadPoolExecutor(max_workers=thread_count) as executor: - results: Iterator[Dict[str, Any]] = executor.map(azure_get_embedding, text) - generated_embeddings.extend(results) - else: - payload: Dict[str, Union[List[str], str]] = {"model": model, "input": text} - headers["Authorization"] = f"Bearer {self.api_key}" - if self.openai_organization: - headers["OpenAI-Organization"] = self.openai_organization - - res = openai_request(url=self.url, headers=headers, payload=payload, timeout=OPENAI_TIMEOUT) - - unordered_embeddings = [(ans["index"], ans["embedding"]) for ans in res["data"]] - ordered_embeddings = sorted(unordered_embeddings, key=lambda x: x[0]) - - generated_embeddings = [emb[1] for emb in ordered_embeddings] - - return np.array(generated_embeddings) - - def embed_batch(self, model: str, text: List[str]) -> np.ndarray: - all_embeddings = [] - for i in tqdm( - range(0, len(text), self.batch_size), disable=not self.progress_bar, desc="Calculating embeddings" - ): - batch = text[i : i + self.batch_size] - batch_limited = [self._ensure_text_limit(content) for content in batch] - generated_embeddings = self.embed(model, batch_limited) - all_embeddings.append(generated_embeddings) - return np.concatenate(all_embeddings) - - def embed_queries(self, queries: List[str]) -> np.ndarray: - return self.embed_batch(self.query_encoder_model, queries) - - def embed_documents(self, docs: List[Document]) -> np.ndarray: - return self.embed_batch(self.doc_encoder_model, [d.content for d in docs]) - - def train( - self, - training_data: List[Dict[str, Any]], - learning_rate: float = 2e-5, - n_epochs: int = 1, - num_warmup_steps: Optional[int] = None, - batch_size: int = 16, - ): - raise NotImplementedError(f"Training is not implemented for {self.__class__}") - - def save(self, save_dir: Union[Path, str]): - raise NotImplementedError(f"Saving is not implemented for {self.__class__}") diff --git a/haystack/nodes/retriever/base.py b/haystack/nodes/retriever/base.py deleted file mode 100644 index 23f33e2851..0000000000 --- a/haystack/nodes/retriever/base.py +++ /dev/null @@ -1,403 +0,0 @@ -from typing import Dict, List, Optional, Union, Iterator - -import logging -from abc import abstractmethod -from time import perf_counter -from functools import wraps - -from tqdm import tqdm - -from haystack.schema import Document, MultiLabel -from haystack.errors import HaystackError, PipelineError -from haystack.nodes.base import BaseComponent -from haystack.telemetry import send_event -from haystack.document_stores.base import BaseDocumentStore, FilterType - - -logger = logging.getLogger(__name__) - - -class BaseRetriever(BaseComponent): - """ - Base class for regular retrievers. - """ - - document_store: Optional[BaseDocumentStore] - outgoing_edges = 1 - query_count = 0 - index_count = 0 - query_time = 0.0 - index_time = 0.0 - retrieve_time = 0.0 - - @abstractmethod - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query. - - :param query: The query - :param filters: A dictionary where the keys specify a metadata field and the value is a list of accepted values for that field - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the __init__ is used instead. - """ - pass - - @abstractmethod - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - pass - - def timing(self, fn, attr_name): - """Wrapper method used to time functions.""" - - @wraps(fn) - def wrapper(*args, **kwargs): - if attr_name not in self.__dict__: - self.__dict__[attr_name] = 0 - tic = perf_counter() - ret = fn(*args, **kwargs) - toc = perf_counter() - self.__dict__[attr_name] += toc - tic - return ret - - return wrapper - - def eval( - self, - label_index: str = "label", - doc_index: str = "eval_document", - label_origin: str = "gold-label", - top_k: int = 10, - open_domain: bool = False, - return_preds: bool = False, - headers: Optional[Dict[str, str]] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> dict: - """ - Performs evaluation on the Retriever. - Retriever is evaluated based on whether it finds the correct document given the query string and at which - position in the ranking of documents the correct document is. - - Returns a dict containing the following metrics: - - - "recall": Proportion of questions for which correct document is among retrieved documents - - "mrr": Mean of reciprocal rank. Rewards retrievers that give relevant documents a higher rank. - Only considers the highest ranked relevant document. - - "map": Mean of average precision for each question. Rewards retrievers that give relevant - documents a higher rank. Considers all retrieved relevant documents. If ``open_domain=True``, - average precision is normalized by the number of retrieved relevant documents per query. - If ``open_domain=False``, average precision is normalized by the number of all relevant documents - per query. - - :param label_index: Index/Table in DocumentStore where labeled questions are stored - :param doc_index: Index/Table in DocumentStore where documents that are used for evaluation are stored - :param top_k: How many documents to return per query - :param open_domain: If ``True``, retrieval will be evaluated by checking if the answer string to a question is - contained in the retrieved docs (common approach in open-domain QA). - If ``False``, retrieval uses a stricter evaluation that checks if the retrieved document ids - are within ids explicitly stated in the labels. - :param return_preds: Whether to add predictions in the returned dictionary. If True, the returned dictionary - contains the keys "predictions" and "metrics". - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication) - """ - send_event( - event_name="Evaluation", event_properties={"class": self.__class__.__name__, "function_name": "eval"} - ) - # Extract all questions for evaluation - filters: Dict = {"origin": [label_origin]} - - timed_retrieve = self.timing(self.retrieve, "retrieve_time") - - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the eval() method." - ) - labels: List[MultiLabel] = document_store.get_all_labels_aggregated( - index=label_index, - filters=filters, - open_domain=open_domain, - drop_negative_labels=True, - drop_no_answers=False, - headers=headers, - ) - - correct_retrievals = 0 - summed_avg_precision = 0.0 - summed_reciprocal_rank = 0.0 - - # Collect questions and corresponding answers/document_ids in a dict - question_label_dict = {} - for label in labels: - # document_ids are empty if no_answer == True - if not label.no_answer: - id_question_tuple = (label.document_ids[0], label.query) - if open_domain: - # here are no no_answer '' included if there are other actual answers - question_label_dict[id_question_tuple] = label.answers - else: - deduplicated_doc_ids = list({str(x) for x in label.document_ids}) - question_label_dict[id_question_tuple] = deduplicated_doc_ids - - predictions = [] - - # Option 1: Open-domain evaluation by checking if the answer string is in the retrieved docs - logger.info("Performing eval queries...") - if open_domain: - for (_, question), gold_answers in tqdm(question_label_dict.items()): - retrieved_docs = timed_retrieve(question, top_k=top_k, index=doc_index, headers=headers) - if return_preds: - predictions.append({"question": question, "retrieved_docs": retrieved_docs}) - # check if correct doc in retrieved docs - found_relevant_doc = False - relevant_docs_found = 0 - current_avg_precision = 0.0 - for doc_idx, doc in enumerate(retrieved_docs): - for gold_answer in gold_answers: - if gold_answer in doc.content: - relevant_docs_found += 1 - if not found_relevant_doc: - correct_retrievals += 1 - summed_reciprocal_rank += 1 / (doc_idx + 1) - current_avg_precision += relevant_docs_found / (doc_idx + 1) - found_relevant_doc = True - break - if found_relevant_doc: - summed_avg_precision += current_avg_precision / relevant_docs_found - # Option 2: Strict evaluation by document ids that are listed in the labels - else: - for (_, question), gold_ids in tqdm(question_label_dict.items()): - retrieved_docs = timed_retrieve(question, top_k=top_k, index=doc_index, headers=headers) - if return_preds: - predictions.append({"question": question, "retrieved_docs": retrieved_docs}) - # check if correct doc in retrieved docs - found_relevant_doc = False - relevant_docs_found = 0 - current_avg_precision = 0.0 - for doc_idx, doc in enumerate(retrieved_docs): - for gold_id in gold_ids: - if str(doc.id) == gold_id: - relevant_docs_found += 1 - if not found_relevant_doc: - correct_retrievals += 1 - summed_reciprocal_rank += 1 / (doc_idx + 1) - current_avg_precision += relevant_docs_found / (doc_idx + 1) - found_relevant_doc = True - break - if found_relevant_doc: - all_relevant_docs = len(set(gold_ids)) - summed_avg_precision += current_avg_precision / all_relevant_docs - # Metrics - number_of_questions = len(question_label_dict) - recall = correct_retrievals / number_of_questions - mean_reciprocal_rank = summed_reciprocal_rank / number_of_questions - mean_avg_precision = summed_avg_precision / number_of_questions - - logger.info( - "For {} out of {} questions ({:.2%}), the answer was in the top-{} candidate passages selected by the retriever.".format( - correct_retrievals, number_of_questions, recall, top_k - ) - ) - - metrics = { - "recall": recall, - "map": mean_avg_precision, - "mrr": mean_reciprocal_rank, - "retrieve_time": self.retrieve_time, - "n_questions": number_of_questions, - "top_k": top_k, - } - - if return_preds: - return {"metrics": metrics, "predictions": predictions} - else: - return metrics - - def run( # type: ignore - self, - root_node: str, - query: Optional[str] = None, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - documents: Optional[List[Document]] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - ): - """ - :param root_node: The root node of the pipeline's graph. - :param query: Query string. - :param filters: A dictionary where the keys specify a metadata field and the value is a list of accepted values for that field. - :param top_k: How many documents to return per query. - :param documents: List of Documents to Retrieve. - :param index: The name of the index in the DocumentStore from which to retrieve documents. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication). - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default), similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise, raw similarity scores (e.g. cosine or dot_product) will be used. - """ - if root_node == "Query": - if query is None: - raise HaystackError( - "Must provide a 'query' parameter for retrievers in pipelines where Query is the root node." - ) - if not isinstance(query, str): - logger.error( - "The retriever received an unusual query: '%s' This query is likely to produce garbage output.", - query, - ) - self.query_count += 1 - run_query_timed = self.timing(self.run_query, "query_time") - output, stream = run_query_timed( - query=query, filters=filters, top_k=top_k, index=index, headers=headers, scale_score=scale_score - ) - elif root_node == "File": - self.index_count += len(documents) if documents else 0 - run_indexing = self.timing(self.run_indexing, "index_time") - output, stream = run_indexing(documents=documents) - else: - raise PipelineError(f"Invalid root_node '{root_node}'.") - return output, stream - - def run_batch( # type: ignore - self, - root_node: str, - queries: Optional[List[str]] = None, - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - ): - """ - :param root_node: The root node of the pipeline's graph. - :param queries: The list of query strings. - :param filters: A dictionary where the keys specify a metadata field and the value is a list of accepted values for that field. - :param top_k: How many documents to return per query. - :param documents: List of Documents of Retrieve. - :param index: The name of the index in the DocumentStore from which to retrieve documents. - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='} for basic authentication). - """ - if root_node == "Query": - if queries is None: - raise HaystackError( - "Must provide a 'queries' parameter for retrievers in pipelines where Query is the root node." - ) - if not all(isinstance(query, str) for query in queries): - logger.error( - "The retriever received an unusual list of queries: '%s' Some of these queries are likely to produce garbage output.", - queries, - ) - self.query_count += len(queries) if isinstance(queries, list) else 1 - run_query_batch_timed = self.timing(self.run_query_batch, "query_time") - output, stream = run_query_batch_timed( - queries=queries, filters=filters, top_k=top_k, index=index, headers=headers - ) - - elif root_node == "File": - self.index_count += len(documents) # type: ignore - run_indexing = self.timing(self.run_indexing, "index_time") - output, stream = run_indexing(documents=documents) - else: - raise PipelineError(f"Invalid root_node '{root_node}'.") - return output, stream - - def run_query( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - ): - documents = self.retrieve( - query=query, filters=filters, top_k=top_k, index=index, headers=headers, scale_score=scale_score - ) - document_ids = [doc.id for doc in documents] - logger.debug("Retrieved documents with IDs: %s", document_ids) - output = {"documents": documents} - - return output, "output_1" - - def run_query_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - ): - documents = self.retrieve_batch( - queries=queries, filters=filters, top_k=top_k, index=index, headers=headers, batch_size=batch_size - ) - if isinstance(queries, str): - document_ids = [] - for doc in documents: - if not isinstance(doc, Document): - raise HaystackError(f"doc was of type {type(doc)}, but expected a Document.") - document_ids.append(doc.id) - logger.debug("Retrieved documents with IDs: %s", document_ids) - else: - for doc_list in documents: - if not isinstance(doc_list, list): - raise HaystackError(f"doc_list was of type {type(doc_list)}, but expected a list of Documents.") - document_ids = [doc.id for doc in doc_list] - logger.debug("Retrieved documents with IDs: %s", document_ids) - output = {"documents": documents} - - return output, "output_1" - - def run_indexing(self, documents: List[Document]): - output = {"documents": documents} - return output, "output_1" - - def print_time(self): - print("Retriever (Speed)") - print("---------------") - if not self.index_count: - print("No indexing performed via Retriever.run()") - else: - print(f"Documents indexed: {self.index_count}") - print(f"Index time: {self.index_time}s") - print(f"{self.query_time / self.query_count} seconds per document") - if not self.query_count: - print("No querying performed via Retriever.run()") - else: - print(f"Queries Performed: {self.query_count}") - print(f"Query time: {self.query_time}s") - print(f"{self.query_time / self.query_count} seconds per query") - - @staticmethod - def _get_batches(queries: List[str], batch_size: Optional[int]) -> Iterator[List[str]]: - if batch_size is None: - yield queries - return - else: - for index in range(0, len(queries), batch_size): - yield queries[index : index + batch_size] diff --git a/haystack/nodes/retriever/dense.py b/haystack/nodes/retriever/dense.py deleted file mode 100644 index d4663e6cfd..0000000000 --- a/haystack/nodes/retriever/dense.py +++ /dev/null @@ -1,2331 +0,0 @@ -# pylint: disable=ungrouped-imports -from abc import abstractmethod -from typing import List, Dict, Union, Optional, Any, Literal - -import logging -from pathlib import Path -from copy import deepcopy -from requests.exceptions import HTTPError - -import numpy as np -from tqdm import tqdm - -import pandas as pd -from huggingface_hub import hf_hub_download - -from haystack.errors import HaystackError -from haystack.schema import Document, FilterType -from haystack.document_stores import BaseDocumentStore -from haystack.nodes.retriever.base import BaseRetriever -from haystack.nodes.retriever._embedding_encoder import _EMBEDDING_ENCODERS, COHERE_EMBEDDING_MODELS -from haystack.utils.early_stopping import EarlyStopping -from haystack.telemetry import send_event -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from torch.nn import DataParallel - from torch.utils.data.sampler import SequentialSampler - from transformers import AutoConfig, AutoTokenizer - from haystack.modeling.model.language_model import get_language_model, DPREncoder - from haystack.modeling.model.biadaptive_model import BiAdaptiveModel - from haystack.modeling.model.triadaptive_model import TriAdaptiveModel - from haystack.modeling.model.prediction_head import TextSimilarityHead - from haystack.modeling.data_handler.processor import TextSimilarityProcessor, TableTextSimilarityProcessor - from haystack.modeling.data_handler.data_silo import DataSilo - from haystack.modeling.data_handler.dataloader import NamedDataLoader - from haystack.modeling.model.optimization import initialize_optimizer - from haystack.modeling.training.base import Trainer - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class DenseRetriever(BaseRetriever): - """ - Base class for all dense retrievers. - """ - - @abstractmethod - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - pass - - @abstractmethod - def embed_documents(self, documents: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of documents. - - :param documents: List of documents to embed. - :return: Embeddings of documents, one per input document, shape: (documents, embedding_dim) - """ - pass - - def run_indexing(self, documents: List[Document]): - embeddings = self.embed_documents(documents) - for doc, emb in zip(documents, embeddings): - doc.embedding = emb - output = {"documents": documents} - return output, "output_1" - - -class DensePassageRetriever(DenseRetriever): - """ - Retriever that uses a bi-encoder (one transformer for query, one transformer for passage). - See the original paper for more details: - Karpukhin, Vladimir, et al. (2020): "Dense Passage Retrieval for Open-Domain Question Answering." - (https://arxiv.org/abs/2004.04906). - """ - - def __init__( - self, - document_store: Optional[BaseDocumentStore] = None, - query_embedding_model: Union[Path, str] = "facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model: Union[Path, str] = "facebook/dpr-ctx_encoder-single-nq-base", - model_version: Optional[str] = None, - max_seq_len_query: int = 64, - max_seq_len_passage: int = 256, - top_k: int = 10, - use_gpu: bool = True, - batch_size: int = 16, - embed_title: bool = True, - use_fast_tokenizers: bool = True, - similarity_function: str = "dot_product", - global_loss_buffer_size: int = 150000, - progress_bar: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - use_auth_token: Optional[Union[str, bool]] = None, - scale_score: bool = True, - ): - """ - Init the Retriever incl. the two encoder models from a local or remote model checkpoint. - The checkpoint format matches huggingface transformers' model format - - **Example:** - - ```python - # remote model from FAIR - DensePassageRetriever(document_store=your_doc_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base") - # or from local path - DensePassageRetriever(document_store=your_doc_store, - query_embedding_model="model_directory/question-encoder", - passage_embedding_model="model_directory/context-encoder") - ``` - - :param document_store: An instance of DocumentStore from which to retrieve documents. - :param query_embedding_model: Local path or remote name of question encoder checkpoint. The format equals the - one used by hugging-face transformers' modelhub models - Currently available remote names: ``"facebook/dpr-question_encoder-single-nq-base"`` - :param passage_embedding_model: Local path or remote name of passage encoder checkpoint. The format equals the - one used by hugging-face transformers' modelhub models - Currently available remote names: ``"facebook/dpr-ctx_encoder-single-nq-base"`` - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param max_seq_len_query: Longest length of each query sequence. Maximum number of tokens for the query text. Longer ones will be cut down." - :param max_seq_len_passage: Longest length of each passage/context sequence. Maximum number of tokens for the passage text. Longer ones will be cut down." - :param top_k: How many documents to return per query. - :param use_gpu: Whether to use all available GPUs or the CPU. Falls back on CPU if no GPU is available. - :param batch_size: Number of questions or passages to encode at once. In case of multiple gpus, this will be the total batch size. - :param embed_title: Whether to concatenate title and passage to a text pair that is then used to create the embedding. - This is the approach used in the original paper and is likely to improve performance if your - titles contain meaningful information for retrieval (topic, entities etc.) . - The title is expected to be present in doc.meta["name"] and can be supplied in the documents - before writing them to the DocumentStore like this: - {"text": "my text", "meta": {"name": "my title"}}. - :param use_fast_tokenizers: Whether to use fast Rust tokenizers - :param similarity_function: Which function to apply for calculating the similarity of query and passage embeddings during training. - Options: `dot_product` (Default) or `cosine` - :param global_loss_buffer_size: Buffer size for all_gather() in DDP. - Increase if errors like "encoded data exceeds max_size ..." come up - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - Note: as multi-GPU training is currently not implemented for DPR, training - will only use the first device provided in this list. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - """ - torch_and_transformers_import.check() - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=True) - - if batch_size < len(self.devices): - logger.warning("Batch size is less than the number of devices. All gpus will not be utilized.") - - self.document_store = document_store - self.batch_size = batch_size - self.progress_bar = progress_bar - self.top_k = top_k - self.scale_score = scale_score - self.use_auth_token = use_auth_token - - if document_store and document_store.similarity != "dot_product": - logger.warning( - "You are using a Dense Passage Retriever model with the %s function. " - "We recommend you use dot_product instead. " - "This can be set when initializing the DocumentStore", - document_store.similarity, - ) - - # Init & Load Encoders - self.query_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=query_embedding_model, - revision=model_version, - do_lower_case=True, - use_fast=use_fast_tokenizers, - use_auth_token=use_auth_token, - ) - self.query_encoder = DPREncoder( - pretrained_model_name_or_path=query_embedding_model, - model_type="DPRQuestionEncoder", - use_auth_token=use_auth_token, - ) - self.passage_tokenizer = AutoTokenizer.from_pretrained( - pretrained_model_name_or_path=passage_embedding_model, - revision=model_version, - do_lower_case=True, - use_fast=use_fast_tokenizers, - use_auth_token=use_auth_token, - ) - self.passage_encoder = DPREncoder( - pretrained_model_name_or_path=passage_embedding_model, - model_type="DPRContextEncoder", - use_auth_token=use_auth_token, - ) - - self.processor = TextSimilarityProcessor( - query_tokenizer=self.query_tokenizer, - passage_tokenizer=self.passage_tokenizer, - max_seq_len_passage=max_seq_len_passage, - max_seq_len_query=max_seq_len_query, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - embed_title=embed_title, - num_hard_negatives=0, - num_positives=1, - ) - prediction_head = TextSimilarityHead( - similarity_function=similarity_function, global_loss_buffer_size=global_loss_buffer_size - ) - self.model = BiAdaptiveModel( - language_model1=self.query_encoder, - language_model2=self.passage_encoder, - prediction_heads=[prediction_head], - embeds_dropout_prob=0.1, - lm1_output_types=["per_sequence"], - lm2_output_types=["per_sequence"], - device=self.devices[0], - ) - - self.model.connect_heads_with_processor(self.processor.tasks, require_labels=False) - - if len(self.devices) > 1: - self.model = DataParallel(self.model, device_ids=self.devices) # type: ignore [assignment] - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through the documents in a DocumentStore and return a small number of documents - that are most relevant to the query. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic API_KEY'} for basic authentication) - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve() method." - ) - if top_k is None: - top_k = self.top_k - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - query_emb = self.embed_queries(queries=[query]) - documents = document_store.query_by_embedding( - query_emb=query_emb[0], top_k=top_k, filters=filters, index=index, headers=headers, scale_score=scale_score - ) - return documents - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - """ - Scan through the documents in a DocumentStore and return a small number of documents - that are most relevant to the supplied queries. - - Returns a list of lists of Documents (one per query). - - :param queries: List of query strings. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. Can be a single filter that will be applied to each query or a list of filters - (one filter per query). - - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic API_KEY'} for basic authentication) - :param batch_size: Number of queries to embed at a time. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different - value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve() method." - ) - - if top_k is None: - top_k = self.top_k - - if batch_size is None: - batch_size = self.batch_size - - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - - query_embs: List[np.ndarray] = [] - for batch in self._get_batches(queries=queries, batch_size=batch_size): - query_embs.extend(self.embed_queries(queries=batch)) - documents = document_store.query_by_embedding_batch( - query_embs=query_embs, top_k=top_k, filters=filters, index=index, headers=headers, scale_score=scale_score - ) - - return documents - - def _get_predictions(self, dicts: List[Dict[str, Any]]) -> Dict[str, np.ndarray]: - """ - Feed a preprocessed dataset to the model and get the actual predictions (forward pass + formatting). - - :param dicts: list of dictionaries - examples:[{'query': "where is florida?"}, {'query': "who wrote lord of the rings?"}, ...] - [{'passages': [{ - "title": 'Big Little Lies (TV series)', - "text": 'series garnered several accolades. It received..', - "label": 'positive', - "external_id": '18768923'}, - {"title": 'Framlingham Castle', - "text": 'Castle on the Hill "Castle on the Hill" is a song by English..', - "label": 'positive', - "external_id": '19930582'}, ...] - :return: dictionary of embeddings for "passages" and "query" - """ - dataset, tensor_names, _, _ = self.processor.dataset_from_dicts( - dicts, indices=list(range(len(dicts))), return_baskets=True - ) - - data_loader = NamedDataLoader( - dataset=dataset, sampler=SequentialSampler(dataset), batch_size=self.batch_size, tensor_names=tensor_names - ) - query_embeddings_batched = [] - passage_embeddings_batched = [] - self.model.eval() - - # When running evaluations etc., we don't want a progress bar for every single query - if len(dataset) == 1: - disable_tqdm = True - else: - disable_tqdm = not self.progress_bar - - with tqdm( - total=len(data_loader) * self.batch_size, - unit=" Docs", - desc="Create embeddings", - position=1, - leave=False, - disable=disable_tqdm, - ) as progress_bar: - for raw_batch in data_loader: - batch = {key: raw_batch[key].to(self.devices[0]) for key in raw_batch} - - # get logits - with torch.inference_mode(): - query_embeddings, passage_embeddings = self.model.forward( - query_input_ids=batch.get("query_input_ids", None), - query_segment_ids=batch.get("query_segment_ids", None), - query_attention_mask=batch.get("query_attention_mask", None), - passage_input_ids=batch.get("passage_input_ids", None), - passage_segment_ids=batch.get("passage_segment_ids", None), - passage_attention_mask=batch.get("passage_attention_mask", None), - )[0] - if query_embeddings is not None: - query_embeddings_batched.append(query_embeddings.cpu().numpy()) - if passage_embeddings is not None: - passage_embeddings_batched.append(passage_embeddings.cpu().numpy()) - progress_bar.update(self.batch_size) - - all_embeddings: Dict[str, np.ndarray] = {} - if passage_embeddings_batched: - all_embeddings["passages"] = np.concatenate(passage_embeddings_batched) - if query_embeddings_batched: - all_embeddings["query"] = np.concatenate(query_embeddings_batched) - return all_embeddings - - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries using the query encoder. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - query_dicts = [{"query": q} for q in queries] - result = self._get_predictions(query_dicts)["query"] - return result - - def embed_documents(self, documents: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of documents using the passage encoder. - - :param documents: List of documents to embed. - :return: Embeddings of documents, one per input document, shape: (documents, embedding_dim) - """ - if self.processor.num_hard_negatives != 0: - logger.warning( - "'num_hard_negatives' is set to %s, but inference does " - "not require any hard negatives. Setting num_hard_negatives to 0.", - self.processor.num_hard_negatives, - ) - self.processor.num_hard_negatives = 0 - - passages = [ - { - "passages": [ - { - "title": d.meta["name"] if d.meta and "name" in d.meta else "", - "text": d.content, - "label": d.meta["label"] if d.meta and "label" in d.meta else "positive", - "external_id": d.id, - } - ] - } - for d in documents - ] - embeddings = self._get_predictions(passages)["passages"] - return embeddings - - def train( - self, - data_dir: str, - train_filename: str, - dev_filename: Optional[str] = None, - test_filename: Optional[str] = None, - max_samples: Optional[int] = None, - max_processes: int = 128, - multiprocessing_strategy: Optional[str] = None, - dev_split: float = 0, - batch_size: int = 2, - embed_title: bool = True, - num_hard_negatives: int = 1, - num_positives: int = 1, - n_epochs: int = 3, - evaluate_every: int = 1000, - n_gpu: int = 1, - learning_rate: float = 1e-5, - epsilon: float = 1e-08, - weight_decay: float = 0.0, - num_warmup_steps: int = 100, - grad_acc_steps: int = 1, - use_amp: bool = False, - optimizer_name: str = "AdamW", - optimizer_correct_bias: bool = True, - save_dir: str = "../saved_models/dpr", - query_encoder_save_dir: str = "query_encoder", - passage_encoder_save_dir: str = "passage_encoder", - checkpoint_root_dir: Path = Path("model_checkpoints"), - checkpoint_every: Optional[int] = None, - checkpoints_to_keep: int = 3, - early_stopping: Optional[EarlyStopping] = None, - ): - """ - train a DensePassageRetrieval model - :param data_dir: Directory where training file, dev file and test file are present - :param train_filename: training filename - :param dev_filename: development set filename, file to be used by model in eval step of training - :param test_filename: test set filename, file to be used by model in test step after training - :param max_samples: maximum number of input samples to convert. Can be used for debugging a smaller dataset. - :param max_processes: the maximum number of processes to spawn in the multiprocessing.Pool used in DataSilo. - It can be set to 1 to disable the use of multiprocessing or make debugging easier. - :param multiprocessing_strategy: Set the multiprocessing sharing strategy, this can be one of file_descriptor/file_system depending on your OS. - If your system has low limits for the number of open file descriptors, and you can’t raise them, - you should use the file_system strategy. - :param dev_split: The proportion of the train set that will be sliced. Only works if dev_filename is set to None - :param batch_size: total number of samples in 1 batch of data - :param embed_title: whether to concatenate passage title with each passage. The default setting in official DPR embeds passage title with the corresponding passage - :param num_hard_negatives: number of hard negative passages(passages which are very similar(high score by BM25) to query but do not contain the answer - :param num_positives: number of positive passages - :param n_epochs: number of epochs to train the model on - :param evaluate_every: number of training steps after evaluation is run - :param n_gpu: number of gpus to train on - :param learning_rate: learning rate of optimizer - :param epsilon: epsilon parameter of optimizer - :param weight_decay: weight decay parameter of optimizer - :param grad_acc_steps: number of steps to accumulate gradient over before back-propagation is done - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param optimizer_name: what optimizer to use (default: AdamW) - :param num_warmup_steps: number of warmup steps - :param optimizer_correct_bias: Whether to correct bias in optimizer - :param save_dir: directory where models are saved - :param query_encoder_save_dir: directory inside save_dir where query_encoder model files are saved - :param passage_encoder_save_dir: directory inside save_dir where passage_encoder model files are saved - :param checkpoint_root_dir: The Path of a directory where all train checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoint_every: Save a train checkpoint after this many steps of training. - :param checkpoints_to_keep: The maximum number of train checkpoints to save. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - - Checkpoints can be stored via setting `checkpoint_every` to a custom number of steps. - If any checkpoints are stored, a subsequent run of train() will resume training from the latest available checkpoint. - """ - send_event(event_name="Training", event_properties={"class": self.__class__.__name__, "function_name": "train"}) - self.processor.embed_title = embed_title - self.processor.data_dir = Path(data_dir) - self.processor.train_filename = train_filename - self.processor.dev_filename = dev_filename - self.processor.test_filename = test_filename - self.processor.max_samples = max_samples - self.processor.dev_split = dev_split - self.processor.num_hard_negatives = num_hard_negatives - self.processor.num_positives = num_positives - - if isinstance(self.model, DataParallel): - self.model.module.connect_heads_with_processor(self.processor.tasks, require_labels=True) # type: ignore [operator] - else: - self.model.connect_heads_with_processor(self.processor.tasks, require_labels=True) - - data_silo = DataSilo( - processor=self.processor, - batch_size=batch_size, - distributed=False, - max_processes=max_processes, - multiprocessing_strategy=multiprocessing_strategy, - ) - - # 5. Create an optimizer - self.model, optimizer, lr_schedule = initialize_optimizer( - model=self.model, # type: ignore [arg-type] - learning_rate=learning_rate, - optimizer_opts={ - "name": optimizer_name, - "correct_bias": optimizer_correct_bias, - "weight_decay": weight_decay, - "eps": epsilon, - }, - schedule_opts={"name": "LinearWarmup", "num_warmup_steps": num_warmup_steps}, - n_batches=len(data_silo.loaders["train"]), - n_epochs=n_epochs, - grad_acc_steps=grad_acc_steps, - device=self.devices[0], # Only use first device while multi-gpu training is not implemented - ) - - # 6. Feed everything to the Trainer, which keeps care of growing our model and evaluates it from time to time - trainer = Trainer.create_or_load_checkpoint( - model=self.model, - optimizer=optimizer, - data_silo=data_silo, - epochs=n_epochs, - n_gpu=n_gpu, - lr_schedule=lr_schedule, - evaluate_every=evaluate_every, - device=self.devices[0], # Only use first device while multi-gpu training is not implemented - use_amp=use_amp, - checkpoint_root_dir=Path(checkpoint_root_dir), - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - early_stopping=early_stopping, - ) - - # 7. Let it grow! Watch the tracked metrics live on experiment tracker (e.g. Mlflow) - trainer.train() - - self.model.save(Path(save_dir), lm1_name=query_encoder_save_dir, lm2_name=passage_encoder_save_dir) - self.query_tokenizer.save_pretrained(f"{save_dir}/{query_encoder_save_dir}") - self.passage_tokenizer.save_pretrained(f"{save_dir}/{passage_encoder_save_dir}") - - if len(self.devices) > 1 and not isinstance(self.model, DataParallel): - self.model = DataParallel(self.model, device_ids=self.devices) # type: ignore [assignment] - - def save( - self, - save_dir: Union[Path, str], - query_encoder_dir: str = "query_encoder", - passage_encoder_dir: str = "passage_encoder", - ): - """ - Save DensePassageRetriever to the specified directory. - - :param save_dir: Directory to save to. - :param query_encoder_dir: Directory in save_dir that contains query encoder model. - :param passage_encoder_dir: Directory in save_dir that contains passage encoder model. - :return: None - """ - save_dir = Path(save_dir) - self.model.save(save_dir, lm1_name=query_encoder_dir, lm2_name=passage_encoder_dir) - save_dir = str(save_dir) - self.query_tokenizer.save_pretrained(save_dir + f"/{query_encoder_dir}") - self.passage_tokenizer.save_pretrained(save_dir + f"/{passage_encoder_dir}") - - @classmethod - def load( - cls, - load_dir: Union[Path, str], - document_store: BaseDocumentStore, - max_seq_len_query: int = 64, - max_seq_len_passage: int = 256, - use_gpu: bool = True, - batch_size: int = 16, - embed_title: bool = True, - use_fast_tokenizers: bool = True, - similarity_function: str = "dot_product", - query_encoder_dir: str = "query_encoder", - passage_encoder_dir: str = "passage_encoder", - ): - """ - Load DensePassageRetriever from the specified directory. - """ - load_dir = Path(load_dir) - dpr = cls( - document_store=document_store, - query_embedding_model=Path(load_dir) / query_encoder_dir, - passage_embedding_model=Path(load_dir) / passage_encoder_dir, - max_seq_len_query=max_seq_len_query, - max_seq_len_passage=max_seq_len_passage, - use_gpu=use_gpu, - batch_size=batch_size, - embed_title=embed_title, - use_fast_tokenizers=use_fast_tokenizers, - similarity_function=similarity_function, - ) - logger.info("DPR model loaded from %s", load_dir) - - return dpr - - -class TableTextRetriever(DenseRetriever): - """ - Retriever that uses a tri-encoder to jointly retrieve among a database consisting of text passages and tables - (one transformer for query, one transformer for text passages, one transformer for tables). - See the original paper for more details: - Kostić, Bogdan, et al. (2021): "Multi-modal Retrieval of Tables and Texts Using Tri-encoder Models" - (https://arxiv.org/abs/2108.04049), - """ - - def __init__( - self, - document_store: Optional[BaseDocumentStore] = None, - query_embedding_model: Union[Path, str] = "deepset/bert-small-mm_retrieval-question_encoder", - passage_embedding_model: Union[Path, str] = "deepset/bert-small-mm_retrieval-passage_encoder", - table_embedding_model: Union[Path, str] = "deepset/bert-small-mm_retrieval-table_encoder", - model_version: Optional[str] = None, - max_seq_len_query: int = 64, - max_seq_len_passage: int = 256, - max_seq_len_table: int = 256, - top_k: int = 10, - use_gpu: bool = True, - batch_size: int = 16, - embed_meta_fields: Optional[List[str]] = None, - use_fast_tokenizers: bool = True, - similarity_function: str = "dot_product", - global_loss_buffer_size: int = 150000, - progress_bar: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - use_auth_token: Optional[Union[str, bool]] = None, - scale_score: bool = True, - use_fast: bool = True, - ): - """ - Init the Retriever incl. the two encoder models from a local or remote model checkpoint. - The checkpoint format matches huggingface transformers' model format - - :param document_store: An instance of DocumentStore from which to retrieve documents. - :param query_embedding_model: Local path or remote name of question encoder checkpoint. The format equals the - one used by hugging-face transformers' modelhub models. - :param passage_embedding_model: Local path or remote name of passage encoder checkpoint. The format equals the - one used by hugging-face transformers' modelhub models. - :param table_embedding_model: Local path or remote name of table encoder checkpoint. The format equals the - one used by hugging-face transformers' modelhub models. - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param max_seq_len_query: Longest length of each query sequence. Maximum number of tokens for the query text. Longer ones will be cut down." - :param max_seq_len_passage: Longest length of each passage/context sequence. Maximum number of tokens for the passage text. Longer ones will be cut down." - :param top_k: How many documents to return per query. - :param use_gpu: Whether to use all available GPUs or the CPU. Falls back on CPU if no GPU is available. - :param batch_size: Number of questions or passages to encode at once. In case of multiple gpus, this will be the total batch size. - :param embed_meta_fields: Concatenate the provided meta fields and text passage / table to a text pair that is - then used to create the embedding. - This is the approach used in the original paper and is likely to improve - performance if your titles contain meaningful information for retrieval - (topic, entities etc.). If no value is provided, a default will be created. - That default embeds name, section title and caption. - :param use_fast_tokenizers: Whether to use fast Rust tokenizers - :param similarity_function: Which function to apply for calculating the similarity of query and passage embeddings during training. - Options: `dot_product` (Default) or `cosine` - :param global_loss_buffer_size: Buffer size for all_gather() in DDP. - Increase if errors like "encoded data exceeds max_size ..." come up - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - Note: as multi-GPU training is currently not implemented for TableTextRetriever, - training will only use the first device provided in this list. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param use_fast: Whether to use the fast version of DPR tokenizers or fallback to the standard version. Defaults to True. - """ - torch_and_transformers_import.check() - - if embed_meta_fields is None: - embed_meta_fields = ["name", "section_title", "caption"] - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=True) - - if batch_size < len(self.devices): - logger.warning("Batch size is less than the number of devices.All gpus will not be utilized.") - - self.document_store = document_store - self.batch_size = batch_size - self.progress_bar = progress_bar - self.top_k = top_k - self.embed_meta_fields = embed_meta_fields - self.scale_score = scale_score - - # Init & Load Encoders - self.query_tokenizer = AutoTokenizer.from_pretrained( - query_embedding_model, - revision=model_version, - do_lower_case=True, - use_fast=use_fast_tokenizers, - use_auth_token=use_auth_token, - ) - self.query_encoder = get_language_model( - pretrained_model_name_or_path=query_embedding_model, revision=model_version, use_auth_token=use_auth_token - ) - self.passage_tokenizer = AutoTokenizer.from_pretrained( - passage_embedding_model, - revision=model_version, - do_lower_case=True, - use_fast=use_fast_tokenizers, - use_auth_token=use_auth_token, - ) - self.passage_encoder = get_language_model( - pretrained_model_name_or_path=passage_embedding_model, revision=model_version, use_auth_token=use_auth_token - ) - self.table_tokenizer = AutoTokenizer.from_pretrained( - table_embedding_model, - revision=model_version, - do_lower_case=True, - use_fast=use_fast_tokenizers, - use_auth_token=use_auth_token, - ) - self.table_encoder = get_language_model( - pretrained_model_name_or_path=table_embedding_model, revision=model_version, use_auth_token=use_auth_token - ) - - self.processor = TableTextSimilarityProcessor( - query_tokenizer=self.query_tokenizer, - passage_tokenizer=self.passage_tokenizer, - table_tokenizer=self.table_tokenizer, - max_seq_len_query=max_seq_len_query, - max_seq_len_passage=max_seq_len_passage, - max_seq_len_table=max_seq_len_table, - label_list=["hard_negative", "positive"], - metric="text_similarity_metric", - embed_meta_fields=embed_meta_fields, - num_hard_negatives=0, - num_positives=1, - ) - - prediction_head = TextSimilarityHead( - similarity_function=similarity_function, global_loss_buffer_size=global_loss_buffer_size - ) - - self.model = TriAdaptiveModel( - language_model1=self.query_encoder, - language_model2=self.passage_encoder, - language_model3=self.table_encoder, - prediction_heads=[prediction_head], - embeds_dropout_prob=0.1, - lm1_output_types=["per_sequence"], - lm2_output_types=["per_sequence"], - lm3_output_types=["per_sequence"], - device=self.devices[0], - ) - - self.model.connect_heads_with_processor(self.processor.tasks, require_labels=False) - - if len(self.devices) > 1: - self.model = DataParallel(self.model, device_ids=self.devices) # type: ignore [assignment] - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - if top_k is None: - top_k = self.top_k - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve() method." - ) - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - query_emb = self.embed_queries(queries=[query]) - documents = document_store.query_by_embedding( - query_emb=query_emb[0], top_k=top_k, filters=filters, index=index, headers=headers, scale_score=scale_score - ) - return documents - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - """ - Scan through the documents in a DocumentStore and return a small number of documents - that are most relevant to the supplied queries. - - Returns a list of lists of Documents (one per query). - - :param queries: List of query strings. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. Can be a single filter that will be applied to each query or a list of filters - (one filter per query). - - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic API_KEY'} for basic authentication) - :param batch_size: Number of queries to embed at a time. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different - value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve_batch() method." - ) - - if top_k is None: - top_k = self.top_k - - if batch_size is None: - batch_size = self.batch_size - - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - - # embed_queries is already batched within by batch_size, so no need to batch the input here - query_embs: np.ndarray = self.embed_queries(queries=queries) - batched_query_embs: List[np.ndarray] = [] - for i in range(0, len(query_embs), batch_size): - batched_query_embs.extend(query_embs[i : i + batch_size]) - documents = document_store.query_by_embedding_batch( - query_embs=batched_query_embs, - top_k=top_k, - filters=filters, - index=index, - headers=headers, - scale_score=scale_score, - ) - - return documents - - def _get_predictions(self, dicts: List[Dict[str, Any]]) -> Dict[str, np.ndarray]: - """ - Feed a preprocessed dataset to the model and get the actual predictions (forward pass + formatting). - - :param dicts: list of dictionaries - examples:[{'query': "where is florida?"}, {'query': "who wrote lord of the rings?"}, ...] - [{'passages': [{ - "title": 'Big Little Lies (TV series)', - "text": 'series garnered several accolades. It received..', - "label": 'positive', - "external_id": '18768923'}, - {"title": 'Framlingham Castle', - "text": 'Castle on the Hill "Castle on the Hill" is a song by English..', - "label": 'positive', - "external_id": '19930582'}, ...] - :return: dictionary of embeddings for "passages" and "query" - """ - - dataset, tensor_names, _, _ = self.processor.dataset_from_dicts( - dicts, indices=list(range(len(dicts))), return_baskets=True - ) - - data_loader = NamedDataLoader( - dataset=dataset, sampler=SequentialSampler(dataset), batch_size=self.batch_size, tensor_names=tensor_names - ) - query_embeddings_batched = [] - passage_embeddings_batched = [] - self.model.eval() - - # When running evaluations etc., we don't want a progress bar for every single query - if dataset and len(dataset) == 1: - disable_tqdm = True - else: - disable_tqdm = not self.progress_bar - - with tqdm( - total=len(data_loader) * self.batch_size, - unit=" Docs", - desc="Create embeddings", - position=1, - leave=False, - disable=disable_tqdm, - ) as progress_bar: - for batch in data_loader: - batch = {key: batch[key].to(self.devices[0]) for key in batch} - - # get logits - with torch.inference_mode(): - query_embeddings, passage_embeddings = self.model.forward(**batch)[0] - if query_embeddings is not None: - query_embeddings_batched.append(query_embeddings.cpu().numpy()) - if passage_embeddings is not None: - passage_embeddings_batched.append(passage_embeddings.cpu().numpy()) - progress_bar.update(self.batch_size) - - all_embeddings: Dict[str, np.ndarray] = {} - if passage_embeddings_batched: - all_embeddings["passages"] = np.concatenate(passage_embeddings_batched) - if query_embeddings_batched: - all_embeddings["query"] = np.concatenate(query_embeddings_batched) - return all_embeddings - - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries using the query encoder. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - query_dicts = [{"query": q} for q in queries] - result = self._get_predictions(query_dicts)["query"] - return result - - def embed_documents(self, documents: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of text documents and / or tables using the text passage encoder and - the table encoder. - - :param documents: List of documents to embed. - :return: Embeddings of documents, one per input document, shape: (documents, embedding_dim) - """ - - if self.processor.num_hard_negatives != 0: - logger.warning( - "'num_hard_negatives' is set to %s, but inference does " - "not require any hard negatives. Setting num_hard_negatives to 0.", - self.processor.num_hard_negatives, - ) - self.processor.num_hard_negatives = 0 - - model_input = [] - for doc in documents: - if doc.content_type == "table": - model_input.append( - { - "passages": [ - { - "meta": [ - doc.meta[meta_field] - for meta_field in self.embed_meta_fields - if meta_field in doc.meta and isinstance(doc.meta[meta_field], str) - ], - "columns": doc.content.columns.tolist(), # type: ignore - "rows": doc.content.values.tolist(), # type: ignore - "label": doc.meta["label"] if doc.meta and "label" in doc.meta else "positive", - "type": "table", - "external_id": doc.id, - } - ] - } - ) - else: - model_input.append( - { - "passages": [ - { - "meta": [ - doc.meta[meta_field] - for meta_field in self.embed_meta_fields - if meta_field in doc.meta and isinstance(doc.meta[meta_field], str) - ], - "text": doc.content, - "label": doc.meta["label"] if doc.meta and "label" in doc.meta else "positive", - "type": "text", - "external_id": doc.id, - } - ] - } - ) - - embeddings = self._get_predictions(model_input)["passages"] - - return embeddings - - def train( - self, - data_dir: str, - train_filename: str, - dev_filename: Optional[str] = None, - test_filename: Optional[str] = None, - max_samples: Optional[int] = None, - max_processes: int = 128, - dev_split: float = 0, - batch_size: int = 2, - embed_meta_fields: Optional[List[str]] = None, - num_hard_negatives: int = 1, - num_positives: int = 1, - n_epochs: int = 3, - evaluate_every: int = 1000, - n_gpu: int = 1, - learning_rate: float = 1e-5, - epsilon: float = 1e-08, - weight_decay: float = 0.0, - num_warmup_steps: int = 100, - grad_acc_steps: int = 1, - use_amp: bool = False, - optimizer_name: str = "AdamW", - optimizer_correct_bias: bool = True, - save_dir: str = "../saved_models/mm_retrieval", - query_encoder_save_dir: str = "query_encoder", - passage_encoder_save_dir: str = "passage_encoder", - table_encoder_save_dir: str = "table_encoder", - checkpoint_root_dir: Path = Path("model_checkpoints"), - checkpoint_every: Optional[int] = None, - checkpoints_to_keep: int = 3, - early_stopping: Optional[EarlyStopping] = None, - ): - """ - Train a TableTextRetrieval model. - :param data_dir: Directory where training file, dev file and test file are present. - :param train_filename: Training filename. - :param dev_filename: Development set filename, file to be used by model in eval step of training. - :param test_filename: Test set filename, file to be used by model in test step after training. - :param max_samples: Maximum number of input samples to convert. Can be used for debugging a smaller dataset. - :param max_processes: The maximum number of processes to spawn in the multiprocessing.Pool used in DataSilo. - It can be set to 1 to disable the use of multiprocessing or make debugging easier. - :param dev_split: The proportion of the train set that will be sliced. Only works if dev_filename is set to None. - :param batch_size: Total number of samples in 1 batch of data. - :param embed_meta_fields: Concatenate meta fields with each passage and table. - If no value is provided, a default will be created. That default embeds page title, - section title and caption with the corresponding table and title with - corresponding text passage. - :param num_hard_negatives: Number of hard negative passages (passages which are - very similar (high score by BM25) to query but do not contain the answer)- - :param num_positives: Number of positive passages. - :param n_epochs: Number of epochs to train the model on. - :param evaluate_every: Number of training steps after evaluation is run. - :param n_gpu: Number of gpus to train on. - :param learning_rate: Learning rate of optimizer. - :param epsilon: Epsilon parameter of optimizer. - :param weight_decay: Weight decay parameter of optimizer. - :param grad_acc_steps: Number of steps to accumulate gradient over before back-propagation is done. - :param use_amp: Whether to use automatic mixed precision (AMP) natively implemented in PyTorch to improve - training speed and reduce GPU memory usage. - For more information, see (Haystack Optimization)[https://haystack.deepset.ai/guides/optimization] - and (Automatic Mixed Precision Package - Torch.amp)[https://pytorch.org/docs/stable/amp.html]. - :param optimizer_name: What optimizer to use (default: TransformersAdamW). - :param num_warmup_steps: Number of warmup steps. - :param optimizer_correct_bias: Whether to correct bias in optimizer. - :param save_dir: Directory where models are saved. - :param query_encoder_save_dir: Directory inside save_dir where query_encoder model files are saved. - :param passage_encoder_save_dir: Directory inside save_dir where passage_encoder model files are saved. - :param table_encoder_save_dir: Directory inside save_dir where table_encoder model files are saved. - :param checkpoint_root_dir: The Path of a directory where all train checkpoints are saved. For each individual - checkpoint, a subdirectory with the name epoch_{epoch_num}_step_{step_num} is created. - :param checkpoint_every: Save a train checkpoint after this many steps of training. - :param checkpoints_to_keep: The maximum number of train checkpoints to save. - :param early_stopping: An initialized EarlyStopping object to control early stopping and saving of the best models. - """ - send_event(event_name="Training", event_properties={"class": self.__class__.__name__, "function_name": "train"}) - if embed_meta_fields is None: - embed_meta_fields = ["page_title", "section_title", "caption"] - - self.processor.embed_meta_fields = embed_meta_fields - self.processor.data_dir = Path(data_dir) - self.processor.train_filename = train_filename - self.processor.dev_filename = dev_filename - self.processor.test_filename = test_filename - self.processor.max_samples = max_samples - self.processor.dev_split = dev_split - self.processor.num_hard_negatives = num_hard_negatives - self.processor.num_positives = num_positives - - if isinstance(self.model, DataParallel): - self.model.module.connect_heads_with_processor(self.processor.tasks, require_labels=True) # type: ignore [operator] - else: - self.model.connect_heads_with_processor(self.processor.tasks, require_labels=True) - - data_silo = DataSilo( - processor=self.processor, batch_size=batch_size, distributed=False, max_processes=max_processes - ) - - # 5. Create an optimizer - self.model, optimizer, lr_schedule = initialize_optimizer( - model=self.model, # type: ignore [arg-type] - learning_rate=learning_rate, - optimizer_opts={ - "name": optimizer_name, - "correct_bias": optimizer_correct_bias, - "weight_decay": weight_decay, - "eps": epsilon, - }, - schedule_opts={"name": "LinearWarmup", "num_warmup_steps": num_warmup_steps}, - n_batches=len(data_silo.loaders["train"]), - n_epochs=n_epochs, - grad_acc_steps=grad_acc_steps, - device=self.devices[0], # Only use first device while multi-gpu training is not implemented - ) - - # 6. Feed everything to the Trainer, which keeps care of growing our model and evaluates it from time to time - trainer = Trainer.create_or_load_checkpoint( - model=self.model, - optimizer=optimizer, - data_silo=data_silo, - epochs=n_epochs, - n_gpu=n_gpu, - lr_schedule=lr_schedule, - evaluate_every=evaluate_every, - device=self.devices[0], # Only use first device while multi-gpu training is not implemented - use_amp=use_amp, - checkpoint_root_dir=Path(checkpoint_root_dir), - checkpoint_every=checkpoint_every, - checkpoints_to_keep=checkpoints_to_keep, - early_stopping=early_stopping, - ) - - # 7. Let it grow! Watch the tracked metrics live on experiment tracker (e.g. Mlflow) - trainer.train() - - self.model.save( - Path(save_dir), - lm1_name=query_encoder_save_dir, - lm2_name=passage_encoder_save_dir, - lm3_name=table_encoder_save_dir, - ) - self.query_tokenizer.save_pretrained(f"{save_dir}/{query_encoder_save_dir}") - self.passage_tokenizer.save_pretrained(f"{save_dir}/{passage_encoder_save_dir}") - self.table_tokenizer.save_pretrained(f"{save_dir}/{table_encoder_save_dir}") - - if len(self.devices) > 1: - self.model = DataParallel(self.model, device_ids=self.devices) # type: ignore [assignment] - - def save( - self, - save_dir: Union[Path, str], - query_encoder_dir: str = "query_encoder", - passage_encoder_dir: str = "passage_encoder", - table_encoder_dir: str = "table_encoder", - ): - """ - Save TableTextRetriever to the specified directory. - - :param save_dir: Directory to save to. - :param query_encoder_dir: Directory in save_dir that contains query encoder model. - :param passage_encoder_dir: Directory in save_dir that contains passage encoder model. - :param table_encoder_dir: Directory in save_dir that contains table encoder model. - :return: None - """ - save_dir = Path(save_dir) - self.model.save(save_dir, lm1_name=query_encoder_dir, lm2_name=passage_encoder_dir, lm3_name=table_encoder_dir) - save_dir = str(save_dir) - self.query_tokenizer.save_pretrained(save_dir + f"/{query_encoder_dir}") - self.passage_tokenizer.save_pretrained(save_dir + f"/{passage_encoder_dir}") - self.table_tokenizer.save_pretrained(save_dir + f"/{table_encoder_dir}") - - @classmethod - def load( - cls, - load_dir: Union[Path, str], - document_store: BaseDocumentStore, - max_seq_len_query: int = 64, - max_seq_len_passage: int = 256, - max_seq_len_table: int = 256, - use_gpu: bool = True, - batch_size: int = 16, - embed_meta_fields: Optional[List[str]] = None, - use_fast_tokenizers: bool = True, - similarity_function: str = "dot_product", - query_encoder_dir: str = "query_encoder", - passage_encoder_dir: str = "passage_encoder", - table_encoder_dir: str = "table_encoder", - ): - """ - Load TableTextRetriever from the specified directory. - """ - if embed_meta_fields is None: - embed_meta_fields = ["name", "section_title", "caption"] - - load_dir = Path(load_dir) - mm_retriever = cls( - document_store=document_store, - query_embedding_model=Path(load_dir) / query_encoder_dir, - passage_embedding_model=Path(load_dir) / passage_encoder_dir, - table_embedding_model=Path(load_dir) / table_encoder_dir, - max_seq_len_query=max_seq_len_query, - max_seq_len_passage=max_seq_len_passage, - max_seq_len_table=max_seq_len_table, - use_gpu=use_gpu, - batch_size=batch_size, - embed_meta_fields=embed_meta_fields, - use_fast_tokenizers=use_fast_tokenizers, - similarity_function=similarity_function, - ) - logger.info("TableTextRetriever model loaded from %s", load_dir) - - return mm_retriever - - -class EmbeddingRetriever(DenseRetriever): - def __init__( - self, - embedding_model: str, - document_store: Optional[BaseDocumentStore] = None, - model_version: Optional[str] = None, - use_gpu: bool = True, - batch_size: int = 32, - max_seq_len: int = 512, - model_format: Optional[str] = None, - pooling_strategy: str = "reduce_mean", - query_prompt: Optional[str] = None, - passage_prompt: Optional[str] = None, - emb_extraction_layer: int = -1, - top_k: int = 10, - progress_bar: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - use_auth_token: Optional[Union[str, bool]] = None, - scale_score: bool = True, - embed_meta_fields: Optional[List[str]] = None, - api_key: Optional[str] = None, - azure_api_version: str = "2022-12-01", - azure_base_url: Optional[str] = None, - azure_deployment_name: Optional[str] = None, - api_base: str = "https://api.openai.com/v1", - openai_organization: Optional[str] = None, - ): - """ - :param document_store: An instance of DocumentStore from which to retrieve documents. - :param embedding_model: Local path or name of model in Hugging Face's model hub such - as ``'sentence-transformers/all-MiniLM-L6-v2'``. The embedding model could also - potentially be an OpenAI model ["ada", "babbage", "davinci", "curie"] or - a Cohere model ["embed-english-v2.0", "embed-english-light-v2.0", "embed-multilingual-v2.0"]. - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param use_gpu: Whether to use all available GPUs or the CPU. Falls back on CPU if no GPU is available. - :param batch_size: Number of documents to encode at once. - :param max_seq_len: Longest length of each document sequence. Maximum number of tokens for the document text. Longer ones will be cut down. - :param model_format: Name of framework that was used for saving the model or model type. If no model_format is - provided, it will be inferred automatically from the model configuration files. - Options: - - 1. `farm` : (will use `_DefaultEmbeddingEncoder` as embedding encoder) - 2. `transformers` : (will use `_DefaultEmbeddingEncoder` as embedding encoder) - 3. `sentence_transformers` : (will use `_SentenceTransformersEmbeddingEncoder` as embedding encoder) - 4. `retribert` : (will use `_RetribertEmbeddingEncoder` as embedding encoder) - 5. `openai` : (will use `_OpenAIEmbeddingEncoder` as embedding encoder) - 6. `cohere` : (will use `_CohereEmbeddingEncoder` as embedding encoder) - - :param pooling_strategy: Strategy for combining the embeddings from the model (for farm / transformers models only). - Options: - - 1. `cls_token` (sentence vector) - 2. `reduce_mean` (sentence vector) - 3. `reduce_max` (sentence vector) - 4. `per_token` (individual token vectors) - :param query_prompt: Model instruction for embedding texts to be used as queries. - :param passage_prompt: Model instruction for embedding texts to be retrieved. - :param emb_extraction_layer: Number of layer from which the embeddings shall be extracted (for farm / transformers models only). - Default: -1 (very last layer). - :param top_k: How many documents to return per query. - :param progress_bar: If true displays progress bar during embedding. - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - Note: As multi-GPU training is currently not implemented for EmbeddingRetriever, - training will only use the first device provided in this list. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param embed_meta_fields: Concatenate the provided meta fields and text passage / table to a text pair that is - then used to create the embedding. - This approach is also used in the TableTextRetriever paper and is likely to improve - performance if your titles contain meaningful information for retrieval - (topic, entities etc.). - If no value is provided, a default empty list will be created. - :param api_key: The OpenAI API key or the Cohere API key. Required if one wants to use OpenAI/Cohere embeddings. - For more details see https://beta.openai.com/account/api-keys and https://dashboard.cohere.ai/api-keys - :param azure_api_version: The version of the Azure OpenAI API to use. The default is `2022-12-01` version. - :param azure_base_url: The base URL for the Azure OpenAI API. If not supplied, Azure OpenAI API will not be used. - This parameter is an OpenAI Azure endpoint, usually in the form `https://.openai.azure.com' - :param azure_deployment_name: The name of the Azure OpenAI API deployment. If not supplied, Azure OpenAI API - will not be used. - :param api_base: The OpenAI API base URL, defaults to `"https://api.openai.com/v1"`. - :param openai_organization: The OpenAI-Organization ID, defaults to `None`. For more details, see OpenAI - [documentation](https://platform.openai.com/docs/api-reference/requesting-organization). - """ - torch_and_transformers_import.check() - - if embed_meta_fields is None: - embed_meta_fields = [] - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=True) - - if batch_size < len(self.devices): - logger.warning("Batch size is less than the number of devices.All gpus will not be utilized.") - - self.document_store = document_store - self.embedding_model = embedding_model - self.model_version = model_version - self.use_gpu = use_gpu - self.batch_size = batch_size - self.max_seq_len = max_seq_len - self.pooling_strategy = pooling_strategy - self.emb_extraction_layer = emb_extraction_layer - self.query_prompt = query_prompt - self.passage_prompt = passage_prompt - self.top_k = top_k - self.progress_bar = progress_bar - self.use_auth_token = use_auth_token - self.scale_score = scale_score - self.api_key = api_key - self.api_base = api_base - self.api_version = azure_api_version - self.azure_base_url = azure_base_url - self.azure_deployment_name = azure_deployment_name - self.openai_organization = openai_organization - self.model_format = ( - self._infer_model_format(model_name_or_path=embedding_model, use_auth_token=use_auth_token) - if model_format is None - else model_format - ) - - logger.info("Init retriever using embeddings of model %s", embedding_model) - - if self.model_format not in _EMBEDDING_ENCODERS.keys(): - raise ValueError(f"Unknown retriever embedding model format {model_format}") - - if ( - self.embedding_model.startswith("sentence-transformers") - and model_format - and model_format != "sentence_transformers" - ): - logger.warning( - "You seem to be using a Sentence Transformer embedding model but 'model_format' is set to '%s'." - " You may need to set model_format='sentence_transformers' to ensure correct loading of model." - "As an alternative, you can let Haystack derive the format automatically by not setting the " - "'model_format' parameter at all.", - self.model_format, - ) - - self.embedding_encoder = _EMBEDDING_ENCODERS[self.model_format](retriever=self) - self.embed_meta_fields = embed_meta_fields - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through the documents in a DocumentStore and return a small number of documents - that are most relevant to the query. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic API_KEY'} for basic authentication) - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve() method." - ) - if top_k is None: - top_k = self.top_k - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - query_emb = self.embed_queries(queries=[query]) - documents = document_store.query_by_embedding( - query_emb=query_emb[0], filters=filters, top_k=top_k, index=index, headers=headers, scale_score=scale_score - ) - return documents - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - """ - Scan through the documents in a DocumentStore and return a small number of documents - that are most relevant to the supplied queries. - - Returns a list of lists of Documents (one per query). - - :param queries: List of query strings. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. Can be a single filter that will be applied to each query or a list of filters - (one filter per query). - - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic API_KEY'} for basic authentication) - :param batch_size: Number of queries to embed at a time. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different - value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve_batch() method." - ) - if top_k is None: - top_k = self.top_k - - if batch_size is None: - batch_size = self.batch_size - - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - - # embed_queries is already batched within by batch_size, so no need to batch the input here - query_embs: np.ndarray = self.embed_queries(queries=queries) - batched_query_embs: List[np.ndarray] = [] - for i in range(0, len(query_embs), batch_size): - batched_query_embs.extend(query_embs[i : i + batch_size]) - documents = document_store.query_by_embedding_batch( - query_embs=batched_query_embs, - top_k=top_k, - filters=filters, - index=index, - headers=headers, - scale_score=scale_score, - ) - - return documents - - def embed_queries(self, queries: List[str]) -> np.ndarray: - """ - Create embeddings for a list of queries. - - :param queries: List of queries to embed. - :return: Embeddings, one per input query, shape: (queries, embedding_dim) - """ - # for backward compatibility: cast pure str input - if isinstance(queries, str): - queries = [queries] - assert isinstance(queries, list), "Expecting a list of texts, i.e. create_embeddings(texts=['text1',...])" - if self.query_prompt: - queries = [self.query_prompt + " " + q for q in queries] - return self.embedding_encoder.embed_queries(queries) - - def embed_documents(self, documents: List[Document]) -> np.ndarray: - """ - Create embeddings for a list of documents. - - :param documents: List of documents to embed. - :return: Embeddings, one per input document, shape: (docs, embedding_dim) - """ - documents = self._preprocess_documents(documents) - if self.passage_prompt: - for doc in documents: - doc.content = self.passage_prompt + " " + doc.content - return self.embedding_encoder.embed_documents(documents) - - def _preprocess_documents(self, docs: List[Document]) -> List[Document]: - """ - Turns table documents into text documents by representing the table in csv format. - This allows us to use text embedding models for table retrieval. - It also concatenates specified meta data fields with the text representations. - - :param docs: List of documents to linearize. If the document is not a table, it is returned as is. - :return: List of documents with meta data + linearized tables or original documents if they are not tables. - """ - linearized_docs = [] - for doc in docs: - doc = deepcopy(doc) - if doc.content_type == "table": - if isinstance(doc.content, pd.DataFrame): - doc.content = doc.content.to_csv(index=False) - else: - raise HaystackError("Documents of type 'table' need to have a pd.DataFrame as content field") - # Gather all relevant metadata fields - meta_data_fields = [] - for key in self.embed_meta_fields: - if key in doc.meta and doc.meta[key]: - if isinstance(doc.meta[key], list): - meta_data_fields.extend(list(doc.meta[key])) - else: - meta_data_fields.append(doc.meta[key]) - # Convert to type string (e.g. for ints or floats) - meta_data_fields = [str(field) for field in meta_data_fields] - doc.content = "\n".join(meta_data_fields + [doc.content]) - linearized_docs.append(doc) - return linearized_docs - - @staticmethod - def _infer_model_format(model_name_or_path: str, use_auth_token: Optional[Union[str, bool]]) -> str: - valid_openai_model_name = model_name_or_path in ["ada", "babbage", "davinci", "curie"] or any( - m in model_name_or_path for m in ["-ada-", "-babbage-", "-davinci-", "-curie-"] - ) - if valid_openai_model_name: - return "openai" - if model_name_or_path in COHERE_EMBEDDING_MODELS: - return "cohere" - # Check if model name is a local directory with sentence transformers config file in it - if Path(model_name_or_path).exists(): - if Path(f"{model_name_or_path}/config_sentence_transformers.json").exists(): - return "sentence_transformers" - # Check if sentence transformers config file in model hub - else: - try: - hf_hub_download( # type: ignore [call-arg] - repo_id=model_name_or_path, - filename="config_sentence_transformers.json", - use_auth_token=use_auth_token, - ) - return "sentence_transformers" - except HTTPError: - pass - - # Check if retribert model - config = AutoConfig.from_pretrained(model_name_or_path, use_auth_token=use_auth_token) - if config.model_type == "retribert": - return "retribert" - - # Model is neither sentence-transformers nor retribert model -> use _DefaultEmbeddingEncoder - return "farm" - - def train( - self, - training_data: List[Dict[str, Any]], - learning_rate: float = 2e-5, - n_epochs: int = 1, - num_warmup_steps: Optional[int] = None, - batch_size: int = 16, - train_loss: Literal["mnrl", "margin_mse"] = "mnrl", - num_workers: int = 0, - use_amp: bool = False, - **kwargs, - ) -> None: - """ - Trains/adapts the underlying embedding model. We only support the training of sentence-transformer embedding models. - - Each training data example is a dictionary with the following keys: - - * question: the question string - * pos_doc: the positive document string - * neg_doc: the negative document string - * score: the score margin - - :param training_data: The training data in a dictionary format. - :param learning_rate: The learning rate. - :param n_epochs: The number of epochs that you want the train for. - :param num_warmup_steps: Behavior depends on the scheduler. For WarmupLinear (default), the learning rate is - increased from 0 up to the maximal learning rate. After these many training steps, the learning rate is - decreased linearly back to zero. - :param batch_size: The batch size to use for the training. The default values is 16. - :param train_loss: The loss to use for training. - If you're using a sentence-transformer embedding_model (which is the only model that training is supported for), - possible values are 'mnrl' (Multiple Negatives Ranking Loss) or 'margin_mse' (MarginMSE). - :param num_workers: The number of subprocesses to use for the Pytorch DataLoader. - :param use_amp: Use Automatic Mixed Precision (AMP). - :param kwargs: Additional training key word arguments to pass to the `SentenceTransformer.fit` function. Please - reference the Sentence-Transformers [documentation](https://www.sbert.net/docs/training/overview.html#sentence_transformers.SentenceTransformer.fit) - for a full list of keyword arguments. - """ - send_event(event_name="Training", event_properties={"class": self.__class__.__name__, "function_name": "train"}) - self.embedding_encoder.train( - training_data, - learning_rate=learning_rate, - n_epochs=n_epochs, - num_warmup_steps=num_warmup_steps, - batch_size=batch_size, - train_loss=train_loss, - num_workers=num_workers, - use_amp=use_amp, - **kwargs, - ) - - def save(self, save_dir: Union[Path, str]) -> None: - """ - Save the model to the given directory - - :param save_dir: The directory where the model will be saved - :type save_dir: Union[Path, str] - """ - self.embedding_encoder.save(save_dir=save_dir) - - -class MultihopEmbeddingRetriever(EmbeddingRetriever): - """ - Retriever that applies iterative retrieval using a shared encoder for query and passage. - See original paper for more details: - - Xiong, Wenhan, et. al. (2020): "Answering complex open-domain questions with multi-hop dense retrieval" - (https://arxiv.org/abs/2009.12756) - """ - - def __init__( - self, - embedding_model: str, - document_store: Optional[BaseDocumentStore] = None, - model_version: Optional[str] = None, - num_iterations: int = 2, - use_gpu: bool = True, - batch_size: int = 32, - max_seq_len: int = 512, - model_format: str = "farm", - pooling_strategy: str = "reduce_mean", - emb_extraction_layer: int = -1, - top_k: int = 10, - progress_bar: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - use_auth_token: Optional[Union[str, bool]] = None, - scale_score: bool = True, - embed_meta_fields: Optional[List[str]] = None, - ): - """ - :param document_store: An instance of DocumentStore from which to retrieve documents. - :param embedding_model: Local path or name of model in Hugging Face's model hub such as ``'sentence-transformers/all-MiniLM-L6-v2'`` - :param model_version: The version of model to use from the HuggingFace model hub. Can be tag name, branch name, or commit hash. - :param num_iterations: The number of times passages are retrieved, i.e., the number of hops (Defaults to 2.) - :param use_gpu: Whether to use all available GPUs or the CPU. Falls back on CPU if no GPU is available. - :param batch_size: Number of documents to encode at once. - :param max_seq_len: Longest length of each document sequence. Maximum number of tokens for the document text. Longer ones will be cut down. - :param model_format: Name of framework that was used for saving the model or model type. If no model_format is - provided, it will be inferred automatically from the model configuration files. - Options: - - - ``'farm'`` (will use `_DefaultEmbeddingEncoder` as embedding encoder) - - ``'transformers'`` (will use `_DefaultEmbeddingEncoder` as embedding encoder) - - ``'sentence_transformers'`` (will use `_SentenceTransformersEmbeddingEncoder` as embedding encoder) - - ``'retribert'`` (will use `_RetribertEmbeddingEncoder` as embedding encoder) - :param pooling_strategy: Strategy for combining the embeddings from the model (for farm / transformers models only). - Options: - - - ``'cls_token'`` (sentence vector) - - ``'reduce_mean'`` (sentence vector) - - ``'reduce_max'`` (sentence vector) - - ``'per_token'`` (individual token vectors) - :param emb_extraction_layer: Number of layer from which the embeddings shall be extracted (for farm / transformers models only). - Default: -1 (very last layer). - :param top_k: How many documents to return per query. - :param progress_bar: If true displays progress bar during embedding. - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - Note: As multi-GPU training is currently not implemented for EmbeddingRetriever, - training will only use the first device provided in this list. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param embed_meta_fields: Concatenate the provided meta fields and text passage / table to a text pair that is - then used to create the embedding. - This approach is also used in the TableTextRetriever paper and is likely to improve - performance if your titles contain meaningful information for retrieval - (topic, entities etc.). - If no value is provided, a default empty list will be created. - """ - torch_and_transformers_import.check() - - if embed_meta_fields is None: - embed_meta_fields = [] - super().__init__( - embedding_model=embedding_model, - document_store=document_store, - model_version=model_version, - use_gpu=use_gpu, - batch_size=batch_size, - max_seq_len=max_seq_len, - model_format=model_format, - pooling_strategy=pooling_strategy, - emb_extraction_layer=emb_extraction_layer, - top_k=top_k, - progress_bar=progress_bar, - devices=devices, - use_auth_token=use_auth_token, - scale_score=scale_score, - embed_meta_fields=embed_meta_fields, - ) - self.num_iterations = num_iterations - - def _merge_query_and_context(self, query: str, context: List[Document], sep: str = " "): - return sep.join([query] + [doc.content for doc in context]) - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through the documents in a DocumentStore and return a small number of documents - that are most relevant to the query. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic API_KEY'} for basic authentication) - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - return self.retrieve_batch( - queries=[query], - filters=[filters] if filters is not None else None, - top_k=top_k, - index=index, - headers=headers, - scale_score=scale_score, - batch_size=1, - )[0] - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - """ - Scan through the documents in a DocumentStore and return a small number of documents - that are most relevant to the supplied queries. - - If you supply a single query, a single list of Documents is returned. If you supply a list of queries, a list of - lists of Documents (one per query) is returned. - - :param queries: Single query string or list of queries. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. Can be a single filter that will be applied to each query or a list of filters - (one filter per query). - - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to document store client if supported (e.g. {'Authorization': 'Basic API_KEY'} for basic authentication) - :param batch_size: Number of queries to embed at a time. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different - value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve_batch() method." - ) - - if top_k is None: - top_k = self.top_k - - if batch_size is None: - batch_size = self.batch_size - - if isinstance(filters, list): - if len(filters) != len(queries): - raise HaystackError( - "Number of filters does not match number of queries. Please provide as many filters" - " as queries or a single filter that will be applied to each query." - ) - else: - filters = [filters] * len(queries) - - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - - documents = [] - batches = self._get_batches(queries=queries, batch_size=batch_size) - # TODO: Currently filters are applied both for final and context documents. - # maybe they should only apply for final docs? or make it configurable with a param? - pb = tqdm(total=len(queries), disable=not self.progress_bar, desc="Querying") - for batch, cur_filters in zip(batches, filters): - context_docs: List[List[Document]] = [[] for _ in range(len(batch))] - for it in range(self.num_iterations): - texts = [self._merge_query_and_context(q, c) for q, c in zip(batch, context_docs)] - query_embs = self.embed_queries(texts) - cur_docs_batch = document_store.query_by_embedding_batch( - query_embs=query_embs, - top_k=top_k, - filters=cur_filters, - index=index, - headers=headers, - scale_score=scale_score, - ) - if it < self.num_iterations - 1: - # add doc with highest score to context - for idx, cur_docs in enumerate(cur_docs_batch): - if len(cur_docs) > 0: - context_docs[idx].append(cur_docs[0]) - else: - # documents in the last iteration are final results - documents.extend(cur_docs_batch) - pb.update(len(batch)) - pb.close() - - return documents diff --git a/haystack/nodes/retriever/link_content.py b/haystack/nodes/retriever/link_content.py deleted file mode 100644 index 7f353cb7ff..0000000000 --- a/haystack/nodes/retriever/link_content.py +++ /dev/null @@ -1,354 +0,0 @@ -import inspect -import io -import logging -from collections import defaultdict -from datetime import datetime -from http import HTTPStatus -from typing import Optional, Dict, List, Union, Callable, Any, Tuple -from urllib.parse import urlparse - -import requests -from boilerpy3 import extractors -from requests import Response -from requests.exceptions import InvalidURL, HTTPError -from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type, RetryCallState - -from haystack import __version__ -from haystack.lazy_imports import LazyImport -from haystack.nodes import PreProcessor, BaseComponent -from haystack.schema import Document, MultiLabel - -logger = logging.getLogger(__name__) - -with LazyImport("Run 'pip install farm-haystack[pdf]'") as fitz_import: - import fitz - - -def html_content_handler(response: Response) -> Optional[str]: - """ - Extracts text from HTML response text using the boilerpy3 extractor. - :param response: Response object from the request. - :return: The extracted text. - """ - extractor = extractors.ArticleExtractor(raise_on_failure=False) - return extractor.get_content(response.text) - - -def pdf_content_handler(response: Response) -> Optional[str]: - """ - Extracts text from PDF response stream using the PyMuPDF library. - - :param response: Response object from the request. - :return: The extracted text. - """ - file_path = io.BytesIO(response.content) - with fitz.open(stream=file_path, filetype="pdf") as doc: - text = "\f".join([page.get_text() for page in doc]) - - return text.encode("ascii", errors="ignore").decode() - - -class LinkContentFetcher(BaseComponent): - """ - LinkContentFetcher fetches content from a URL and converts it into a list of Document objects. - - LinkContentFetcher supports the following content types: - - HTML - - PDF - - LinkContentFetcher offers a few options for customizing the content extraction process: - - content_handlers: A dictionary of content handlers to use for extracting content from a response. - - processor: PreProcessor to apply to the extracted text - - raise_on_failure: A boolean indicating whether to raise an exception when a failure occurs - - One can use LinkContentFetcher as a standalone component or as part of a Pipeline. Here is an example of using - LinkContentFetcher as a standalone component: - - ```python - from haystack.nodes import LinkContentFetcher - from haystack.schema import Document - - link_content_fetcher = LinkContentFetcher() - dl_wiki: List[Document] = link_content_fetcher.fetch(url="https://en.wikipedia.org/wiki/Deep_learning") - print(dl_wiki) - ``` - - One can also use LinkContentFetcher as part of a Pipeline. Here is an example of using LinkContentFetcher as part - of a Pipeline: - - ```python - import os - from haystack.nodes import PromptNode, LinkContentFetcher, PromptTemplate - from haystack import Pipeline - - anthropic_key = os.environ.get("ANTHROPIC_API_KEY") - if not anthropic_key: - raise ValueError("Please set the ANTHROPIC_API_KEY environment variable") - - - retriever = LinkContentFetcher() # optionally add additional user agents - pt = PromptTemplate( - "Given the content below, create a summary consisting of three sections: Objectives, " - "Implementation and Learnings/Conclusions.\n" - "Each section should have at least three bullet points. \n" - "In the content below disregard References section.\n\n: {documents}" - ) - - prompt_node = PromptNode("claude-instant-1", - api_key=anthropic_key, - max_length=512, - default_prompt_template=pt, - model_kwargs={"stream": True} - ) - - pipeline = Pipeline() - pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - pipeline.add_node(component=prompt_node, name="PromptNode", inputs=["Retriever"]) - - research_papers = ["https://arxiv.org/pdf/2307.03172.pdf", "https://arxiv.org/pdf/1706.03762.pdf"] - - for research_paper in research_papers: - print(f"Research paper summary: {research_paper}") - pipeline.run(research_paper) - print("\n\n\n") - """ - - outgoing_edges = 1 - - _USER_AGENT = f"haystack/LinkContentRetriever/{__version__}" - - _REQUEST_HEADERS = { - "accept": "*/*", - "User-Agent": _USER_AGENT, - "Accept-Language": "en-US,en;q=0.9,it;q=0.8,es;q=0.7", - "referer": "https://www.google.com/", - } - - def __init__( - self, - content_handlers: Optional[Dict[str, Callable]] = None, - processor: Optional[PreProcessor] = None, - raise_on_failure: Optional[bool] = False, - user_agents: Optional[List[str]] = None, - retry_attempts: Optional[int] = None, - ): - """ - - Creates a LinkContentFetcher instance. - :param content_handlers: A dictionary of content handlers to use for extracting content from a response. - :param processor: PreProcessor to apply to the extracted text - :param raise_on_failure: A boolean indicating whether to raise an exception when a failure occurs - during content extraction. If False, the error is simply logged and the program continues. - Defaults to False. - :param user_agents: A list of user agents to use when fetching content. Defaults to None. - :param retry_attempts: The number of times to retry fetching content. Defaults to 2. - """ - super().__init__() - self.processor = processor - self.raise_on_failure = raise_on_failure - self.user_agents = user_agents or [LinkContentFetcher._USER_AGENT] - self.current_user_agent_idx: int = 0 - self.retry_attempts = retry_attempts or 2 - self.handlers: Dict[str, Callable] = defaultdict(lambda: html_content_handler) - - # register default content handlers - self._register_content_handler("text/html", html_content_handler) - if fitz_import.is_successful(): - self._register_content_handler("application/pdf", pdf_content_handler) - - # register custom content handlers, can override default handlers - if content_handlers: - for content_type, handler in content_handlers.items(): - self._register_content_handler(content_type, handler) - - def fetch(self, url: str, timeout: Optional[int] = 3, doc_kwargs: Optional[dict] = None) -> List[Document]: - """ - Fetches content from a URL and converts it into a list of Document objects. If no content is extracted, - an empty list is returned. - - :param url: URL to fetch content from. - :param timeout: Timeout in seconds for the request. - :param doc_kwargs: Optional kwargs to pass to the Document constructor. - :return: List of Document objects or an empty list if no content is extracted. - """ - if not self._is_valid_url(url): - raise InvalidURL("Invalid or missing URL: {}".format(url)) - - doc_kwargs = doc_kwargs or {} - extracted_doc: Dict[str, Union[str, dict]] = { - "meta": {"url": url, "timestamp": int(datetime.utcnow().timestamp())} - } - extracted_doc.update(doc_kwargs) - response = self._get_response(url, timeout=timeout or 3) - has_content = response.status_code == HTTPStatus.OK and (response.text or response.content) - fetched_documents = [] - if has_content: - # if we get here, we have a valid response, let's try to extract content - # using the registered content handler - extracted_content: str = "" - handler: Callable = self._get_content_type_handler(response.headers.get("Content-Type", "")) - try: - extracted_content = handler(response) - except Exception as e: - if self.raise_on_failure: - raise e - logger.warning("failed to extract content from %s", response.url) - content = extracted_content or extracted_doc.get("snippet_text", "") # fallback to snippet_text - if not content: - return [] - if extracted_content: - logger.debug("%s handler extracted content from %s", handler, url) - - extracted_doc["content"] = content - else: - extracted_doc["content"] = extracted_doc.get("snippet_text", "") # fallback to snippet_text - document = Document.from_dict(extracted_doc) - fetched_documents = self.processor.process(documents=[document]) if self.processor else [document] - - return fetched_documents - - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - ) -> Tuple[Dict, str]: - """ - Fetches content from a URL specified by query parameter and converts it into a list of Document objects. - - param query: The query - a URL to fetch content from. - param file_paths: Not used. - param labels: Not used. - param documents: Not used. - param meta: Not used. - - return: List of Document objects. - """ - if not query: - raise ValueError("LinkContentFetcher run requires the `query` parameter") - documents = self.fetch(url=query) - return {"documents": documents}, "output_1" - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - """ - Takes a list of queries, where each query is expected to be a URL. For each query, the method - fetches content from the specified URL and transforms it into a list of Document objects. The output is a list - of these document lists, where each individual list of Document objects corresponds to the content retrieved - - param queries: List of queries - URLs to fetch content from. - param file_paths: Not used. - param labels: Not used. - param documents: Not used. - param meta: Not used. - param params: Not used. - param debug: Not used. - - return: List of lists of Document objects. - """ - results = [] - if isinstance(queries, str): - queries = [queries] - elif not isinstance(queries, list): - raise ValueError( - "LinkContentFetcher run_batch requires the `queries` parameter to be Union[str, List[str]]" - ) - for query in queries: - results.append(self.fetch(url=query)) - - return {"documents": results}, "output_1" - - def _register_content_handler(self, content_type: str, handler: Callable): - """ - Register a new content handler for a specific content type. - If a handler for the given content type already exists, it will be overridden. - - :param content_type: The content type for which the handler should be used. - :param handler: The handler function. This function should accept a requests.Response object parameter, - and return the extracted text (or None). - """ - if not callable(handler): - raise ValueError(f"handler must be a callable, but got {type(handler).__name__}") - - params = inspect.signature(handler).parameters - if len(params) != 1 or list(params.keys()) != ["response"]: - raise ValueError(f"{content_type} handler must accept 'response: requests.Response' as a single parameter") - - self.handlers[content_type] = handler - - def _get_response(self, url: str, timeout: Optional[int] = None) -> requests.Response: - """ - Fetches content from a URL. Returns a response object. - :param url: The URL to fetch content from. - :param timeout: The timeout in seconds. - :return: A response object. - """ - - @retry( - # we want to reraise the exception if we fail after the last self.retry_attempts - # then we can catch it in the outer try/except block, see below - reraise=True, - stop=stop_after_attempt(self.retry_attempts), - wait=wait_exponential(multiplier=1, min=2, max=10), - retry=(retry_if_exception_type((HTTPError, requests.RequestException))), - # This method is invoked only after failed requests (exception raised) - after=self._switch_user_agent, - ) - def _request(): - # we need a request copy because we modify the headers - headers = self._REQUEST_HEADERS.copy() - headers["User-Agent"] = self.user_agents[self.current_user_agent_idx] - r = requests.get(url, headers=headers, timeout=timeout or 3) - r.raise_for_status() - return r - - try: - response = _request() - except Exception as e: - # catch all exceptions including HTTPError and RequestException - if self.raise_on_failure: - raise e - # if we don't raise on failure, log it, and return a response object - logger.warning("Couldn't retrieve content from %s", url) - response = requests.Response() - finally: - self.current_user_agent_idx = 0 - return response - - def _get_content_type_handler(self, content_type: str) -> Callable: - """ - Get the appropriate content handler based on the content type. - :param content_type: The content type of the response. - :return: The matching content handler callable or the default html_content_handler if no match is found. - """ - content_type_lookup: str = (content_type or "").split(";")[0] - return self.handlers[content_type_lookup] - - def _switch_user_agent(self, retry_state: RetryCallState) -> None: - """ - Switches the User-Agent for this LinkContentRetriever to the next one in the list of user agents. - :param retry_state: The retry state (unused, required by tenacity). - """ - self.current_user_agent_idx = (self.current_user_agent_idx + 1) % len(self.user_agents) - - def _is_valid_url(self, url: str) -> bool: - """ - Checks if a URL is valid. - - :param url: The URL to check. - :return: True if the URL is valid, False otherwise. - """ - - result = urlparse(url) - # schema is http or https and netloc is not empty - return all([result.scheme in ["http", "https"], result.netloc]) diff --git a/haystack/nodes/retriever/multimodal/__init__.py b/haystack/nodes/retriever/multimodal/__init__.py deleted file mode 100644 index 1f445c8e94..0000000000 --- a/haystack/nodes/retriever/multimodal/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.retriever.multimodal.retriever import MultiModalRetriever -from haystack.nodes.retriever.multimodal.embedder import MultiModalEmbedder diff --git a/haystack/nodes/retriever/multimodal/embedder.py b/haystack/nodes/retriever/multimodal/embedder.py deleted file mode 100644 index d5251e1f1a..0000000000 --- a/haystack/nodes/retriever/multimodal/embedder.py +++ /dev/null @@ -1,215 +0,0 @@ -from typing import Union, Optional, Dict, List, Any - -import logging -from pathlib import Path - -from tqdm import tqdm -import numpy as np -from PIL import Image - -from haystack.errors import NodeError, ModelingError -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from haystack.utils.torch_utils import get_devices # pylint: disable=ungrouped-imports - from haystack.modeling.model.multimodal import get_model # pylint: disable=ungrouped-imports - from haystack.modeling.model.multimodal.base import HaystackModel # pylint: disable=ungrouped-imports - - -class MultiModalRetrieverError(NodeError): - pass - - -FilterType = Dict[str, Union[Dict[str, Any], List[Any], str, int, float, bool]] - - -# TODO the keys should match with ContentTypes (currently 'audio' is missing) -DOCUMENT_CONVERTERS = { - # NOTE: Keep this '?' cleaning step, it needs to be double-checked for impact on the inference results. - "text": lambda doc: doc.content[:-1] if doc.content[-1] == "?" else doc.content, - "table": lambda doc: " ".join( - doc.content.columns.tolist() + [cell for row in doc.content.values.tolist() for cell in row] - ), - "image": lambda doc: Image.open(doc.content), -} - -CAN_EMBED_META = ["text", "table"] - - -class MultiModalEmbedder: - def __init__( - self, - embedding_models: Dict[str, Union[Path, str]], # replace str with ContentTypes starting from Python3.8 - feature_extractors_params: Optional[Dict[str, Dict[str, Any]]] = None, - batch_size: int = 16, - embed_meta_fields: Optional[List[str]] = None, - progress_bar: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - use_auth_token: Optional[Union[str, bool]] = None, - ): - """ - Init the Retriever and all its models from a local or remote model checkpoint. - The checkpoint format matches the Hugging Face transformers' model format. - - :param embedding_models: A dictionary matching a local path or remote name of encoder checkpoint with - the content type it should handle ("text", "table", "image", etc...). - The format is the one that Hugging Face Hub models use. - Expected input format: `{'text': 'name_or_path_to_text_model', 'image': 'name_or_path_to_image_model', ... }` - Keep in mind that the models should output in the same embedding space for this retriever to work. - :param feature_extractors_params: A dictionary matching a content type ("text", "table", "image" and so on) with the - parameters of its own feature extractor if the model requires one. - Expected input format: `{'text': {'param_name': 'param_value', ...}, 'image': {'param_name': 'param_value', ...}, ...}` - :param batch_size: Number of questions or passages to encode at once. In case of multiple GPUs, this will be the total batch size. - :param embed_meta_fields: Concatenate the provided meta fields and text passage / image to a text pair that is - then used to create the embedding. - This is the approach used in the original paper and is likely to improve - performance if your titles contain meaningful information for retrieval - (topic, entities etc.). - If no value is provided, a default with "name" as embedding field is created. - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param devices: List of GPU (or CPU) devices to limit inference to certain GPUs and not use all available ones. - These strings are converted into pytorch devices, so use the string notation described - [in the pytorch documentation](https://pytorch.org/docs/simage/tensor_attributes.html?highlight=torch%20device#torch.torch.device) - (for example, ["cuda:0"]). Note: as multi-GPU training is currently not implemented for TableTextRetriever, - training only uses the first device provided in this list. - :param use_auth_token: API token used to download private models from Hugging Face. If this parameter is set to `True`, - the local token is used, which must be previously created using `transformer-cli login`. - For more information, see [Hugging Face documentation](https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained) - """ - torch_and_transformers_import.check() - - if embed_meta_fields is None: - embed_meta_fields = ["name"] - super().__init__() - - self.devices = get_devices(devices) - if batch_size < len(self.devices): - logger.warning("Batch size is lower than the number of devices. Not all GPUs will be utilized.") - - self.batch_size = batch_size - self.progress_bar = progress_bar - self.embed_meta_fields = embed_meta_fields - - feature_extractors_params = { - content_type: {"max_length": 256, **(feature_extractors_params or {}).get(content_type, {})} - for content_type in ["text", "table", "image", "audio"] # FIXME get_args(ContentTypes) from Python3.8 on - } - - self.models: Dict[str, HaystackModel] = {} # replace str with ContentTypes starting from Python3.8 - for content_type, embedding_model in embedding_models.items(): - self.models[content_type] = get_model( - pretrained_model_name_or_path=embedding_model, - content_type=content_type, - devices=self.devices, - autoconfig_kwargs={"use_auth_token": use_auth_token}, - model_kwargs={"use_auth_token": use_auth_token}, - feature_extractor_kwargs=feature_extractors_params[content_type], - ) - - # Check embedding sizes for models: they must all match - if len(self.models) > 1: - sizes = {model.embedding_dim for model in self.models.values()} - if None in sizes: - logger.warning( - "Haystack could not find the output embedding dimensions for '%s'. " - "Dimensions won't be checked before computing the embeddings.", - ", ".join( - {str(model.model_name_or_path) for model in self.models.values() if model.embedding_dim is None} - ), - ) - elif len(sizes) > 1: - embedding_sizes: Dict[int, List[str]] = {} - for model in self.models.values(): - embedding_sizes[model.embedding_dim] = embedding_sizes.get(model.embedding_dim, []) + [ - str(model.model_name_or_path) - ] - raise ValueError(f"Not all models have the same embedding size: {embedding_sizes}") - - def embed(self, documents: List[Document], batch_size: Optional[int] = None) -> np.ndarray: - """ - Create embeddings for a list of documents using the relevant encoder for their content type. - - :param documents: Documents to embed. - :return: Embeddings, one per document, in the form of a np.array - """ - batch_size = batch_size if batch_size is not None else self.batch_size - - all_embeddings = [] - for batch_index in tqdm( - iterable=range(0, len(documents), batch_size), - unit=" Docs", - desc="Create embeddings", - position=1, - leave=False, - disable=not self.progress_bar, - ): - docs_batch = documents[batch_index : batch_index + batch_size] - data_by_type = self._docs_to_data(documents=docs_batch) - - # Get output for each model - outputs_by_type: Dict[str, torch.Tensor] = {} # replace str with ContentTypes starting Python3.8 - for data_type, data in data_by_type.items(): - model = self.models.get(data_type) - if not model: - raise ModelingError( - f"Some data of type {data_type} was passed, but no model capable of handling such data was " - f"initialized. Initialized models: {', '.join(self.models.keys())}" - ) - outputs_by_type[data_type] = model.encode(data=data) - - # Check the output sizes - embedding_sizes = [output.shape[-1] for output in outputs_by_type.values()] - - if not all(embedding_size == embedding_sizes[0] for embedding_size in embedding_sizes): - raise ModelingError( - "Some of the models are using a different embedding size. They should all match. " - f"Embedding sizes by model: " - f"{ {name: output.shape[-1] for name, output in outputs_by_type.items()} }" - ) - - # Combine the outputs in a single matrix - outputs = torch.stack(list(outputs_by_type.values())) - embeddings = outputs.view(-1, embedding_sizes[0]) - embeddings = embeddings.cpu() - all_embeddings.append(embeddings) - - return np.concatenate(all_embeddings) - - def _docs_to_data( - self, documents: List[Document] - ) -> Dict[str, List[Any]]: # FIXME replace str to ContentTypes from Python3.8 - """ - Extract the data to embed from each document and return them classified by content type. - - :param documents: The documents to prepare fur multimodal embedding. - :return: A dictionary containing one key for each content type, and a list of data extracted - from each document, ready to be passed to the feature extractor (for example the content - of a text document, a linearized table, a PIL image object, and so on) - """ - docs_data: Dict[str, List[Any]] = { # FIXME replace str to ContentTypes from Python3.8 - key: [] for key in ["text", "table", "image", "audio"] - } # FIXME get_args(ContentTypes) from Python3.8 on - for doc in documents: - try: - document_converter = DOCUMENT_CONVERTERS[doc.content_type] - except KeyError as e: - raise MultiModalRetrieverError( - f"Unknown content type '{doc.content_type}'. Known types: 'text', 'table', 'image'." # FIXME {', '.join(get_args(ContentTypes))}" from Python3.8 on - ) from e - - data = document_converter(doc) - - if doc.content_type in CAN_EMBED_META: - meta = [v for k, v in (doc.meta or {}).items() if k in self.embed_meta_fields] - data = f"{' '.join(meta)} {data}" if meta else data - - docs_data[doc.content_type].append(data) - - return {key: values for key, values in docs_data.items() if values} diff --git a/haystack/nodes/retriever/multimodal/retriever.py b/haystack/nodes/retriever/multimodal/retriever.py deleted file mode 100644 index 64ed31f77f..0000000000 --- a/haystack/nodes/retriever/multimodal/retriever.py +++ /dev/null @@ -1,222 +0,0 @@ -from typing import Union, Optional, Dict, List, Any - -import logging -from pathlib import Path - -import numpy as np - -from haystack.nodes.retriever import DenseRetriever -from haystack.nodes.retriever.multimodal.embedder import MultiModalEmbedder -from haystack.document_stores import BaseDocumentStore -from haystack.schema import ContentTypes, Document, FilterType -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - - -class MultiModalRetriever(DenseRetriever): - def __init__( - self, - document_store: BaseDocumentStore, - query_embedding_model: Union[Path, str], - document_embedding_models: Dict[str, Union[Path, str]], # Replace str with ContentTypes starting Python3.8 - query_type: str = "text", # Replace str with ContentTypes starting Python3.8 - query_feature_extractor_params: Optional[Dict[str, Any]] = None, - document_feature_extractors_params: Optional[Dict[str, Dict[str, Any]]] = None, - top_k: int = 10, - batch_size: int = 16, - embed_meta_fields: Optional[List[str]] = None, - similarity_function: str = "dot_product", - progress_bar: bool = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - use_auth_token: Optional[Union[str, bool]] = None, - scale_score: bool = True, - ): - """ - Retriever that uses a multiple encoder to jointly retrieve among a database consisting of different - data types. See the original paper for more details: - Kostić, Bogdan, et al. (2021): "Multi-modal Retrieval of Tables and Texts Using Tri-encoder Models" - (https://arxiv.org/abs/2108.04049), - - :param document_store: An instance of DocumentStore from which to retrieve documents. - :param query_embedding_model: Local path or remote name of question encoder checkpoint. The format equals the - one used by Hugging Face transformers' modelhub models. - :param document_embedding_models: Dictionary matching a local path or remote name of document encoder - checkpoint with the content type it should handle ("text", "table", "image", and so on). - The format equals the one used by Hugging Face transformers' modelhub models. - :param query_type: The content type of the query ("text", "image" and so on). - :param query_feature_extraction_params: The parameters to pass to the feature extractor of the query. If no value is provided, a default dictionary with "max_length": 64 will be set. - :param document_feature_extraction_params: The parameters to pass to the feature extractor of the documents. If no value is provided, a default dictionary with "text": {"max_length": 256} will be set. - :param top_k: How many documents to return per query. - :param batch_size: Number of questions or documents to encode at once. For multiple GPUs, this is - the total batch size. - :param embed_meta_fields: Concatenate the provided meta fields to a (text) pair that is then used to create - the embedding. This is likely to improve performance if your titles contain meaningful information - for retrieval (topic, entities, and so on). Note that only text and table documents support this feature. If no values is provided, a default with "name" as embedding field will be created. - :param similarity_function: Which function to apply for calculating the similarity of query and document - embeddings during training. Options: `dot_product` (default) or `cosine`. - :param progress_bar: Whether to show a tqdm progress bar or not. - Can be helpful to disable in production deployments to keep the logs clean. - :param devices: List of GPU (or CPU) devices to limit inference to certain GPUs and not use all available ones. - These strings will be converted into pytorch devices, so use the string notation described in [Tensor Attributes] - (https://pytorch.org/docs/simage/tensor_attributes.html?highlight=torch%20device#torch.torch.device) - (e.g. ["cuda:0"]). Note: As multi-GPU training is currently not implemented for TableTextRetriever, - training only uses the first device provided in this list. - :param use_auth_token: API token used to download private models from Hugging Face. If this parameter is set - to `True`, the local token is used, which must be previously created using `transformer-cli login`. - For more information, see - [Hugging Face documentation](https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained) - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value - range are scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (for example, cosine or dot_product) are used. - """ - torch_and_transformers_import.check() - - if query_feature_extractor_params is None: - query_feature_extractor_params = {"max_length": 64} - if document_feature_extractors_params is None: - document_feature_extractors_params = {"text": {"max_length": 256}} - if embed_meta_fields is None: - embed_meta_fields = ["name"] - super().__init__() - - self.similarity_function = similarity_function - self.progress_bar = progress_bar - self.top_k = top_k - self.scale_score = scale_score - - self.document_embedder = MultiModalEmbedder( - embedding_models=document_embedding_models, - feature_extractors_params=document_feature_extractors_params, - batch_size=batch_size, - embed_meta_fields=embed_meta_fields, - progress_bar=progress_bar, - devices=devices, - use_auth_token=use_auth_token, - ) - - # Try to reuse the same embedder for queries if there is overlap - if document_embedding_models.get(query_type, None) == query_embedding_model: - self.query_embedder = self.document_embedder - else: - self.query_embedder = MultiModalEmbedder( - embedding_models={query_type: query_embedding_model}, - feature_extractors_params={query_type: query_feature_extractor_params}, - batch_size=batch_size, - embed_meta_fields=embed_meta_fields, - progress_bar=progress_bar, - devices=devices, - use_auth_token=use_auth_token, - ) - - self.document_store = document_store - - def retrieve( # type: ignore - self, - query: Any, - query_type: ContentTypes = "text", - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number of documents that are most relevant to the - supplied query. Returns a list of Documents. - - :param query: Query value. It might be text, a path, a table, and so on. - :param query_type: Type of the query ("text", "table", "image" and so on). - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. It can be a single filter applied to each query or a list of filters - (one filter per query). - :param top_k: How many documents to return per query. Must be > 0. - :param index: The name of the index in the DocumentStore from which to retrieve documents. - :param batch_size: Number of queries to embed at a time. Must be > 0. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true, similarity scores (for example, cosine or dot_product) which naturally have a different - value range is scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (for example, cosine or dot_product) are used. - """ - return self.retrieve_batch( - queries=[query], - queries_type=query_type, - filters=[filters], - top_k=top_k, - index=index, - headers=headers, - batch_size=1, - scale_score=scale_score, - document_store=document_store, - )[0] - - def retrieve_batch( # type: ignore - self, - queries: List[Any], - queries_type: ContentTypes = "text", - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - """ - Scan through documents in DocumentStore and return a small number of documents that are most relevant to the - supplied queries. Returns a list of lists of Documents (one list per query). - - This method assumes all queries are of the same data type. Mixed-type query batches (for example one image and one text) - are currently not supported. Group the queries by type and call `retrieve()` on uniform batches only. - - :param queries: List of query values. They might be text, paths, tables, and so on. - :param queries_type: Type of the query ("text", "table", "image" and so on) - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. It can be a single filter that will be applied to each query or a list of filters - (one filter per query). - :param top_k: How many documents to return per query. Must be > 0. - :param index: The name of the index in the DocumentStore from which to retrieve documents. - :param batch_size: Number of queries to embed at a time. Must be > 0. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If True, similarity scores (for example, cosine or dot_product) which naturally have a different - value range are scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (for example, cosine or dot_product) are used. - """ - top_k = top_k or self.top_k - document_store = document_store or self.document_store - if not document_store: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve() or retrieve_batch() method." - ) - index = index or document_store.index - scale_score = scale_score or self.scale_score - - # Embed the queries - we need them into Document format to leverage MultiModalEmbedder.embed() - query_docs = [Document(content=query, content_type=queries_type) for query in queries] - query_embeddings = self.query_embedder.embed(documents=query_docs, batch_size=batch_size) - - # Query documents by embedding (the actual retrieval step) - documents = document_store.query_by_embedding_batch( - query_embs=query_embeddings, - top_k=top_k, - filters=filters, - index=index, - headers=headers, - scale_score=scale_score, - ) - - return documents - - def embed_documents(self, docs: List[Document]) -> np.ndarray: - return self.document_embedder.embed(documents=docs) - - def embed_queries(self, queries: List[str]) -> np.ndarray: - query_documents = [Document(content=query, content_type="text") for query in queries] - return self.query_embedder.embed(documents=query_documents) diff --git a/haystack/nodes/retriever/sparse.py b/haystack/nodes/retriever/sparse.py deleted file mode 100644 index 708dcdb834..0000000000 --- a/haystack/nodes/retriever/sparse.py +++ /dev/null @@ -1,661 +0,0 @@ -# mypy: disable-error-code=override -from typing import Dict, List, Optional, Union, Any - -import logging -from collections import OrderedDict, namedtuple - -import pandas as pd -from sklearn.feature_extraction.text import TfidfVectorizer - -from haystack.schema import Document -from haystack.document_stores.base import BaseDocumentStore, FilterType -from haystack.document_stores import KeywordDocumentStore -from haystack.nodes.retriever import BaseRetriever -from haystack.errors import DocumentStoreError - - -logger = logging.getLogger(__name__) - - -class BM25Retriever(BaseRetriever): - def __init__( - self, - document_store: Optional[KeywordDocumentStore] = None, - top_k: int = 10, - all_terms_must_match: bool = False, - custom_query: Optional[str] = None, - scale_score: bool = True, - ): - """ - :param document_store: An instance of one of the following DocumentStores to retrieve from: InMemoryDocumentStore, ElasticsearchDocumentStore and OpenSearchDocumentStore. - If None, a document store must be passed to the retrieve method for this Retriever to work. - :param all_terms_must_match: Whether all terms of the query must match the document. - If true all query terms must be present in a document in order to be retrieved (i.e the AND operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy AND fish AND restaurant"). - Otherwise at least one query term must be present in a document in order to be retrieved (i.e the OR operator is being used implicitly between query terms: "cozy fish restaurant" -> "cozy OR fish OR restaurant"). - Defaults to False. - :param custom_query: The query string containing a mandatory `${query}` and an optional `${filters}` placeholder. - - **An example custom_query:** - - ```python - { - "size": 10, - "query": { - "bool": { - "should": [{"multi_match": { - "query": ${query}, // mandatory query placeholder - "type": "most_fields", - "fields": ["content", "title"]}}], - "filter": ${filters} // optional filter placeholder - } - }, - } - ``` - - **For this custom_query, a sample `retrieve()` could be:** - - ```python - self.retrieve(query="Why did the revenue increase?", - filters={"years": ["2019"], "quarters": ["Q1", "Q2"]}) - ``` - - Optionally, highlighting can be defined by specifying Elasticsearch's highlight settings. - See https://www.elastic.co/guide/en/elasticsearch/reference/current/highlighting.html. - You will find the highlighted output in the returned Document's meta field by key "highlighted". - - - **Example custom_query with highlighting:** - - ```python - { - "size": 10, - "query": { - "bool": { - "should": [{"multi_match": { - "query": ${query}, // mandatory query placeholder - "type": "most_fields", - "fields": ["content", "title"]}}], - } - }, - "highlight": { // enable highlighting - "fields": { // for fields content and title - "content": {}, - "title": {} - } - }, - } - ``` - - **For this custom_query, highlighting info can be accessed by:** - ```python - docs = self.retrieve(query="Why did the revenue increase?") - highlighted_content = docs[0].meta["highlighted"]["content"] - highlighted_title = docs[0].meta["highlighted"]["title"] - ``` - - :param top_k: How many documents to return per query. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true (default) similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - - """ - super().__init__() - self.document_store: Optional[KeywordDocumentStore] = document_store - self.top_k = top_k - self.custom_query = custom_query - self.all_terms_must_match = all_terms_must_match - self.scale_score = scale_score - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - all_terms_must_match: Optional[bool] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query. - - :param query: The query - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param all_terms_must_match: Whether all terms of the query must match the document. - When set to `True`, the Retriever returns only documents that contain all query terms (that means the AND operator is being used implicitly between query terms. For example, the query "cozy fish restaurant" is read as "cozy AND fish AND restaurant"). - When set to `False`, the Retriever returns documents containing at least one query term (this means the OR operator is being used implicitly between query terms. For example, the query "cozy fish restaurant" is read as "cozy OR fish OR restaurant"). - Defaults to `None`. If you set a value for this parameter, it overwrites self.all_terms_must_match at runtime. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to elasticsearch client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve() method." - ) - if not isinstance(document_store, KeywordDocumentStore): - raise ValueError("document_store must be a subclass of KeywordDocumentStore.") - - if top_k is None: - top_k = self.top_k - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - if all_terms_must_match is None: - all_terms_must_match = self.all_terms_must_match - - documents = document_store.query( - query=query, - filters=filters, - top_k=top_k, - all_terms_must_match=all_terms_must_match, - custom_query=self.custom_query, - index=index, - headers=headers, - scale_score=scale_score, - ) - return documents - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - all_terms_must_match: Optional[bool] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the supplied queries. - - Returns a list of lists of Documents (one per query). - - :param queries: List of query strings. - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain - conditions. - Filters are defined as nested dictionaries. The keys of the dictionaries can be a logical - operator (`"$and"`, `"$or"`, `"$not"`), a comparison operator (`"$eq"`, `"$in"`, `"$gt"`, - `"$gte"`, `"$lt"`, `"$lte"`) or a metadata field name. - Logical operator keys take a dictionary of metadata field names and/or logical operators as - value. Metadata field names take a dictionary of comparison operators as value. Comparison - operator keys take a single value or (in case of `"$in"`) a list of values as value. - If no logical operator is provided, `"$and"` is used as default operation. If no comparison - operator is provided, `"$eq"` (or `"$in"` if the comparison value is a list) is used as default - operation. - - __Example__: - - ```python - filters = { - "$and": { - "type": {"$eq": "article"}, - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": {"$in": ["economy", "politics"]}, - "publisher": {"$eq": "nytimes"} - } - } - } - # or simpler using default operators - filters = { - "type": "article", - "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}, - "rating": {"$gte": 3}, - "$or": { - "genre": ["economy", "politics"], - "publisher": "nytimes" - } - } - ``` - - To use the same logical operator multiple times on the same level, logical operators take - optionally a list of dictionaries as value. - - __Example__: - - ```python - filters = { - "$or": [ - { - "$and": { - "Type": "News Paper", - "Date": { - "$lt": "2019-01-01" - } - } - }, - { - "$and": { - "Type": "Blog Post", - "Date": { - "$gte": "2019-01-01" - } - } - } - ] - } - ``` - :param top_k: How many documents to return per query. - :param all_terms_must_match: Whether all terms of the query must match the document. - When set to `True`, the Retriever returns only documents that contain all query terms (that means the AND operator is being used implicitly between query terms. For example, the query "cozy fish restaurant" is read as "cozy AND fish AND restaurant"). - When set to `False`, the Retriever returns documents containing at least one query term (this means the OR operator is being used implicitly between query terms. For example, the query "cozy fish restaurant" is read as "cozy OR fish OR restaurant").). - Defaults to `None`. If you set a value for this parameter, it overwrites self.all_terms_must_match at runtime. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to elasticsearch client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param batch_size: Not applicable. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different - value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve_batch() method." - ) - if not isinstance(document_store, KeywordDocumentStore): - raise ValueError("document_store must be a subclass of KeywordDocumentStore.") - - if top_k is None: - top_k = self.top_k - if index is None: - index = document_store.index - if scale_score is None: - scale_score = self.scale_score - if all_terms_must_match is None: - all_terms_must_match = self.all_terms_must_match - - documents = document_store.query_batch( - queries=queries, - filters=filters, - top_k=top_k, - all_terms_must_match=all_terms_must_match, - custom_query=self.custom_query, - index=index, - headers=headers, - scale_score=scale_score, - ) - return documents - - -class FilterRetriever(BM25Retriever): - """ - Naive "Retriever" that returns all documents that match the given filters. No impact of query at all. - Helpful for benchmarking, testing and if you want to do QA on small documents without an "active" retriever. - """ - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query. - - :param query: Has no effect, can pass in empty string - :param filters: A dictionary where the keys specify a metadata field and the value is a list of accepted values for that field - :param top_k: Has no effect, pass in any int or None - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param headers: Custom HTTP headers to pass to elasticsearch client (e.g. {'Authorization': 'Basic YWRtaW46cm9vdA=='}) - Check out https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html for more information. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the retrieve() method." - ) - if index is None: - index = document_store.index - documents = document_store.get_all_documents(filters=filters, index=index, headers=headers) - return documents - - -# TODO make Paragraph generic for configurable units of text eg, pages, paragraphs, or split by a char_limit -Paragraph = namedtuple("Paragraph", ["paragraph_id", "document_id", "content", "meta"]) - - -class TfidfRetriever(BaseRetriever): - """ - Read all documents from a SQL backend. - - Split documents into smaller units (eg, paragraphs or pages) to reduce the - computations when text is passed on to a Reader for QA. - - It uses sklearn's TfidfVectorizer to compute a tf-idf matrix. - """ - - def __init__(self, document_store: Optional[BaseDocumentStore] = None, top_k: int = 10, auto_fit=True): - """ - :param document_store: an instance of a DocumentStore to retrieve documents from. - :param top_k: How many documents to return per query. - :param auto_fit: Whether to automatically update tf-idf matrix by calling fit() after new documents have been added - """ - super().__init__() - - self.vectorizer = TfidfVectorizer( - lowercase=True, stop_words=None, token_pattern=r"(?u)\b\w\w+\b", ngram_range=(1, 1) - ) - self.document_store = document_store - self.top_k = top_k - self.auto_fit = auto_fit - self.dataframes: Dict[str, pd.DataFrame] = {} - self.tfidf_matrices: Dict[str, Any] = {} - self.document_counts: Dict[str, int] = {} - if document_store and document_store.get_document_count(): - self.fit(document_store=document_store) - - def _get_all_paragraphs(self, document_store: BaseDocumentStore, index: Optional[str]) -> List[Paragraph]: - """ - Split the list of documents in paragraphs - """ - index = index or document_store.index - documents = document_store.get_all_documents(index=index) - - paragraphs = [] - p_id = 0 - for doc in documents: - for p in doc.content.split( - "\n\n" - ): # TODO: this assumes paragraphs are separated by "\n\n". Can be switched to paragraph tokenizer. - if not p.strip(): # skip empty paragraphs - continue - paragraphs.append(Paragraph(document_id=doc.id, paragraph_id=p_id, content=(p,), meta=doc.meta)) - p_id += 1 - logger.info("Found %s candidate paragraphs from %s docs in DB", len(paragraphs), len(documents)) - return paragraphs - - def _calc_scores(self, queries: List[str], index: str) -> List[Dict[int, float]]: - question_vector = self.vectorizer.transform(queries) - doc_scores_per_query = self.tfidf_matrices[index].dot(question_vector.T).T.toarray() - doc_scores_per_query = [list(enumerate(doc_scores)) for doc_scores in doc_scores_per_query] - indices_and_scores: List[Dict] = [ - OrderedDict(sorted(query_idx_scores, key=lambda tup: tup[1], reverse=True)) - for query_idx_scores in doc_scores_per_query - ] - return indices_and_scores - - def retrieve( - self, - query: str, - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the query. - - :param query: The query - :param filters: A dictionary where the keys specify a metadata field and the value is a list of accepted values for that field - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - if filters: - raise NotImplementedError("TfidfRetriever doesn't support filters.") - if scale_score: - raise NotImplementedError("TfidfRetriever doesn't support scaling score to the unit interval.") - - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "Pass a DocumentStore in the retrieve() method. The Retriever needs a Document Store instance to work." - ) - index = index or document_store.index - if index is None: - raise ValueError( - "Both the `index` parameter passed to the `retrieve` method and the default `index` of the Document store are null. Pass a non-null `index` value." - ) - - if self.auto_fit and ( - index not in self.document_counts - or document_store.get_document_count(headers=headers, index=index) != self.document_counts[index] - ): - # run fit() to update self.dataframes, self.tfidf_matrices and self.document_counts - logger.warning( - "Indexed documents have been updated and fit() method needs to be run before retrieval. Running it now." - ) - self.fit(document_store=document_store, index=index) - if self.dataframes[index] is None: - raise DocumentStoreError( - "Retrieval requires dataframe and tf-idf matrix but fit() did not calculate them probably due to an empty document store." - ) - - if top_k is None: - top_k = self.top_k - # get scores - indices_and_scores = self._calc_scores(queries=[query], index=index) - - # rank paragraphs - df_sliced = self.dataframes[index].loc[indices_and_scores[0].keys()] - df_sliced = df_sliced[:top_k] - - logger.debug( - "Identified %s candidates via retriever:\n%s", - df_sliced.shape[0], - df_sliced.to_string(col_space=10, index=False), - ) - - # get actual content for the top candidates - paragraphs = list(df_sliced.content.values) - meta_data = [ - {"document_id": row["document_id"], "paragraph_id": row["paragraph_id"], "meta": row.get("meta", {})} - for idx, row in df_sliced.iterrows() - ] - - documents = [] - for para, meta in zip(paragraphs, meta_data): - documents.append(Document(id=meta["document_id"], content=para, meta=meta.get("meta", {}))) - - return documents - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - """ - Scan through documents in DocumentStore and return a small number documents - that are most relevant to the supplied queries. - - Returns a list of lists of Documents (one per query). - - :param queries: Single query string or list of queries. - :param filters: A dictionary where the keys specify a metadata field and the value is a list of accepted values for that field - :param top_k: How many documents to return per query. - :param index: The name of the index in the DocumentStore from which to retrieve documents - :param batch_size: Not applicable. - :param scale_score: Whether to scale the similarity score to the unit interval (range of [0,1]). - If true similarity scores (e.g. cosine or dot_product) which naturally have a different - value range will be scaled to a range of [0,1], where 1 means extremely relevant. - Otherwise raw similarity scores (e.g. cosine or dot_product) will be used. - :param document_store: the docstore to use for retrieval. If `None`, the one given in the `__init__` is used instead. - """ - if filters: - raise NotImplementedError("TfidfRetriever doesn't support filters.") - if scale_score: - raise NotImplementedError("TfidfRetriever doesn't support scaling score to the unit interval.") - - document_store = document_store or self.document_store - if document_store is None: - raise ValueError( - "Pass a DocumentStore in the retrieve_batch() method. The Retriever needs a Document Store instance to work." - ) - - index = index or document_store.index - if index is None: - raise ValueError( - "Both the `index` parameter passed to the `retrieve_batch` method and the default `index` of the Document store are null. Pass a non-null `index` value." - ) - - if self.auto_fit and ( - index not in self.document_counts - or document_store.get_document_count(headers=headers, index=index) != self.document_counts[index] - ): - # run fit() to update self.dataframes, self.tfidf_matrices and self.document_counts - logger.warning( - "Indexed documents have been updated and fit() method needs to be run before retrieval. Running it now." - ) - self.fit(document_store=document_store, index=index) - if self.dataframes[index] is None: - raise DocumentStoreError( - "Retrieval requires dataframe and tf-idf matrix but fit() did not calculate them probably because of an empty document store." - ) - - if top_k is None: - top_k = self.top_k - - indices_and_scores = self._calc_scores(queries=queries, index=index) - all_documents = [] - for query_result in indices_and_scores: - df_sliced = self.dataframes[index].loc[query_result.keys()] - df_sliced = df_sliced[:top_k] - logger.debug( - "Identified %s candidates via retriever:\n%s", - df_sliced.shape[0], - df_sliced.to_string(col_space=10, index=False), - ) - - # get actual content for the top candidates - paragraphs = list(df_sliced.content.values) - meta_data = [ - {"document_id": row["document_id"], "paragraph_id": row["paragraph_id"], "meta": row.get("meta", {})} - for idx, row in df_sliced.iterrows() - ] - cur_documents = [] - for para, meta in zip(paragraphs, meta_data): - cur_documents.append(Document(id=meta["document_id"], content=para, meta=meta.get("meta", {}))) - all_documents.append(cur_documents) - - return all_documents - - def fit(self, document_store: BaseDocumentStore, index: Optional[str] = None): - """ - Performing training on this class according to the TF-IDF algorithm. - """ - if document_store is None: - raise ValueError( - "This Retriever was not initialized with a Document Store. Provide one to the fit() method." - ) - - index = index or document_store.index - if index is None: - raise ValueError( - "Both the `index` parameter passed to the `fit` method and the default `index` of the Document store are null. Pass a non-null `index` value." - ) - - paragraphs = self._get_all_paragraphs(document_store=document_store, index=index) - if not paragraphs or len(paragraphs) == 0: - raise DocumentStoreError("Fit method called with empty document store") - - df = pd.DataFrame.from_dict(paragraphs) - df["content"] = df["content"].apply(" ".join) - self.dataframes[index] = df - - tfidf_matrix = self.vectorizer.fit_transform(df["content"]) - self.tfidf_matrices[index] = tfidf_matrix - - self.document_counts[index] = document_store.get_document_count(index=index) diff --git a/haystack/nodes/retriever/web.py b/haystack/nodes/retriever/web.py deleted file mode 100644 index 9f8c9448e3..0000000000 --- a/haystack/nodes/retriever/web.py +++ /dev/null @@ -1,327 +0,0 @@ -import logging -from concurrent.futures import ThreadPoolExecutor -from dataclasses import dataclass -from datetime import datetime, timedelta -from multiprocessing import cpu_count -from typing import Dict, Iterator, List, Optional, Literal, Union, Tuple, Any - -from haystack.schema import Document -from haystack.document_stores.base import BaseDocumentStore -from haystack.nodes.preprocessor import PreProcessor -from haystack.nodes.retriever.base import BaseRetriever -from haystack.nodes.retriever.link_content import LinkContentFetcher -from haystack.nodes.search_engine.web import SearchEngine -from haystack.nodes.search_engine.web import WebSearch -from haystack.schema import FilterType - -logger = logging.getLogger(__name__) - - -@dataclass -class SearchResult: - url: str - snippet: str - score: float - position: Optional[str] - - -class WebRetriever(BaseRetriever): - """ - The WebRetriever is an effective tool designed to extract relevant documents from the web. It leverages the WebSearch - class to obtain web page results, strips the HTML from those pages, and extracts the raw text content. Depending on - the operation mode, this text can be further broken down into smaller documents with the help of a PreProcessor. - - The WebRetriever supports three distinct modes of operation: - - - Snippets Mode: In this mode, the WebRetriever generates a list of Document instances, where each Document - represents a snippet or a segment from a web page result. It's important to note that this mode does not involve - actual web page retrieval. - - - Raw Documents Mode: In this mode, the WebRetriever generates a list of Document instances, where each Document - represents an entire web page (retrieved from the search result link) devoid of any HTML and containing only the raw - text content. - - - Preprocessed Documents Mode: This mode is similar to the Raw Documents Mode but includes an additional step - - the raw text from each retrieved web page is divided into smaller Document instances using a specified PreProcessor. - If no PreProcessor is specified, the default PreProcessor is used. - """ - - def __init__( - self, - api_key: str, - search_engine_provider: Union[str, SearchEngine] = "SerperDev", - search_engine_kwargs: Optional[Dict[str, Any]] = None, - top_search_results: Optional[int] = 10, - top_k: Optional[int] = 5, - mode: Literal["snippets", "raw_documents", "preprocessed_documents"] = "snippets", - preprocessor: Optional[PreProcessor] = None, - cache_document_store: Optional[BaseDocumentStore] = None, - cache_index: Optional[str] = None, - cache_headers: Optional[Dict[str, str]] = None, - cache_time: int = 1 * 24 * 60 * 60, - allowed_domains: Optional[List[str]] = None, - link_content_fetcher: Optional[LinkContentFetcher] = None, - ): - """ - :param api_key: API key for the search engine provider. - :param search_engine_provider: Name of the search engine provider class. The options are "SerperDev" (default), "SearchApi", "SerpAPI", "BingAPI" or "GoogleAPI" - :param search_engine_kwargs: Additional parameters to pass to the search engine provider. - :param top_search_results: Number of top search results to be retrieved. - :param top_k: Top k documents to be returned by the retriever. - :param mode: Whether to return snippets, raw documents, or preprocessed documents. Snippets are the default. - :param preprocessor: Optional PreProcessor to be used to split documents into paragraphs. If not provided, the default PreProcessor is used. - :param cache_document_store: DocumentStore to be used to cache search results. - :param cache_index: Index name to be used to cache search results. - :param cache_headers: Headers to be used to cache search results. - :param cache_time: Time in seconds to cache search results. Defaults to 24 hours. - :param allowed_domains: List of domains to restrict the search to. If not provided, the search is unrestricted. - :param link_content_fetcher: LinkContentFetcher to be used to fetch the content from the links. If not provided, - the default LinkContentFetcher is used. - - """ - super().__init__() - self.web_search = WebSearch( - api_key=api_key, - top_k=top_search_results, - allowed_domains=allowed_domains, - search_engine_provider=search_engine_provider, - search_engine_kwargs=search_engine_kwargs, - ) - self.link_content_fetcher = link_content_fetcher or LinkContentFetcher() - self.mode = mode - self.cache_document_store = cache_document_store - self.document_store = cache_document_store - self.cache_index = cache_index - self.top_k = top_k - self.cache_headers = cache_headers - self.cache_time = cache_time - self.preprocessor = ( - preprocessor or PreProcessor(progress_bar=False) if mode == "preprocessed_documents" else None - ) - - def retrieve( # type: ignore[override] - self, - query: str, - top_k: Optional[int] = None, - preprocessor: Optional[PreProcessor] = None, - cache_document_store: Optional[BaseDocumentStore] = None, - cache_index: Optional[str] = None, - cache_headers: Optional[Dict[str, str]] = None, - cache_time: Optional[int] = None, - **kwargs, - ) -> List[Document]: - """ - Retrieve Documents in real-time from the web based on the URLs provided by the WebSearch. - - This method takes a search query as input, retrieves the corresponding web documents, and - returns them in a structured format suitable for further processing or analysis. The documents - are retrieved at runtime, ensuring up-to-date information. - - Optionally, the retrieved documents can be stored in a DocumentStore for future use, saving time - and resources on repeated retrievals. This caching mechanism can significantly improve retrieval times - for frequently accessed URLs. - - :param query: The query string. - :param top_k: The number of Documents to be returned by the retriever. - :param preprocessor: The PreProcessor to be used to split documents into paragraphs. - :param cache_document_store: The DocumentStore to cache the documents to. - :param cache_index: The index name to save the documents to. - :param cache_headers: The headers to save the documents to. - :param cache_time: The time limit in seconds for the documents in the cache. If objects are older than this time, - they will be deleted from the cache on the next retrieval. - """ - - # Initialize default parameters - preprocessor = preprocessor or self.preprocessor - cache_index = cache_index or self.cache_index - top_k = top_k or self.top_k - cache_headers = cache_headers or self.cache_headers - cache_time = cache_time or self.cache_time - - search_results, _ = self.web_search.run(query=query) - result_docs = search_results["documents"] - - if self.mode != "snippets": - # for raw_documents and preprocessed_documents modes, we need to retrieve the links from the search results - links: List[SearchResult] = self._prepare_links(result_docs) - - links_found_in_cache, cached_docs = self._check_cache(links) - logger.debug("Found %d links in cache", len(links_found_in_cache)) - - links_to_fetch = [link for link in links if link not in links_found_in_cache] - logger.debug("Fetching %d links", len(links_to_fetch)) - result_docs = self._scrape_links(links_to_fetch) - - # Save result_docs to cache - self._save_to_cache( - result_docs, cache_index=cache_index, cache_headers=cache_headers, cache_time=cache_time - ) - - # join cached_docs and result_docs - result_docs = cached_docs + result_docs - - # Preprocess documents - if preprocessor: - result_docs = preprocessor.process(result_docs) - - # Return results - return result_docs[:top_k] - - def _prepare_links(self, search_results: List[Document]) -> List[SearchResult]: - """ - Prepare a list of SearchResult objects based on the search results from the search engine. - - :param search_results: List of Document objects obtained from web search. - :return: List of SearchResult objects. - """ - if not search_results: - return [] - - links: List[SearchResult] = [ - SearchResult(r.meta["link"], r.content, float(r.meta.get("score", 0.0)), r.meta.get("position")) - for r in search_results - if r.meta.get("link") - ] - return links - - def _scrape_links(self, links: List[SearchResult]) -> List[Document]: - """ - Scrape the links and return the documents. - - :param links: List of SearchResult objects. - :return: List of Document objects obtained by fetching the content from the links. - """ - if not links: - return [] - - def link_fetch(link: SearchResult) -> List[Document]: - """ - Encapsulate the link fetching logic in a function to be used in a ThreadPoolExecutor. - """ - docs: List[Document] = [] - try: - docs = self.link_content_fetcher.fetch( - url=link.url, - doc_kwargs={ - "id_hash_keys": ["meta.url"], - "search.score": link.score, - "search.position": link.position, - "snippet_text": link.snippet, - }, - ) - except Exception as e: - # Log the exception for debugging - logger.debug("Error fetching documents from %s : %s", link.url, str(e)) - - return docs - - thread_count = min(cpu_count() if len(links) > cpu_count() else len(links), 10) # max 10 threads - with ThreadPoolExecutor(max_workers=thread_count) as executor: - fetched_pages: Iterator[List[Document]] = executor.map(link_fetch, links) - - # Flatten list of lists to a single list - extracted_docs = [doc for doc_list in fetched_pages for doc in doc_list] - - # Sort by score - extracted_docs = sorted(extracted_docs, key=lambda x: x.meta["search.score"], reverse=True) - - return extracted_docs - - def _check_cache(self, links: List[SearchResult]) -> Tuple[List[SearchResult], List[Document]]: - """ - Check the DocumentStore cache for documents. - - :param links: List of SearchResult objects. - :return: Tuple of lists of SearchResult and Document objects that were found in the cache. - """ - if not links or not self.cache_document_store: - return [], [] - - cache_documents: List[Document] = [] - cached_links: List[SearchResult] = [] - - valid_links = [link for link in links if link.url] - for link in valid_links: - cache_filter: FilterType = {"url": link.url} - documents = self.cache_document_store.get_all_documents(filters=cache_filter, return_embedding=False) - if documents: - cache_documents.extend(documents) - cached_links.append(link) - - return cached_links, cache_documents - - def _save_to_cache( - self, - documents: List[Document], - cache_index: Optional[str] = None, - cache_headers: Optional[Dict[str, str]] = None, - cache_time: Optional[int] = None, - ) -> None: - """ - Save the documents to the cache and potentially delete old expired documents from the cache. - - :param documents: List of Document objects to be saved to the cache. - :param cache_index: Optional index name to save the documents to. - :param cache_headers: Optional headers made to use when saving the documents to the cache. - :param cache_time: Optional time to live in seconds for the documents in the cache. If objects are older than - this time, they will be deleted from the cache. - """ - cache_document_store = self.cache_document_store - - if cache_document_store is not None and documents: - cache_document_store.write_documents( - documents=documents, index=cache_index, headers=cache_headers, duplicate_documents="overwrite" - ) - - if cache_document_store and cache_time is not None and cache_time > 0: - cache_filter: FilterType = { - "timestamp": {"$lt": int((datetime.utcnow() - timedelta(seconds=cache_time)).timestamp())} - } - - cache_document_store.delete_documents(index=cache_index, headers=cache_headers, filters=cache_filter) - logger.debug("Deleted documents in the cache using filter: %s", cache_filter) - - def retrieve_batch( # type: ignore[override] - self, - queries: List[str], - top_p: Optional[int] = None, - top_k: Optional[int] = None, - preprocessor: Optional[PreProcessor] = None, - cache_document_store: Optional[BaseDocumentStore] = None, - cache_index: Optional[str] = None, - cache_headers: Optional[Dict[str, str]] = None, - cache_time: Optional[int] = None, - ) -> List[List[Document]]: - """ - Batch retrieval method that fetches documents for a list of queries. Each query is passed to the `retrieve` - method which fetches documents from the web in real-time or from a DocumentStore cache. The fetched documents - are then extended to a list of documents. - - :param queries: List of query strings to retrieve documents for. - :param top_p: The number of documents to be returned by the retriever for each query. If None, the instance's - default value is used. - :param top_k: The maximum number of documents to be retrieved for each query. If None, the instance's default - value is used. - :param preprocessor: The PreProcessor to be used to split documents into paragraphs. If None, the instance's - default PreProcessor is used. - :param cache_document_store: The DocumentStore to cache the documents to. If None, the instance's default - DocumentStore is used. - :param cache_index: The index name to save the documents to. If None, the instance's default cache_index is used. - :param cache_headers: The headers to save the documents to. If None, the instance's default cache_headers is used. - :param cache_time: The time limit in seconds for the documents in the cache. - - :returns: A list of lists where each inner list represents the documents fetched for a particular query. - """ - documents = [] - for q in queries: - documents.append( - self.retrieve( - query=q, - top_k=top_k, - preprocessor=preprocessor, - cache_document_store=cache_document_store, - cache_index=cache_index, - ) - ) - - return documents diff --git a/haystack/nodes/sampler/__init__.py b/haystack/nodes/sampler/__init__.py deleted file mode 100644 index 60b78dc2e1..0000000000 --- a/haystack/nodes/sampler/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.sampler.base import BaseSampler -from haystack.nodes.sampler.top_p_sampler import TopPSampler diff --git a/haystack/nodes/sampler/base.py b/haystack/nodes/sampler/base.py deleted file mode 100644 index 2906549977..0000000000 --- a/haystack/nodes/sampler/base.py +++ /dev/null @@ -1,91 +0,0 @@ -from typing import List, Optional, Union - -import logging -from abc import abstractmethod -from functools import wraps -from time import perf_counter - -from haystack.schema import Document -from haystack.nodes.base import BaseComponent - - -logger = logging.getLogger(__name__) - - -class BaseSampler(BaseComponent): - return_no_answers: bool - outgoing_edges = 1 - query_count = 0 - query_time = 0 - - @abstractmethod - def predict(self, query: str, documents: List[Document], top_p: Optional[float] = None): - pass - - @abstractmethod - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_p: Optional[int] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - pass - - def run(self, query: str, documents: List[Document], top_p: Optional[float] = None): # type: ignore - self.query_count += 1 - if documents: - predict = self.timing(self.predict, "query_time") - results = predict(query=query, documents=documents, top_p=top_p) - else: - results = [] - - document_ids = [doc.id for doc in results] - logger.debug("Retrieved documents with IDs: %s", document_ids) - output = {"documents": results} - - return output, "output_1" - - def run_batch( # type: ignore - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_p: Optional[float] = None, - batch_size: Optional[int] = None, - ): - self.query_count += len(queries) - predict_batch = self.timing(self.predict_batch, "query_time") - results = predict_batch(queries=queries, documents=documents, top_p=top_p, batch_size=batch_size) - - for doc_list in results: - document_ids = [doc.id for doc in doc_list] - logger.debug("Ranked documents with IDs: %s", document_ids) - - output = {"documents": results} - - return output, "output_1" - - def timing(self, fn, attr_name): - """A wrapper method used for time functions.""" - - @wraps(fn) - def wrapper(*args, **kwargs): - if attr_name not in self.__dict__: - self.__dict__[attr_name] = 0 - tic = perf_counter() - ret = fn(*args, **kwargs) - toc = perf_counter() - self.__dict__[attr_name] += toc - tic - return ret - - return wrapper - - def print_time(self): - print("Sampler (Speed)") - print("---------------") - if not self.query_count: - print("No querying performed with Retriever.run()") - else: - print(f"Queries Performed: {self.query_count}") - print(f"Query time: {self.query_time}s") - print(f"{self.query_time / self.query_count} seconds per query") diff --git a/haystack/nodes/sampler/top_p_sampler.py b/haystack/nodes/sampler/top_p_sampler.py deleted file mode 100644 index b77e448760..0000000000 --- a/haystack/nodes/sampler/top_p_sampler.py +++ /dev/null @@ -1,166 +0,0 @@ -import logging -from pathlib import Path -from typing import List, Optional, Union - -import numpy as np -from haystack.nodes.sampler.base import BaseSampler -from haystack.schema import Document -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from sentence_transformers import CrossEncoder - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class TopPSampler(BaseSampler): - """ - Filters documents based on the cumulative probability of the similarity scores between the - query and the documents using top p sampling. - - Top p sampling selects a subset of the most relevant data points from a larger set of data. The technique - involves calculating the cumulative probability of the scores of each data point, and then - selecting the top p percent of data points with the highest cumulative probability. - - In the context of TopPSampler, the `run()` method takes in a query and a set of documents, - calculates the similarity scores between the query and the documents, and then filters - the documents based on the cumulative probability of these scores. The TopPSampler provides a - way to efficiently select the most relevant documents based on their similarity to a given query. - - Usage example: - - ```python - prompt_node = PromptNode( - "text-davinci-003", - api_key=openai_key, - max_length=256, - default_prompt_template="question-answering-with-document-scores", - ) - retriever = WebRetriever(api_key=os.environ.get("SERPERDEV_API_KEY"), mode="preprocessed_documents") - sampler = TopPSampler(top_p=0.95) - - pipeline = WebQAPipeline(retriever=retriever, prompt_node=prompt_node, sampler=sampler) - print(pipeline.run(query="What's the secret of the Universe?")) - ``` - """ - - def __init__( - self, - model_name_or_path: Union[str, Path] = "cross-encoder/ms-marco-MiniLM-L-6-v2", - top_p: Optional[float] = 1.0, - strict: Optional[bool] = False, - score_field: Optional[str] = "score", - use_gpu: Optional[bool] = True, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Initialize a TopPSampler. - - :param model_name_or_path: Path to a pretrained sentence-transformers model. - :param top_p: Cumulative probability threshold for filtering the documents (usually between 0.9 and 0.99). - :param strict: If `top_p` is set to a low value and sampler returned no documents, then setting `strict` to - `False` ensures at least one document is returned. If `strict` is set to `True`, then no documents are returned. - :param score_field: The name of the field that should be used to store the scores a document's meta data. - :param use_gpu: Whether to use GPU (if available). If no GPUs are available, it falls back on a CPU. - :param devices: List of torch devices (for example, cuda:0, cpu, mps) to limit inference to specific devices. - """ - torch_and_transformers_import.check() - super().__init__() - - self.top_p = top_p - self.score_field = score_field - self.strict = strict - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=True) - self.cross_encoder = CrossEncoder(model_name_or_path, device=str(self.devices[0])) - - def predict(self, query: str, documents: List[Document], top_p: Optional[float] = None) -> List[Document]: - """ - Returns a list of documents filtered using `top_p`, based on the similarity scores between the query and the - documents whose cumulative probability is less than or equal to `top_p`. - - :param query: Query string. - :param documents: List of Documents. - :param top_p: Cumulative probability threshold for filtering the documents. If not provided, the top_p value - set during TopPSampler initialization is used. - :return: List of Documents sorted by (desc.) similarity with the query. - """ - if top_p is None: - top_p = self.top_p if self.top_p else 1.0 - - if not documents: - return [] - - # prepare the data for the cross encoder - query_doc_pairs = [[query, doc.content] for doc in documents] - - # compute the similarity scores for these combinations - similarity_scores = self.cross_encoder.predict(query_doc_pairs) - - # Apply softmax normalization to the similarity scores - probs = np.exp(similarity_scores) / np.sum(np.exp(similarity_scores)) - - # Sort the probabilities and calculate their cumulative sum - sorted_probs = np.sort(probs)[::-1] - cumulative_probs = np.cumsum(sorted_probs) - - # Find the indices with cumulative probabilities that exceed top_p - top_p_indices = np.where(cumulative_probs <= top_p)[0] - - # Map the selected indices back to their original indices - original_indices = np.argsort(probs)[::-1][top_p_indices] - # and select the top_p responses - selected_docs = [documents[i] for i in original_indices] - - # if strict is set to False, low p resulted in no documents being selected, then - # return at least one document - if not selected_docs and not self.strict: - highest_prob_indices = np.argsort(probs)[::-1] - selected_docs = [documents[highest_prob_indices[0]]] - - # include prob scores in the results - if self.score_field: - for idx, doc in enumerate(selected_docs): - doc.meta[self.score_field] = str(sorted_probs[idx]) - return selected_docs - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_p: Optional[float] = None, - batch_size: Optional[int] = None, - ) -> Union[List[Document], List[List[Document]]]: - """ - - If you provide a list containing a single query... - - - ... and a single list of Documents, the single list of Documents is re-ranked based on the - supplied query. - - ... and a list of lists of Documents, each list of Documents is re-ranked individually based on the - supplied query. - - - - If you provide a list of multiple queries, provide a list of lists of Documents. Each list of Documents - is re-ranked based on its corresponding query. - """ - if top_p is None: - top_p = self.top_p - - # TODO: add support for batch_size if possible - - if len(queries) == 1 and isinstance(documents[0], Document): - return self.predict(queries[0], documents, top_p) # type: ignore - - if len(queries) == 1 and isinstance(documents[0], list): - return [self.predict(queries[0], docs, top_p) for docs in documents] # type: ignore - - if len(queries) > 1 and isinstance(documents[0], list): - return [self.predict(query, docs, top_p) for query, docs in zip(queries, documents)] # type: ignore - - raise ValueError( - f"The following queries {queries} and documents {documents} were provided as input but it seems they're not valid." - f"Check the documentation of this method for valid parameters and their types." - ) diff --git a/haystack/nodes/search_engine/__init__.py b/haystack/nodes/search_engine/__init__.py deleted file mode 100644 index eb7d5fa271..0000000000 --- a/haystack/nodes/search_engine/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.search_engine.base import SearchEngine -from haystack.nodes.search_engine.web import WebSearch diff --git a/haystack/nodes/search_engine/base.py b/haystack/nodes/search_engine/base.py deleted file mode 100644 index d1edf42a07..0000000000 --- a/haystack/nodes/search_engine/base.py +++ /dev/null @@ -1,31 +0,0 @@ -from abc import ABC, abstractmethod -from typing import List, Optional - -from haystack import Document -from haystack.nodes.search_engine.utils import calculate_ranking_scores - - -class SearchEngine(ABC): - """ - Abstract base class for search engines providers. - """ - - @abstractmethod - def search(self, query: str, **kwargs) -> List[Document]: - """ - Search the search engine for the given query and return the results. - :param query: The query to search for. - :param kwargs: Additional parameters to pass to the search engine, such as top_k. - :return: List of search results as documents. - """ - - def score_results( - self, results: List[Document], has_answer_box: Optional[bool] = False, boost_factor: Optional[int] = 5 - ) -> List[Document]: - """ - Assigns scores to search results based on their rank position and ensures that the scores add up to 1. - """ - scores = calculate_ranking_scores(results, boost_first_factor=boost_factor if has_answer_box else None) - for doc, score in zip(results, scores): - doc.score = doc.meta["score"] = score - return results diff --git a/haystack/nodes/search_engine/providers.py b/haystack/nodes/search_engine/providers.py deleted file mode 100644 index 83d9621329..0000000000 --- a/haystack/nodes/search_engine/providers.py +++ /dev/null @@ -1,491 +0,0 @@ -import json -import logging -from typing import Dict, List, Union, Optional, Any - -import requests - -from haystack import Document -from haystack.nodes.search_engine.base import SearchEngine - -logger = logging.getLogger(__name__) - - -class SerpAPI(SearchEngine): - """ - SerpAPI is a search engine that provides a REST API to access search results from Google, Bing, Yahoo, Yandex, - Amazon, and similar. See the [SerpAPI website](https://serpapi.com/) for more details. - """ - - def __init__( - self, - api_key: str, - top_k: Optional[int] = 10, - allowed_domains: Optional[List[str]] = None, - engine: Optional[str] = "google", - search_engine_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - :param api_key: API key for SerpAPI. - :param top_k: Number of results to return. - :param allowed_domains: List of domains to limit the search to. - :param engine: Search engine to use, for example google, bing, baidu, duckduckgo, yahoo, yandex. - See the [SerpAPI documentation](https://serpapi.com/search-api) for the full list of supported engines. - :param search_engine_kwargs: Additional parameters passed to the SerperDev API. For example, you can set 'lr' to 'lang_en' - to limit the search to English. - See the [SerpAPI documentation](https://serpapi.com/search-api) for the full list of supported parameters. - """ - super().__init__() - self.params_dict: Dict[str, Union[str, int, float]] = {} - self.api_key = api_key - self.kwargs = search_engine_kwargs if search_engine_kwargs else {} - self.engine = engine - self.top_k = top_k - self.allowed_domains = allowed_domains - - def search(self, query: str, **kwargs) -> List[Document]: - """ - :param query: Query string. - :param kwargs: Additional parameters passed to the SerpAPI. For example, you can set 'lr' to 'lang_en' - to limit the search to English. - See the [SerpAPI documentation](https://serpapi.com/search-api) for the full list of supported parameters. - :return: List[Document] - """ - kwargs = {**self.kwargs, **kwargs} - top_k = kwargs.pop("top_k", self.top_k) - url = "https://serpapi.com/search" - - allowed_domains = kwargs.pop("allowed_domains", self.allowed_domains) - query_prepend = "OR ".join(f"site:{domain} " for domain in allowed_domains) if allowed_domains else "" - params = {"source": "python", "serp_api_key": self.api_key, "q": query_prepend + query, **kwargs} - - if self.engine: - params["engine"] = self.engine - response = requests.get(url, params, timeout=30) - - if response.status_code != 200: - raise Exception(f"Error while querying {self.__class__.__name__}: {response.text}") - - json_result = json.loads(response.text) - - organic = [ - Document.from_dict(d, field_map={"snippet": "content"}) - for d in json_result["organic_results"] - if "snippet" in d - ] - answer_box = [] - if "answer_box" in json_result: - answer_dict = json_result["answer_box"] - for key in ["answer", "snippet_highlighted_words", "snippet", "title"]: - if key in answer_dict: - answer_box_content = answer_dict[key] - if isinstance(answer_box_content, list): - answer_box_content = answer_box_content[0] - answer_box = [ - Document.from_dict( - { - "title": answer_dict.get("title", ""), - "content": answer_box_content, - "link": answer_dict.get("displayed_link", ""), - } - ) - ] - break - - people_also_search = [] - if "people_also_search_for" in json_result: - for result in json_result["people_also_search_for"]: - people_also_search.append( - Document.from_dict( - { - "title": result["title"], - "content": result["snippet"] if result.get("snippet") else result["title"], - "link": result["link"], - } - ) - ) - - related_questions = [] - if "related_questions" in json_result: - for result in json_result["related_questions"]: - related_questions.append( - Document.from_dict( - { - "title": result["title"], - "content": result["snippet"] if result.get("snippet") else result["title"], - "link": result["link"], - } - ) - ) - - documents = answer_box + organic + people_also_search + related_questions - - logger.debug("SerpAPI returned %s documents for the query '%s'", len(documents), query) - result_docs = documents[:top_k] - return self.score_results(result_docs, len(answer_box) > 0) - - -class SearchApi(SearchEngine): - """ - SearchApi is a real-time search engine that provides an API to access search results from Google, Google Scholar, YouTube, - YouTube transcripts and more. See the [SearchApi website](https://www.searchapi.io/) for more details. - """ - - def __init__( - self, - api_key: str, - top_k: Optional[int] = 10, - allowed_domains: Optional[List[str]] = None, - engine: Optional[str] = "google", - search_engine_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - :param api_key: API key for SearchApi. - :param top_k: Number of results to return. - :param allowed_domains: List of domains to limit the search to. - :param engine: Search engine to use, for example google, google_scholar, youtube, youtube_transcripts. - See the [SearchApi documentation](https://www.searchapi.io/docs/google) for the full list of supported engines. - :param search_engine_kwargs: Additional parameters passed to the SearchApi. - See the [SearchApi documentation](https://www.searchapi.io/docs/google) for the full list of supported parameters. - """ - super().__init__() - self.params_dict: Dict[str, Union[str, int, float]] = {} - self.api_key = api_key - self.kwargs = search_engine_kwargs if search_engine_kwargs else {} - self.engine = engine - self.top_k = top_k - self.allowed_domains = allowed_domains - - def search(self, query: str, **kwargs) -> List[Document]: - """ - :param query: Query string. - :param kwargs: Additional parameters passed to the SearchApi. For example, you can set 'location' to 'New York,United States' - to localize search to the specific location. - :return: List[Document] - """ - kwargs = {**self.kwargs, **kwargs} - top_k = kwargs.pop("top_k", self.top_k) - url = "https://www.searchapi.io/api/v1/search" - - allowed_domains = kwargs.pop("allowed_domains", self.allowed_domains) - query_prepend = "OR ".join(f"site:{domain} " for domain in allowed_domains) if allowed_domains else "" - params = {"q": query_prepend + " " + query, **kwargs} - headers = {"Authorization": f"Bearer {self.api_key}", "X-SearchApi-Source": "Haystack"} - - if self.engine: - params["engine"] = self.engine - response = requests.get(url, params=params, headers=headers, timeout=90) - - if response.status_code != 200: - raise Exception(f"Error while querying {self.__class__.__name__}: {response.text}") - - json_result = json.loads(response.text) - - # organic results are the main results from the search engine - organic_results = [] - if "organic_results" in json_result: - for result in json_result["organic_results"]: - organic_results.append( - Document.from_dict({"title": result["title"], "content": result["snippet"], "link": result["link"]}) - ) - - # answer box has a direct answer to the query - answer_box = [] - if "answer_box" in json_result: - answer_box = [ - Document.from_dict( - { - "title": json_result["answer_box"].get("title", ""), - "content": json_result["answer_box"].get("answer", ""), - "link": json_result["answer_box"].get("link", ""), - } - ) - ] - - knowledge_graph = [] - if "knowledge_graph" in json_result: - knowledge_graph = [ - Document.from_dict( - { - "title": json_result["knowledge_graph"].get("title", ""), - "content": json_result["knowledge_graph"].get("description", ""), - } - ) - ] - - related_questions = [] - if "related_questions" in json_result: - for result in json_result["related_questions"]: - related_questions.append( - Document.from_dict( - { - "title": result["question"], - "content": result["answer"] if result.get("answer") else result.get("answer_highlight", ""), - "link": result.get("source", {}).get("link", ""), - } - ) - ) - - documents = answer_box + knowledge_graph + organic_results + related_questions - - logger.debug("SearchApi returned %s documents for the query '%s'", len(documents), query) - result_docs = documents[:top_k] - return self.score_results(result_docs, len(answer_box) > 0) - - -class SerperDev(SearchEngine): - """ - Search engine using SerperDev API. See the [Serper Dev website](https://serper.dev/) for more details. - """ - - def __init__( - self, - api_key: str, - top_k: Optional[int] = 10, - allowed_domains: Optional[List[str]] = None, - search_engine_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - :param api_key: API key for the SerperDev API. - :param top_k: Number of documents to return. - :param allowed_domains: List of domains to limit the search to. - :param search_engine_kwargs: Additional parameters passed to the SerperDev API. - For example, you can set 'num' to 20 to increase the number of search results. - """ - super().__init__() - self.api_key = api_key - self.top_k = top_k - self.allowed_domains = allowed_domains - self.kwargs = search_engine_kwargs if search_engine_kwargs else {} - - def search(self, query: str, **kwargs) -> List[Document]: - """ - :param query: Query string. - :param kwargs: Additional parameters passed to the SerperDev API, such as top_k. - :return: List[Document] - """ - kwargs = {**self.kwargs, **kwargs} - top_k = kwargs.pop("top_k", self.top_k) - allowed_domains = kwargs.pop("allowed_domains", self.allowed_domains) - query_prepend = "OR ".join(f"site:{domain} " for domain in allowed_domains) if allowed_domains else "" - - url = "https://google.serper.dev/search" - - payload = json.dumps({"q": query_prepend + query, "gl": "us", "hl": "en", "autocorrect": True, **kwargs}) - headers = {"X-API-KEY": self.api_key, "Content-Type": "application/json"} - - response = requests.request("POST", url, headers=headers, data=payload, timeout=30) - if response.status_code != 200: - raise Exception(f"Error while querying {self.__class__.__name__}: {response.text}") - - json_result = response.json() - organic = [ - Document.from_dict(d, field_map={"snippet": "content"}) for d in json_result["organic"] if "snippet" in d - ] - answer_box = [] - if "answerBox" in json_result: - answer_dict = json_result["answerBox"] - highlighted_answers = answer_dict.get("snippetHighlighted") - answer_box_content = ( - highlighted_answers[0] - if isinstance(highlighted_answers, list) and len(highlighted_answers) > 0 - else highlighted_answers - if isinstance(highlighted_answers, str) - else None - ) - if not answer_box_content: - for key in ["snippet", "answer", "title"]: - if key in answer_dict: - answer_box_content = answer_dict[key] - break - if answer_box_content: - answer_box = [ - Document.from_dict( - { - "title": answer_dict.get("title", ""), - "content": answer_box_content, - "link": answer_dict.get("link", ""), - } - ) - ] - - people_also_ask = [] - if "peopleAlsoAsk" in json_result: - for result in json_result["peopleAlsoAsk"]: - title = result.get("title", "") - people_also_ask.append( - Document.from_dict( - { - "title": title, - "content": result["snippet"] if result.get("snippet") else title, - "link": result.get("link", None), - } - ) - ) - - documents = answer_box + organic + people_also_ask - - logger.debug("Serper Dev returned %s documents for the query '%s'", len(documents), query) - result_docs = documents[:top_k] - return self.score_results(result_docs, len(answer_box) > 0) - - -class BingAPI(SearchEngine): - """ - Search engine using the Bing API. See [Bing Web Search API](https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/overview) for more details. - """ - - def __init__( - self, - api_key: str, - top_k: Optional[int] = 10, - allowed_domains: Optional[List[str]] = None, - search_engine_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - :param api_key: API key for the Bing API. - :param top_k: Number of documents to return. - :param allowed_domains: List of domains to limit the search to. - :param search_engine_kwargs: Additional parameters passed to the Bing. As an example, you can pass the market parameter to specify the market to use for the query: 'mkt':'en-US'. - """ - super().__init__() - self.api_key = api_key - self.top_k = top_k - self.allowed_domains = allowed_domains - self.kwargs = search_engine_kwargs if search_engine_kwargs else {} - - def search(self, query: str, **kwargs) -> List[Document]: - """ - :param query: Query string. - :param kwargs: Additional parameters passed to the BingAPI. - As an example, you can pass the market parameter to specify the market to use for the query: 'mkt':'en-US'. - If you don't specify the market parameter, the default market for the user's location is used. - For a complete list of the market codes, see [Market Codes](https://learn.microsoft.com/en-us/rest/api/cognitiveservices-bingsearch/bing-web-api-v7-reference#market-codes). - You can also pass the count parameter to specify the number of results to return: 'count':10. - You can find a full list of parameters at [Query Parameters](https://docs.microsoft.com/en-us/rest/api/cognitiveservices-bingsearch/bing-web-api-v7-reference#query-parameters). - :return: List[Document] - """ - kwargs = {**self.kwargs, **kwargs} - top_k = kwargs.pop("top_k", self.top_k) - url = "https://api.bing.microsoft.com/v7.0/search" - - allowed_domains = kwargs.pop("allowed_domains", self.allowed_domains) - query_prepend = "OR ".join(f"site:{domain} " for domain in allowed_domains) if allowed_domains else "" - - params: Dict[str, Union[str, int, float]] = {"q": query_prepend + query, "count": 50, **kwargs} - - headers = {"Ocp-Apim-Subscription-Key": self.api_key} - - response = requests.get(url, headers=headers, params=params, timeout=10) - if response.status_code != 200: - raise Exception(f"Error while querying {self.__class__.__name__}: {response.text}") - - json_result = response.json() - - documents: List[Document] = [] - for web_page in json_result["webPages"]["value"]: - documents.append( - Document.from_dict( - { - "title": web_page["name"], - "content": web_page["snippet"], - "position": int(web_page["id"].replace("https://api.bing.microsoft.com/api/v7/#WebPages.", "")), - "link": web_page["url"], - "language": web_page["language"], - } - ) - ) - if web_page.get("deepLinks"): - for deep_link in web_page["deepLinks"]: - documents.append( - Document.from_dict( - { - "title": deep_link["name"], - "content": deep_link["snippet"] if deep_link.get("snippet") else deep_link["name"], - "link": deep_link["url"], - } - ) - ) - - logger.debug("Bing API returned %s documents for the query '%s'", len(documents), query) - return documents[:top_k] - - -class GoogleAPI(SearchEngine): - """Search engine using the Google API. See [Google Search API](https://developers.google.com/custom-search/v1/overview) for more details.""" - - def __init__( - self, - top_k: Optional[int] = 10, - allowed_domains: Optional[List[str]] = None, - api_key: Optional[str] = None, - engine_id: Optional[str] = None, - search_engine_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - :param top_k: Number of documents to return. - :param allowed_domains: List of domains to limit the search to. - :param api_key: API key for the Google API. - :param engine_id: Engine ID for the Google API. - :param search_engine_kwargs: Additional parameters passed to the Google API. As an example, you can pass the hl parameter to specify the language to use for the query: 'hl':'en'. - """ - super().__init__() - self.api_key = api_key - self.engine_id = engine_id - self.top_k = top_k - self.allowed_domains = allowed_domains - self.kwargs = search_engine_kwargs if search_engine_kwargs else {} - - def _validate_environment(self): - """ - Validate if the environment variables are set. - """ - if not self.api_key: - raise ValueError( - "You need to provide an API key for the Google API. See https://developers.google.com/custom-search/v1/overview" - ) - if not self.engine_id: - raise ValueError( - "You need to provide an engine ID for the Google API. See https://developers.google.com/custom-search/v1/overview" - ) - - # check if google api is installed - try: - from googleapiclient.discovery import build - except ImportError: - raise ImportError( - "You need to install the Google API client. You can do so by running 'pip install google-api-python-client'." - ) - # create a custom search service - self.service = build("customsearch", "v1", developerKey=self.api_key) - - def search(self, query: str, **kwargs) -> List[Document]: - """ - :param query: Query string. - :param kwargs: Additional parameters passed to the Google API. - As an example, you can pass the hl parameter to specify the language to use for the query: 'hl':'en'. - If you don't specify the hl parameter, the default language for the user's location is used. - For a complete list of the language codes, see [Language Codes](https://developers.google.com/custom-search/docs/xml_results#languageCollections). - You can also pass the num parameter to specify the number of results to return: 'num':10. - You can find a full list of parameters at [Query Parameters](https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list). - :return: List[Document] - """ - kwargs = {**self.kwargs, **kwargs} - self.engine_id = kwargs.pop("engine_id", self.engine_id) - - self._validate_environment() - - top_k = kwargs.pop("top_k", self.top_k) - allowed_domains = kwargs.pop("allowed_domains", self.allowed_domains) - query_prepend = "OR ".join(f"site:{domain} " for domain in allowed_domains) if allowed_domains else "" - - params: Dict[str, Union[str, int, float]] = {"num": 10, **kwargs} - res = self.service.cse().list(q=query_prepend + query, cx=self.engine_id, **params).execute() - documents: List[Document] = [] - for i, result in enumerate(res["items"]): - documents.append( - Document.from_dict( - {"title": result["title"], "content": result["snippet"], "position": i, "link": result["link"]} - ) - ) - logger.debug("Google API returned %s documents for the query '%s'", len(documents), query) - return documents[:top_k] diff --git a/haystack/nodes/search_engine/utils.py b/haystack/nodes/search_engine/utils.py deleted file mode 100644 index cac15e916b..0000000000 --- a/haystack/nodes/search_engine/utils.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import List, Any, Optional - - -def calculate_ranking_scores(list_items: List[Any], boost_first_factor: Optional[int] = None) -> List[float]: - """ - Assigns scores to items in a list based on their rank position and ensures that the scores add up to 1. - :param list_items: The list of items to score. - :param boost_first_factor: The factor to boost the score of the first item by. - """ - n = len(list_items) - scores = [0.0] * n - - # Compute the scores based on rank position - for i, _ in enumerate(list_items): - scores[i] = (n - i) / ((n * (n + 1)) / 2) - - # Apply the boost factor to the first item - if boost_first_factor is not None and n > 0: - scores[0] *= boost_first_factor - - # Normalize the scores so they add up to 1 - total_score = sum(scores) - normalized_scores = [score / total_score for score in scores] - - return normalized_scores diff --git a/haystack/nodes/search_engine/web.py b/haystack/nodes/search_engine/web.py deleted file mode 100644 index a19011d7d0..0000000000 --- a/haystack/nodes/search_engine/web.py +++ /dev/null @@ -1,108 +0,0 @@ -import pydoc -from typing import List, Dict, Any, Optional, Union, Tuple, Type - -from haystack.nodes.base import BaseComponent -from haystack import MultiLabel, Document -from haystack.nodes.search_engine.base import SearchEngine - - -class WebSearch(BaseComponent): - """ - WebSearch queries a search engine and retrieves results as a list of Documents. WebSearch abstracts away the details - of the underlying search engine provider, provides common interface for all providers, and makes it possible to use various - search engines. - - WebSearch currently supports the following search engines providers (bridges): - - SerperDev (default) - - SearchApi - - SerpAPI - - BingAPI - - GoogleAPI - - """ - - outgoing_edges = 1 - - def __init__( - self, - api_key: str, - top_k: Optional[int] = 10, - allowed_domains: Optional[List[str]] = None, - search_engine_provider: Union[str, SearchEngine] = "SerperDev", - search_engine_kwargs: Optional[Dict[str, Any]] = None, - ): - """ - :param api_key: API key for the search engine provider. - :param search_engine_provider: Name of the search engine provider class, see `providers.py` for a list of - supported providers. - :param search_engine_kwargs: Additional parameters to pass to the search engine provider. - """ - super().__init__() - if isinstance(search_engine_provider, str): - # try to find the provider class - search_path = [f"haystack.nodes.search_engine.providers.{search_engine_provider}", search_engine_provider] - klass: Type[SearchEngine] = next((pydoc.locate(path) for path in search_path), None) # type: ignore - - if not klass: - raise ValueError( - f"Could not locate the SearchEngine class with the name {search_engine_provider}. " - f"Make sure you pass the full path to the class." - ) - if not issubclass(klass, SearchEngine): - raise ValueError(f"Class {search_engine_provider} is not a subclass of SearchEngine.") - self.search_engine = klass(api_key=api_key, top_k=top_k, allowed_domains=allowed_domains, search_engine_kwargs=search_engine_kwargs) # type: ignore - elif isinstance(search_engine_provider, SearchEngine): - self.search_engine = search_engine_provider - else: - raise ValueError( - "search_engine_provider must be either a string (SearchEngine class name) or a SearchEngine instance." - ) - - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - top_k: Optional[int] = None, - ) -> Tuple[Dict, str]: - """ - Search the search engine for the given query and return the results. Only the query parameter and the top_k - parameter are used. - :param query: The query to search for. - :param file_paths: Not used. - :param labels: Not used. - :param documents: Not used. - :param meta: Not used. - :param top_k: return only the top_k results. If None, the top_k value passed to the constructor is used. - - - :return: List of search results as documents. - """ - # query is a required parameter for search, we need to keep the signature of run() the same as in other nodes - if not query: - raise ValueError("WebSearch run requires the `query` parameter") - search_kwargs = {} - if top_k is not None: - search_kwargs["top_k"] = top_k - return {"documents": self.search_engine.search(query, **search_kwargs)}, "output_1" - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - results = [] - if isinstance(queries, str): - queries = [queries] - elif not isinstance(queries, list): - raise ValueError("WebSearch run_batch requires the `queries` parameter to be Union[str, List[str]]") - for query in queries: - results.append(self.search_engine.search(query)) - return {"documents": results}, "output_1" diff --git a/haystack/nodes/summarizer/__init__.py b/haystack/nodes/summarizer/__init__.py deleted file mode 100644 index d62d059870..0000000000 --- a/haystack/nodes/summarizer/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.summarizer.base import BaseSummarizer -from haystack.nodes.summarizer.transformers import TransformersSummarizer diff --git a/haystack/nodes/summarizer/base.py b/haystack/nodes/summarizer/base.py deleted file mode 100644 index bd121d8add..0000000000 --- a/haystack/nodes/summarizer/base.py +++ /dev/null @@ -1,52 +0,0 @@ -from typing import List, Dict, Optional, Union - -from abc import abstractmethod - -from haystack.schema import Document -from haystack.nodes.base import BaseComponent - - -class BaseSummarizer(BaseComponent): - """ - Abstract class for Summarizer - """ - - outgoing_edges = 1 - - @abstractmethod - def predict(self, documents: List[Document]) -> List[Document]: - """ - Abstract method for creating a summary. - - :param documents: Related documents (e.g. coming from a retriever) that the answer shall be conditioned on. - :return: List of Documents, where Document.meta["summary"] contains the summarization - """ - pass - - @abstractmethod - def predict_batch( - self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None - ) -> Union[List[Document], List[List[Document]]]: - pass - - def run(self, documents: List[Document]): # type: ignore - """ - :param documents: Related documents (e.g. coming from a retriever) that the answer shall be conditioned on. - """ - results: Dict = {"documents": []} - - if documents: - results["documents"] = self.predict(documents=documents) - - return results, "output_1" - - def run_batch( # type: ignore - self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None - ): - """ - :param documents: List of related documents. - :param batch_size: Number of Documents to process at a time. - """ - results = self.predict_batch(documents=documents, batch_size=batch_size) - - return {"documents": results}, "output_1" diff --git a/haystack/nodes/summarizer/transformers.py b/haystack/nodes/summarizer/transformers.py deleted file mode 100644 index cad388a36b..0000000000 --- a/haystack/nodes/summarizer/transformers.py +++ /dev/null @@ -1,264 +0,0 @@ -import itertools -from typing import List, Optional, Set, Union - -import logging - -from tqdm import tqdm - -from haystack.schema import Document -from haystack.nodes.summarizer.base import BaseSummarizer -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import pipeline - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - from haystack.utils.torch_utils import ListDataset - - -class TransformersSummarizer(BaseSummarizer): - """ - Summarizes documents using the Hugging Face's transformers framework. - - You can use any model fine-tuned on a summarization task. For example: - '`bart-large-cnn`', '`t5-small`', '`t5-base`', '`t5-large`', '`t5-3b`', '`t5-11b`'. - See the up-to-date list of available models in [Hugging Face Documentattion](https://huggingface.co/models?filter=summarization). - - **Example** - - ```python - docs = [Document(content="PG&E stated it scheduled the blackouts in response to forecasts for high winds amid dry conditions." - "The aim is to reduce the risk of wildfires. Nearly 800 thousand customers were scheduled to be affected by" - "the shutoffs which were expected to last through at least midday tomorrow.")] - - # Summarize - summary = summarizer.predict( - documents=docs) - - # Show results (List of Documents, containing summary and original content) - print(summary) - - [ - { - "content": "PGE stated it scheduled the blackouts in response to forecasts for high winds amid dry conditions. ...", - ... - "meta": { - "summary": "California's largest electricity provider has turned off power to hundreds of thousands of customers.", - ... - }, - ... - }, - ``` - """ - - def __init__( - self, - model_name_or_path: str = "google/pegasus-xsum", - model_version: Optional[str] = None, - tokenizer: Optional[str] = None, - max_length: int = 200, - min_length: int = 5, - use_gpu: bool = True, - clean_up_tokenization_spaces: bool = True, - batch_size: int = 16, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """ - Load a summarization model from transformers. - See the up-to-date list of available models at [Hugging Face](https://huggingface.co/models?filter=summarization). - - :param model_name_or_path: The path to the locally saved model or the name of a public model, for example - 'facebook/rag-token-nq', 'facebook/rag-sequence-nq'. - See [Hugging Face](https://huggingface.co/models?filter=summarization) for a full list of available models. - :param model_version: The version of the model to use from the Hugging Face model hub. Can be a tag name, a branch name, or a commit hash. - :param tokenizer: Name of the tokenizer (usually the same as model). - :param max_length: Maximum length of the summarized text. - :param min_length: Minimum length of the summarized text. - :param use_gpu: Whether to use GPU (if available). - :param clean_up_tokenization_spaces: Whether or not to clean up the potential extra spaces in the text output. - :param batch_size: Number of documents to process at a time. - :param progress_bar: Whether to show a progress bar. - :param use_auth_token: The API token used to download private models from Hugging Face. - If set to `True`, the token generated when running - `transformers-cli login` (stored in ~/.huggingface) is used. - More information at [Hugging Face](https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained). - :param devices: List of torch devices (for example, cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects or strings is supported (for example - [torch.device('cuda:0'), "mps", "cuda:1"]). If you specify `use_gpu=False`, the devices - parameter is not used and a single CPU device is used for inference. - """ - torch_and_transformers_import.check() - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s} inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - if tokenizer is None: - tokenizer = model_name_or_path - - self.summarizer = pipeline( - task="summarization", - model=model_name_or_path, - tokenizer=tokenizer, - revision=model_version, - device=self.devices[0], - use_auth_token=use_auth_token, - ) - self.max_length = max_length - self.min_length = min_length - self.clean_up_tokenization_spaces = clean_up_tokenization_spaces - self.print_log: Set[str] = set() - self.batch_size = batch_size - self.progress_bar = progress_bar - - def predict(self, documents: List[Document]) -> List[Document]: - """ - Produce the summarization from the supplied documents. - The documents can come from the Retriever. - - :param documents: A list of Documents (for example, coming from a Retriever) to summarize individually. - :return: List of Documents, where Document.meta["summary"] contains the summarization. - """ - if self.min_length > self.max_length: - raise ValueError("min_length cannot be greater than max_length") - - if len(documents) == 0: - raise ValueError("Summarizer needs at least one document to produce a summary.") - - contexts: List[str] = [doc.content for doc in documents] - - encoded_input = self.summarizer.tokenizer(contexts, verbose=False) - for input_id in encoded_input["input_ids"]: - tokens_count: int = len(input_id) - if tokens_count > self.summarizer.tokenizer.model_max_length: - truncation_warning = ( - "One or more of your input document texts is longer than the specified " - f"maximum sequence length for this summarizer model. " - f"Generating summary from first {self.summarizer.tokenizer.model_max_length}" - f" tokens." - ) - if truncation_warning not in self.print_log: - logger.warning(truncation_warning) - self.print_log.add(truncation_warning) - - summaries = self.summarizer( - contexts, - min_length=self.min_length, - max_length=self.max_length, - return_text=True, - clean_up_tokenization_spaces=self.clean_up_tokenization_spaces, - truncation=True, - ) - - result: List[Document] = [] - - for summary, document in zip(summaries, documents): - document.meta.update({"summary": summary["summary_text"]}) - result.append(document) - - return result - - def predict_batch( - self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None - ) -> Union[List[Document], List[List[Document]]]: - """ - Summarize supplied documents in batches. - These documents can come from the Retriever. - - :param documents: A single list of documents or a list of lists of documents - (for example, coming from a Retriever) to summarize. - :param batch_size: Number of Documents to process at a time. - """ - if self.min_length > self.max_length: - raise ValueError("min_length cannot be greater than max_length") - - if len(documents) == 0 or ( - isinstance(documents[0], list) and all(len(docs) == 0 for docs in documents if isinstance(docs, list)) - ): - raise ValueError("Summarizer needs at least one document to produce a summary.") - - if batch_size is None: - batch_size = self.batch_size - - is_doclist_flat = isinstance(documents[0], Document) - if is_doclist_flat: - contexts = [doc.content for doc in documents if isinstance(doc, Document)] - else: - contexts = [ - [doc.content for doc in docs if isinstance(doc, Document)] - for docs in documents - if isinstance(docs, list) - ] - number_of_docs = [len(context_group) for context_group in contexts] - contexts = list(itertools.chain.from_iterable(contexts)) - - encoded_input = self.summarizer.tokenizer(contexts, verbose=False) - for input_id in encoded_input["input_ids"]: - tokens_count: int = len(input_id) - if tokens_count > self.summarizer.tokenizer.model_max_length: - truncation_warning = ( - "One or more of your input document texts is longer than the specified " - f"maximum sequence length for this summarizer model. " - f"Generating summary from first {self.summarizer.tokenizer.model_max_length}" - f" tokens." - ) - logger.warning(truncation_warning) - break - - summaries = [] - # HF pipeline progress bar hack, see https://discuss.huggingface.co/t/progress-bar-for-hf-pipelines/20498/2 - summaries_dataset = ListDataset(contexts) - for summary_batch in tqdm( - self.summarizer( - summaries_dataset, - min_length=self.min_length, - max_length=self.max_length, - return_text=True, - clean_up_tokenization_spaces=self.clean_up_tokenization_spaces, - truncation=True, - batch_size=batch_size, - ), - disable=not self.progress_bar, - total=len(summaries_dataset), - desc="Summarizing", - ): - summaries.extend(summary_batch) - - if is_doclist_flat: - flat_result: List[Document] = [] - flat_doc_list: List[Document] = [doc for doc in documents if isinstance(doc, Document)] - for summary, document in zip(summaries, flat_doc_list): - document.meta.update({"summary": summary["summary_text"]}) - flat_result.append(document) - return flat_result - else: - nested_result: List[List[Document]] = [] - nested_doc_list: List[List[Document]] = [lst for lst in documents if isinstance(lst, list)] - - # Group summaries together - grouped_summaries = [] - left_idx = 0 - right_idx = 0 - for number in number_of_docs: - right_idx = left_idx + number - grouped_summaries.append(summaries[left_idx:right_idx]) - left_idx = right_idx - - for summary_group, docs_group in zip(grouped_summaries, nested_doc_list): - cur_summaries = [] - for summary, document in zip(summary_group, docs_group): - document.meta.update({"summary": summary["summary_text"]}) - cur_summaries.append(document) - nested_result.append(cur_summaries) - return nested_result diff --git a/haystack/nodes/translator/__init__.py b/haystack/nodes/translator/__init__.py deleted file mode 100644 index 0a8d09aab6..0000000000 --- a/haystack/nodes/translator/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from haystack.nodes.translator.base import BaseTranslator -from haystack.nodes.translator.transformers import TransformersTranslator diff --git a/haystack/nodes/translator/base.py b/haystack/nodes/translator/base.py deleted file mode 100644 index 8164ce62c6..0000000000 --- a/haystack/nodes/translator/base.py +++ /dev/null @@ -1,104 +0,0 @@ -from typing import Any, Dict, List, Mapping, Optional, Union -from copy import deepcopy -from abc import abstractmethod - -from haystack.nodes.base import BaseComponent -from haystack.schema import Document, Answer - - -class BaseTranslator(BaseComponent): - """ - Abstract class for a Translator component that translates either a query or a doc from language A to language B. - """ - - outgoing_edges = 1 - - @abstractmethod - def translate( - self, - results: Optional[List[Dict[str, Any]]] = None, - query: Optional[str] = None, - documents: Optional[Union[List[Document], List[Answer], List[str], List[Dict[str, Any]]]] = None, - dict_key: Optional[str] = None, - ) -> Union[str, List[Document], List[Answer], List[str], List[Dict[str, Any]]]: - """ - Translate the passed query or a list of documents from language A to B. - """ - pass - - @abstractmethod - def translate_batch( - self, - queries: Optional[List[str]] = None, - documents: Optional[Union[List[Document], List[Answer], List[List[Document]], List[List[Answer]]]] = None, - batch_size: Optional[int] = None, - ) -> List[Union[str, List[Document], List[Answer], List[str], List[Dict[str, Any]]]]: - pass - - def run( # type: ignore - self, - results: Optional[List[Dict[str, Any]]] = None, - query: Optional[str] = None, - documents: Optional[Union[List[Document], List[Answer], List[str], List[Dict[str, Any]]]] = None, - answers: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - dict_key: Optional[str] = None, - ): - """ - Method that gets executed when this class is used as a Node in a Haystack Pipeline. - :param results: Generated QA pairs to translate. - :param query: The query string to translate. - :param documents: The documents to translate. - :param answers: Passes the answers to the TranslationWrapperPipeline. See [Haystack documentation](https://docs.haystack.deepset.ai/docs/ready_made_pipelines#translationwrapperpipeline) for more details. - :param dict_key: If you pass a dictionary in `documents`, you can specify here the field which shall be translated. - """ - translation_results = {} - - if results is not None: - translation_results = {"results": deepcopy(results)} - translated_queries_answers = self.translate(results=translation_results["results"]) - for i, result in enumerate(translation_results["results"]): - result["query"] = translated_queries_answers[i] - result["answers"][0].answer = translated_queries_answers[len(translation_results["results"]) + i] - return translation_results, "output_1" - - # This will cover input query stage - if query: - translation_results["query"] = self.translate(query=query) # type: ignore - # This will cover retriever and summarizer - if documents: - _dict_key = dict_key or "text" - translation_results["documents"] = self.translate(documents=documents, dict_key=_dict_key) # type: ignore - - if answers: - _dict_key = dict_key or "answer" - if isinstance(answers, Mapping): - # This will cover reader - translation_results["answers"] = self.translate(documents=answers["answers"], dict_key=_dict_key) # type: ignore - else: - # This will cover generator - translation_results["answers"] = self.translate(documents=answers, dict_key=_dict_key) # type: ignore - - return translation_results, "output_1" - - def run_batch( # type: ignore - self, - queries: Optional[List[str]] = None, - documents: Optional[Union[List[Document], List[Answer], List[List[Document]], List[List[Answer]]]] = None, - answers: Optional[Union[List[Answer], List[List[Answer]]]] = None, - batch_size: Optional[int] = None, - ): - """ - :param queries: List of query strings to translate. - :param documents: The documents to translate. - :param answers: - :param batch_size: Number of records to process at a time. - """ - translation_results = {} - if queries: - translation_results["queries"] = self.translate_batch(queries=queries) - if documents: - translation_results["documents"] = self.translate_batch(documents=documents) - if answers: - translation_results["answers"] = self.translate_batch(documents=answers) - - return translation_results, "output_1" diff --git a/haystack/nodes/translator/transformers.py b/haystack/nodes/translator/transformers.py deleted file mode 100644 index 69e98ee631..0000000000 --- a/haystack/nodes/translator/transformers.py +++ /dev/null @@ -1,233 +0,0 @@ -import logging -from copy import deepcopy -from typing import Any, Dict, List, Optional, Union - -from tqdm import tqdm - -from haystack.errors import HaystackError -from haystack.schema import Document, Answer -from haystack.nodes.translator.base import BaseTranslator -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport(message="Run 'pip install farm-haystack[inference]'") as torch_and_transformers_import: - import torch - from transformers import AutoModelForSeq2SeqLM, AutoTokenizer - from haystack.modeling.utils import initialize_device_settings # pylint: disable=ungrouped-imports - - -class TransformersTranslator(BaseTranslator): - """ - Translator component based on Seq2Seq models from Huggingface's transformers library. - Exemplary use cases: - - Translate a query from Language A to B (e.g. if you only have good models + documents in language B) - - Translate a document from Language A to B (e.g. if you want to return results in the native language of the user) - - We currently recommend using OPUS models (see __init__() for details) - - **Example:** - - ```python - DOCS = [ - Document(content="Heinz von Foerster was an Austrian American scientist combining physics and philosophy, - and widely attributed as the originator of Second-order cybernetics.") - ] - translator = TransformersTranslator(model_name_or_path="Helsinki-NLP/opus-mt-en-de") - res = translator.translate(documents=DOCS, query=None) - ``` - """ - - def __init__( - self, - model_name_or_path: str, - tokenizer_name: Optional[str] = None, - max_seq_len: Optional[int] = None, - clean_up_tokenization_spaces: Optional[bool] = True, - use_gpu: bool = True, - progress_bar: bool = True, - use_auth_token: Optional[Union[str, bool]] = None, - devices: Optional[List[Union[str, "torch.device"]]] = None, - ): - """Initialize the translator with a model that fits your targeted languages. While we support all seq2seq - models from Hugging Face's model hub, we recommend using the OPUS models from Helsinki NLP. They provide plenty - of different models, usually one model per language pair and translation direction. - They have a pretty standardized naming that should help you find the right model: - - "Helsinki-NLP/opus-mt-en-de" => translating from English to German - - "Helsinki-NLP/opus-mt-de-en" => translating from German to English - - "Helsinki-NLP/opus-mt-fr-en" => translating from French to English - - "Helsinki-NLP/opus-mt-hi-en"=> translating from Hindi to English - ... - - They also have a few multilingual models that support multiple languages at once. - - :param model_name_or_path: Name of the seq2seq model that shall be used for translation. - Can be a remote name from Huggingface's modelhub or a local path. - :param tokenizer_name: Optional tokenizer name. If not supplied, `model_name_or_path` will also be used for the - tokenizer. - :param max_seq_len: The maximum sentence length the model accepts. (Optional) - :param clean_up_tokenization_spaces: Whether or not to clean up the tokenization spaces. (default True) - :param use_gpu: Whether to use GPU or the CPU. Falls back on CPU if no GPU is available. - :param progress_bar: Whether to show a progress bar. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - - :param devices: List of torch devices (e.g. cuda, cpu, mps) to limit inference to specific devices. - A list containing torch device objects and/or strings is supported (For example - [torch.device('cuda:0'), "mps", "cuda:1"]). When specifying `use_gpu=False` the devices - parameter is not used and a single cpu device is used for inference. - """ - torch_and_transformers_import.check() - super().__init__() - - self.devices, _ = initialize_device_settings(devices=devices, use_cuda=use_gpu, multi_gpu=False) - if len(self.devices) > 1: - logger.warning( - "Multiple devices are not supported in %s inference, using the first device %s.", - self.__class__.__name__, - self.devices[0], - ) - - self.max_seq_len = max_seq_len - self.clean_up_tokenization_spaces = clean_up_tokenization_spaces - self.progress_bar = progress_bar - tokenizer_name = tokenizer_name or model_name_or_path - self.tokenizer = AutoTokenizer.from_pretrained(tokenizer_name, use_auth_token=use_auth_token) - self.model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path, use_auth_token=use_auth_token) - self.model.to(str(self.devices[0])) - - def translate( - self, - results: Optional[List[Dict[str, Any]]] = None, - query: Optional[str] = None, - documents: Optional[Union[List[Document], List[Answer], List[str], List[Dict[str, Any]]]] = None, - dict_key: Optional[str] = None, - ) -> Union[str, List[Document], List[Answer], List[str], List[Dict[str, Any]]]: - """ - Run the actual translation. You can supply a query or a list of documents. Whatever is supplied will be translated. - :param results: Generated QA pairs to translate - :param query: The query string to translate - :param documents: The documents to translate - :param dict_key: If you pass a dictionary in `documents`, you can specify here the field which shall be translated. - """ - queries_for_translator = None - answers_for_translator = None - if results is not None: - queries_for_translator = [result["query"] for result in results] - answers_for_translator = [result["answers"][0].answer for result in results] - if not query and not documents and results is None: - raise AttributeError("Translator needs a query or documents to perform translation.") - - if query and documents: - raise AttributeError("Translator needs either a query or documents but not both.") - - if documents and len(documents) == 0: - logger.warning("Empty documents list is passed") - return documents - - dict_key = dict_key or "content" - - if queries_for_translator is not None and answers_for_translator is not None: - text_for_translator = queries_for_translator + answers_for_translator - - elif isinstance(documents, list): - if isinstance(documents[0], Document): - text_for_translator = [doc.content for doc in documents] # type: ignore - elif isinstance(documents[0], Answer): - text_for_translator = [answer.answer for answer in documents] # type: ignore - elif isinstance(documents[0], str): - text_for_translator = documents # type: ignore - else: - if not isinstance(documents[0].get(dict_key, None), str): # type: ignore - raise AttributeError(f"Dictionary should have {dict_key} key and it's value should be `str` type") - text_for_translator = [doc[dict_key] for doc in documents] # type: ignore - else: - text_for_translator: List[str] = [query] # type: ignore - - batch = self.tokenizer( - text=text_for_translator, - return_tensors="pt", - max_length=self.max_seq_len, - padding="longest", - truncation=True, - ).to(self.devices[0]) - - generated_output = self.model.generate(**batch) - translated_texts = self.tokenizer.batch_decode( - generated_output, skip_special_tokens=True, clean_up_tokenization_spaces=self.clean_up_tokenization_spaces - ) - - if queries_for_translator is not None and answers_for_translator is not None: - return translated_texts - elif query: - return translated_texts[0] - elif documents: - if isinstance(documents, list) and isinstance(documents[0], str): - return list(translated_texts) - - translated_documents: Union[ - List[Document], List[Answer], List[str], List[Dict[str, Any]] - ] = [] # type: ignore - for translated_text, doc in zip(translated_texts, documents): - translated_document = deepcopy(doc) - if isinstance(translated_document, Document): - translated_document.content = translated_text - elif isinstance(translated_document, Answer): - translated_document.answer = translated_text - else: - translated_document[dict_key] = translated_text # type: ignore - translated_documents.append(translated_document) # type: ignore - - return translated_documents - - raise AttributeError("Translator needs a query or documents to perform translation") - - def translate_batch( - self, - queries: Optional[List[str]] = None, - documents: Optional[Union[List[Document], List[Answer], List[List[Document]], List[List[Answer]]]] = None, - batch_size: Optional[int] = None, - ) -> List[Union[str, List[Document], List[Answer], List[str], List[Dict[str, Any]]]]: - """ - Run the actual translation. You can supply a single query, a list of queries or a list (of lists) of documents. - - :param queries: Single query or list of queries. - :param documents: List of documents or list of lists of documets. - :param batch_size: Not applicable. - """ - # TODO: This method currently just calls the translate method multiple times, so there is room for improvement. - - if queries and documents: - raise AttributeError("Translator needs either query or documents but not both.") - - if not queries and not documents: - raise AttributeError("Translator needs a query or documents to perform translation.") - - translated = [] - # Translate queries - if queries: - for query in tqdm(queries, disable=not self.progress_bar, desc="Translating"): - cur_translation = self.translate(query=query) - translated.append(cur_translation) - - # Translate docs / answers - elif documents: - # Single list of documents / answers - if not isinstance(documents[0], list): - translated.append(self.translate(documents=documents)) # type: ignore - # Multiple lists of document / answer lists - else: - for cur_list in tqdm(documents, disable=not self.progress_bar, desc="Translating"): - if not isinstance(cur_list, list): - raise HaystackError( - f"cur_list was of type {type(cur_list)}, but expected a list of Documents / Answers." - ) - cur_translation = self.translate(documents=cur_list) - translated.append(cur_translation) - - return translated diff --git a/haystack/pipelines/__init__.py b/haystack/pipelines/__init__.py deleted file mode 100644 index ca770cd05a..0000000000 --- a/haystack/pipelines/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from haystack.pipelines.base import Pipeline, RootNode -from haystack.pipelines.ray import RayPipeline -from haystack.pipelines.standard_pipelines import ( - BaseStandardPipeline, - DocumentSearchPipeline, - QuestionGenerationPipeline, - TranslationWrapperPipeline, - SearchSummarizationPipeline, - MostSimilarDocumentsPipeline, - QuestionAnswerGenerationPipeline, - RetrieverQuestionGenerationPipeline, - GenerativeQAPipeline, - ExtractiveQAPipeline, - FAQPipeline, - TextIndexingPipeline, - WebQAPipeline, -) diff --git a/haystack/pipelines/base.py b/haystack/pipelines/base.py deleted file mode 100644 index 0b93b119cc..0000000000 --- a/haystack/pipelines/base.py +++ /dev/null @@ -1,2614 +0,0 @@ -# pylint: disable=too-many-public-methods,too-many-lines - -from __future__ import annotations - -import itertools -from functools import partial -from hashlib import md5 -from time import time -from typing import Dict, List, Optional, Any, Set, Tuple, Union, Literal - -import copy -import json -import inspect -import logging -import tempfile -from pathlib import Path - -import yaml -import numpy as np -import pandas as pd -import networkx as nx -from pandas.core.frame import DataFrame -from tqdm import tqdm -from networkx import DiGraph -from networkx.drawing.nx_agraph import to_agraph - -from haystack import __version__ - -from haystack.pipelines.config import ( - get_component_definitions, - get_pipeline_definition, - read_pipeline_config_from_yaml, - validate_config, - _add_node_to_pipeline_graph, - _init_pipeline_graph, - VALID_ROOT_NODES, -) -from haystack.pipelines.utils import generate_code, print_eval_report -from haystack.utils.deepsetcloud import DeepsetCloud -from haystack.schema import Answer, EvaluationResult, MultiLabel, Document, Span -from haystack.errors import HaystackError, PipelineError, PipelineConfigError, DocumentStoreError -from haystack.nodes import BaseGenerator, Docs2Answers, BaseReader, BaseSummarizer, BaseTranslator, QuestionGenerator -from haystack.nodes.base import BaseComponent, RootNode -from haystack.nodes.retriever.base import BaseRetriever -from haystack.document_stores.base import BaseDocumentStore -from haystack.utils.experiment_tracking import MLflowTrackingHead, Tracker as tracker -from haystack.telemetry import send_event, send_pipeline_event -from haystack.lazy_imports import LazyImport - - -logger = logging.getLogger(__name__) - - -with LazyImport() as modeling_import: - from haystack.modeling.evaluation.metrics import semantic_answer_similarity - from haystack.modeling.evaluation.squad import compute_f1 as calculate_f1_str - from haystack.modeling.evaluation.squad import compute_exact as calculate_em_str - from haystack.utils.context_matching import calculate_context_similarity - - -ROOT_NODE_TO_PIPELINE_NAME = {"query": "query", "file": "indexing"} -CODE_GEN_DEFAULT_COMMENT = "This code has been generated." -TRACKING_TOOL_TO_HEAD = {"mlflow": MLflowTrackingHead} - - -class Pipeline: - """ - Pipeline brings together building blocks to build a complex search pipeline with Haystack and user-defined components. - - Under the hood, a Pipeline is represented as a directed acyclic graph of component nodes. You can use it for custom query flows with the option to branch queries (for example, extractive question answering and keyword match query), merge candidate documents for a Reader from multiple Retrievers, or re-ranking of candidate documents. - """ - - def __init__(self): - self.graph = DiGraph() - self.config_hash = None - self.last_config_hash = None - self.runs = 0 - - @property - def root_node(self) -> Optional[str]: - """ - Returns the root node of the pipeline's graph. - """ - if len(self.graph.nodes) < 1: - return None - return list(self.graph.nodes)[0] # List conversion is required, see networkx docs - - @property - def components(self) -> Dict[str, BaseComponent]: - """ - Returns all components used by this pipeline. - Note that this also includes such components that are being utilized by other components only and are not being used as a pipeline node directly. - """ - all_components = self._find_all_components() - return {component.name: component for component in all_components if component.name is not None} - - def _find_all_components(self, seed_components: Optional[List[BaseComponent]] = None) -> Set[BaseComponent]: - """ - Finds all components given the provided seed components. - Components are found by traversing the provided seed components and their utilized components. - If seed_components is None, the node components (except the root node) of the pipeline will be used as seed components. - """ - if seed_components is None: - seed_components = [ - attributes["component"] - for attributes in self.graph.nodes.values() - if not isinstance(attributes["component"], RootNode) - ] - - distinct_components = set(seed_components) - for component in seed_components: - sub_components = self._find_all_components(component.utilized_components) - distinct_components.update(sub_components) - return distinct_components - - def to_code( - self, pipeline_variable_name: str = "pipeline", generate_imports: bool = True, add_comment: bool = False - ) -> str: - """ - Returns the code to create this pipeline as string. - - :param pipeline_variable_name: The variable name of the generated pipeline. - Default value is 'pipeline'. - :param generate_imports: Whether to include the required import statements into the code. - Default value is True. - :param add_comment: Whether to add a preceding comment that this code has been generated. - Default value is False. - """ - pipeline_config = self.get_config() - code = generate_code( - pipeline_config=pipeline_config, - pipeline_variable_name=pipeline_variable_name, - generate_imports=generate_imports, - comment=CODE_GEN_DEFAULT_COMMENT if add_comment else None, - ) - return code - - def to_notebook_cell( - self, pipeline_variable_name: str = "pipeline", generate_imports: bool = True, add_comment: bool = True - ): - """ - Creates a new notebook cell with the code to create this pipeline. - - :param pipeline_variable_name: The variable name of the generated pipeline. - Default value is 'pipeline'. - :param generate_imports: Whether to include the required import statements into the code. - Default value is True. - :param add_comment: Whether to add a preceding comment that this code has been generated. - Default value is True. - """ - pipeline_config = self.get_config() - code = generate_code( - pipeline_config=pipeline_config, - pipeline_variable_name=pipeline_variable_name, - generate_imports=generate_imports, - comment=CODE_GEN_DEFAULT_COMMENT if add_comment else None, - add_pipeline_cls_import=False, - ) - try: - get_ipython().set_next_input(code) # type: ignore - except NameError: - logger.error("Could not create notebook cell. Make sure you're running in a notebook environment.") - - @classmethod - def load_from_deepset_cloud( - cls, - pipeline_config_name: str, - pipeline_name: str = "query", - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - overwrite_with_env_variables: bool = False, - ): - """ - Load Pipeline from Deepset Cloud defining the individual components and how they're tied together to form - a Pipeline. A single config can declare multiple Pipelines, in which case an explicit `pipeline_name` must - be passed. - - In order to get a list of all available pipeline_config_names, call `list_pipelines_on_deepset_cloud()`. - Use the returned `name` as `pipeline_config_name`. - - :param pipeline_config_name: name of the config file inside the Deepset Cloud workspace. - To get a list of all available pipeline_config_names, call `list_pipelines_on_deepset_cloud()`. - :param pipeline_name: specifies which pipeline to load from config. - Deepset Cloud typically provides a 'query' and a 'index' pipeline per config. - :param workspace: workspace in Deepset Cloud - :param api_key: Secret value of the API key. - If not specified, will be read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the Deepset Cloud API. - If not specified, will be read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - :param overwrite_with_env_variables: Overwrite the config with environment variables. For example, - to change return_no_answer param for a FARMReader, an env - variable 'READER_PARAMS_RETURN_NO_ANSWER=False' can be set. Note that an - `_` sign must be used to specify nested hierarchical properties. - """ - client = DeepsetCloud.get_pipeline_client( - api_key=api_key, api_endpoint=api_endpoint, workspace=workspace, pipeline_config_name=pipeline_config_name - ) - pipeline_config = client.get_pipeline_config() - - # update document store params in order to connect to correct index - for component_config in pipeline_config["components"]: - if component_config["type"] == "DeepsetCloudDocumentStore": - params = component_config.get("params", {}) - params["index"] = pipeline_config_name - params["workspace"] = workspace - if api_endpoint is not None: - params["api_endpoint"] = api_endpoint - if api_key is not None: - params["api_key"] = api_key - component_config["params"] = params - - del pipeline_config["name"] # Would fail validation otherwise - pipeline = cls.load_from_config( - pipeline_config=pipeline_config, - pipeline_name=pipeline_name, - overwrite_with_env_variables=overwrite_with_env_variables, - ) - return pipeline - - @classmethod - def list_pipelines_on_deepset_cloud( - cls, workspace: str = "default", api_key: Optional[str] = None, api_endpoint: Optional[str] = None - ) -> List[dict]: - """ - Lists all pipeline configs available on Deepset Cloud. - - :param workspace: workspace in Deepset Cloud - :param api_key: Secret value of the API key. - If not specified, will be read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the Deepset Cloud API. - If not specified, will be read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - - Returns: - list of dictionaries: List[dict] - each dictionary: { - "name": str -> `pipeline_config_name` to be used in `load_from_deepset_cloud()`, - "..." -> additional pipeline meta information - } - example: - - ```python - [{'name': 'my_super_nice_pipeline_config', - 'pipeline_id': '2184e0c1-c6ec-40a1-9b28-5d2768e5efa2', - 'status': 'DEPLOYED', - 'created_at': '2022-02-01T09:57:03.803991+00:00', - 'deleted': False, - 'is_default': False, - 'indexing': {'status': 'IN_PROGRESS', - 'pending_file_count': 3, - 'total_file_count': 31}}] - ``` - """ - client = DeepsetCloud.get_pipeline_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - pipeline_config_infos = list(client.list_pipeline_configs()) - return pipeline_config_infos - - @classmethod - def save_to_deepset_cloud( - cls, - query_pipeline: Pipeline, - index_pipeline: Pipeline, - pipeline_config_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - overwrite: bool = False, - ): - """ - Saves a Pipeline config to Deepset Cloud defining the individual components and how they're tied together to form - a Pipeline. A single config must declare a query pipeline and a index pipeline. - - :param query_pipeline: the query pipeline to save. - :param index_pipeline: the index pipeline to save. - :param pipeline_config_name: name of the config file inside the Deepset Cloud workspace. - :param workspace: workspace in Deepset Cloud - :param api_key: Secret value of the API key. - If not specified, will be read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the Deepset Cloud API. - If not specified, will be read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - :param overwrite: Whether to overwrite the config if it already exists. Otherwise an error is being raised. - """ - query_config = query_pipeline.get_config() - index_config = index_pipeline.get_config() - pipelines = query_config["pipelines"] + index_config["pipelines"] - all_components = query_config["components"] + index_config["components"] - distinct_components = list({component["name"]: component for component in all_components}.values()) - document_stores = [c for c in distinct_components if c["type"].endswith("DocumentStore")] - for document_store in document_stores: - if document_store["type"] != "DeepsetCloudDocumentStore": - logger.info( - "In order to be used on Deepset Cloud, component '%s' of type '%s' " - "has been automatically converted to type DeepsetCloudDocumentStore. " - "Usually this replacement will result in equivalent pipeline quality. " - "However depending on chosen settings of '%s' differences might occur.", - document_store["name"], - document_store["type"], - document_store["name"], - ) - document_store["type"] = "DeepsetCloudDocumentStore" - document_store["params"] = {} - config = {"components": distinct_components, "pipelines": pipelines, "version": __version__} - - client = DeepsetCloud.get_pipeline_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - pipeline_config_info = client.get_pipeline_config_info(pipeline_config_name=pipeline_config_name) - if pipeline_config_info: - if overwrite: - if pipeline_config_info["status"] == "DEPLOYED": - raise ValueError( - f"Deployed pipeline configs are not allowed to be updated. Please undeploy pipeline config '{pipeline_config_name}' first." - ) - client.update_pipeline_config(config=config, pipeline_config_name=pipeline_config_name) - logger.info("Pipeline config '%s' successfully updated.", pipeline_config_name) - else: - raise ValueError( - f"Pipeline config '{pipeline_config_name}' already exists. Set `overwrite=True` to overwrite pipeline config." - ) - else: - client.save_pipeline_config(config=config, pipeline_config_name=pipeline_config_name) - logger.info("Pipeline config '%s' successfully created.", pipeline_config_name) - - @classmethod - def deploy_on_deepset_cloud( - cls, - pipeline_config_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - timeout: int = 60, - show_curl_message: bool = True, - ): - """ - Deploys the pipelines of a pipeline config on Deepset Cloud. - Blocks until pipelines are successfully deployed, deployment failed or timeout exceeds. - If pipelines are already deployed no action will be taken and an info will be logged. - If timeout exceeds a TimeoutError will be raised. - If deployment fails a DeepsetCloudError will be raised. - - Pipeline config must be present on Deepset Cloud. See save_to_deepset_cloud() for more information. - - :param pipeline_config_name: name of the config file inside the Deepset Cloud workspace. - :param workspace: workspace in Deepset Cloud - :param api_key: Secret value of the API key. - If not specified, will be read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the Deepset Cloud API. - If not specified, will be read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - :param timeout: The time in seconds to wait until deployment completes. - If the timeout is exceeded an error will be raised. - :param show_curl_message: Whether to print an additional message after successful deployment showing how to query the pipeline using curl. - """ - client = DeepsetCloud.get_pipeline_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - client.deploy(pipeline_config_name=pipeline_config_name, timeout=timeout, show_curl_message=show_curl_message) - - @classmethod - def undeploy_on_deepset_cloud( - cls, - pipeline_config_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - timeout: int = 60, - ): - """ - Undeploys the pipelines of a pipeline config on Deepset Cloud. - Blocks until pipelines are successfully undeployed, undeployment failed or timeout exceeds. - If pipelines are already undeployed no action will be taken and an info will be logged. - If timeout exceeds a TimeoutError will be raised. - If deployment fails a DeepsetCloudError will be raised. - - Pipeline config must be present on Deepset Cloud. See save_to_deepset_cloud() for more information. - - :param pipeline_config_name: name of the config file inside the Deepset Cloud workspace. - :param workspace: workspace in Deepset Cloud - :param api_key: Secret value of the API key. - If not specified, will be read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the Deepset Cloud API. - If not specified, will be read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - :param timeout: The time in seconds to wait until undeployment completes. - If the timeout is exceeded an error will be raised. - """ - client = DeepsetCloud.get_pipeline_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - client.undeploy(pipeline_config_name=pipeline_config_name, timeout=timeout) - - def add_node(self, component: BaseComponent, name: str, inputs: List[str]): - """ - Add a new node to the pipeline. - - :param component: The object to be called when the data is passed to the node. It can be a Haystack component - (like Retriever, Reader, or Generator) or a user-defined object that implements a run() - method to process incoming data from predecessor node. - :param name: The name for the node. It must not contain any dots. - :param inputs: A list of inputs to the node. If the predecessor node has a single outgoing edge, just the name - of node is sufficient. For instance, a 'BM25Retriever' node would always output a single - edge with a list of documents. It can be represented as ["BM25Retriever"]. - - In cases when the predecessor node has multiple outputs, e.g., a "QueryClassifier", the output - must be specified explicitly as "QueryClassifier.output_2". - """ - if len(self.graph.nodes) < 1: - candidate_roots = [input_node for input_node in inputs if input_node in VALID_ROOT_NODES] - if len(candidate_roots) != 1: - raise PipelineConfigError( - "The first node of a pipeline must have one single root node " - f"as input ({' or '.join(VALID_ROOT_NODES)})." - ) - self.graph = _init_pipeline_graph(root_node_name=candidate_roots[0]) - - # Check for duplicate names before adding the component - # Note that the very same component must be addable multiple times: - # E.g. for indexing pipelines it's common to add a retriever first and a document store afterwards. - # The document store is already being used by the retriever however. - # Thus the very same document store will be added twice, first as a subcomponent of the retriever and second as a first level node. - if name in self.components.keys() and self.components[name] != component: - raise PipelineConfigError(f"A node named '{name}' is already in the pipeline. Choose another name.") - - component_definitions = get_component_definitions(pipeline_config=self.get_config()) - component_definitions[name] = component._component_config - - # Name any nested component before adding them - component.name = name - component_names = self._get_all_component_names() - component_names.add(name) - self._set_sub_component_names(component, component_names=component_names) - - self.graph = _add_node_to_pipeline_graph( - graph=self.graph, - components=component_definitions, - node={"name": name, "inputs": inputs}, - instance=component, - ) - self.update_config_hash() - - def update_config_hash(self): - """ - Used for telemetry. Hashes the config, except for the node names, to send an event only when the pipeline changes. - See haystack/telemetry.py::send_pipeline_event - """ - try: - config_to_hash = copy.copy(self.get_config()) - for comp in config_to_hash["components"]: - del comp["name"] - config_hash = json.dumps(config_to_hash, default=str) - self.config_hash = md5(config_hash.encode()).hexdigest() - except Exception as exc: - logger.debug("Telemetry exception: %s", str(exc)) - self.config_hash = "[an exception occurred during hashing]" - - def get_node(self, name: str) -> Optional[BaseComponent]: - """ - Get a node from the Pipeline. - - :param name: The name of the node. - """ - graph_node = self.graph.nodes.get(name) - component = graph_node["component"] if graph_node else None - return component - - # FIXME unused and untested. In which cases do we need to set nodes? Can this be removed? - def set_node(self, name: str, component): - """ - Set the component for a node in the Pipeline. - - :param name: The name of the node. - :param component: The component object to be set at the node. - """ - self.graph.nodes[name]["component"] = component - - def _run_node(self, node_id: str, node_input: Dict[str, Any]) -> Tuple[Dict, str]: - return self.graph.nodes[node_id]["component"]._dispatch_run(**node_input) - - async def _arun_node(self, node_id: str, node_input: Dict[str, Any]) -> Tuple[Dict, str]: - node = self.graph.nodes[node_id]["component"] - # If a component has a `arun` method, prefer that one over `run` - if hasattr(node, "arun") and callable(node.arun): - run_method = node.arun - else: - # note this might or might not be async, but `_adispatch_run_general` - # will work in both cases. This is a safe fall-back. - run_method = node.run - - return await node._adispatch_run_general(run_method, **node_input) - - def run( # type: ignore - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[Union[dict, List[dict]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - """ - Runs the Pipeline, one node at a time. - - :param query: The search query (for query pipelines only). - :param file_paths: The files to index (for indexing pipelines only). - :param labels: Ground-truth labels that you can use to perform an isolated evaluation of pipelines. These labels are input to nodes in the pipeline. - :param documents: A list of Document objects to be processed by the Pipeline Nodes. - :param meta: Files' metadata. Used in indexing pipelines in combination with `file_paths`. - :param params: A dictionary of parameters that you want to pass to the nodes. - To pass a parameter to all Nodes, use: `{"top_k": 10}`. - To pass a parameter to targeted Nodes, run: - `{"Retriever": {"top_k": 10}, "Reader": {"top_k": 3, "debug": True}}` - :param debug: Specifies whether the Pipeline should instruct Nodes to collect debug information - about their execution. By default, this information includes the input parameters - the Nodes received and the output they generated. You can then find all debug information in the dictionary returned by this method under the key `_debug`. - """ - self.runs += 1 - - send_pipeline_event( - pipeline=self, - query=query, - file_paths=file_paths, - labels=labels, - documents=documents, - meta=meta, - params=params, - debug=debug, - ) - - # validate the node names - self._validate_node_names_in_params(params=params) - - root_node = self.root_node - if not root_node: - raise PipelineError("Cannot run a pipeline with no nodes.") - - node_output = None - queue: Dict[str, Any] = { - root_node: {"root_node": root_node, "params": params} - } # ordered dict with "node_id" -> "input" mapping that acts as a FIFO queue - if query is not None: - queue[root_node]["query"] = query - if file_paths: - queue[root_node]["file_paths"] = file_paths - if labels: - queue[root_node]["labels"] = labels - if documents: - queue[root_node]["documents"] = documents - if meta: - queue[root_node]["meta"] = meta - - i = 0 # the first item is popped off the queue unless it is a "join" node with unprocessed predecessors - while queue: - node_id = list(queue.keys())[i] - node_input = queue[node_id] - node_input["node_id"] = node_id - - # Apply debug attributes to the node input params - # NOTE: global debug attributes will override the value specified - # in each node's params dictionary. - if debug is None and node_input and node_input.get("params", {}): - debug = params.get("debug", None) # type: ignore - if debug is not None: - if not node_input.get("params", None): - node_input["params"] = {} - if node_id not in node_input["params"].keys(): - node_input["params"][node_id] = {} - node_input["params"][node_id]["debug"] = debug - - predecessors = set(nx.ancestors(self.graph, node_id)) - if predecessors.isdisjoint(set(queue.keys())): # only execute if predecessor nodes are executed - try: - logger.debug("Running node '%s` with input: %s", node_id, node_input) - start = time() - node_output, stream_id = self._run_node(node_id, node_input) - if "_debug" in node_output and node_id in node_output["_debug"]: - node_output["_debug"][node_id]["exec_time_ms"] = round((time() - start) * 1000, 2) - except Exception as e: - # The input might be a really large object with thousands of embeddings. - # If you really want to see it, raise the log level. - logger.debug("Exception while running node '%s' with input %s", node_id, node_input) - raise Exception( - f"Exception while running node '{node_id}': {e}\nEnable debug logging to see the data that was passed when the pipeline failed." - ) from e - queue.pop(node_id) - # - if stream_id == "split": - for stream_id in [key for key in node_output.keys() if key.startswith("output_")]: - current_node_output = {k: v for k, v in node_output.items() if not k.startswith("output_")} - current_docs = node_output.pop(stream_id) - current_node_output["documents"] = current_docs - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: - queue[n] = current_node_output - else: - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: # add successor nodes with corresponding inputs to the queue - if queue.get(n): # concatenate inputs if it's a join node - existing_input = queue[n] - if "inputs" not in existing_input.keys(): - updated_input: dict = {"inputs": [existing_input, node_output], "params": params} - if "_debug" in existing_input.keys() or "_debug" in node_output.keys(): - updated_input["_debug"] = { - **existing_input.get("_debug", {}), - **node_output.get("_debug", {}), - } - if query: - updated_input["query"] = query - if file_paths: - updated_input["file_paths"] = file_paths - if labels: - updated_input["labels"] = labels - if documents: - updated_input["documents"] = documents - if meta: - updated_input["meta"] = meta - else: - existing_input["inputs"].append(node_output) - updated_input = existing_input - queue[n] = updated_input - else: - queue[n] = node_output - i = 0 - else: - i += 1 # attempt executing next node in the queue as current `node_id` has unprocessed predecessors - - return node_output - - async def _arun( # noqa: C901,PLR0912 type: ignore - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[Union[dict, List[dict]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - """ - Runs the Pipeline, one node at a time. - - :param query: The search query (for query pipelines only). - :param file_paths: The files to index (for indexing pipelines only). - :param labels: Ground-truth labels that you can use to perform an isolated evaluation of pipelines. These labels are input to nodes in the pipeline. - :param documents: A list of Document objects to be processed by the Pipeline Nodes. - :param meta: Files' metadata. Used in indexing pipelines in combination with `file_paths`. - :param params: A dictionary of parameters that you want to pass to the nodes. - To pass a parameter to all Nodes, use: `{"top_k": 10}`. - To pass a parameter to targeted Nodes, run: - `{"Retriever": {"top_k": 10}, "Reader": {"top_k": 3, "debug": True}}` - :param debug: Specifies whether the Pipeline should instruct Nodes to collect debug information - about their execution. By default, this information includes the input parameters - the Nodes received and the output they generated. You can then find all debug information in the dictionary returned by this method under the key `_debug`. - """ - self.runs += 1 - - send_pipeline_event( - pipeline=self, - query=query, - file_paths=file_paths, - labels=labels, - documents=documents, - meta=meta, - params=params, - debug=debug, - ) - - # validate the node names - self._validate_node_names_in_params(params=params) - - root_node = self.root_node - if not root_node: - raise PipelineError("Cannot run a pipeline with no nodes.") - - node_output = None - queue: Dict[str, Any] = { - root_node: {"root_node": root_node, "params": params} - } # ordered dict with "node_id" -> "input" mapping that acts as a FIFO queue - if query is not None: - queue[root_node]["query"] = query - if file_paths: - queue[root_node]["file_paths"] = file_paths - if labels: - queue[root_node]["labels"] = labels - if documents: - queue[root_node]["documents"] = documents - if meta: - queue[root_node]["meta"] = meta - - i = 0 # the first item is popped off the queue unless it is a "join" node with unprocessed predecessors - while queue: - node_id = list(queue.keys())[i] - node_input = queue[node_id] - node_input["node_id"] = node_id - - # Apply debug attributes to the node input params - # NOTE: global debug attributes will override the value specified - # in each node's params dictionary. - if debug is None and node_input and node_input.get("params", {}): - debug = params.get("debug", None) # type: ignore - if debug is not None: - if not node_input.get("params", None): - node_input["params"] = {} - if node_id not in node_input["params"].keys(): - node_input["params"][node_id] = {} - node_input["params"][node_id]["debug"] = debug - - predecessors = set(nx.ancestors(self.graph, node_id)) - if predecessors.isdisjoint(set(queue.keys())): # only execute if predecessor nodes are executed - try: - logger.debug("Running node '%s` with input: %s", node_id, node_input) - start = time() - node_output, stream_id = await self._arun_node(node_id, node_input) - if "_debug" in node_output and node_id in node_output["_debug"]: - node_output["_debug"][node_id]["exec_time_ms"] = round((time() - start) * 1000, 2) - except Exception as e: - # The input might be a really large object with thousands of embeddings. - # If you really want to see it, raise the log level. - logger.debug("Exception while running node '%s' with input %s", node_id, node_input) - raise Exception( - f"Exception while running node '{node_id}': {e}\nEnable debug logging to see the data that was passed when the pipeline failed." - ) from e - queue.pop(node_id) - # - if stream_id == "split": - for stream_id in [key for key in node_output.keys() if key.startswith("output_")]: - current_node_output = {k: v for k, v in node_output.items() if not k.startswith("output_")} - current_docs = node_output.pop(stream_id) - current_node_output["documents"] = current_docs - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: - queue[n] = current_node_output - else: - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: # add successor nodes with corresponding inputs to the queue - if queue.get(n): # concatenate inputs if it's a join node - existing_input = queue[n] - if "inputs" not in existing_input.keys(): - updated_input: dict = {"inputs": [existing_input, node_output], "params": params} - if "_debug" in existing_input.keys() or "_debug" in node_output.keys(): - updated_input["_debug"] = { - **existing_input.get("_debug", {}), - **node_output.get("_debug", {}), - } - if query: - updated_input["query"] = query - if file_paths: - updated_input["file_paths"] = file_paths - if labels: - updated_input["labels"] = labels - if documents: - updated_input["documents"] = documents - if meta: - updated_input["meta"] = meta - else: - existing_input["inputs"].append(node_output) - updated_input = existing_input - queue[n] = updated_input - else: - queue[n] = node_output - i = 0 - else: - i += 1 # attempt executing next node in the queue as current `node_id` has unprocessed predecessors - - return node_output - - def run_batch( # noqa: C901,PLR0912 type: ignore - self, - queries: Optional[List[str]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - """ - Runs the Pipeline in a batch mode, one node at a time. The batch mode means that the Pipeline can take more than one query as input. You can use this method for query pipelines only. When used with an indexing pipeline, it calls the pipeline `run()` method. - - Here's what this method returns for Retriever-Reader pipelines: - - Single query: Retrieves top-k relevant Documents and returns a list of answers for each retrieved Document. - - A list of queries: Retrieves top-k relevant Documents for each query and returns a list of answers for each query. - - Here's what this method returns for Reader-only pipelines: - - Single query + a list of Documents: Applies the query to each Document individually and returns answers for each single Document. - - Single query + a list of lists of Documents: Applies the query to each list of Documents and returns aggregated answers for each list of Documents. - - A list of queries + a list of Documents: Applies each query to each Document individually and returns answers for each query-document pair. - - A list of queries + a list of lists of Documents: Applies each query to its corresponding Document list and aggregates answers for each list of Documents. - - - :param queries: List of search queries (for query pipelines only). - :param file_paths: The files to index (for indexing pipelines only). If you provide `file_paths` the Pipeline's `run` method instead of `run_batch` is called. - :param labels: Ground-truth labels that you can use to perform an isolated evaluation of pipelines. These labels are input to nodes in the pipeline. - :param documents: A list of Document objects or a list of lists of Document objects to be processed by the Pipeline Nodes. - :param meta: Files' metadata. Used in indexing pipelines in combination with `file_paths`. - :param params: A dictionary of parameters that you want to pass to the nodes. - To pass a parameter to all Nodes, use: `{"top_k": 10}`. - To pass a parameter to targeted Nodes, run: - `{"Retriever": {"top_k": 10}, "Reader": {"top_k": 3, "debug": True}}` - :param debug: Specifies whether the Pipeline should instruct Nodes to collect debug information - about their execution. By default, this information includes the input parameters - the Nodes received and the output they generated. You can then find all debug information in the dictionary returned by this method under the key `_debug`. - """ - self.runs += 1 - - send_pipeline_event( - pipeline=self, - queries=queries, - file_paths=file_paths, - labels=labels, - documents=documents, - meta=meta, - params=params, - debug=debug, - ) - - if file_paths is not None or meta is not None: - logger.info( - "It seems that an indexing Pipeline is run, so using the nodes' run method instead of run_batch." - ) - if isinstance(queries, list): - raise PipelineError("For indexing, only a single query can be provided.") - if isinstance(labels, list): - raise PipelineError("For indexing, only one MultiLabel object can be provided as labels.") - flattened_documents: List[Document] = [] - if documents and isinstance(documents[0], list): - for doc_list in documents: - assert isinstance(doc_list, list) - flattened_documents.extend(doc_list) - return self.run( - query=queries, - file_paths=file_paths, - labels=labels, - documents=flattened_documents, - meta=meta, - params=params, - debug=debug, - ) - # Validate node names - self._validate_node_names_in_params(params=params) - - root_node = self.root_node - if not root_node: - raise PipelineError("Cannot run a pipeline with no nodes.") - - node_output = None - queue: Dict[str, Any] = { - root_node: {"root_node": root_node, "params": params} - } # ordered dict with "node_id" -> "input" mapping that acts as a FIFO queue - if queries: - queue[root_node]["queries"] = queries - if file_paths: - queue[root_node]["file_paths"] = file_paths - if labels: - queue[root_node]["labels"] = labels - if documents: - queue[root_node]["documents"] = documents - if meta: - queue[root_node]["meta"] = meta - - i = 0 # the first item is popped off the queue unless it is a "join" node with unprocessed predecessors - while queue: - node_id = list(queue.keys())[i] - node_input = queue[node_id] - node_input["node_id"] = node_id - - # Apply debug attributes to the node input params - # NOTE: global debug attributes will override the value specified in each node's params dictionary. - if debug is None and node_input and node_input.get("params", {}): - debug = params.get("debug", None) # type: ignore - if debug is not None: - if not node_input.get("params", None): - node_input["params"] = {} - if node_id not in node_input["params"].keys(): - node_input["params"][node_id] = {} - node_input["params"][node_id]["debug"] = debug - - predecessors = set(nx.ancestors(self.graph, node_id)) - if predecessors.isdisjoint(set(queue.keys())): # only execute if predecessor nodes are executed - try: - logger.debug("Running node '%s` with input: %s", node_id, node_input) - node_output, stream_id = self.graph.nodes[node_id]["component"]._dispatch_run_batch(**node_input) - except Exception as e: - # The input might be a really large object with thousands of embeddings. - # If you really want to see it, raise the log level. - logger.debug("Exception while running node '%s' with input %s", node_id, node_input) - raise Exception( - f"Exception while running node '{node_id}': {e}\nEnable debug logging to see the data that was passed when the pipeline failed." - ) from e - queue.pop(node_id) - - if stream_id == "split": - for stream_id in [key for key in node_output.keys() if key.startswith("output_")]: - current_node_output = {k: v for k, v in node_output.items() if not k.startswith("output_")} - current_docs = node_output.pop(stream_id) - current_node_output["documents"] = current_docs - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: - queue[n] = current_node_output - else: - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: - if queue.get(n): # concatenate inputs if it's a join node - existing_input = queue[n] - if "inputs" not in existing_input.keys(): - updated_input: Dict = {"inputs": [existing_input, node_output], "params": params} - if queries: - updated_input["queries"] = queries - if file_paths: - updated_input["file_paths"] = file_paths - if labels: - updated_input["labels"] = labels - if documents: - updated_input["documents"] = documents - if meta: - updated_input["meta"] = meta - else: - existing_input["inputs"].append(node_output) - updated_input = existing_input - queue[n] = updated_input - else: - queue[n] = node_output - i = 0 - else: - i += 1 # attempt executing next node in the queue as current `node_id` has unprocessed predecessors - - return node_output - - @classmethod - def eval_beir( - cls, - index_pipeline: Pipeline, - query_pipeline: Pipeline, - index_params: Optional[Dict] = None, - query_params: Optional[Dict] = None, - dataset: str = "scifact", - dataset_dir: Path = Path("."), - num_documents: Optional[int] = None, - top_k_values: Optional[List[int]] = None, - keep_index: bool = False, - ) -> Tuple[Dict[str, float], Dict[str, float], Dict[str, float], Dict[str, float]]: - """ - Runs information retrieval evaluation of a pipeline using BEIR on a specified BEIR dataset. - See https://github.com/beir-cellar/beir for more information. - - :param index_pipeline: The indexing pipeline to use. - :param query_pipeline: The query pipeline to evaluate. - :param index_params: The params to use during indexing (see pipeline.run's params). - :param query_params: The params to use during querying (see pipeline.run's params). - :param dataset: The BEIR dataset to use. - :param dataset_dir: The directory to store the dataset to. - :param num_documents: Maximum number of documents to load from given dataset. If set to None (default) - or to a value larger than the number of documents in the dataset, the full dataset is loaded. - :param top_k_values: The top_k values each metric will be calculated for. By default, the values are 1, 3, 5, 10, 100, and 1000. - :param keep_index: Whether to keep the index after evaluation. - If True the index will be kept after beir evaluation. Otherwise it will be deleted immediately afterwards. - Defaults to False. - - Returns a tuple containing the ncdg, map, recall and precision scores. - Each metric is represented by a dictionary containing the scores for each top_k value. - """ - - if index_params is None: - index_params = {} - if query_params is None: - query_params = {} - if top_k_values is None: - top_k_values = [1, 3, 5, 10, 100, 1000] - try: - from beir import util - from beir.datasets.data_loader import GenericDataLoader - from beir.retrieval.evaluation import EvaluateRetrieval - except ModuleNotFoundError as e: - raise HaystackError("beir is not installed. Please run 'pip install beir'") from e - - url = f"https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/{dataset}.zip" - data_path = util.download_and_unzip(url, dataset_dir) - logger.info("Dataset downloaded here: %s", data_path) - corpus, queries, qrels = GenericDataLoader(data_path).load(split="test") # or split = "train" or "dev" - - # crop dataset if `dataset_size` is provided and is valid - if num_documents is not None and 0 < num_documents < len(corpus): - logger.info("Cropping dataset from %s to %s documents", len(corpus), num_documents) - corpus = dict(itertools.islice(corpus.items(), num_documents)) - # Remove queries that don't contain the remaining documents - corpus_ids = set(corpus.keys()) - qrels_new = {} - for query_id, document_rel_dict in qrels.items(): - document_rel_ids_intersection = list(corpus_ids & set(document_rel_dict.keys())) - # If there are no remaining documents related to the query, delete the query - if len(document_rel_ids_intersection) == 0: - del queries[query_id] - # If there are remaining documents, update qrels - else: - qrels_new[query_id] = {_id: qrels[query_id][_id] for _id in document_rel_ids_intersection} - qrels = qrels_new - elif num_documents is not None and (num_documents < 1 or num_documents > len(corpus)): - logger.warning( - "'num_documents' variable should be lower than corpus length and have a positive value, but it's %s." - " Dataset size remains unchanged.", - num_documents, - ) - - # check index before eval - document_store = index_pipeline.get_document_store() - if document_store is not None: - if document_store.get_document_count() > 0: - raise HaystackError(f"Index '{document_store.index}' is not empty. Please provide an empty index.") - - if hasattr(document_store, "search_fields"): - search_fields = getattr(document_store, "search_fields") - if "name" not in search_fields: - logger.warning( - "Field 'name' is not part of your DocumentStore's search_fields. Titles won't be searchable. " - "Please set search_fields appropriately." - ) - - haystack_retriever = _HaystackBeirRetrieverAdapter( - index_pipeline=index_pipeline, - query_pipeline=query_pipeline, - index_params=index_params, - query_params=query_params, - ) - retriever = EvaluateRetrieval(haystack_retriever, k_values=top_k_values) - - # Retrieve results (format of results is identical to qrels) - results = retriever.retrieve(corpus, queries) - - # Clean up document store - if not keep_index and document_store is not None and document_store.index is not None: - logger.info("Cleaning up: deleting index '%s' ...", document_store.index) - document_store.delete_index(document_store.index) - - # Evaluate your retrieval using NDCG@k, MAP@K ... - logger.info("Retriever evaluation for k in: %s", retriever.k_values) - ndcg, map_, recall, precision = retriever.evaluate(qrels, results, retriever.k_values) - return ndcg, map_, recall, precision - - @classmethod - def execute_eval_run( - cls, - index_pipeline: Pipeline, - query_pipeline: Pipeline, - evaluation_set_labels: List[MultiLabel], - corpus_file_paths: List[str], - experiment_name: str, - experiment_run_name: str, - experiment_tracking_tool: Literal["mlflow", None] = None, - experiment_tracking_uri: Optional[str] = None, - corpus_file_metas: Optional[List[Dict[str, Any]]] = None, - corpus_meta: Optional[Dict[str, Any]] = None, - evaluation_set_meta: Optional[Dict[str, Any]] = None, - pipeline_meta: Optional[Dict[str, Any]] = None, - index_params: Optional[Dict] = None, - query_params: Optional[Dict] = None, - sas_model_name_or_path: Optional[str] = None, - sas_batch_size: int = 32, - sas_use_gpu: bool = True, - use_batch_mode: bool = False, - add_isolated_node_eval: bool = False, - reuse_index: bool = False, - custom_document_id_field: Optional[str] = None, - document_scope: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "document_id_or_answer", - ] = "document_id_or_answer", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - context_matching_min_length: int = 100, - context_matching_boost_split_overlaps: bool = True, - context_matching_threshold: float = 65.0, - ) -> EvaluationResult: - """ - Starts an experiment run that first indexes the specified files (forming a corpus) using the index pipeline - and subsequently evaluates the query pipeline on the provided labels (forming an evaluation set) using pipeline.eval(). - Parameters and results (metrics and predictions) of the run are tracked by an experiment tracking tool for further analysis. - You can specify the experiment tracking tool by setting the params `experiment_tracking_tool` and `experiment_tracking_uri` - or by passing a (custom) tracking head to Tracker.set_tracking_head(). - Note, that `experiment_tracking_tool` only supports `mlflow` currently. - - For easier comparison you can pass additional metadata regarding corpus (corpus_meta), evaluation set (evaluation_set_meta) and pipelines (pipeline_meta). - E.g. you can give them names or ids to identify them across experiment runs. - - This method executes an experiment run. Each experiment run is part of at least one experiment. - An experiment typically consists of multiple runs to be compared (e.g. using different retrievers in query pipeline). - Experiment tracking tools usually share the same concepts of experiments and provide additional functionality to easily compare runs across experiments. - - E.g. you can call execute_eval_run() multiple times with different retrievers in your query pipeline and compare the runs in mlflow: - - ```python - for retriever_type, query_pipeline in zip(["sparse", "dpr", "embedding"], [sparse_pipe, dpr_pipe, embedding_pipe]): - eval_result = Pipeline.execute_eval_run( - index_pipeline=index_pipeline, - query_pipeline=query_pipeline, - evaluation_set_labels=labels, - corpus_file_paths=file_paths, - corpus_file_metas=file_metas, - experiment_tracking_tool="mlflow", - experiment_tracking_uri="http://localhost:5000", - experiment_name="my-retriever-experiment", - experiment_run_name=f"run_{retriever_type}", - pipeline_meta={"name": f"my-pipeline-{retriever_type}"}, - evaluation_set_meta={"name": "my-evalset"}, - corpus_meta={"name": "my-corpus"}. - reuse_index=False - ) - ``` - - :param index_pipeline: The indexing pipeline to use. - :param query_pipeline: The query pipeline to evaluate. - :param evaluation_set_labels: The labels to evaluate on forming an evaluation set. - :param corpus_file_paths: The files to be indexed and searched during evaluation forming a corpus. - :param experiment_name: The name of the experiment - :param experiment_run_name: The name of the experiment run - :param experiment_tracking_tool: The experiment tracking tool to be used. Currently we only support "mlflow". - If left unset the current TrackingHead specified by Tracker.set_tracking_head() will be used. - :param experiment_tracking_uri: The uri of the experiment tracking server to be used. Must be specified if experiment_tracking_tool is set. - You can use deepset's public mlflow server via https://public-mlflow.deepset.ai/. - Note, that artifact logging (e.g. Pipeline YAML or evaluation result CSVs) are currently not allowed on deepset's public mlflow server as this might expose sensitive data. - :param corpus_file_metas: The optional metadata to be stored for each corpus file (e.g. title). - :param corpus_meta: Metadata about the corpus to track (e.g. name, date, author, version). - :param evaluation_set_meta: Metadata about the evalset to track (e.g. name, date, author, version). - :param pipeline_meta: Metadata about the pipelines to track (e.g. name, author, version). - :param index_params: The params to use during indexing (see pipeline.run's params). - :param query_params: The params to use during querying (see pipeline.run's params). - :param sas_model_name_or_path: Name or path of "Semantic Answer Similarity (SAS) model". When set, the model will be used to calculate similarity between predictions and labels and generate the SAS metric. - The SAS metric correlates better with human judgement of correct answers as it does not rely on string overlaps. - Example: Prediction = "30%", Label = "thirty percent", EM and F1 would be overly pessimistic with both being 0, while SAS paints a more realistic picture with being close to 1. - More info in the paper: https://arxiv.org/abs/2108.06130 - Here are some guidelines regarding the models that you can use: - - You can use Bi Encoders (sentence transformers) or cross encoders trained on Semantic Textual Similarity (STS) data. - The return type of the encoder needs to be a single prediction score (as opposed to multiple scores). - If you use custom cross encoders please make sure they work with sentence_transformers.CrossEncoder class - - Good default for multiple languages: "sentence-transformers/paraphrase-multilingual-mpnet-base-v2" - - Large, powerful, but slow model for English only: "cross-encoder/stsb-roberta-large" - - Large model for German only: "deepset/gbert-large-sts" - :param sas_batch_size: Number of prediction label pairs to encode at once by CrossEncoder or SentenceTransformer while calculating SAS. - :param sas_use_gpu: Whether to use a GPU or the CPU for calculating semantic answer similarity. - Falls back to CPU if no GPU is available. - :param use_batch_mode: Whether to use batches for pipeline executions or single queries (default). - :param add_isolated_node_eval: If set to True, in addition to the integrated evaluation of the pipeline, each node is evaluated in isolated evaluation mode. - The isolated mode shows you how each node is performing on its own and helps to understand the bottlenecks of a pipeline in terms of output quality of each individual node. - If a node performs much better in the isolated evaluation than in the integrated evaluation, the previous node needs to be optimized to improve the pipeline's performance. - If a node's performance is similar in both modes, this node itself needs to be optimized to improve the pipeline's performance. - The isolated evaluation calculates the upper bound of each node's evaluation metrics under the assumption that it received perfect inputs from the previous node. - To this end, labels are used as input to the node instead of the output of the previous node in the pipeline. - The generated dataframes in the EvaluationResult then contain additional rows, which can be distinguished from the integrated evaluation results based on the - values "integrated" or "isolated" in the column "eval_mode" and the evaluation report then additionally lists the upper bound of each node's evaluation metrics. - :param reuse_index: Whether to reuse existing non-empty index and to keep the index after evaluation. - If True the index will be kept after evaluation and no indexing will take place if index has already documents. Otherwise it will be deleted immediately afterwards. - Defaults to False. - :param custom_document_id_field: Custom field name within `Document`'s `meta` which identifies the document and is being used as criterion for matching documents to labels during evaluation. - This is especially useful if you want to match documents on other criteria (e.g. file names) than the default document ids as these could be heavily influenced by preprocessing. - If not set (default) the `Document`'s `id` is being used as criterion for matching documents to labels. - :param document_scope: A criterion for deciding whether documents are relevant or not. - You can select between: - - 'document_id': Specifies that the document ID must match. You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - A typical use case is Document Retrieval. - - 'context': Specifies that the content of the document must match. Uses fuzzy matching (see `context_matching_...` params). - A typical use case is Document-Independent Passage Retrieval. - - 'document_id_and_context': A Boolean operation specifying that both `'document_id' AND 'context'` must match. - A typical use case is Document-Specific Passage Retrieval. - - 'document_id_or_context': A Boolean operation specifying that either `'document_id' OR 'context'` must match. - A typical use case is Document Retrieval having sparse context labels. - - 'answer': Specifies that the document contents must include the answer. The selected `answer_scope` is enforced automatically. - A typical use case is Question Answering. - - 'document_id_or_answer' (default): A Boolean operation specifying that either `'document_id' OR 'answer'` must match. - This is intended to be a proper default value in order to support both main use cases: - - Document Retrieval - - Question Answering - The default value is 'document_id_or_answer'. - :param answer_scope: Specifies the scope in which a matching answer is considered correct. - You can select between: - - 'any' (default): Any matching answer is considered correct. - - 'context': The answer is only considered correct if its context matches as well. - Uses fuzzy matching (see `context_matching_...` params). - - 'document_id': The answer is only considered correct if its document ID matches as well. - You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - - 'document_id_and_context': The answer is only considered correct if its document ID and its context match as well. - The default value is 'any'. - In Question Answering, to enforce that the retrieved document is considered correct whenever the answer is correct, set `document_scope` to 'answer' or 'document_id_or_answer'. - :param context_matching_min_length: The minimum string length context and candidate need to have in order to be scored. - Returns 0.0 otherwise. - :param context_matching_boost_split_overlaps: Whether to boost split overlaps (e.g. [AB] <-> [BC]) that result from different preprocessing params. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries - we cut the context on the same side, recalculate the score and take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - :param context_matching_threshold: Score threshold that candidates must surpass to be included into the result list. Range: [0,100] - """ - if corpus_meta is None: - corpus_meta = {} - if evaluation_set_meta is None: - evaluation_set_meta = {} - if pipeline_meta is None: - pipeline_meta = {} - if index_params is None: - index_params = {} - if query_params is None: - query_params = {} - - if experiment_tracking_tool is not None: - tracking_head_cls = TRACKING_TOOL_TO_HEAD.get(experiment_tracking_tool, None) - if tracking_head_cls is None: - raise HaystackError( - f"Please specify a valid experiment_tracking_tool. Possible values are: {TRACKING_TOOL_TO_HEAD.keys()}" - ) - if experiment_tracking_uri is None: - raise HaystackError("experiment_tracking_uri must be specified if experiment_tracking_tool is set.") - tracking_head = tracking_head_cls(tracking_uri=experiment_tracking_uri) - tracker.set_tracking_head(tracking_head) - - try: - tracker.init_experiment( - experiment_name=experiment_name, run_name=experiment_run_name, tags={experiment_name: "True"} - ) - tracker.track_params( - { - "evaluation_set_label_count": len(evaluation_set_labels), - "evaluation_set": evaluation_set_meta, - "sas_model_name_or_path": sas_model_name_or_path, - "sas_batch_size": sas_batch_size, - "sas_use_gpu": sas_use_gpu, - "pipeline_index_params": index_params, - "pipeline_query_params": query_params, - "pipeline": pipeline_meta, - "corpus_file_count": len(corpus_file_paths), - "corpus": corpus_meta, - "type": "offline/evaluation", - "document_scope": document_scope, - "answer_scope": answer_scope, - "custom_document_id_field": custom_document_id_field, - "context_matching_min_length": context_matching_min_length, - "context_matching_boost_split_overlaps": context_matching_boost_split_overlaps, - "context_matching_threshold": context_matching_threshold, - } - ) - - # check index before eval - document_store = index_pipeline.get_document_store() - if document_store is None: - raise HaystackError("Document store not found. Please provide pipelines with proper document store.") - document_count = document_store.get_document_count() - - if document_count > 0: - if not reuse_index: - raise HaystackError(f"Index '{document_store.index}' is not empty. Please provide an empty index.") - else: - logger.info("indexing %s documents...", len(corpus_file_paths)) - index_pipeline.run(file_paths=corpus_file_paths, meta=corpus_file_metas, params=index_params) - document_count = document_store.get_document_count() - logger.info("indexing %s files to %s documents finished.", len(evaluation_set_labels), document_count) - - tracker.track_params({"pipeline_index_document_count": document_count}) - - if use_batch_mode: - eval_result = query_pipeline.eval_batch( - labels=evaluation_set_labels, - params=query_params, - sas_model_name_or_path=sas_model_name_or_path, - sas_batch_size=sas_batch_size, - sas_use_gpu=sas_use_gpu, - add_isolated_node_eval=add_isolated_node_eval, - custom_document_id_field=custom_document_id_field, - context_matching_boost_split_overlaps=context_matching_boost_split_overlaps, - context_matching_min_length=context_matching_min_length, - context_matching_threshold=context_matching_threshold, - ) - else: - eval_result = query_pipeline.eval( - labels=evaluation_set_labels, - params=query_params, - sas_model_name_or_path=sas_model_name_or_path, - sas_batch_size=sas_batch_size, - sas_use_gpu=sas_use_gpu, - add_isolated_node_eval=add_isolated_node_eval, - custom_document_id_field=custom_document_id_field, - context_matching_boost_split_overlaps=context_matching_boost_split_overlaps, - context_matching_min_length=context_matching_min_length, - context_matching_threshold=context_matching_threshold, - ) - - integrated_metrics = eval_result.calculate_metrics(document_scope=document_scope, answer_scope=answer_scope) - integrated_top_1_metrics = eval_result.calculate_metrics( - simulated_top_k_reader=1, document_scope=document_scope, answer_scope=answer_scope - ) - metrics = {"integrated": integrated_metrics, "integrated_top_1": integrated_top_1_metrics} - if add_isolated_node_eval: - isolated_metrics = eval_result.calculate_metrics( - eval_mode="isolated", document_scope=document_scope, answer_scope=answer_scope - ) - isolated_top_1_metrics = eval_result.calculate_metrics( - eval_mode="isolated", - simulated_top_k_reader=1, - document_scope=document_scope, - answer_scope=answer_scope, - ) - metrics["isolated"] = isolated_metrics - metrics["isolated_top_1"] = isolated_top_1_metrics - tracker.track_metrics(metrics, step=0) - - with tempfile.TemporaryDirectory() as temp_dir: - eval_result_dir = Path(temp_dir) / "eval_result" - eval_result_dir.mkdir(exist_ok=True) - eval_result.save(out_dir=eval_result_dir) - tracker.track_artifacts(eval_result_dir, artifact_path="eval_result") - with open(Path(temp_dir) / "pipelines.yaml", "w") as outfile: - index_config = index_pipeline.get_config() - query_config = query_pipeline.get_config() - components = list( - {c["name"]: c for c in (index_config["components"] + query_config["components"])}.values() - ) - pipelines = index_config["pipelines"] + query_config["pipelines"] - config = {"version": index_config["version"], "components": components, "pipelines": pipelines} - yaml.dump(config, outfile, default_flow_style=False) - tracker.track_artifacts(temp_dir) - - # Clean up document store - if not reuse_index and document_store.index is not None: - logger.info("Cleaning up: deleting index '%s'...", document_store.index) - document_store.delete_index(document_store.index) - - finally: - tracker.end_run() - - return eval_result - - def eval( - self, - labels: List[MultiLabel], - documents: Optional[List[List[Document]]] = None, - params: Optional[dict] = None, - sas_model_name_or_path: Optional[str] = None, - sas_batch_size: int = 32, - sas_use_gpu: bool = True, - add_isolated_node_eval: bool = False, - custom_document_id_field: Optional[str] = None, - context_matching_min_length: int = 100, - context_matching_boost_split_overlaps: bool = True, - context_matching_threshold: float = 65.0, - use_auth_token: Optional[Union[str, bool]] = None, - ) -> EvaluationResult: - """ - Evaluates the pipeline by running the pipeline once per query in debug mode - and putting together all data that is needed for evaluation, e.g. calculating metrics. - - If you want to calculate SAS (Semantic Answer Similarity) metrics, you have to specify `sas_model_name_or_path`. - - You will be able to control the scope within which an answer or a document is considered correct afterwards (See `document_scope` and `answer_scope` params in `EvaluationResult.calculate_metrics()`). - Some of these scopes require additional information that already needs to be specified during `eval()`: - - `custom_document_id_field` param to select a custom document ID from document's meta data for ID matching (only affects 'document_id' scopes) - - `context_matching_...` param to fine-tune the fuzzy matching mechanism that determines whether some text contexts match each other (only affects 'context' scopes, default values should work most of the time) - - :param labels: The labels to evaluate on - :param documents: List of List of Document that the first node in the pipeline should get as input per multilabel. Can be used to evaluate a pipeline that consists of a reader without a retriever. - :param params: A dictionary of parameters that you want to pass to the nodes. - If you want to pass a param to all nodes, you can just use: {"top_k":10} - If you want to pass it to targeted nodes, you can do: - {"Retriever": {"top_k": 10}, "Reader": {"top_k": 3, "debug": True}} - :param sas_model_name_or_path: Name or path of "Semantic Answer Similarity (SAS) model". When set, the model will be used to calculate similarity between predictions and labels and generate the SAS metric. - The SAS metric correlates better with human judgement of correct answers as it does not rely on string overlaps. - Example: Prediction = "30%", Label = "thirty percent", EM and F1 would be overly pessimistic with both being 0, while SAS paints a more realistic picture with being close to 1. - More info in the paper: https://arxiv.org/abs/2108.06130 - Here are some guidelines regarding the models that you can use: - - You can use Bi Encoders (sentence transformers) or cross encoders trained on Semantic Textual Similarity (STS) data. - The return type of the encoder needs to be a single prediction score (as opposed to multiple scores). - If you use custom cross encoders please make sure they work with sentence_transformers.CrossEncoder class - - Good default for multiple languages: "sentence-transformers/paraphrase-multilingual-mpnet-base-v2" - - Large, powerful, but slow model for English only: "cross-encoder/stsb-roberta-large" - - Large model for German only: "deepset/gbert-large-sts" - :param sas_batch_size: Number of prediction label pairs to encode at once by CrossEncoder or SentenceTransformer while calculating SAS. - :param sas_use_gpu: Whether to use a GPU or the CPU for calculating semantic answer similarity. - Falls back to CPU if no GPU is available. - :param add_isolated_node_eval: If set to True, in addition to the integrated evaluation of the pipeline, each node is evaluated in isolated evaluation mode. - The isolated mode shows you how each node is performing on its own and helps to understand the bottlenecks of a pipeline in terms of output quality of each individual node. - If a node performs much better in the isolated evaluation than in the integrated evaluation, the previous node needs to be optimized to improve the pipeline's performance. - If a node's performance is similar in both modes, this node itself needs to be optimized to improve the pipeline's performance. - The isolated evaluation calculates the upper bound of each node's evaluation metrics under the assumption that it received perfect inputs from the previous node. - To this end, labels are used as input to the node instead of the output of the previous node in the pipeline. - The generated dataframes in the EvaluationResult then contain additional rows, which can be distinguished from the integrated evaluation results based on the - values "integrated" or "isolated" in the column "eval_mode" and the evaluation report then additionally lists the upper bound of each node's evaluation metrics. - :param custom_document_id_field: Custom field name within `Document`'s `meta` which identifies the document and is being used as criterion for matching documents to labels during evaluation. - This is especially useful if you want to match documents on other criteria (e.g. file names) than the default document ids as these could be heavily influenced by preprocessing. - If not set (default) the `Document`'s `id` is being used as criterion for matching documents to labels. - :param context_matching_min_length: The minimum string length context and candidate need to have in order to be scored. - Returns 0.0 otherwise. - :param context_matching_boost_split_overlaps: Whether to boost split overlaps (e.g. [AB] <-> [BC]) that result from different preprocessing params. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries - we cut the context on the same side, recalculate the score and take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - :param context_matching_threshold: Score threshold that candidates must surpass to be included into the result list. Range: [0,100] - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - send_event( - event_name="Evaluation", - event_properties={"pipeline.classname": self.__class__.__name__, "pipeline.config_hash": self.config_hash}, - ) - - eval_result = EvaluationResult() - if add_isolated_node_eval: - params = {} if params is None else params.copy() - params["add_isolated_node_eval"] = True - - # if documents is None, set docs_per_label to None for each label - for docs_per_label, label in zip(documents or [None] * len(labels), labels): # type: ignore - params_per_label = copy.deepcopy(params) - # If the label contains a filter, the filter is applied unless documents are already given - if label.filters is not None and documents is None: - if params_per_label is None: - params_per_label = {"filters": label.filters} - else: - # join both filters and overwrite filters in params with filters in labels - params_per_label["filters"] = {**params_per_label.get("filters", {}), **label.filters} - predictions = self.run( - query=label.query, labels=label, documents=docs_per_label, params=params_per_label, debug=True - ) - - for node_name in predictions["_debug"].keys(): - node_output = predictions["_debug"][node_name]["output"] - df = self._build_eval_dataframe( - queries=[label.query], - query_labels_per_query=[label], - node_name=node_name, - node_output=node_output, - custom_document_id_field=custom_document_id_field, - context_matching_threshold=context_matching_threshold, - context_matching_boost_split_overlaps=context_matching_boost_split_overlaps, - context_matching_min_length=context_matching_min_length, - ) - eval_result.append(node_name, df) - - eval_result = self._add_sas_to_eval_result( - sas_model_name_or_path=sas_model_name_or_path, - sas_batch_size=sas_batch_size, - sas_use_gpu=sas_use_gpu, - context_matching_threshold=context_matching_threshold, - eval_result=eval_result, - use_auth_token=use_auth_token, - ) - # reorder columns for better qualitative evaluation - eval_result = self._reorder_columns_in_eval_result(eval_result=eval_result) - - return eval_result - - def eval_batch( - self, - labels: List[MultiLabel], - documents: Optional[List[List[Document]]] = None, - params: Optional[dict] = None, - sas_model_name_or_path: Optional[str] = None, - sas_batch_size: int = 32, - sas_use_gpu: bool = True, - add_isolated_node_eval: bool = False, - custom_document_id_field: Optional[str] = None, - context_matching_min_length: int = 100, - context_matching_boost_split_overlaps: bool = True, - context_matching_threshold: float = 65.0, - use_auth_token: Optional[Union[str, bool]] = None, - ) -> EvaluationResult: - """ - Evaluates the pipeline by running it in batches in the debug mode - and putting together all data that are needed for evaluation, for example, calculating metrics. - - To calculate SAS (Semantic Answer Similarity) metrics, specify `sas_model_name_or_path`. - - You can control the scope within which an answer or a document is considered correct afterwards (see `document_scope` and `answer_scope` params in `EvaluationResult.calculate_metrics()`). - For some of these scopes, you need to add the following information during `eval()`: - - `custom_document_id_field` parameter to select a custom document ID from document's metadata for ID matching (only affects 'document_id' scopes). - - `context_matching_...` parameter to fine-tune the fuzzy matching mechanism that determines whether text contexts match each other (only affects 'context' scopes, default values should work most of the time). - - :param labels: The labels to evaluate on. - :param documents: List of List of Document that the first node in the pipeline gets as input per multilabel. You can use it to evaluate a pipeline that consists of a reader without a retriever. - :param params: Dictionary of parameters to be dispatched to the nodes. - To pass a parameter to all nodes, just use: {"top_k":10}. - To pass a parametrer to targeted nodes, you can type: - {"Retriever": {"top_k": 10}, "Reader": {"top_k": 3, "debug": True}} - :param sas_model_name_or_path: Name or path of the SAS model. If you specify the path, the model is used to calculate the similarity between predictions and labels and to generate the SAS metric. - The SAS metric correlates better with the human judgment of correct answers as it does not rely on string overlaps. - Example: Prediction = "30%", Label = "thirty percent", EM and F1 would be overly pessimistic with both being 0, while SAS paints a more realistic picture. - If you want to learn more, have a look at the [Semantic Answer Similarity for Evaluating Question Answering Models](https://arxiv.org/abs/2108.06130) paper. - Models: - - You can use Bi Encoders (sentence transformers) or cross encoders trained on Semantic Textual Similarity (STS) data. - The return type of the encoder needs to be a single prediction score (as opposed to multiple scores). - When using custom cross encoders, ensure they work with the `sentence_transformers.CrossEncoder` class. - - This is a good default model for multiple languages: "sentence-transformers/paraphrase-multilingual-mpnet-base-v2." - - A large, powerful, but slow model for English only: "cross-encoder/stsb-roberta-large". - - A large model for German only: "deepset/gbert-large-sts". - :param sas_batch_size: The number of prediction label pairs you want to encode at once by CrossEncoder or SentenceTransformer while calculating SAS. - :param sas_use_gpu: Whether to use a GPU or the CPU for calculating semantic answer similarity. - It uses CPU if no GPU is available. - :param add_isolated_node_eval: If set to True, in addition to the integrated evaluation of the pipeline, each node is evaluated in isolated evaluation mode. - The isolated mode shows you how each node is performing on its own and helps to understand the bottlenecks of a pipeline in terms of output quality of each individual node. - If a node performs much better in the isolated evaluation than in the integrated evaluation, it means you should optimize the preceding node to improve the pipeline's performance. - If a node's performance is similar in both modes, it means you should optimize this node itself to improve the pipeline's performance. - The isolated evaluation calculates the upper bound of each node's evaluation metrics, assuming it received perfect inputs from the previous node. - To achieve this, the isolated evaluation uses labels as input to the node instead of the output of the previous node in the pipeline. - The generated dataframes in the EvaluationResult then contain additional rows, which you can tell apart from the integrated evaluation results based on the - values "integrated" or "isolated" in the column "eval_mode". The evaluation report then additionally lists the upper bound of each node's evaluation metrics. - :param custom_document_id_field: Custom field name within `Document`'s `meta` which identifies the document. This field is used as a criterion for matching documents to labels during evaluation. - This is especially useful if you want to match documents on other criteria (for example, file names) than the default document IDs as these could be heavily influenced by preprocessing. - If you don't set any value, the default `Document`'s `id` is used as a criterion for matching documents to labels. - :param context_matching_min_length: The minimum string length context and candidate need to have in order to be scored. - Returns 0.0 otherwise. - :param context_matching_boost_split_overlaps: Whether to boost split overlaps (for example, [AB] <-> [BC]) that result from different preprocessing params. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries, - we cut the context on the same side, recalculate the score and, take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - :param context_matching_threshold: Score threshold that candidates must surpass to be included into the result list. Range: [0,100]. - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - send_event( - event_name="Evaluation", - event_properties={"pipeline.classname": self.__class__.__name__, "pipeline.config_hash": self.config_hash}, - ) - if add_isolated_node_eval: - params = {} if params is None else params.copy() - params["add_isolated_node_eval"] = True - - predictions_batches = self.run_batch( - queries=[label.query for label in labels], labels=labels, documents=documents, params=params, debug=True - ) - - eval_result = self._generate_eval_result_from_batch_preds( - predictions_batches=predictions_batches, - sas_model_name_or_path=sas_model_name_or_path, - sas_batch_size=sas_batch_size, - sas_use_gpu=sas_use_gpu, - custom_document_id_field=custom_document_id_field, - context_matching_min_length=context_matching_min_length, - context_matching_boost_split_overlaps=context_matching_boost_split_overlaps, - context_matching_threshold=context_matching_threshold, - use_auth_token=use_auth_token, - ) - - return eval_result - - def _generate_eval_result_from_batch_preds( - self, - predictions_batches: Dict, - sas_model_name_or_path: Optional[str] = None, - sas_batch_size: int = 32, - sas_use_gpu: bool = True, - custom_document_id_field: Optional[str] = None, - context_matching_min_length: int = 100, - context_matching_boost_split_overlaps: bool = True, - context_matching_threshold: float = 65.0, - use_auth_token: Optional[Union[str, bool]] = None, - ) -> EvaluationResult: - eval_result = EvaluationResult() - - for node_name in predictions_batches["_debug"].keys(): - node_output = predictions_batches["_debug"][node_name]["output"] - df = self._build_eval_dataframe( - queries=predictions_batches["queries"], - query_labels_per_query=predictions_batches["labels"], - node_name=node_name, - node_output=node_output, - custom_document_id_field=custom_document_id_field, - context_matching_threshold=context_matching_threshold, - context_matching_boost_split_overlaps=context_matching_boost_split_overlaps, - context_matching_min_length=context_matching_min_length, - ) - eval_result.append(node_name, df) - - eval_result = self._add_sas_to_eval_result( - sas_model_name_or_path=sas_model_name_or_path, - sas_batch_size=sas_batch_size, - sas_use_gpu=sas_use_gpu, - context_matching_threshold=context_matching_threshold, - eval_result=eval_result, - use_auth_token=use_auth_token, - ) - # reorder columns for better qualitative evaluation - eval_result = self._reorder_columns_in_eval_result(eval_result=eval_result) - - return eval_result - - def _add_sas_to_eval_result( - self, - sas_model_name_or_path: Optional[str], - sas_batch_size: int, - sas_use_gpu: bool, - context_matching_threshold: float, - eval_result: EvaluationResult, - use_auth_token: Optional[Union[str, bool]] = None, - ) -> EvaluationResult: - modeling_import.check() - - # add sas values in batch mode for whole Dataframe - # this is way faster than if we calculate it for each query separately - if sas_model_name_or_path is not None: - for df in eval_result.node_results.values(): - if len(df[df["type"] == "answer"]) > 0: - gold_labels = df["gold_answers"].values - predictions = [[a] for a in df["answer"].values] - sas, _, pred_label_sas_grid = semantic_answer_similarity( - predictions=predictions, - gold_labels=gold_labels, - sas_model_name_or_path=sas_model_name_or_path, - batch_size=sas_batch_size, - use_gpu=sas_use_gpu, - use_auth_token=use_auth_token, - ) - df["sas"] = sas - df["gold_answers_sas"] = [ - gold_answers_sas_per_pred[0] for gold_answers_sas_per_pred in pred_label_sas_grid - ] - df.map_rows = partial(df.apply, axis=1) - df["sas_context_scope"] = df.map_rows( - lambda row: max( - sas - for sas, sim in zip( - row["gold_answers_sas"] + [0.0], row["gold_contexts_similarity"] + [100] - ) - if sim > context_matching_threshold - ) - ) - df["sas_document_id_scope"] = df.map_rows( - lambda row: max( - sas - for sas, doc_match in zip( - row["gold_answers_sas"] + [0.0], row["gold_documents_id_match"] + [1.0] - ) - if doc_match == 1.0 - ) - ) - df["sas_document_id_and_context_scope"] = df.map_rows( - lambda row: max( - sas - for sas, sim, doc_match in zip( - row["gold_answers_sas"] + [0.0], - row["gold_contexts_similarity"] + [100], - row["gold_documents_id_match"] + [1.0], - ) - if sim > context_matching_threshold and doc_match == 1.0 - ) - ) - - return eval_result - - def _reorder_columns_in_eval_result(self, eval_result: EvaluationResult) -> EvaluationResult: - desired_col_order = [ - "multilabel_id", # generic - "query", # generic - "filters", # generic - "gold_answers", # generic - "answer", # answer-specific - "context", # generic - "exact_match", # answer-specific - "f1", # answer-specific - "sas", # answer-specific - "exact_match_context_scope", # answer-specific - "f1_context_scope", # answer-specific - "sas_context_scope", # answer-specific - "exact_match_document_id_scope", # answer-specific - "f1_document_id_scope", # answer-specific - "sas_document_id_scope", # answer-specific - "exact_match_document_id_and_context_scope", # answer-specific - "f1_document_id_and_context_scope", # answer-specific - "sas_document_id_and_context_scope", # answer-specific - "gold_contexts", # generic - "gold_id_match", # doc-specific - "context_match", # doc-specific - "answer_match", # doc-specific - "gold_id_or_answer_match", # doc-specific - "gold_id_and_answer_match", # doc-specific - "gold_id_or_context_match", # doc-specific - "gold_id_and_context_match", # doc-specific - "gold_id_and_context_and_answer_match", # doc-specific - "context_and_answer_match", # doc-specific - "rank", # generic - "document_id", # document-specific - "document_ids", # answer-specific - "gold_document_ids", # generic - "custom_document_id", # document-specific - "custom_document_ids", # answer-specific - "gold_custom_document_ids", # generic - "offsets_in_document", # answer-specific - "gold_offsets_in_documents", # answer-specific - "offsets_in_context", # answer-specific - "gold_offsets_in_contexts", # answer-specific - "gold_answers_exact_match", # answer-specific - "gold_answers_f1", # answer-specific - "gold_answers_sas", # answer-specific - "gold_documents_id_match", # generic - "gold_contexts_similarity", # generic - "gold_answers_match", # doc-specific - "type", # generic - "node", # generic - "eval_mode", # generic - "prompt", # answer-specific - ] - for key, df in eval_result.node_results.items(): - eval_result.node_results[key] = self._reorder_columns(df, desired_col_order) - - return eval_result - - def _reorder_columns(self, df: DataFrame, desired_order: List[str]) -> DataFrame: - filtered_order = [col for col in desired_order if col in df.columns] - missing_columns = [col for col in df.columns if col not in desired_order] - reordered_columns = filtered_order + missing_columns - assert len(reordered_columns) == len(df.columns) - return df.reindex(columns=reordered_columns) - - def _build_eval_dataframe( - self, - queries: List[str], - query_labels_per_query: List[MultiLabel], - node_name: str, - node_output: dict, - custom_document_id_field: Optional[str] = None, - context_matching_min_length: int = 100, - context_matching_boost_split_overlaps: bool = True, - context_matching_threshold: float = 65.0, - ) -> DataFrame: - """ - Builds a Dataframe for each query from which evaluation metrics can be calculated. - Currently only answer or document returning nodes are supported, returns None otherwise. - - Each row contains either an answer or a document that has been retrieved during evaluation. - Rows are being enriched with basic infos like rank, query, type or node. - Additional answer or document specific evaluation infos like gold labels - and metrics depicting whether the row matches the gold labels are included, too. - """ - modeling_import.check() - - # Disable all the cell-var-from-loop violations in this function - # pylint: disable=cell-var-from-loop - - partial_dfs = [] - for i, (query, query_labels) in enumerate(zip(queries, query_labels_per_query)): - if query_labels is None or query_labels.labels is None: - logger.warning("There is no label for query '%s'. Query will be omitted.", query) - continue - - # remarks for no_answers: - # Single 'no_answer'-labels are not contained in MultiLabel aggregates. - # If all labels are no_answers, MultiLabel.answers will be [""] and the other aggregates [] - gold_answers = query_labels.answers - gold_offsets_in_documents = query_labels.offsets_in_documents - gold_offsets_in_contexts = query_labels.offsets_in_contexts - gold_document_ids = query_labels.document_ids - gold_custom_document_ids = ( - [l.document.meta[custom_document_id_field] for l in query_labels.labels if not l.no_answer] - if custom_document_id_field is not None - else [] - ) - gold_contexts = query_labels.contexts - - # if node returned answers, include answer specific info: - # - the answer returned itself - # - the document_id the answer was found in - # - the position or offsets within the document the answer was found - # - the surrounding context of the answer within the document - # - the gold answers - # - the position or offsets of the gold answer within the document - # - the gold document ids containing the answer - # - the exact_match metric depicting if the answer exactly matches the gold label - # - the f1 metric depicting how well the answer overlaps with the gold label on token basis - # - the sas metric depicting how well the answer matches the gold label on a semantic basis. - # this will be calculated on all queries in eval() for performance reasons if a sas model has been provided - - for field_name in ["answers", "answers_isolated"]: - df_answers = pd.DataFrame() - answers = node_output.get(field_name, None) - if answers is not None: - if i < len(answers) and isinstance(answers[i], list): - # answers_isolated refers to only one relevant document and thus only a list of answers - # answers refers to multiple relevant documents and thus multiple lists of lists of answers - answers = answers[i] - if len(answers) == 0: - # add no_answer if there was no answer retrieved, so query does not get lost in dataframe - answers = [ - Answer( - answer="", - offsets_in_document=[Span(start=0, end=0)], - offsets_in_context=[Span(start=0, end=0)], - ) - ] - answer_cols_to_keep = [ - "answer", - "document_ids", - "offsets_in_document", - "offsets_in_context", - "context", - ] - df_answers = pd.DataFrame(answers, columns=answer_cols_to_keep) - df_answers.map_rows = partial(df_answers.apply, axis=1) - df_answers["rank"] = np.arange(1, len(df_answers) + 1) - df_answers["gold_answers"] = [gold_answers] * len(df_answers) - df_answers["gold_offsets_in_documents"] = [gold_offsets_in_documents] * len(df_answers) - df_answers["gold_offsets_in_contexts"] = [gold_offsets_in_contexts] * len(df_answers) - df_answers["gold_document_ids"] = [gold_document_ids] * len(df_answers) - df_answers["gold_contexts"] = [gold_contexts] * len(df_answers) - if any(answer for answer in answers if answer.type == "generative"): - df_answers["prompt"] = [(answer.meta or {}).get("prompt") for answer in answers] - df_answers["gold_answers_exact_match"] = df_answers.map_rows( - lambda row: [calculate_em_str(gold_answer, row["answer"]) for gold_answer in gold_answers] - ) - df_answers["gold_answers_f1"] = df_answers.map_rows( - lambda row: [calculate_f1_str(gold_answer, row["answer"]) for gold_answer in gold_answers] - ) - df_answers["gold_contexts_similarity"] = df_answers.map_rows( - lambda row: [ - calculate_context_similarity( - str(gold_context), # could be dataframe or list of lists - str(row["context"]) - if row["context"] is not None - else "", # could be dataframe or list of lists - min_length=context_matching_min_length, - boost_split_overlaps=context_matching_boost_split_overlaps, - ) - for gold_context in gold_contexts - ] - ) - df_answers["gold_documents_id_match"] = df_answers.map_rows( - lambda row: [ - 1.0 if gold_id in (row["document_ids"] or []) else 0.0 for gold_id in gold_document_ids - ] - ) - - if custom_document_id_field is not None: - df_answers["gold_custom_document_ids"] = [gold_custom_document_ids] * len(df_answers) - df_answers["custom_document_ids"] = [ - [ - meta.get(custom_document_id_field, "") - for meta in answer.meta.get("doc_metas", [answer.meta]) - ] - for answer in answers - ] - df_answers["gold_documents_id_match"] = df_answers.map_rows( - lambda row: [ - 1.0 if gold_custom_id in row["custom_document_ids"] else 0.0 - for gold_custom_id in gold_custom_document_ids - ] - ) - - # answer_scope: any - df_answers["exact_match"] = df_answers.map_rows( - lambda row: max(row["gold_answers_exact_match"] + [0.0]) - ) - df_answers["f1"] = df_answers.map_rows(lambda row: max(row["gold_answers_f1"] + [0.0])) - - # answer_scope: context - df_answers["exact_match_context_scope"] = df_answers.map_rows( - lambda row: max( - em - for em, sim in zip( - row["gold_answers_exact_match"] + [0.0], row["gold_contexts_similarity"] + [100] - ) - if sim > context_matching_threshold - ) - ) - df_answers["f1_context_scope"] = df_answers.map_rows( - lambda row: max( - f1 - for f1, sim in zip(row["gold_answers_f1"] + [0.0], row["gold_contexts_similarity"] + [100]) - if sim > context_matching_threshold - ) - ) - - # answer_scope: document_id - df_answers["exact_match_document_id_scope"] = df_answers.map_rows( - lambda row: max( - em - for em, doc_match in zip( - row["gold_answers_exact_match"] + [0.0], row["gold_documents_id_match"] + [1.0] - ) - if doc_match == 1.0 - ) - ) - df_answers["f1_document_id_scope"] = df_answers.map_rows( - lambda row: max( - f1 - for f1, doc_match in zip( - row["gold_answers_f1"] + [0.0], row["gold_documents_id_match"] + [1.0] - ) - if doc_match == 1.0 - ) - ) - - # answer_scope: document_id_and_context - df_answers["exact_match_document_id_and_context_scope"] = df_answers.map_rows( - lambda row: max( - f1 - for f1, sim, doc_match in zip( - row["gold_answers_exact_match"] + [0.0], - row["gold_contexts_similarity"] + [100], - row["gold_documents_id_match"] + [1.0], - ) - if sim > context_matching_threshold and doc_match == 1.0 - ) - ) - df_answers["f1_document_id_and_context_scope"] = df_answers.map_rows( - lambda row: max( - f1 - for f1, sim, doc_match in zip( - row["gold_answers_f1"] + [0.0], - row["gold_contexts_similarity"] + [100], - row["gold_documents_id_match"] + [1.0], - ) - if sim > context_matching_threshold and doc_match == 1.0 - ) - ) - - # add general info - df_answers["type"] = "answer" - df_answers["node"] = node_name - df_answers["multilabel_id"] = query_labels.id - df_answers["query"] = query - df_answers["filters"] = ( - json.dumps(query_labels.filters, sort_keys=True).encode() - if query_labels.filters is not None - else None - ) - df_answers["eval_mode"] = "isolated" if "isolated" in field_name else "integrated" - partial_dfs.append(df_answers) - - # if node returned documents, include document specific info: - # - the document_id - # - the content of the document - # - the gold document ids - # - the gold document contents - # - the gold_id_match metric depicting whether one of the gold document ids matches the document - # - the answer_match metric depicting whether the document contains the answer - # - the gold_id_or_answer_match metric depicting whether one of the former two conditions are met - for field_name in ["documents", "documents_isolated"]: - df_docs = pd.DataFrame() - documents = node_output.get(field_name, None) - if documents is not None: - if i < len(documents) and isinstance(documents[i], list): - documents = documents[i] - if len(documents) == 0: - # add dummy document if there was no document retrieved, so query does not get lost in dataframe - documents = [Document(content="", id="")] - document_cols_to_keep = ["content", "id"] - df_docs = pd.DataFrame(documents, columns=document_cols_to_keep) - df_docs.map_rows = partial(df_docs.apply, axis=1) - df_docs.rename(columns={"id": "document_id", "content": "context"}, inplace=True) - df_docs["gold_document_ids"] = [gold_document_ids] * len(df_docs) - df_docs["gold_answers"] = [gold_answers] * len(df_docs) - df_docs["gold_contexts"] = [gold_contexts] * len(df_docs) - df_docs["gold_contexts_similarity"] = df_docs.map_rows( - lambda row: [ - calculate_context_similarity( - str(gold_context) - if isinstance(gold_context, (pd.DataFrame, list)) - else gold_context, # could be dataframe or list of lists - str(row["context"]) - if isinstance( - row["context"], (pd.DataFrame, list) - ) # could be dataframe or list of lists - else row["context"] or "", - min_length=context_matching_min_length, - boost_split_overlaps=context_matching_boost_split_overlaps, - ) - for gold_context in gold_contexts - ] - ) - df_docs["gold_documents_id_match"] = df_docs.map_rows( - lambda row: [1.0 if row["document_id"] == gold_id else 0.0 for gold_id in gold_document_ids] - ) - - if custom_document_id_field is not None: - df_docs["gold_custom_document_ids"] = [gold_custom_document_ids] * len(df_docs) - df_docs["custom_document_id"] = [ - document.meta.get(custom_document_id_field, "") for document in documents - ] - df_docs["gold_documents_id_match"] = df_docs.map_rows( - lambda row: [ - 1.0 if row["custom_document_id"] == gold_custom_id else 0.0 - for gold_custom_id in gold_custom_document_ids - ] - ) - - df_docs["gold_answers_match"] = df_docs.map_rows( - lambda row: [ - 1.0 if gold_answer != "" and gold_answer in row["context"] else 0.0 - for gold_answer in gold_answers - ] - ) - - # document_relevance_criterion: "document_id" - df_docs["gold_id_match"] = df_docs.map_rows(lambda row: max(row["gold_documents_id_match"] + [0.0])) - - # document_relevance_criterion: "answer", - df_docs["answer_match"] = df_docs.map_rows(lambda row: max(row["gold_answers_match"] + [0.0])) - - # document_relevance_criterion: "document_id_or_answer", - df_docs["gold_id_or_answer_match"] = df_docs.map_rows( - lambda row: max(row["gold_id_match"], row["answer_match"]) - ) - - # document_relevance_criterion: "document_id_and_answer", - df_docs["gold_id_and_answer_match"] = df_docs.map_rows( - lambda row: max( - min(id_match, answer_match) - for id_match, answer_match in zip( - row["gold_documents_id_match"] + [0.0], row["gold_answers_match"] + [0.0] - ) - ) - ) - - # document_relevance_criterion: "context", - df_docs["context_match"] = df_docs.map_rows( - lambda row: 1.0 - if any(sim for sim in row["gold_contexts_similarity"] if sim > context_matching_threshold) - else 0.0 - ) - - # document_relevance_criterion: "document_id_or_context", - df_docs["gold_id_or_context_match"] = df_docs.map_rows( - lambda row: max(row["gold_id_match"], row["context_match"]) - ) - - # document_relevance_criterion: "document_id_and_context", - df_docs["gold_id_and_context_match"] = df_docs.map_rows( - lambda row: max( - min(id_match, 1.0 if context_similarity > context_matching_threshold else 0.0) - for id_match, context_similarity in zip( - row["gold_documents_id_match"] + [0.0], row["gold_contexts_similarity"] + [0.0] - ) - ) - ) - - # document_relevance_criterion: "document_id_and_context_and_answer", - df_docs["gold_id_and_context_and_answer_match"] = df_docs.map_rows( - lambda row: max( - min(id_match, 1.0 if context_similarity > context_matching_threshold else 0.0, answer_match) - for id_match, context_similarity, answer_match in zip( - row["gold_documents_id_match"] + [0.0], - row["gold_contexts_similarity"] + [0.0], - row["gold_answers_match"] + [0.0], - ) - ) - ) - - # document_relevance_criterion: "context_and_answer", - df_docs["context_and_answer_match"] = df_docs.map_rows( - lambda row: max( - min(1.0 if context_similarity > context_matching_threshold else 0.0, answer_match) - for context_similarity, answer_match in zip( - row["gold_contexts_similarity"], row["gold_answers_match"] - ) - ) - if any(row["gold_answers_match"]) and any(row["gold_contexts_similarity"]) - else 0.0 - ) - - df_docs["rank"] = np.arange(1, len(df_docs) + 1) - - # add general info - df_docs["type"] = "document" - df_docs["node"] = node_name - df_docs["multilabel_id"] = query_labels.id - df_docs["query"] = query - df_docs["filters"] = json.dumps(query_labels.filters, sort_keys=True).encode() - df_docs["eval_mode"] = "isolated" if "isolated" in field_name else "integrated" - partial_dfs.append(df_docs) - - if len(partial_dfs) == 0: - return pd.DataFrame() - - return pd.concat(partial_dfs, ignore_index=True).reset_index() - - def get_next_nodes(self, node_id: str, stream_id: str): - current_node_edges = self.graph.edges(node_id, data=True) - next_nodes = [ - next_node - for _, next_node, data in current_node_edges - if not stream_id or data["label"] == stream_id or stream_id == "output_all" - ] - return next_nodes - - def get_nodes_by_class(self, class_type) -> List[Any]: - """ - Gets all nodes in the pipeline that are an instance of a certain class (incl. subclasses). - This is for example helpful if you loaded a pipeline and then want to interact directly with the document store. - Example: - - ``` python - from haystack.document_stores.base import BaseDocumentStore - INDEXING_PIPELINE = Pipeline.load_from_yaml(Path(PIPELINE_YAML_PATH), pipeline_name=INDEXING_PIPELINE_NAME) - res = INDEXING_PIPELINE.get_nodes_by_class(class_type=BaseDocumentStore) - ``` - - :return: List of components that are an instance the requested class - """ - - matches = [ - self.graph.nodes.get(node)["component"] - for node in self.graph.nodes - if isinstance(self.graph.nodes.get(node)["component"], class_type) - ] - return matches - - def get_document_store(self) -> Optional[BaseDocumentStore]: - """ - Return the document store object used in the current pipeline. - - :return: Instance of DocumentStore or None - """ - matches = self.get_nodes_by_class(class_type=BaseDocumentStore) - if len(matches) == 0: - matches = list( - {retriever.document_store for retriever in self.get_nodes_by_class(class_type=BaseRetriever)} - ) - - if len(matches) > 1: - raise Exception(f"Multiple Document Stores found in Pipeline: {matches}") - if len(matches) == 0: - return None - else: - return matches[0] - - def draw(self, path: Path = Path("pipeline.png")): - """ - Create a Graphviz visualization of the pipeline. - - :param path: the path to save the image. - """ - try: - import pygraphviz # pylint: disable=unused-import - except ImportError: - raise ImportError( - "Could not import `pygraphviz`. Please install via: \n" - "'pip install pygraphviz'\n" - "(You might need to run this first: apt install libgraphviz-dev graphviz )" - ) - - graphviz = to_agraph(self.graph) - graphviz.layout("dot") - graphviz.draw(path) - - @classmethod - def load_from_yaml( - cls, - path: Path, - pipeline_name: Optional[str] = None, - overwrite_with_env_variables: bool = True, - strict_version_check: bool = False, - ): - """ - Load Pipeline from a YAML file defining the individual components and how they're tied together to form - a Pipeline. A single YAML can declare multiple Pipelines, in which case an explicit `pipeline_name` must - be passed. - - Here's a sample configuration: - - ```yaml - version: '1.9.0' - - components: # define all the building-blocks for Pipeline - - name: MyReader # custom-name for the component; helpful for visualization & debugging - type: FARMReader # Haystack Class name for the component - params: - model_name_or_path: deepset/roberta-base-squad2 - - name: MyRetriever - type: BM25Retriever - params: - document_store: MyDocumentStore # params can reference other components defined in the YAML - - name: MyDocumentStore - type: ElasticsearchDocumentStore - params: - index: haystack_test - - pipelines: # multiple Pipelines can be defined using the components from above - - name: my_query_pipeline # a simple extractive-qa Pipeline - nodes: - - name: MyRetriever - inputs: [Query] - - name: MyReader - inputs: [MyRetriever] - ``` - - Note that, in case of a mismatch in version between Haystack and the YAML, a warning will be printed. - If the pipeline loads correctly regardless, save again the pipeline using `Pipeline.save_to_yaml()` to remove the warning. - - :param path: path of the YAML file. - :param pipeline_name: if the YAML contains multiple pipelines, the pipeline_name to load must be set. - :param overwrite_with_env_variables: Overwrite the YAML configuration with environment variables. For example, - to change index name param for an ElasticsearchDocumentStore, an env - variable 'MYDOCSTORE_PARAMS_INDEX=documents-2021' can be set. Note that an - `_` sign must be used to specify nested hierarchical properties. - :param strict_version_check: whether to fail in case of a version mismatch (throws a warning otherwise) - """ - config = read_pipeline_config_from_yaml(path) - pipeline = cls.load_from_config( - pipeline_config=config, - pipeline_name=pipeline_name, - overwrite_with_env_variables=overwrite_with_env_variables, - strict_version_check=strict_version_check, - ) - return pipeline - - @classmethod - def load_from_config( - cls, - pipeline_config: Dict, - pipeline_name: Optional[str] = None, - overwrite_with_env_variables: bool = True, - strict_version_check: bool = False, - ): - """ - Load Pipeline from a config dict defining the individual components and how they're tied together to form - a Pipeline. A single config can declare multiple Pipelines, in which case an explicit `pipeline_name` must - be passed. - - Here's a sample configuration: - - ```python - { - "version": "ignore", - "components": [ - { # define all the building-blocks for Pipeline - "name": "MyReader", # custom-name for the component; helpful for visualization & debugging - "type": "FARMReader", # Haystack Class name for the component - "params": {"no_ans_boost": -10, "model_name_or_path": "deepset/roberta-base-squad2"}, - }, - { - "name": "MyRetriever", - "type": "BM25Retriever", - "params": { - "document_store": "MyDocumentStore", # params can reference other components defined in the YAML - "custom_query": None, - }, - }, - {"name": "MyDocumentStore", "type": "ElasticsearchDocumentStore", "params": {"index": "haystack_test"}}, - ], - "pipelines": [ - { # multiple Pipelines can be defined using the components from above - "name": "my_query_pipeline", # a simple extractive-qa Pipeline - "nodes": [ - {"name": "MyRetriever", "inputs": ["Query"]}, - {"name": "MyReader", "inputs": ["MyRetriever"]}, - ], - } - ], - } - ``` - - :param pipeline_config: the pipeline config as dict - :param pipeline_name: if the config contains multiple pipelines, the pipeline_name to load must be set. - :param overwrite_with_env_variables: Overwrite the configuration with environment variables. For example, - to change index name param for an ElasticsearchDocumentStore, an env - variable 'MYDOCSTORE_PARAMS_INDEX=documents-2021' can be set. Note that an - `_` sign must be used to specify nested hierarchical properties. - :param strict_version_check: whether to fail in case of a version mismatch (throws a warning otherwise). - """ - validate_config(pipeline_config, strict_version_check=strict_version_check) - pipeline = cls() - - pipeline_definition = get_pipeline_definition(pipeline_config=pipeline_config, pipeline_name=pipeline_name) - component_definitions = get_component_definitions( - pipeline_config=pipeline_config, overwrite_with_env_variables=overwrite_with_env_variables - ) - components: Dict[str, BaseComponent] = {} - for node_config in pipeline_definition["nodes"]: - component = cls._load_or_get_component( - name=node_config["name"], definitions=component_definitions, components=components - ) - pipeline.add_node(component=component, name=node_config["name"], inputs=node_config["inputs"]) - - pipeline.update_config_hash() - return pipeline - - @classmethod - def _load_or_get_component(cls, name: str, definitions: dict, components: dict): - """ - Load a component from the definition or return if component object already present in `components` dict. - - :param name: name of the component to load or get. - :param definitions: dict containing definitions of all components retrieved from the YAML. - :param components: dict containing component objects. - """ - try: - if name in components.keys(): # check if component is already loaded. - return components[name] - - component_params = definitions[name].get("params", {}) - component_type = definitions[name]["type"] - logger.debug("Loading component '%s' of type '%s'", name, definitions[name]["type"]) - - for key, value in component_params.items(): - # Component params can reference to other components. For instance, a Retriever can reference a - # DocumentStore defined in the YAML. All references should be recursively resolved. - if ( - isinstance(value, str) and value in definitions.keys() and value != name - ): # check if the param value is a reference to another component. - if value not in components.keys(): # check if the referenced component is already loaded. - cls._load_or_get_component(name=value, definitions=definitions, components=components) - component_params[key] = components[ - value - ] # substitute reference (string) with the component object. - - component_instance = BaseComponent._create_instance( - component_type=component_type, component_params=component_params, name=name - ) - components[name] = component_instance - return component_instance - - except KeyError as ke: - raise PipelineConfigError( - f"Failed loading pipeline component '{name}': " - "seems like the component does not exist. Did you spell its name correctly?" - ) from ke - except ConnectionError as ce: - raise DocumentStoreError(f"Failed loading pipeline component '{name}': '{ce}'") from ce - except DocumentStoreError as de: - raise de - except Exception as e: - raise PipelineConfigError( - f"Failed loading pipeline component '{name}'. See the stacktrace above for more information." - ) from e - - def save_to_yaml(self, path: Path, return_defaults: bool = False): - """ - Save a YAML configuration for the Pipeline that can be used with `Pipeline.load_from_yaml()`. - - :param path: path of the output YAML file. - :param return_defaults: whether to output parameters that have the default values. - """ - config = self.get_config(return_defaults=return_defaults) - with open(path, "w") as outfile: - yaml.dump(config, outfile, default_flow_style=False) - - def get_config(self, return_defaults: bool = False) -> dict: - """ - Returns a configuration for the Pipeline that can be used with `Pipeline.load_from_config()`. - - :param return_defaults: whether to output parameters that have the default values. - """ - if self.root_node: - pipeline_name = ROOT_NODE_TO_PIPELINE_NAME[self.root_node.lower()] - else: - pipeline_name = "pipeline" - - pipeline_definitions: Dict[str, Dict] = {pipeline_name: {"name": pipeline_name, "nodes": []}} - - component_definitions: Dict[str, Dict] = {} - for node_name, node_attributes in self.graph.nodes.items(): - if node_name == self.root_node: - continue - - component: BaseComponent = node_attributes["component"] - if node_name != component.name: - raise PipelineError(f"Component name '{component.name}' does not match node name '{node_name}'.") - - self._add_component_to_definitions( - component=component, component_definitions=component_definitions, return_defaults=return_defaults - ) - - # create the Pipeline definition with how the Component are connected - inputs = [] - for predecessor in self.graph.predecessors(node_name): - predecessor_out_edges = list(self.graph.edges(predecessor, data=True)) - # if there are multiple outputs and we're not coming from a root node we have to specify the stream - if predecessor not in VALID_ROOT_NODES and len(predecessor_out_edges) > 1: - target_edge = next(edge for edge in predecessor_out_edges if edge[1] == node_name) - # data consists of a dictionary containing the stream_id at the "label" key - stream_id = target_edge[2]["label"] - inputs.append(f"{predecessor}.{stream_id}") - else: - inputs.append(predecessor) - - pipeline_definitions[pipeline_name]["nodes"].append({"name": node_name, "inputs": inputs}) - - config = { - "components": list(component_definitions.values()), - "pipelines": list(pipeline_definitions.values()), - "version": __version__, - } - return config - - def _add_component_to_definitions( - self, component: BaseComponent, component_definitions: Dict[str, Dict], return_defaults: bool = False - ): - """ - Add the definition of the component and all its dependencies (components too) to the component_definitions dict. - This is used to collect all component definitions within Pipeline.get_config() - """ - if component.name is None: - raise PipelineError(f"Component with config '{component._component_config}' does not have a name.") - - component_params: Dict[str, Any] = component.get_params(return_defaults) - # handling of subcomponents: add to definitions and substitute by reference - for param_key, param_value in component_params.items(): - if isinstance(param_value, BaseComponent): - sub_component = param_value - self._add_component_to_definitions(sub_component, component_definitions, return_defaults) - component_params[param_key] = sub_component.name - - component_definitions[component.name] = { - "name": component.name, - "type": component.type, - "params": component_params, - } - - def _get_all_component_names(self, components_to_search: Optional[List[BaseComponent]] = None) -> Set[str]: - component_names = set() - if components_to_search is None: - components_to_search = list(self.components.values()) - for component in components_to_search: - if component and component.name is not None: - component_names.add(component.name) - sub_component_names = self._get_all_component_names(component.utilized_components) - component_names.update(sub_component_names) - return component_names - - def _set_sub_component_names(self, component: BaseComponent, component_names: Set[str]): - for sub_component in component.utilized_components: - if sub_component.name is None: - sub_component.name = self._generate_component_name( - type_name=sub_component.type, existing_component_names=component_names - ) - component_names.add(sub_component.name) - self._set_sub_component_names(sub_component, component_names=component_names) - - def _generate_component_name(self, type_name: str, existing_component_names: Set[str]) -> str: - component_name: str = type_name - # add number if there are multiple distinct ones of the same type - while component_name in existing_component_names: - occupied_num = 1 - if len(component_name) > len(type_name): - occupied_num = int(component_name[len(type_name) + 1 :]) - new_num = occupied_num + 1 - component_name = f"{type_name}_{new_num}" - return component_name - - def _validate_node_names_in_params(self, params: Optional[Dict]): - """ - Validates the node names provided in the 'params' arg of run/run_batch method. - """ - if params and not all(node_id in self.graph.nodes for node_id in params.keys()): - # Might be a non-targeted param. Verify that too - not_a_node = set(params.keys()) - set(self.graph.nodes) - # "debug" will be picked up by _dispatch_run, see its code - # "add_isolated_node_eval" is set by pipeline.eval / pipeline.eval_batch - valid_global_params = {"debug", "add_isolated_node_eval"} - for node_id in self.graph.nodes: - run_signature_args = self._get_run_node_signature(node_id) - valid_global_params |= set(run_signature_args) - invalid_keys = [key for key in not_a_node if key not in valid_global_params] - - if invalid_keys: - raise ValueError( - f"No node(s) or global parameter(s) named {', '.join(invalid_keys)} found in pipeline." - ) - - def _get_run_node_signature(self, node_id: str): - return inspect.signature(self.graph.nodes[node_id]["component"].run).parameters.keys() - - def print_eval_report( - self, - eval_result: EvaluationResult, - n_wrong_examples: int = 3, - metrics_filter: Optional[Dict[str, List[str]]] = None, - document_scope: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "document_id_or_answer", - ] = "document_id_or_answer", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - wrong_examples_fields: Optional[List[str]] = None, - max_characters_per_field: int = 150, - ): - """ - Prints evaluation report containing a metrics funnel and worst queries for further analysis. - - :param eval_result: The evaluation result, can be obtained by running eval(). - :param n_wrong_examples: The number of worst queries to show. - :param metrics_filter: The metrics to show per node. If None all metrics will be shown. - :param document_scope: A criterion for deciding whether documents are relevant or not. - You can select between: - - 'document_id': Specifies that the document ID must match. You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - A typical use case is Document Retrieval. - - 'context': Specifies that the content of the document must match. Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - A typical use case is Document-Independent Passage Retrieval. - - 'document_id_and_context': A Boolean operation specifying that both `'document_id' AND 'context'` must match. - A typical use case is Document-Specific Passage Retrieval. - - 'document_id_or_context': A Boolean operation specifying that either `'document_id' OR 'context'` must match. - A typical use case is Document Retrieval having sparse context labels. - - 'answer': Specifies that the document contents must include the answer. The selected `answer_scope` is enforced automatically. - A typical use case is Question Answering. - - 'document_id_or_answer' (default): A Boolean operation specifying that either `'document_id' OR 'answer'` must match. - This is intended to be a proper default value in order to support both main use cases: - - Document Retrieval - - Question Answering - The default value is 'document_id_or_answer'. - :param answer_scope: Specifies the scope in which a matching answer is considered correct. - You can select between: - - 'any' (default): Any matching answer is considered correct. - - 'context': The answer is only considered correct if its context matches as well. - Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - - 'document_id': The answer is only considered correct if its document ID matches as well. - You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - - 'document_id_and_context': The answer is only considered correct if its document ID and its context match as well. - The default value is 'any'. - In Question Answering, to enforce that the retrieved document is considered correct whenever the answer is correct, set `document_scope` to 'answer' or 'document_id_or_answer'. - :param wrong_examples_fields: A list of fields to include in the worst samples. By default, "answer", "context", and "document_id" are included. - :param max_characters_per_field: The maximum number of characters to include in the worst samples report (per field). - """ - if wrong_examples_fields is None: - wrong_examples_fields = ["answer", "context", "document_id"] - graph = DiGraph(self.graph.edges) - print_eval_report( - eval_result=eval_result, - graph=graph, - n_wrong_examples=n_wrong_examples, - metrics_filter=metrics_filter, - document_scope=document_scope, - answer_scope=answer_scope, - wrong_examples_fields=wrong_examples_fields, - max_characters_per_field=max_characters_per_field, - ) - - def get_type(self) -> str: - """ - Returns the type of the pipeline. - """ - # values of the dict are functions evaluating whether components of this pipeline match the pipeline type - # specified by dict keys - pipeline_types = { - # QuestionGenerationPipeline has only one component, which is a QuestionGenerator - "QuestionGenerationPipeline": lambda x: all(isinstance(x, QuestionGenerator) for x in x.values()), - # GenerativeQAPipeline has at least BaseGenerator and BaseRetriever components - "GenerativeQAPipeline": lambda x: any(isinstance(x, BaseRetriever) for x in x.values()) - and any(isinstance(x, BaseGenerator) for x in x.values()), - # FAQPipeline has at least one Docs2Answers component - "FAQPipeline": lambda x: any(isinstance(x, Docs2Answers) for x in x.values()), - # ExtractiveQAPipeline has at least one BaseRetriever component and one BaseReader component - "ExtractiveQAPipeline": lambda x: any(isinstance(x, BaseRetriever) for x in x.values()) - and any(isinstance(x, BaseReader) for x in x.values()), - # ExtractiveQAPipeline has at least one BaseSummarizer component and one BaseRetriever component - "SearchSummarizationPipeline": lambda x: any(isinstance(x, BaseRetriever) for x in x.values()) - and any(isinstance(x, BaseSummarizer) for x in x.values()), - # TranslationWrapperPipeline has two or more BaseTranslator components - "TranslationWrapperPipeline": lambda x: [isinstance(x, BaseTranslator) for x in x.values()].count(True) - >= 2, - # RetrieverQuestionGenerationPipeline has at least one BaseRetriever component and one - # QuestionGenerator component - "RetrieverQuestionGenerationPipeline": lambda x: any(isinstance(x, BaseRetriever) for x in x.values()) - and any(isinstance(x, QuestionGenerator) for x in x.values()), - # QuestionAnswerGenerationPipeline has at least one BaseReader component and one QuestionGenerator component - "QuestionAnswerGenerationPipeline": lambda x: any(isinstance(x, BaseReader) for x in x.values()) - and any(isinstance(x, QuestionGenerator) for x in x.values()), - # MostSimilarDocumentsPipeline has only BaseDocumentStore component - "MostSimilarDocumentsPipeline": lambda x: len(x.values()) == 1 - and isinstance(list(x.values())[0], BaseDocumentStore), - # DocumentSearchPipeline has at least one BaseRetriever component - "DocumentSearchPipeline": lambda x: any(isinstance(x, BaseRetriever) for x in x.values()), - } - retrievers = [type(comp).__name__ for comp in self.components.values() if isinstance(comp, BaseRetriever)] - doc_stores = [type(comp).__name__ for comp in self.components.values() if isinstance(comp, BaseDocumentStore)] - - pipeline_type = next( - (p_type for p_type, eval_f in pipeline_types.items() if eval_f(self.components)), "Unknown pipeline" - ) - retrievers_used = retrievers if retrievers else "None" - doc_stores_used = doc_stores if doc_stores else "None" - return f"{pipeline_type} (retriever: {retrievers_used}, doc_store: {doc_stores_used})" - - -class _HaystackBeirRetrieverAdapter: - def __init__(self, index_pipeline: Pipeline, query_pipeline: Pipeline, index_params: dict, query_params: dict): - """ - Adapter mimicking a BEIR retriever used by BEIR's EvaluateRetrieval class to run BEIR evaluations on Haystack Pipelines. - This has nothing to do with Haystack's retriever classes. - See https://github.com/beir-cellar/beir/blob/main/beir/retrieval/evaluation.py. - - :param index_pipeline: The indexing pipeline to use. - :param query_pipeline: The query pipeline to evaluate. - :param index_params: The params to use during indexing (see pipeline.run's params). - :param query_params: The params to use during querying (see pipeline.run's params). - """ - self.index_pipeline = index_pipeline - self.query_pipeline = query_pipeline - self.index_params = index_params - self.query_params = query_params - - def search( - self, corpus: Dict[str, Dict[str, str]], queries: Dict[str, str], top_k: int, score_function: str, **kwargs - ) -> Dict[str, Dict[str, float]]: - with tempfile.TemporaryDirectory() as temp_dir: - file_paths = [] - metas = [] - for id, doc in corpus.items(): - file_path = f"{temp_dir}/{id}" - with open(file_path, "w") as f: - f.write(doc["text"]) - file_paths.append(file_path) - metas.append({"id": id, "name": doc.get("title", None)}) - - logger.info("indexing %s documents...", len(corpus)) - self.index_pipeline.run(file_paths=file_paths, meta=metas, params=self.index_params) - logger.info("indexing finished.") - - # adjust query_params to ensure top_k is retrieved - query_params = copy.deepcopy(self.query_params) - query_params["top_k"] = top_k - - results = {} - for q_id, query in tqdm(queries.items(), total=len(queries)): - res = self.query_pipeline.run(query=query, params=query_params) - docs = res["documents"] - query_results = {doc.meta["id"]: doc.score for doc in docs} - results[q_id] = query_results - - return results diff --git a/haystack/pipelines/config.py b/haystack/pipelines/config.py deleted file mode 100644 index d654679c38..0000000000 --- a/haystack/pipelines/config.py +++ /dev/null @@ -1,519 +0,0 @@ -from typing import Any, Dict, List, Optional - -import re -import os -import logging -from pathlib import Path -from copy import copy - -import yaml -import networkx as nx -from jsonschema.validators import Draft7Validator -from jsonschema.exceptions import ValidationError - -from haystack import __version__ -from haystack.nodes.base import BaseComponent, RootNode -from haystack.nodes._json_schema import load_schema, inject_definition_in_schema -from haystack.errors import PipelineError, PipelineConfigError, PipelineSchemaError - - -logger = logging.getLogger(__name__) - - -VALID_KEY_REGEX = re.compile(r"^[-\w/\\.:*]+$") -VALID_VALUE_REGEX = re.compile(r"^[-\w/\\.:* \[\]]+$") -VALID_ROOT_NODES = ["Query", "File"] - - -def get_pipeline_definition(pipeline_config: Dict[str, Any], pipeline_name: Optional[str] = None) -> Dict[str, Any]: - """ - Get the definition of Pipeline from a given pipeline config. If the config contains more than one Pipeline, - then the pipeline_name must be supplied. - - :param pipeline_config: Dict Pipeline config parsed as a dictionary. - :param pipeline_name: name of the Pipeline. - """ - if pipeline_name is None: - if len(pipeline_config["pipelines"]) != 1: - raise PipelineConfigError("The YAML contains multiple pipelines. Please specify the pipeline name to load.") - return pipeline_config["pipelines"][0] - - matching_pipelines = [p for p in pipeline_config["pipelines"] if p["name"] == pipeline_name] - - if len(matching_pipelines) == 1: - return matching_pipelines[0] - - if not matching_pipelines: - raise PipelineConfigError( - f"Cannot find any pipeline with name '{pipeline_name}' declared in the YAML file. " - f"Existing pipelines: {[p['name'] for p in pipeline_config['pipelines']]}" - ) - raise PipelineConfigError( - f"There's more than one pipeline called '{pipeline_name}' in the YAML file. " - "Please give the two pipelines different names." - ) - - -def get_component_definitions( - pipeline_config: Dict[str, Any], overwrite_with_env_variables: bool = True -) -> Dict[str, Dict[str, Any]]: - """ - Returns the definitions of all components from a given pipeline config. - - :param pipeline_config: Dict Pipeline config parsed as a dictionary. - :param overwrite_with_env_variables: Overwrite the YAML configuration with environment variables. For example, - to change index name param for an ElasticsearchDocumentStore, an env - variable 'MYDOCSTORE_PARAMS_INDEX=documents-2021' can be set. Note that an - `_` sign must be used to specify nested hierarchical properties. - """ - component_definitions = {} # definitions of each component from the YAML. - - for raw_component_definition in pipeline_config["components"]: - name = raw_component_definition["name"] - # We perform a shallow copy here because of https://github.com/deepset-ai/haystack/issues/2568 - component_definition = {key: copy(value) for key, value in raw_component_definition.items() if key != "name"} - component_definitions[name] = component_definition - - if overwrite_with_env_variables: - for key, value in os.environ.items(): - env_prefix = f"{name}_params_".upper() - if key.startswith(env_prefix): - param_name = key.replace(env_prefix, "").lower() - if "params" not in component_definition: - component_definition["params"] = {} - component_definition["params"][param_name] = value - logger.info( - "Param '%s' of component '%s' overwritten with environment variable '%s' value '%s'.", - param_name, - name, - key, - "***", - ) - return component_definitions - - -def read_pipeline_config_from_yaml(path: Path) -> Dict[str, Any]: - """ - Parses YAML files into Python objects. - Fails if the file does not exist. - """ - if not os.path.isfile(path): - raise FileNotFoundError(f"Not found: {path}") - with open(path, "r", encoding="utf-8") as stream: - return yaml.safe_load(stream) - - -def build_component_dependency_graph( - pipeline_definition: Dict[str, Any], component_definitions: Dict[str, Any] -) -> nx.DiGraph: - """ - Builds a dependency graph between components. Dependencies are: - - referenced components during component build time (e.g. init params) - - predecessor components in the pipeline that produce the needed input - - This enables sorting the components in a working and meaningful order for instantiation using topological sorting. - - :param pipeline_definition: the definition of the pipeline (e.g. use get_pipeline_definition() to obtain it) - :param component_definitions: the definition of the pipeline components (e.g. use get_component_definitions() to obtain it) - """ - graph = nx.DiGraph() - for component_name, component_definition in component_definitions.items(): - params = component_definition.get("params", {}) - referenced_components: List[str] = [] - for param_value in params.values(): - # Currently we don't do any additional type validation here. - # See https://github.com/deepset-ai/haystack/pull/2253#discussion_r815951591. - if param_value in component_definitions: - referenced_components.append(param_value) - for referenced_component in referenced_components: - graph.add_edge(referenced_component, component_name) - for node in pipeline_definition["nodes"]: - node_name = node["name"] - graph.add_node(node_name) - for input in node["inputs"]: - if input in component_definitions and not graph.has_edge(node_name, input): - # Special case for (actually permitted) cyclic dependencies between two components: - # e.g. DensePassageRetriever depends on ElasticsearchDocumentStore. - # In indexing pipelines ElasticsearchDocumentStore depends on DensePassageRetriever's output. - # But this second dependency is looser, so we neglect it. - graph.add_edge(input, node_name) - return graph - - -def validate_yaml( - path: Path, - strict_version_check: bool = False, - overwrite_with_env_variables: bool = True, - extras: Optional[str] = None, -): - """ - Ensures that the given YAML file can be loaded without issues. - - Validates: - - The YAML schema, so the configuration's structure and types - - The pipeline's graph, so that all nodes are connected properly - - Does not validate: - - The content of each node's parameter (except for their type), - as this method does NOT load the nodes during the validation. - - :param path: path to the YAML file to validatethe configuration to validate - :param strict_version_check: whether to fail in case of a version mismatch (throws a warning otherwise) - :param overwrite_with_env_variables: Overwrite the YAML configuration with environment variables. For example, - to change index name param for an ElasticsearchDocumentStore, an env - variable 'MYDOCSTORE_PARAMS_INDEX=documents-2021' can be set. Note that an - `_` sign must be used to specify nested hierarchical properties. - :param extras: which values are allowed in the `extras` field (for example, `ray`). If None, does not allow the `extras` field at all. - :return: None if validation is successful - :raise: `PipelineConfigError` in case of issues. - """ - pipeline_config = read_pipeline_config_from_yaml(path) - validate_config( - pipeline_config=pipeline_config, - strict_version_check=strict_version_check, - extras=extras, - overwrite_with_env_variables=overwrite_with_env_variables, - ) - logger.debug("'%s' contains valid Haystack pipelines.", path) - - -def validate_config( - pipeline_config: Dict[str, Any], - strict_version_check: bool = False, - overwrite_with_env_variables: bool = True, - extras: Optional[str] = None, -): - """ - Ensures that the given YAML file can be loaded without issues. - - Validates: - - The YAML schema, so the configuration's structure and types - - The pipeline's graph, so that all nodes are connected properly - - Does not validate: - - The content of each node's parameter (except for their type), - as this method does NOT load the nodes during the validation. - - :param pipeline_config: the configuration to validate (from reading up a YAML file or from .get_config()) - :param strict_version_check: whether to fail in case of a version mismatch (throws a warning otherwise) - :param overwrite_with_env_variables: Overwrite the YAML configuration with environment variables. For example, - to change index name param for an ElasticsearchDocumentStore, an env - variable 'MYDOCSTORE_PARAMS_INDEX=documents-2021' can be set. Note that an - `_` sign must be used to specify nested hierarchical properties. - :param extras: which values are allowed in the `extras` field (for example, `ray`). If None, does not allow the `extras` field at all. - :return: None if validation is successful - :raise: `PipelineConfigError` in case of issues. - """ - validate_schema(pipeline_config=pipeline_config, strict_version_check=strict_version_check, extras=extras) - - for pipeline_definition in pipeline_config["pipelines"]: - component_definitions = get_component_definitions( - pipeline_config=pipeline_config, overwrite_with_env_variables=overwrite_with_env_variables - ) - validate_pipeline_graph(pipeline_definition=pipeline_definition, component_definitions=component_definitions) - - -def validate_schema(pipeline_config: Dict, strict_version_check: bool = False, extras: Optional[str] = None) -> None: - """ - Check that the YAML abides the JSON schema, so that every block - of the pipeline configuration file contains all required information - and that every node's type and parameter are correct. - - Does NOT validate the pipeline's graph, nor the values given to - the node's parameters (apart from their type). - - :param pipeline_config: the configuration to validate - :param strict_version_check: whether to fail in case of a version mismatch (throws a warning otherwise) - :param extras: which values are allowed in the `extras` field (for example, `ray`). If None, does not allow the `extras` field at all. - :return: None if validation is successful - :raise: `PipelineConfigError` in case of issues. - """ - logger.debug("Validating the following config:\n%s", pipeline_config) - - if not isinstance(pipeline_config, dict): - raise PipelineConfigError( - "Your pipeline configuration seems to be not a dictionary. " - "Make sure you're loading the correct one, or enable DEBUG " - "logs to see what Haystack is trying to load." - ) - - # Check that the extras are respected - extras_in_config = pipeline_config.get("extras", None) - if (not extras and extras_in_config) or (extras and extras_in_config not in extras): - raise PipelineConfigError( - f"Cannot use this class to load a YAML with 'extras: {extras_in_config}'. " - "Use the proper class, for example 'RayPipeline'." - ) - - # Check for the version manually (to avoid validation errors) - pipeline_version = pipeline_config.get("version", None) - - if pipeline_version != __version__: - if strict_version_check: - raise PipelineConfigError( - f"Cannot load pipeline configuration of version {pipeline_version} " - f"in Haystack version {__version__}\n" - "Please check out the release notes (https://github.com/deepset-ai/haystack/releases/latest), " - "the documentation (https://haystack.deepset.ai/components/pipelines#yaml-file-definitions) " - "and fix your configuration accordingly." - ) - ok_to_ignore_version = pipeline_version == "ignore" and "rc" in __version__ - if not ok_to_ignore_version: - logger.warning( - "This pipeline is version '%s', but you're using Haystack %s\n" - "This might cause bugs and unexpected behaviors." - "Please check out the release notes (https://github.com/deepset-ai/haystack/releases/latest), " - "the documentation (https://haystack.deepset.ai/components/pipelines#yaml-file-definitions) " - "and fix your configuration accordingly.", - pipeline_version, - __version__, - ) - - # Load the json schema, and create one if it doesn't exist yet - schema = load_schema() - - # Remove the version value from the schema to prevent validation errors on it - a version only have to be present. - del schema["properties"]["version"]["const"] - - loaded_custom_nodes = [] - while True: - try: - Draft7Validator(schema).validate(instance=pipeline_config) - break - - except ValidationError as validation: - # If the validation comes from an unknown node, try to find it and retry: - if list(validation.relative_schema_path) == ["properties", "components", "items", "anyOf"]: - if validation.instance["type"] not in loaded_custom_nodes: - logger.info( - "Missing definition for node of type %s. Looking into local classes...", - validation.instance["type"], - ) - missing_component_class = BaseComponent.get_subclass(validation.instance["type"]) - schema = inject_definition_in_schema(node_class=missing_component_class, schema=schema) - loaded_custom_nodes.append(validation.instance["type"]) - continue - - # A node with the given name was in the schema, but something else is wrong with it. - # Probably it references unknown classes in its init parameters. - raise PipelineSchemaError( - f"Node of type {validation.instance['type']} found, but it failed validation. Possible causes:\n" - " - The node is missing some mandatory parameter\n" - " - Wrong indentation of some parameter in YAML\n" - "See the stacktrace for more information." - ) from validation - - # Format the error to make it as clear as possible - error_path = [ - i - for i in list(validation.relative_schema_path)[:-1] - if repr(i) != "'items'" and repr(i) != "'properties'" - ] - error_location = "->".join(repr(index) for index in error_path) - if error_location: - error_location = f"The error is in {error_location}." - - raise PipelineConfigError( - f"Validation failed. {validation.message}. {error_location} " "See the stacktrace for more information." - ) from validation - - logger.debug("The given configuration is valid according to the JSON schema.") - - -def validate_pipeline_graph(pipeline_definition: Dict[str, Any], component_definitions: Dict[str, Any]): - """ - Validates a pipeline's graph without loading the nodes. - - :param pipeline_definition: from get_pipeline_definition() - :param component_definitions: from get_component_definitions() - """ - root_node_name = _find_root_in_pipeline_definition(pipeline_definition) - graph = _init_pipeline_graph(root_node_name=root_node_name) - for node in pipeline_definition["nodes"]: - graph = _add_node_to_pipeline_graph(graph=graph, node=node, components=component_definitions) - logger.debug("The graph for pipeline '%s' is valid.", pipeline_definition["name"]) - - -def _find_root_in_pipeline_definition(pipeline_definition: Dict[str, Any]): - """ - Returns the first input node that could be a root node for the pipeline. - Does not validate for multiple root nodes in the same pipeline. - - Raises PipelineConfigError of no root node is found. - """ - for node in pipeline_definition["nodes"]: - for input_node in node["inputs"]: - if input_node in VALID_ROOT_NODES: - return input_node - raise PipelineConfigError( - "This pipeline seems to have no root nodes. " - f"Please add a root node ({VALID_ROOT_NODES}) as input for the first node of your pipeline." - ) - - -def _init_pipeline_graph(root_node_name: Optional[str]) -> nx.DiGraph: - """ - Inits a pipeline graph with a root node. Validates the root node name. - """ - graph = nx.DiGraph() - - if root_node_name not in VALID_ROOT_NODES: - raise PipelineConfigError(f"Root node '{root_node_name}' is invalid. Available options are {VALID_ROOT_NODES}.") - - root_node = RootNode() - root_node.name = root_node_name - graph.add_node(root_node_name, inputs=[], component=root_node) - return graph - - -def _add_node_to_pipeline_graph( - graph: nx.DiGraph, - components: Dict[str, Dict[str, Any]], - node: Dict[str, Any], - instance: Optional[BaseComponent] = None, -) -> nx.DiGraph: - """ - Adds a single node to the provided graph, performing all necessary validation steps. - - :param graph: the graph to add the node to - :param components: the whole list from get_component_definitions() - :param node: `{"name": node_name, "inputs": [node_inputs]}` (the entry to add from get_component_definitions()) - :param instance: Optional instance of the node. Note that the instance is optional because in some cases - we want to be able to validate the graph without loading the nodes in the process. - Even if an instance is given, this method expects the component definition to be in - `components`. Add the content of `BaseComponent._component_config` to `components` under your - component's name before calling this method if that's not the case (see `Pipeline.add_node()`). - """ - # Validate node definition - # NOTE: In here we compare class names instead of classes to avoid issues with locals(). - # Nodes added to the pipeline like `pipeline.add_node(name="node", instance=MyNode(), inputs=['Query'])` - # would fail this check otherwise. - node_class = _get_defined_node_class(node_name=node["name"], components=components) - if instance and not instance.__class__.__name__ == node_class.__name__: - raise PipelineConfigError( - f"You are trying to load a node instance ({instance}) along with " - "the definition for a node of a different class " - f"({node['name']}, defined as {node_class}). " - "Either pass no instance to this method, or correct the node definitions " - "in your pipeline configuration." - ) - - # If the graph is empty, let's first add a root node - if len(graph) == 0: - raise PipelineConfigError( - "Please initialize the graph with `_init_pipeline_graph()` before calling this function." - ) - - if instance is not None and not isinstance(instance, BaseComponent): - raise PipelineError( - f"The object provided for node {node['name']} is not a subclass of BaseComponent. " - "Cannot add it to the pipeline." - ) - - if node["name"] in VALID_ROOT_NODES: - raise PipelineConfigError( - f"non root nodes cannot be named {' or '.join(VALID_ROOT_NODES)}. Choose another name." - ) - - # Check if the same instance has already been added to the graph before - if instance: - existing_node_names = [name for name, data in graph.nodes.items() if data["component"] == instance] - if len(existing_node_names) > 0: - raise PipelineConfigError( - f"Cannot add node '{node['name']}' You have already added the same instance to the pipeline " - f"under the name '{existing_node_names[0]}'." - ) - - graph.add_node(node["name"], component=instance, inputs=node["inputs"]) - - try: - for input_node in node["inputs"]: - # Separate node and edge name, if specified - input_node_name, input_edge_name = input_node, None - if "." in input_node: - input_node_name, input_edge_name = input_node.split(".") - - root_node_name = list(graph.nodes)[0] - if input_node == root_node_name: - input_edge_name = "output_1" - - elif input_node in VALID_ROOT_NODES: - raise PipelineConfigError( - f"This pipeline seems to contain two root nodes. " - f"You can only use one root node (nodes named {' or '.join(VALID_ROOT_NODES)} per pipeline." - ) - - else: - # Validate node definition and edge name - input_node_type = _get_defined_node_class(node_name=input_node_name, components=components) - component_params: Dict[str, Any] = components[input_node_name].get("params", {}) - input_node_edges_count = input_node_type._calculate_outgoing_edges(component_params=component_params) - - if not input_edge_name: - if input_node_edges_count != 1: # Edge was not specified, but input node has many outputs - raise PipelineConfigError( - f"Can't connect {input_node_name} to {node['name']}: " - f"{input_node_name} has {input_node_edges_count} outgoing edges. " - "Please specify the output edge explicitly (like 'filetype_classifier.output_2')." - ) - input_edge_name = "output_1" - - if not input_edge_name.startswith("output_"): - raise PipelineConfigError( - f"'{input_edge_name}' is not a valid edge name. " - "It must start with 'output_' and must contain no dots." - ) - - requested_edge_name = input_edge_name.split("_")[1] - - try: - requested_edge = int(requested_edge_name) - except ValueError: - raise PipelineConfigError( - f"You must specified a numbered edge, like filetype_classifier.output_2, not {input_node}" - ) - - if not requested_edge <= input_node_edges_count: - raise PipelineConfigError( - f"Cannot connect '{node['name']}' to '{input_node}', as {input_node_name} has only " - f"{input_node_edges_count} outgoing edge(s)." - ) - - graph.add_edge(input_node_name, node["name"], label=input_edge_name) - - # Check if adding this edge created a loop in the pipeline graph - if not nx.is_directed_acyclic_graph(graph): - raise PipelineConfigError(f"Cannot add '{node['name']}': it will create a loop in the pipeline.") - - except PipelineConfigError: - graph.remove_node(node["name"]) - raise - - return graph - - -def _get_defined_node_class(node_name: str, components: Dict[str, Dict[str, str]]): - """ - Returns the class of a given component, given the component's list and the - component's name. Will fail if the component is not in the components list, - or the component's class is not a subclass of BaseComponent. - - :param node_name: the name of the node as defined into the component's definition. - :param components: the component definitions from get_component_definitions() - """ - try: - node_type = components[node_name]["type"] - except KeyError as e: - raise PipelineConfigError( - f"Cannot find node '{node_name}'. Make sure that a node " - f"called '{node_name}' is defined under components." - ) from e - - try: - node_class = BaseComponent.get_subclass(node_type) - except KeyError as e: - raise PipelineConfigError( - f"Node of type '{node_type}' not recognized. Check for typos in the node type." - ) from e - - return node_class diff --git a/haystack/pipelines/ray.py b/haystack/pipelines/ray.py deleted file mode 100644 index fc0a44a53e..0000000000 --- a/haystack/pipelines/ray.py +++ /dev/null @@ -1,486 +0,0 @@ -from __future__ import annotations -import inspect -import logging -from time import time -from typing import Any, Dict, List, Optional, Tuple, Union -from pathlib import Path - -import networkx as nx - -try: - from ray import serve - import ray -except: - ray = None # type: ignore - serve = None # type: ignore - -from haystack.errors import PipelineError -from haystack.pipelines.config import ( - get_component_definitions, - get_pipeline_definition, - read_pipeline_config_from_yaml, - validate_config, -) -from haystack.nodes.base import BaseComponent, RootNode -from haystack.pipelines.base import Pipeline -from haystack.schema import Document, MultiLabel -from haystack.telemetry import send_pipeline_event - - -logger = logging.getLogger(__name__) - - -class RayPipeline(Pipeline): - """ - [Ray](https://ray.io) is a framework for distributed computing. - - With Ray, you can distribute a Pipeline's components across a cluster of machines. The individual components of a - Pipeline can be independently scaled. For instance, an extractive QA Pipeline deployment can have three replicas - of the Reader and a single replica for the Retriever. This way, you can use your resources more efficiently by horizontally scaling Components. - - To set the number of replicas, add `num_replicas` in the YAML configuration for the node in a pipeline: - - ```yaml - components: - ... - - pipelines: - - name: ray_query_pipeline - type: RayPipeline - nodes: - - name: Retriever - inputs: [ Query ] - serve_deployment_kwargs: - num_replicas: 2 # number of replicas to create on the Ray cluster - ``` - - A Ray Pipeline can only be created with a YAML Pipeline configuration. - - ```python - from haystack.pipeline import RayPipeline - pipeline = RayPipeline.load_from_yaml(path="my_pipelines.yaml", pipeline_name="my_query_pipeline") - pipeline.run(query="What is the capital of Germany?") - ``` - - By default, RayPipelines create an instance of RayServe locally. To connect to an existing Ray instance, - set the `address` parameter when creating the RayPipeline instance. - - YAML definitions of Ray pipelines are validated at load. For more information, see [YAML File Definitions](https://haystack-website-git-fork-fstau-dev-287-search-deepset-overnice.vercel.app/components/pipelines#yaml-file-definitions). - """ - - def __init__( - self, - address: Optional[str] = None, - ray_args: Optional[Dict[str, Any]] = None, - serve_args: Optional[Dict[str, Any]] = None, - ): - """ - :param address: The IP address for the Ray cluster. If set to `None`, a local Ray instance is started. - :param ray_args: Optional parameters for initializing Ray. - :param serve_args: Optional parameters for initializing Ray Serve. - """ - ray_args = ray_args or {} - if not ray.is_initialized(): - ray.init(address=address, **ray_args) - else: - logger.warning("Ray was already initialized, so reusing that for this RayPipeline.") - self._serve_controller_client = serve.start(**serve_args) - super().__init__() - - @classmethod - def load_from_config( - cls, - pipeline_config: Dict, - pipeline_name: Optional[str] = None, - overwrite_with_env_variables: bool = True, - strict_version_check: bool = False, - address: Optional[str] = None, - ray_args: Optional[Dict[str, Any]] = None, - serve_args: Optional[Dict[str, Any]] = None, - ): - validate_config(pipeline_config, strict_version_check=strict_version_check, extras="ray") - - pipeline_definition = get_pipeline_definition(pipeline_config=pipeline_config, pipeline_name=pipeline_name) - component_definitions = get_component_definitions( - pipeline_config=pipeline_config, overwrite_with_env_variables=overwrite_with_env_variables - ) - pipeline = cls(address=address, ray_args=ray_args or {}, serve_args=serve_args or {}) - - for node_config in pipeline_definition["nodes"]: - if pipeline.root_node is None: - root_node = node_config["inputs"][0] - if root_node in ["Query", "File"]: - handle = cls._create_ray_deployment(component_name=root_node, pipeline_config=pipeline_config) - pipeline._add_ray_deployment_in_graph(handle=handle, name=root_node, outgoing_edges=1, inputs=[]) - else: - raise KeyError(f"Root node '{root_node}' is invalid. Available options are 'Query' and 'File'.") - - name = node_config["name"] - component_type = component_definitions[name]["type"] - component_class = BaseComponent.get_subclass(component_type) - serve_deployment_kwargs = next(node for node in pipeline_definition["nodes"] if node["name"] == name).get( - "serve_deployment_kwargs", {} - ) - handle = cls._create_ray_deployment( - component_name=name, pipeline_config=pipeline_config, serve_deployment_kwargs=serve_deployment_kwargs - ) - pipeline._add_ray_deployment_in_graph( - handle=handle, - name=name, - outgoing_edges=component_class.outgoing_edges, - inputs=node_config.get("inputs", []), - ) - - pipeline.update_config_hash() - return pipeline - - @classmethod - def load_from_yaml( # type: ignore - cls, - path: Path, - pipeline_name: Optional[str] = None, - overwrite_with_env_variables: bool = True, - address: Optional[str] = None, - strict_version_check: bool = False, - ray_args: Optional[Dict[str, Any]] = None, - serve_args: Optional[Dict[str, Any]] = None, - ): - """ - Load Pipeline from a YAML file defining the individual components and how they're tied together to form - a Pipeline. A single YAML can declare multiple Pipelines, in which case an explicit `pipeline_name` must - be passed. - - Here's a sample configuration: - - ```yaml - version: '1.0.0' - - components: # define all the building-blocks for Pipeline - - name: MyReader # custom-name for the component; helpful for visualization & debugging - type: FARMReader # Haystack Class name for the component - params: - no_ans_boost: -10 - model_name_or_path: deepset/roberta-base-squad2 - - name: MyRetriever - type: BM25Retriever - params: - document_store: MyDocumentStore # params can reference other components defined in the YAML - custom_query: null - - name: MyDocumentStore - type: ElasticsearchDocumentStore - params: - index: haystack_test - - pipelines: # multiple Pipelines can be defined using the components from above - - name: my_query_pipeline # a simple extractive-qa Pipeline - type: RayPipeline - nodes: - - name: MyRetriever - inputs: [Query] - serve_deployment_kwargs: - num_replicas: 2 # number of replicas to create on the Ray cluster - - name: MyReader - inputs: [MyRetriever] - ``` - - - Note that, in case of a mismatch in version between Haystack and the YAML, a warning will be printed. - If the pipeline loads correctly regardless, save again the pipeline using `RayPipeline.save_to_yaml()` to remove the warning. - - :param path: path of the YAML file. - :param pipeline_name: if the YAML contains multiple pipelines, the pipeline_name to load must be set. - :param overwrite_with_env_variables: Overwrite the YAML configuration with environment variables. For example, - to change index name param for an ElasticsearchDocumentStore, an env - variable 'MYDOCSTORE_PARAMS_INDEX=documents-2021' can be set. Note that an - `_` sign must be used to specify nested hierarchical properties. - :param address: The IP address for the Ray cluster. If set to None, a local Ray instance is started. - :param serve_args: Optional parameters for initializing Ray Serve. - """ - pipeline_config = read_pipeline_config_from_yaml(path) - return cls.load_from_config( - pipeline_config=pipeline_config, - pipeline_name=pipeline_name, - overwrite_with_env_variables=overwrite_with_env_variables, - strict_version_check=strict_version_check, - address=address, - ray_args=ray_args, - serve_args=serve_args, - ) - - @classmethod - def _create_ray_deployment( - cls, component_name: str, pipeline_config: dict, serve_deployment_kwargs: Optional[Dict[str, Any]] = None - ): - """ - Create a Ray Deployment for the Component. - - :param component_name: Class name of the Haystack Component. - :param pipeline_config: The Pipeline config YAML parsed as a dict. - :param serve_deployment_kwargs: An optional dictionary of arguments to be supplied to the - `ray.serve.deployment()` method, like `num_replicas`, `ray_actor_options`, - `max_concurrent_queries`, etc. See potential values in the - Ray Serve API docs (https://docs.ray.io/en/latest/serve/package-ref.html) - under the `ray.serve.deployment()` method - """ - if serve_deployment_kwargs is None: - serve_deployment_kwargs = {} - RayDeployment = serve.deployment( - _RayDeploymentWrapper, name=component_name, **serve_deployment_kwargs # type: ignore - ) - RayDeployment.deploy(pipeline_config, component_name) - handle = RayDeployment.get_handle() - return handle - - def add_node(self, component, name: str, inputs: List[str]): - raise NotImplementedError( - "The current implementation of RayPipeline only supports loading Pipelines from a YAML file." - ) - - def _add_ray_deployment_in_graph(self, handle, name: str, outgoing_edges: int, inputs: List[str]): - """ - Add the Ray deployment handle in the Pipeline Graph. - - :param handle: Ray deployment `handle` to add in the Pipeline Graph. The handle allow calling a Ray deployment - from Python: https://docs.ray.io/en/main/serve/package-ref.html#servehandle-api. - :param name: The name for the node. It must not contain any dots. - :param inputs: A list of inputs to the node. If the predecessor node has a single outgoing edge, just the name - of node is sufficient. For instance, a 'FilterRetriever' node would always output a single - edge with a list of documents. It can be represented as ["FilterRetriever"]. - - In cases when the predecessor node has multiple outputs, e.g., a "QueryClassifier", the output - must be specified explicitly as "QueryClassifier.output_2". - """ - self.graph.add_node(name, component=handle, inputs=inputs, outgoing_edges=outgoing_edges) - - if len(self.graph.nodes) == 2: # first node added; connect with Root - self.graph.add_edge(self.root_node, name, label="output_1") - return - - for i in inputs: - if "." in i: - [input_node_name, input_edge_name] = i.split(".") - assert "output_" in input_edge_name, f"'{input_edge_name}' is not a valid edge name." - outgoing_edges_input_node = self.graph.nodes[input_node_name]["outgoing_edges"] - assert int(input_edge_name.split("_")[1]) <= outgoing_edges_input_node, ( - f"Cannot connect '{input_edge_name}' from '{input_node_name}' as it only has " - f"{outgoing_edges_input_node} outgoing edge(s)." - ) - else: - outgoing_edges_input_node = self.graph.nodes[i]["outgoing_edges"] - assert outgoing_edges_input_node == 1, ( - f"Adding an edge from {i} to {name} is ambiguous as {i} has {outgoing_edges_input_node} edges. " - f"Please specify the output explicitly." - ) - input_node_name = i - input_edge_name = "output_1" - self.graph.add_edge(input_node_name, name, label=input_edge_name) - - def _run_node(self, node_id: str, node_input: Dict[str, Any]) -> Tuple[Dict, str]: - return ray.get(self.graph.nodes[node_id]["component"].remote(**node_input)) - - async def _run_node_async(self, node_id: str, node_input: Dict[str, Any]) -> Tuple[Dict, str]: - # Async calling of Ray Deployments instead of using `ray.get()` as it is done - # in the sync version, in `_run_node()` above. - # See https://docs.ray.io/en/latest/ray-core/actors/async_api.html#objectrefs-as-asyncio-futures - return await self.graph.nodes[node_id]["component"].remote(**node_input) - - def _get_run_node_signature(self, node_id: str): - return inspect.signature(self.graph.nodes[node_id]["component"].remote).parameters.keys() - - # async version of the `Pipeline.run()` method - async def run_async( # type: ignore - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[Union[dict, List[dict]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - """ - Runs the Pipeline, one node at a time. - - :param query: The search query (for query pipelines only). - :param file_paths: The files to index (for indexing pipelines only). - :param labels: Ground-truth labels that you can use to perform an isolated evaluation of pipelines. These labels are input to nodes in the pipeline. - :param documents: A list of Document objects to be processed by the Pipeline Nodes. - :param meta: Files' metadata. Used in indexing pipelines in combination with `file_paths`. - :param params: A dictionary of parameters that you want to pass to the nodes. - To pass a parameter to all Nodes, use: `{"top_k": 10}`. - To pass a parameter to targeted Nodes, run: - `{"Retriever": {"top_k": 10}, "Reader": {"top_k": 3, "debug": True}}` - :param debug: Specifies whether the Pipeline should instruct Nodes to collect debug information - about their execution. By default, this information includes the input parameters - the Nodes received and the output they generated. You can then find all debug information in the dictionary returned by this method under the key `_debug`. - """ - send_pipeline_event( - pipeline=self, - query=query, - file_paths=file_paths, - labels=labels, - documents=documents, - meta=meta, - params=params, - debug=debug, - ) - - # validate the node names - self._validate_node_names_in_params(params=params) - - root_node = self.root_node - if not root_node: - raise PipelineError("Cannot run a pipeline with no nodes.") - - node_output = None - queue: Dict[str, Any] = { - root_node: {"root_node": root_node, "params": params} - } # ordered dict with "node_id" -> "input" mapping that acts as a FIFO queue - if query is not None: - queue[root_node]["query"] = query - if file_paths: - queue[root_node]["file_paths"] = file_paths - if labels: - queue[root_node]["labels"] = labels - if documents: - queue[root_node]["documents"] = documents - if meta: - queue[root_node]["meta"] = meta - - i = 0 # the first item is popped off the queue unless it is a "join" node with unprocessed predecessors - while queue: - node_id = list(queue.keys())[i] - node_input = queue[node_id] - node_input["node_id"] = node_id - - # Apply debug attributes to the node input params - # NOTE: global debug attributes will override the value specified - # in each node's params dictionary. - if debug is None and node_input and node_input.get("params", {}): - debug = params.get("debug", None) # type: ignore - if debug is not None: - if not node_input.get("params", None): - node_input["params"] = {} - if node_id not in node_input["params"].keys(): - node_input["params"][node_id] = {} - node_input["params"][node_id]["debug"] = debug - - predecessors = set(nx.ancestors(self.graph, node_id)) - if predecessors.isdisjoint(set(queue.keys())): # only execute if predecessor nodes are executed - try: - logger.debug("Running node '%s` with input: %s", node_id, node_input) - start = time() - node_output, stream_id = await self._run_node_async(node_id, node_input) - if "_debug" in node_output and node_id in node_output["_debug"]: - node_output["_debug"][node_id]["exec_time_ms"] = round((time() - start) * 1000, 2) - except Exception as e: - # The input might be a really large object with thousands of embeddings. - # If you really want to see it, raise the log level. - logger.debug("Exception while running node '%s' with input %s", node_id, node_input) - raise Exception( - f"Exception while running node '{node_id}': {e}\nEnable debug logging to see the data that was passed when the pipeline failed." - ) from e - queue.pop(node_id) - # - if stream_id == "split": - for stream_id in [key for key in node_output.keys() if key.startswith("output_")]: - current_node_output = {k: v for k, v in node_output.items() if not k.startswith("output_")} - current_docs = node_output.pop(stream_id) - current_node_output["documents"] = current_docs - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: - queue[n] = current_node_output - else: - next_nodes = self.get_next_nodes(node_id, stream_id) - for n in next_nodes: # add successor nodes with corresponding inputs to the queue - if queue.get(n): # concatenate inputs if it's a join node - existing_input = queue[n] - if "inputs" not in existing_input.keys(): - updated_input: dict = {"inputs": [existing_input, node_output], "params": params} - if "_debug" in existing_input.keys() or "_debug" in node_output.keys(): - updated_input["_debug"] = { - **existing_input.get("_debug", {}), - **node_output.get("_debug", {}), - } - if query: - updated_input["query"] = query - if file_paths: - updated_input["file_paths"] = file_paths - if labels: - updated_input["labels"] = labels - if documents: - updated_input["documents"] = documents - if meta: - updated_input["meta"] = meta - else: - existing_input["inputs"].append(node_output) - updated_input = existing_input - queue[n] = updated_input - else: - queue[n] = node_output - i = 0 - else: - i += 1 # attempt executing next node in the queue as current `node_id` has unprocessed predecessors - - # Disabled due to issue https://github.com/deepset-ai/haystack/issues/3970 - # self.send_pipeline_event_if_needed(is_indexing=file_paths is not None) - return node_output - - def send_pipeline_event(self, is_indexing: bool = False): - """To avoid the RayPipeline serialization bug described at - https://github.com/deepset-ai/haystack/issues/3970""" - pass - - -class _RayDeploymentWrapper: - """ - Ray Serve supports calling of __init__ methods on the Classes to create "deployment" instances. - - In case of Haystack, some Components like Retrievers have complex init methods that needs objects - like Document Stores. - - This wrapper class encapsulates the initialization of Components. Given a Component Class - name, it creates an instance using the YAML Pipeline config. - """ - - node: BaseComponent - - def __init__(self, pipeline_config: dict, component_name: str): - """ - Create an instance of Component. - - :param pipeline_config: Pipeline YAML parsed as a dict. - :param component_name: Component Class name. - """ - if component_name in ["Query", "File"]: - self.node = RootNode() - else: - self.node = self.load_from_pipeline_config(pipeline_config, component_name) - - def __call__(self, *args, **kwargs): - """ - Ray calls this method which is then re-directed to the corresponding component's run(). - """ - return self.node._dispatch_run(*args, **kwargs) - - @staticmethod - def load_from_pipeline_config(pipeline_config: dict, component_name: str): - """ - Load an individual component from a YAML config for Pipelines. - - :param pipeline_config: the Pipelines YAML config parsed as a dict. - :param component_name: the name of the component to load. - """ - all_component_configs = pipeline_config["components"] - all_component_names = [comp["name"] for comp in all_component_configs] - component_config = next(comp for comp in all_component_configs if comp["name"] == component_name) - component_params = component_config["params"] - - for key, value in component_params.items(): - if value in all_component_names: # check if the param value is a reference to another component - component_params[key] = _RayDeploymentWrapper.load_from_pipeline_config(pipeline_config, value) - - component_instance = BaseComponent._create_instance( - component_type=component_config["type"], component_params=component_params, name=component_name - ) - return component_instance diff --git a/haystack/pipelines/standard_pipelines.py b/haystack/pipelines/standard_pipelines.py deleted file mode 100644 index e1f8f61c72..0000000000 --- a/haystack/pipelines/standard_pipelines.py +++ /dev/null @@ -1,780 +0,0 @@ -import logging -from abc import ABC -from copy import deepcopy -from functools import wraps -from pathlib import Path -from typing import Any, Dict, List, Optional, Union, Literal - -from haystack.document_stores.base import BaseDocumentStore, FilterType -from haystack.nodes.answer_generator.base import BaseGenerator -from haystack.nodes.other.docs2answers import Docs2Answers -from haystack.nodes.other.document_merger import DocumentMerger -from haystack.nodes.question_generator.question_generator import QuestionGenerator -from haystack.nodes.reader.base import BaseReader -from haystack.nodes.retriever.base import BaseRetriever -from haystack.nodes.retriever.web import WebRetriever -from haystack.nodes.summarizer.base import BaseSummarizer -from haystack.nodes.translator.base import BaseTranslator -from haystack.nodes import PreProcessor, TextConverter, PromptNode, Shaper, TopPSampler -from haystack.pipelines.base import Pipeline -from haystack.schema import Document, EvaluationResult, MultiLabel, Answer - -logger = logging.getLogger(__name__) - - -class BaseStandardPipeline(ABC): - """ - Base class for pre-made standard Haystack pipelines. - This class does not inherit from Pipeline. - """ - - pipeline: Pipeline - metrics_filter: Optional[Dict[str, List[str]]] = None - - def add_node(self, component, name: str, inputs: List[str]): - """ - Add a new node to the pipeline. - - :param component: The object to be called when the data is passed to the node. It can be a Haystack component - (like Retriever, Reader, or Generator) or a user-defined object that implements a run() - method to process incoming data from predecessor node. - :param name: The name for the node. It must not contain any dots. - :param inputs: A list of inputs to the node. If the predecessor node has a single outgoing edge, just the name - of node is sufficient. For instance, a 'BM25Retriever' node would always output a single - edge with a list of documents. It can be represented as ["BM25Retriever"]. - - In cases when the predecessor node has multiple outputs, e.g., a "QueryClassifier", the output - must be specified explicitly as "QueryClassifier.output_2". - """ - self.pipeline.add_node(component=component, name=name, inputs=inputs) - - def get_node(self, name: str): - """ - Get a node from the Pipeline. - - :param name: The name of the node. - """ - component = self.pipeline.get_node(name) - return component - - def set_node(self, name: str, component): - """ - Set the component for a node in the Pipeline. - - :param name: The name of the node. - :param component: The component object to be set at the node. - """ - self.pipeline.set_node(name, component) - - def draw(self, path: Path = Path("pipeline.png")): - """ - Create a Graphviz visualization of the pipeline. - - :param path: the path to save the image. - """ - self.pipeline.draw(path) - - def get_nodes_by_class(self, class_type) -> List[Any]: - """ - Gets all nodes in the pipeline that are an instance of a certain class (incl. subclasses). - This is for example helpful if you loaded a pipeline and then want to interact directly with the document store. - Example: - ```python - from haystack.document_stores.base import BaseDocumentStore - INDEXING_PIPELINE = Pipeline.load_from_yaml(Path(PIPELINE_YAML_PATH), pipeline_name=INDEXING_PIPELINE_NAME) - res = INDEXING_PIPELINE.get_nodes_by_class(class_type=BaseDocumentStore) - ``` - :return: List of components that are an instance of the requested class - """ - return self.pipeline.get_nodes_by_class(class_type) - - def get_document_store(self) -> Optional[BaseDocumentStore]: - """ - Return the document store object used in the current pipeline. - - :return: Instance of DocumentStore or None - """ - return self.pipeline.get_document_store() - - def get_type(self) -> str: - """ - Return the type of the pipeline. - - :return: Type of the pipeline - """ - return self.pipeline.get_type() - - def eval( - self, - labels: List[MultiLabel], - params: Optional[dict] = None, - sas_model_name_or_path: Optional[str] = None, - sas_batch_size: int = 32, - sas_use_gpu: bool = True, - add_isolated_node_eval: bool = False, - custom_document_id_field: Optional[str] = None, - context_matching_min_length: int = 100, - context_matching_boost_split_overlaps: bool = True, - context_matching_threshold: float = 65.0, - ) -> EvaluationResult: - """ - Evaluates the pipeline by running the pipeline once per query in debug mode - and putting together all data that is needed for evaluation, e.g. calculating metrics. - - If you want to calculate SAS (Semantic Answer Similarity) metrics, you have to specify `sas_model_name_or_path`. - - You will be able to control the scope within which an answer or a document is considered correct afterwards (See `document_scope` and `answer_scope` params in `EvaluationResult.calculate_metrics()`). - Some of these scopes require additional information that already needs to be specified during `eval()`: - - `custom_document_id_field` param to select a custom document ID from document's meta data for ID matching (only affects 'document_id' scopes) - - `context_matching_...` param to fine-tune the fuzzy matching mechanism that determines whether some text contexts match each other (only affects 'context' scopes, default values should work most of the time) - - :param labels: The labels to evaluate on - :param params: Params for the `retriever` and `reader`. For instance, - params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 5}} - :param sas_model_name_or_path: SentenceTransformers semantic textual similarity model to be used for sas value calculation, - should be path or string pointing to downloadable models. - :param sas_batch_size: Number of prediction label pairs to encode at once by CrossEncoder or SentenceTransformer while calculating SAS. - :param sas_use_gpu: Whether to use a GPU or the CPU for calculating semantic answer similarity. - Falls back to CPU if no GPU is available. - :param add_isolated_node_eval: Whether to additionally evaluate the reader based on labels as input instead of output of previous node in pipeline - :param custom_document_id_field: Custom field name within `Document`'s `meta` which identifies the document and is being used as criterion for matching documents to labels during evaluation. - This is especially useful if you want to match documents on other criteria (e.g. file names) than the default document ids as these could be heavily influenced by preprocessing. - If not set (default) the `Document`'s `id` is being used as criterion for matching documents to labels. - :param context_matching_min_length: The minimum string length context and candidate need to have in order to be scored. - Returns 0.0 otherwise. - :param context_matching_boost_split_overlaps: Whether to boost split overlaps (e.g. [AB] <-> [BC]) that result from different preprocessing params. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries - we cut the context on the same side, recalculate the score and take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - :param context_matching_threshold: Score threshold that candidates must surpass to be included into the result list. Range: [0,100] - """ - output = self.pipeline.eval( - labels=labels, - params=params, - sas_model_name_or_path=sas_model_name_or_path, - sas_batch_size=sas_batch_size, - sas_use_gpu=sas_use_gpu, - add_isolated_node_eval=add_isolated_node_eval, - custom_document_id_field=custom_document_id_field, - context_matching_boost_split_overlaps=context_matching_boost_split_overlaps, - context_matching_min_length=context_matching_min_length, - context_matching_threshold=context_matching_threshold, - ) - return output - - def eval_batch( - self, - labels: List[MultiLabel], - params: Optional[dict] = None, - sas_model_name_or_path: Optional[str] = None, - sas_batch_size: int = 32, - sas_use_gpu: bool = True, - add_isolated_node_eval: bool = False, - custom_document_id_field: Optional[str] = None, - context_matching_min_length: int = 100, - context_matching_boost_split_overlaps: bool = True, - context_matching_threshold: float = 65.0, - ) -> EvaluationResult: - """ - Evaluates the pipeline by running the pipeline once per query in the debug mode - and putting together all data that is needed for evaluation, for example, calculating metrics. - - To calculate SAS (Semantic Answer Similarity) metrics, specify `sas_model_name_or_path`. - - You can control the scope within which an Answer or a Document is considered correct afterwards (see `document_scope` and `answer_scope` params in `EvaluationResult.calculate_metrics()`). - For some of these scopes, you need to add the following information during `eval()`: - - `custom_document_id_field` parameter to select a custom document ID from document's metadata for ID matching (only affects 'document_id' scopes). - - `context_matching_...` parameter to fine-tune the fuzzy matching mechanism that determines whether text contexts match each other (only affects 'context' scopes, default values should work most of the time). - - :param labels: The labels to evaluate on. - :param params: Parameters for the `retriever` and `reader`. For instance, - params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 5}}. - :param sas_model_name_or_path: Sentence transformers semantic textual similarity model you want to use for the SAS value calculation. - It should be a path or a string pointing to downloadable models. - :param sas_batch_size: Number of prediction label pairs to encode at once by cross encoder or sentence transformer while calculating SAS. - :param sas_use_gpu: Whether to use a GPU or the CPU for calculating semantic answer similarity. - Falls back to CPU if no GPU is available. - :param add_isolated_node_eval: Whether to additionally evaluate the reader based on labels as input, instead of the output of the previous node in the pipeline. - :param custom_document_id_field: Custom field name within `Document`'s `meta` which identifies the document and is used as a criterion for matching documents to labels during evaluation. - This is especially useful if you want to match documents on other criteria (for example, file names) than the default document IDs, as these could be heavily influenced by preprocessing. - If not set, the default `Document`'s `id` is used as the criterion for matching documents to labels. - :param context_matching_min_length: The minimum string length context and candidate need to have to be scored. - Returns 0.0 otherwise. - :param context_matching_boost_split_overlaps: Whether to boost split overlaps (for example, [AB] <-> [BC]) that result from different preprocessing parameters. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries, - we cut the context on the same side, recalculate the score, and take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - :param context_matching_threshold: Score threshold that candidates must surpass to be included into the result list. Range: [0,100] - """ - output = self.pipeline.eval_batch( - labels=labels, - params=params, - sas_model_name_or_path=sas_model_name_or_path, - sas_batch_size=sas_batch_size, - sas_use_gpu=sas_use_gpu, - add_isolated_node_eval=add_isolated_node_eval, - custom_document_id_field=custom_document_id_field, - context_matching_boost_split_overlaps=context_matching_boost_split_overlaps, - context_matching_min_length=context_matching_min_length, - context_matching_threshold=context_matching_threshold, - ) - return output - - def print_eval_report( - self, - eval_result: EvaluationResult, - n_wrong_examples: int = 3, - metrics_filter: Optional[Dict[str, List[str]]] = None, - document_scope: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "document_id_or_answer", - ] = "document_id_or_answer", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - wrong_examples_fields: Optional[List[str]] = None, - max_characters_per_field: int = 150, - ): - """ - Prints evaluation report containing a metrics funnel and worst queries for further analysis. - - :param eval_result: The evaluation result, can be obtained by running eval(). - :param n_wrong_examples: The number of worst queries to show. - :param metrics_filter: The metrics to show per node. If None all metrics will be shown. - :param document_scope: A criterion for deciding whether documents are relevant or not. - You can select between: - - 'document_id': Specifies that the document ID must match. You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - A typical use case is Document Retrieval. - - 'context': Specifies that the content of the document must match. Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - A typical use case is Document-Independent Passage Retrieval. - - 'document_id_and_context': A Boolean operation specifying that both `'document_id' AND 'context'` must match. - A typical use case is Document-Specific Passage Retrieval. - - 'document_id_or_context': A Boolean operation specifying that either `'document_id' OR 'context'` must match. - A typical use case is Document Retrieval having sparse context labels. - - 'answer': Specifies that the document contents must include the answer. The selected `answer_scope` is enforced automatically. - A typical use case is Question Answering. - - 'document_id_or_answer' (default): A Boolean operation specifying that either `'document_id' OR 'answer'` must match. - This is intended to be a proper default value in order to support both main use cases: - - Document Retrieval - - Question Answering - The default value is 'document_id_or_answer'. - :param answer_scope: Specifies the scope in which a matching answer is considered correct. - You can select between: - - 'any' (default): Any matching answer is considered correct. - - 'context': The answer is only considered correct if its context matches as well. - Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - - 'document_id': The answer is only considered correct if its document ID matches as well. - You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - - 'document_id_and_context': The answer is only considered correct if its document ID and its context match as well. - The default value is 'any'. - In Question Answering, to enforce that the retrieved document is considered correct whenever the answer is correct, set `document_scope` to 'answer' or 'document_id_or_answer'. - :param wrong_examples_fields: A list of field names to include in the worst samples. By default, "answer", "context", and "document_id" are used. - :param max_characters_per_field: The maximum number of characters per wrong example to show (per field). - """ - if wrong_examples_fields is None: - wrong_examples_fields = ["answer", "context", "document_id"] - if metrics_filter is None: - metrics_filter = self.metrics_filter - self.pipeline.print_eval_report( - eval_result=eval_result, - n_wrong_examples=n_wrong_examples, - metrics_filter=metrics_filter, - document_scope=document_scope, - answer_scope=answer_scope, - wrong_examples_fields=wrong_examples_fields, - max_characters_per_field=max_characters_per_field, - ) - - def run_batch(self, queries: List[str], params: Optional[dict] = None, debug: Optional[bool] = None): - """ - Run a batch of queries through the pipeline. - - :param queries: List of query strings. - :param params: Parameters for the individual nodes of the pipeline. For instance, - `params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 5}}` - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default these include the input parameters - they received and the output they generated. - All debug information can then be found in the dict returned - by this method under the key "_debug" - """ - output = self.pipeline.run_batch(queries=queries, params=params, debug=debug) - return output - - -class ExtractiveQAPipeline(BaseStandardPipeline): - """ - Pipeline for Extractive Question Answering. - """ - - def __init__(self, reader: BaseReader, retriever: BaseRetriever): - """ - :param reader: Reader instance - :param retriever: Retriever instance - """ - self.pipeline = Pipeline() - self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - self.pipeline.add_node(component=reader, name="Reader", inputs=["Retriever"]) - self.metrics_filter = {"Retriever": ["recall_single_hit"]} - - def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None): - """ - :param query: The search query string. - :param params: Params for the `retriever` and `reader`. For instance, - params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 5}} - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default these include the input parameters - they received and the output they generated. - All debug information can then be found in the dict returned - by this method under the key "_debug" - """ - output = self.pipeline.run(query=query, params=params, debug=debug) - return output - - -class WebQAPipeline(BaseStandardPipeline): - """ - Pipeline for Generative Question Answering performed based on Documents returned from a web search engine. - """ - - def __init__( - self, - retriever: WebRetriever, - prompt_node: PromptNode, - sampler: Optional[TopPSampler] = None, - shaper: Optional[Shaper] = None, - ): - """ - :param retriever: The WebRetriever used for retrieving documents from a web search engine. - :param prompt_node: The PromptNode used for generating the answer based on retrieved documents. - :param shaper: The Shaper used for transforming the documents and scores into a format that can be used by the PromptNode. Optional. - """ - if not shaper: - shaper = Shaper(func="join_documents_and_scores", inputs={"documents": "documents"}, outputs=["documents"]) - if not sampler and retriever.mode != "snippets": - # Documents returned by WebRetriever in mode "snippets" already have scores. - # For other modes, we need to add a sampler if none is provided to compute the scores. - sampler = TopPSampler(top_p=0.95) - - self.pipeline = Pipeline() - self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - if sampler: - self.pipeline.add_node(component=sampler, name="Sampler", inputs=["Retriever"]) - self.pipeline.add_node(component=shaper, name="Shaper", inputs=["Sampler"]) - else: - self.pipeline.add_node(component=shaper, name="Shaper", inputs=["Retriever"]) - self.pipeline.add_node(component=prompt_node, name="PromptNode", inputs=["Shaper"]) - self.metrics_filter = {"Retriever": ["recall_single_hit"]} - - def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None): - """ - :param query: The search query string. - :param params: Params for the `Retriever`, `Sampler`, `Shaper`, and ``PromptNode. For instance, - params={"Retriever": {"top_k": 3}, "Sampler": {"top_p": 0.8}}. See the API documentation of each node for available parameters and their descriptions. - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default, these include the input parameters - they received and the output they generated. - YOu can then find all debug information in the dict thia method returns - under the key "_debug". - """ - output = self.pipeline.run(query=query, params=params, debug=debug) - # Extract the answer from the last line of the PromptNode's output - output["answers"] = [Answer(answer=output["results"][0].split("\n")[-1], type="generative")] - return output - - -class DocumentSearchPipeline(BaseStandardPipeline): - """ - Pipeline for semantic document search. - """ - - def __init__(self, retriever: BaseRetriever): - """ - :param retriever: Retriever instance - """ - self.pipeline = Pipeline() - self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - - def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None): - """ - :param query: the query string. - :param params: params for the `retriever` and `reader`. For instance, params={"Retriever": {"top_k": 10}} - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default these include the input parameters - they received and the output they generated. - All debug information can then be found in the dict returned - by this method under the key "_debug" - """ - output = self.pipeline.run(query=query, params=params, debug=debug) - return output - - -class GenerativeQAPipeline(BaseStandardPipeline): - """ - Pipeline for Generative Question Answering. - """ - - def __init__(self, generator: BaseGenerator, retriever: BaseRetriever): - """ - :param generator: Generator instance - :param retriever: Retriever instance - """ - self.pipeline = Pipeline() - self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - self.pipeline.add_node(component=generator, name="Generator", inputs=["Retriever"]) - - def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None): - """ - :param query: the query string. - :param params: params for the `retriever` and `generator`. For instance, - params={"Retriever": {"top_k": 10}, "Generator": {"top_k": 5}} - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default these include the input parameters - they received and the output they generated. - All debug information can then be found in the dict returned - by this method under the key "_debug" - """ - output = self.pipeline.run(query=query, params=params, debug=debug) - return output - - -class SearchSummarizationPipeline(BaseStandardPipeline): - """ - Pipeline that retrieves documents for a query and then summarizes those documents. - """ - - def __init__( - self, - summarizer: BaseSummarizer, - retriever: BaseRetriever, - generate_single_summary: bool = False, - return_in_answer_format: bool = False, - ): - """ - :param summarizer: Summarizer instance - :param retriever: Retriever instance - :param generate_single_summary: Whether to generate a single summary for all documents or one summary per document. - :param return_in_answer_format: Whether the results should be returned as documents (False) or in the answer - format used in other QA pipelines (True). With the latter, you can use this - pipeline as a "drop-in replacement" for other QA pipelines. - """ - self.pipeline = Pipeline() - self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - if generate_single_summary is True: - document_merger = DocumentMerger() - self.pipeline.add_node(component=document_merger, name="Document Merger", inputs=["Retriever"]) - self.pipeline.add_node(component=summarizer, name="Summarizer", inputs=["Document Merger"]) - else: - self.pipeline.add_node(component=summarizer, name="Summarizer", inputs=["Retriever"]) - self.return_in_answer_format = return_in_answer_format - - def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None): - """ - :param query: the query string. - :param params: params for the `retriever` and `summarizer`. For instance, - params={"Retriever": {"top_k": 10}, "Summarizer": {"generate_single_summary": True}} - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default these include the input parameters - they received and the output they generated. - All debug information can then be found in the dict returned - by this method under the key "_debug" - """ - output = self.pipeline.run(query=query, params=params, debug=debug) - - # Convert to answer format to allow "drop-in replacement" for other QA pipelines - if self.return_in_answer_format: - results: Dict = {"query": query, "answers": []} - docs = deepcopy(output["documents"]) - for doc in docs: - cur_answer = { - "query": query, - "answer": doc.meta.pop("summary"), - "document_id": doc.id, - "context": doc.content, - "score": None, - "offset_start": None, - "offset_end": None, - "meta": doc.meta, - } - - results["answers"].append(cur_answer) - else: - results = output - return results - - def run_batch(self, queries: List[str], params: Optional[dict] = None, debug: Optional[bool] = None): - """ - Run a batch of queries through the pipeline. - - :param queries: List of query strings. - :param params: Parameters for the individual nodes of the pipeline. For instance, - `params={"Retriever": {"top_k": 10}, "Summarizer": {"generate_single_summary": True}}` - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default these include the input parameters - they received and the output they generated. - All debug information can then be found in the dict returned - by this method under the key "_debug" - """ - output = self.pipeline.run_batch(queries=queries, params=params, debug=debug) - - # Convert to answer format to allow "drop-in replacement" for other QA pipelines - if self.return_in_answer_format: - results: Dict = {"queries": queries, "answers": []} - docs = deepcopy(output["documents"]) - for query, cur_docs in zip(queries, docs): - cur_answers = [] - for doc in cur_docs: - cur_answer = { - "query": query, - "answer": doc.meta.pop("summary"), - "document_id": doc.id, - "context": doc.content, - "score": None, - "offset_start": None, - "offset_end": None, - "meta": doc.meta, - } - cur_answers.append(cur_answer) - - results["answers"].append(cur_answers) - else: - results = output - return results - - -class FAQPipeline(BaseStandardPipeline): - """ - Pipeline for finding similar FAQs using semantic document search. - """ - - def __init__(self, retriever: BaseRetriever): - """ - :param retriever: Retriever instance - """ - self.pipeline = Pipeline() - self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - self.pipeline.add_node(component=Docs2Answers(), name="Docs2Answers", inputs=["Retriever"]) - - def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None): - """ - :param query: the query string. - :param params: params for the `retriever`. For instance, params={"Retriever": {"top_k": 10}} - :param debug: Whether the pipeline should instruct nodes to collect debug information - about their execution. By default these include the input parameters - they received and the output they generated. - All debug information can then be found in the dict returned - by this method under the key "_debug" - """ - output = self.pipeline.run(query=query, params=params, debug=debug) - return output - - -class TranslationWrapperPipeline(BaseStandardPipeline): - """ - Takes an existing search pipeline and adds one "input translation node" after the Query and one - "output translation" node just before returning the results - """ - - def __init__( - self, input_translator: BaseTranslator, output_translator: BaseTranslator, pipeline: BaseStandardPipeline - ): - """ - Wrap a given `pipeline` with the `input_translator` and `output_translator`. - - :param input_translator: A Translator node that shall translate the input query from language A to B - :param output_translator: A Translator node that shall translate the pipeline results from language B to A - :param pipeline: The pipeline object (e.g. ExtractiveQAPipeline) you want to "wrap". - Note that pipelines with split or merge nodes are currently not supported. - """ - - self.pipeline = Pipeline() - self.pipeline.add_node(component=input_translator, name="InputTranslator", inputs=["Query"]) - # Make use of run_batch instead of run for output_translator if pipeline is a QuestionAnswerGenerationPipeline, - # as the reader's run method is overwritten by its run_batch method, which is incompatible with the translator's - # run method. - if isinstance(pipeline, QuestionAnswerGenerationPipeline): - setattr(output_translator, "run", output_translator.run_batch) - - if hasattr(pipeline, "pipeline"): - graph = pipeline.pipeline.graph - else: - graph = pipeline.graph # type: ignore - previous_node_name = ["InputTranslator"] - # Traverse in BFS - for node in graph.nodes: - if node == "Query": - continue - - # TODO: Do not work properly for Join Node and Answer format - if graph.nodes[node]["inputs"] and len(graph.nodes[node]["inputs"]) > 1: - raise AttributeError("Split and merge nodes are not supported currently") - - self.pipeline.add_node(name=node, component=graph.nodes[node]["component"], inputs=previous_node_name) - previous_node_name = [node] - - self.pipeline.add_node(component=output_translator, name="OutputTranslator", inputs=previous_node_name) - - def run(self, **kwargs): - output = self.pipeline.run(**kwargs) - return output - - def run_batch(self, **kwargs): - output = self.pipeline.run_batch(**kwargs) - return output - - -class QuestionGenerationPipeline(BaseStandardPipeline): - """ - A simple pipeline that takes documents as input and generates - questions that it thinks can be answered by the documents. - """ - - def __init__(self, question_generator: QuestionGenerator): - self.pipeline = Pipeline() - self.pipeline.add_node(component=question_generator, name="QuestionGenerator", inputs=["Query"]) - - def run(self, documents, params: Optional[dict] = None, debug: Optional[bool] = None): - output = self.pipeline.run(documents=documents, params=params, debug=debug) - return output - - def run_batch( # type: ignore - self, - documents: Union[List[Document], List[List[Document]]], - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - output = self.pipeline.run_batch(documents=documents, params=params, debug=debug) - return output - - -class RetrieverQuestionGenerationPipeline(BaseStandardPipeline): - """ - A simple pipeline that takes a query as input, performs retrieval, and then generates - questions that it thinks can be answered by the retrieved documents. - """ - - def __init__(self, retriever: BaseRetriever, question_generator: QuestionGenerator): - self.pipeline = Pipeline() - self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"]) - self.pipeline.add_node(component=question_generator, name="QuestionGenerator", inputs=["Retriever"]) - - def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None): - output = self.pipeline.run(query=query, params=params, debug=debug) - return output - - -class QuestionAnswerGenerationPipeline(BaseStandardPipeline): - """ - This is a pipeline which takes a document as input, generates questions that the model thinks can be answered by - this document, and then performs question answering of this questions using that single document. - """ - - def __init__(self, question_generator: QuestionGenerator, reader: BaseReader): - setattr(question_generator, "run", self.formatting_wrapper(question_generator.run)) - # Overwrite reader.run function so it can handle a batch of questions being passed on by the QuestionGenerator - setattr(reader, "run", reader.run_batch) - self.pipeline = Pipeline() - self.pipeline.add_node(component=question_generator, name="QuestionGenerator", inputs=["Query"]) - self.pipeline.add_node(component=reader, name="Reader", inputs=["QuestionGenerator"]) - - # This is used to format the output of the QuestionGenerator so that its questions are ready to be answered by the reader - def formatting_wrapper(self, fn): - @wraps(fn) - def wrapper(*args, **kwargs): - output, output_stream = fn(*args, **kwargs) - questions = [] - documents = [] - for generated_questions, doc in zip(output["generated_questions"], output["documents"]): - questions.extend(generated_questions["questions"]) - documents.extend([[doc]] * len(generated_questions["questions"])) - kwargs["queries"] = questions - kwargs["documents"] = documents - return kwargs, output_stream - - return wrapper - - def run( - self, documents: List[Document], params: Optional[dict] = None, debug: Optional[bool] = None # type: ignore - ): - output = self.pipeline.run(documents=documents, params=params, debug=debug) - return output - - -class MostSimilarDocumentsPipeline(BaseStandardPipeline): - def __init__(self, document_store: BaseDocumentStore): - """ - Initialize a Pipeline for finding the most similar documents to a given document. - This pipeline can be helpful if you already show a relevant document to your end users and they want to search for just similar ones. - - :param document_store: Document Store instance with already stored embeddings. - """ - # we create a pipeline and add the document store as a node - # however, we do not want to use the document store's run method, - # but rather the query_by_embedding method - # pipeline property is here so the superclass methods that rely on pipeline property work - self.pipeline = Pipeline() - self.pipeline.add_node(component=document_store, name="DocumentStore", inputs=["Query"]) - self.document_store = document_store - - def run( - self, document_ids: List[str], filters: Optional[FilterType] = None, top_k: int = 5, index: Optional[str] = None - ): - """ - :param document_ids: document ids - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain conditions - :param top_k: How many documents id to return against single document - :param index: Optionally specify the name of index to query the document from. If None, the DocumentStore's default index (self.index) will be used. - """ - self.document_store.return_embedding = True # type: ignore - - documents = self.document_store.get_documents_by_id(ids=document_ids, index=index) - query_embs = [doc.embedding for doc in documents] - similar_documents = self.document_store.query_by_embedding_batch( - query_embs=query_embs, filters=filters, return_embedding=False, top_k=top_k, index=index # type: ignore [arg-type] - ) - - self.document_store.return_embedding = False # type: ignore - return similar_documents - - def run_batch( # type: ignore - self, document_ids: List[str], filters: Optional[FilterType] = None, top_k: int = 5, index: Optional[str] = None - ): - """ - :param document_ids: document ids - :param filters: Optional filters to narrow down the search space to documents whose metadata fulfill certain conditions - :param top_k: How many documents id to return against single document - :param index: Optionally specify the name of index to query the document from. If None, the DocumentStore's default index (self.index) will be used. - """ - return self.run(document_ids=document_ids, filters=filters, top_k=top_k, index=index) - - -class TextIndexingPipeline(BaseStandardPipeline): - def __init__( - self, - document_store: BaseDocumentStore, - text_converter: Optional[TextConverter] = None, - preprocessor: Optional[PreProcessor] = None, - ): - """ - Initialize a basic Pipeline that converts text files into Documents and indexes them into a DocumentStore. - - :param document_store: The DocumentStore to index the Documents into. - :param text_converter: A TextConverter object to be used in this pipeline for converting the text files into Documents. - :param preprocessor: A PreProcessor object to be used in this pipeline for preprocessing Documents. - """ - - self.pipeline = Pipeline() - self.document_store = document_store - self.text_converter = text_converter or TextConverter() - self.preprocessor = preprocessor or PreProcessor() - self.pipeline.add_node(component=self.text_converter, name="TextConverter", inputs=["File"]) - self.pipeline.add_node(component=self.preprocessor, name="PreProcessor", inputs=["TextConverter"]) - self.pipeline.add_node(component=self.document_store, name="DocumentStore", inputs=["PreProcessor"]) - - def run(self, file_path): - return self.pipeline.run(file_paths=[file_path]) - - def run_batch(self, file_paths): - return self.pipeline.run_batch(file_paths=file_paths) diff --git a/haystack/pipelines/utils.py b/haystack/pipelines/utils.py deleted file mode 100644 index 3234e81eb7..0000000000 --- a/haystack/pipelines/utils.py +++ /dev/null @@ -1,360 +0,0 @@ -from typing import Any, Dict, List, Optional, Literal - -import re -import sys -import inspect -import logging - -import networkx as nx -from networkx import DiGraph - -from haystack.pipelines.config import ( - build_component_dependency_graph, - get_component_definitions, - get_pipeline_definition, - validate_schema, -) -from haystack.schema import EvaluationResult - - -logger = logging.getLogger(__name__) - - -MODULE_NOT_FOUND = "MODULE_NOT_FOUND" -CODE_GEN_ALLOWED_IMPORTS = ["haystack.document_stores", "haystack.nodes", "haystack.pipelines"] -CAMEL_CASE_TO_SNAKE_CASE_REGEX = re.compile(r"(?<=[a-z])(?=[A-Z0-9])") - - -def camel_to_snake_case(input: str) -> str: - return CAMEL_CASE_TO_SNAKE_CASE_REGEX.sub("_", input).lower() - - -def generate_code( - pipeline_config: Dict[str, Any], - pipeline_variable_name: str = "pipeline", - pipeline_name: Optional[str] = None, - generate_imports: bool = True, - comment: Optional[str] = None, - add_pipeline_cls_import: bool = True, -) -> str: - """ - Generates code to create a pipeline. - - :param pipeline_config: The pipeline config that specifies components and pipelines. - :param pipeline_variable_name: The variable name of the pipeline to be generated. - Defaults to "pipeline". - :param pipeline_name: The name of the pipeline defined in pipeline_config to be generated. - If unspecified the first pipeline will be taken. - :param generate_imports: Whether to generate imports code. - Defaults to True. - :param comment: Preceding Comment to add to the code. - :param add_pipeline_cls_import: Whether to add import statement for Pipeline class if generate_imports is True. - Defaults to True. - """ - validate_schema(pipeline_config) - - component_definitions = get_component_definitions( - pipeline_config=pipeline_config, overwrite_with_env_variables=False - ) - component_variable_names = {name: camel_to_snake_case(name) for name in component_definitions.keys()} - pipeline_definition = get_pipeline_definition(pipeline_config=pipeline_config, pipeline_name=pipeline_name) - component_dependency_graph = build_component_dependency_graph( - pipeline_definition=pipeline_definition, component_definitions=component_definitions - ) - - code_parts = [] - if generate_imports: - types_to_import = [component["type"] for component in component_definitions.values()] - if add_pipeline_cls_import: - types_to_import.append("Pipeline") - imports_code = _generate_imports_code(types_to_import=types_to_import) - code_parts.append(imports_code) - - components_code = _generate_components_code( - component_definitions=component_definitions, - component_variable_names=component_variable_names, - dependency_graph=component_dependency_graph, - pipeline_definition=pipeline_definition, - ) - pipeline_code = _generate_pipeline_code( - pipeline_definition=pipeline_definition, - component_variable_names=component_variable_names, - pipeline_variable_name=pipeline_variable_name, - ) - - code_parts.append(components_code) - code_parts.append(pipeline_code) - code = "\n\n".join(code_parts) - - if comment: - comment = re.sub(r"^(#\s)?", "# ", comment, flags=re.MULTILINE) - code = "\n".join([comment, code]) - - return code - - -def _generate_pipeline_code( - pipeline_definition: Dict[str, Any], component_variable_names: Dict[str, str], pipeline_variable_name: str -) -> str: - code_lines = [f"{pipeline_variable_name} = Pipeline()"] - for node in pipeline_definition["nodes"]: - node_name = node["name"] - component_variable_name = component_variable_names[node_name] - inputs = ", ".join(f'"{name}"' for name in node["inputs"]) - code_lines.append( - f'{pipeline_variable_name}.add_node(component={component_variable_name}, name="{node_name}", inputs=[{inputs}])' - ) - - code = "\n".join(code_lines) - return code - - -def _generate_components_code( - component_definitions: Dict[str, Any], - component_variable_names: Dict[str, str], - dependency_graph: DiGraph, - pipeline_definition: Dict[str, Any], -) -> str: - code = "" - declarations = {} - for name, definition in component_definitions.items(): - variable_name = component_variable_names[name] - class_name = definition["type"] - param_value_dict = { - key: component_variable_names.get(value, f'"{value}"') if type(value) == str else value - for key, value in definition.get("params", {}).items() - } - init_args = ", ".join(f"{key}={value}" for key, value in param_value_dict.items()) - declaration = f"{variable_name} = {class_name}({init_args})" - # set name of subcomponents explicitly if it's not the default name as it won't be set via Pipeline.add_node() - if name != class_name and name not in (node["name"] for node in pipeline_definition["nodes"]): - declaration = f'{declaration}\n{variable_name}.name = "{name}"' - declarations[name] = declaration - - ordered_components = nx.topological_sort(dependency_graph) - ordered_declarations = [declarations[component] for component in ordered_components] - code = "\n".join(ordered_declarations) - return code - - -def _generate_imports_code(types_to_import: List[str]) -> str: - code_lines = [] - importable_classes = { - name: mod - for mod in CODE_GEN_ALLOWED_IMPORTS - for name, obj in inspect.getmembers(sys.modules[mod]) - if inspect.isclass(obj) - } - - imports_by_module: Dict[str, List[str]] = {} - for t in types_to_import: - mod = importable_classes.get(t, MODULE_NOT_FOUND) - if mod in imports_by_module: - imports_by_module[mod].append(t) - else: - imports_by_module[mod] = [t] - - for mod in sorted(imports_by_module.keys()): - sorted_types = sorted(set(imports_by_module[mod])) - import_types = ", ".join(sorted_types) - line_prefix = "# " if mod == MODULE_NOT_FOUND else "" - code_lines.append(f"{line_prefix}from {mod} import {import_types}") - - code = "\n".join(code_lines) - return code - - -def print_eval_report( - eval_result: EvaluationResult, - graph: DiGraph, - n_wrong_examples: int = 3, - metrics_filter: Optional[Dict[str, List[str]]] = None, - document_scope: Literal[ - "document_id", "context", "document_id_and_context", "document_id_or_context", "answer", "document_id_or_answer" - ] = "document_id_or_answer", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - wrong_examples_fields: Optional[List[str]] = None, - max_characters_per_field: int = 150, -): - """ - Prints a report for a given EvaluationResult visualizing metrics per node specified by the pipeline graph. - - :param eval_result: The evaluation result. - :param graph: The graph of the pipeline containing the node names and its connections. - :param n_wrong_examples: The number of examples to show in order to inspect wrong predictions. - Defaults to 3. - :param metrics_filter: Specifies which metrics of eval_result to show in the report. - :param document_scope: A criterion for deciding whether documents are relevant or not. - You can select between: - - 'document_id': Specifies that the document ID must match. You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - A typical use case is Document Retrieval. - - 'context': Specifies that the content of the document must match. Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - A typical use case is Document-Independent Passage Retrieval. - - 'document_id_and_context': A Boolean operation specifying that both `'document_id' AND 'context'` must match. - A typical use case is Document-Specific Passage Retrieval. - - 'document_id_or_context': A Boolean operation specifying that either `'document_id' OR 'context'` must match. - A typical use case is Document Retrieval having sparse context labels. - - 'answer': Specifies that the document contents must include the answer. The selected `answer_scope` is enforced automatically. - A typical use case is Question Answering. - - 'document_id_or_answer' (default): A Boolean operation specifying that either `'document_id' OR 'answer'` must match. - This is intended to be a proper default value in order to support both main use cases: - - Document Retrieval - - Question Answering - The default value is 'document_id_or_answer'. - :param answer_scope: Specifies the scope in which a matching answer is considered correct. - You can select between: - - 'any' (default): Any matching answer is considered correct. - - 'context': The answer is only considered correct if its context matches as well. - Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - - 'document_id': The answer is only considered correct if its document ID matches as well. - You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - - 'document_id_and_context': The answer is only considered correct if its document ID and its context match as well. - The default value is 'any'. - In Question Answering, to enforce that the retrieved document is considered correct whenever the answer is correct, set `document_scope` to 'answer' or 'document_id_or_answer'. - :param wrong_examples_fields: A list of field names that should be included in the wrong examples. By default, "answer", "context", and "document_id" are used. - :param max_characters_per_field: The maximum number of characters to show in the wrong examples report (per field). - """ - if wrong_examples_fields is None: - wrong_examples_fields = ["answer", "context", "document_id"] - if any(degree > 1 for node, degree in graph.out_degree): - logger.warning("Pipelines with junctions are currently not supported.") - return - - answer_nodes = {node for node, df in eval_result.node_results.items() if len(df[df["type"] == "answer"]) > 0} - all_top_1_metrics = eval_result.calculate_metrics( - document_scope=document_scope, answer_scope=answer_scope, simulated_top_k_reader=1 - ) - answer_top_1_metrics = {node: metrics for node, metrics in all_top_1_metrics.items() if node in answer_nodes} - - calculated_metrics = { - "": eval_result.calculate_metrics(document_scope=document_scope, answer_scope=answer_scope), - "_top_1": answer_top_1_metrics, - " upper bound": eval_result.calculate_metrics( - document_scope=document_scope, answer_scope=answer_scope, eval_mode="isolated" - ), - } - - if metrics_filter is not None: - calculated_metrics = { - metric_mode: { - node: metrics - if node not in metrics_filter - else {metric: value for metric, value in metrics.items() if metric in metrics_filter[node]} - for node, metrics in node_metrics_dict.items() - } - for metric_mode, node_metrics_dict in calculated_metrics.items() - } - - pipeline_overview = _format_pipeline_overview(calculated_metrics=calculated_metrics, graph=graph) - wrong_examples_report = _format_wrong_examples_report( - eval_result=eval_result, - n_wrong_examples=n_wrong_examples, - document_scope=document_scope, - answer_scope=answer_scope, - fields=wrong_examples_fields, - max_chars=max_characters_per_field, - ) - - print(f"{pipeline_overview}\n" f"{wrong_examples_report}") - - -def _format_document_answer( - document_or_answer: dict, max_chars: Optional[int] = None, field_filter: Optional[List[str]] = None -): - if field_filter is None or len(field_filter) == 0: - field_filter = document_or_answer.keys() # type: ignore - return "\n \t".join(f"{name}: {str(value)[:max_chars]} {'...' if len(str(value)) > max_chars else ''}" for name, value in document_or_answer.items() if name in field_filter) # type: ignore - - -def _format_wrong_example(query: dict, max_chars: int = 150, field_filter: Optional[List[str]] = None): - metrics = "\n \t".join(f"{name}: {value}" for name, value in query["metrics"].items()) - documents = "\n\n \t".join( - _format_document_answer(doc, max_chars, field_filter) for doc in query.get("documents", []) - ) - documents = f"Documents: \n \t{documents}\n" if len(documents) > 0 else "" - answers = "\n\n \t".join(_format_document_answer(doc, max_chars, field_filter) for doc in query.get("answers", [])) - answers = f"Answers: \n \t{answers}\n" if len(answers) > 0 else "" - gold_document_ids = "\n \t".join(query["gold_document_ids"]) - gold_answers = "\n \t".join(query.get("gold_answers", [])) - gold_answers = f"Gold Answers: \n \t{gold_answers}\n" if len(gold_answers) > 0 else "" - s = ( - f"Query: \n \t{query['query']}\n" - f"{gold_answers}" - f"Gold Document Ids: \n \t{gold_document_ids}\n" - f"Metrics: \n \t{metrics}\n" - f"{answers}" - f"{documents}" - f"_______________________________________________________" - ) - return s - - -def _format_wrong_examples_node(node_name: str, wrong_examples_formatted: str): - s = ( - f" Wrong {node_name} Examples\n" - f"=======================================================\n" - f"{wrong_examples_formatted}\n" - f"=======================================================\n" - ) - return s - - -def _format_wrong_examples_report( - eval_result: EvaluationResult, - n_wrong_examples: int = 3, - document_scope: Literal[ - "document_id", "context", "document_id_and_context", "document_id_or_context", "answer", "document_id_or_answer" - ] = "document_id_or_answer", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - fields: Optional[List[str]] = None, - max_chars: int = 150, -): - if fields is None: - fields = ["answer", "context", "document_id"] - examples = { - node: eval_result.wrong_examples( - node, document_scope=document_scope, answer_scope=answer_scope, n=n_wrong_examples - ) - for node in eval_result.node_results.keys() - } - examples_formatted = {} - for node, examples in examples.items(): # type: ignore - if any(examples): - examples_formatted[node] = "\n".join(_format_wrong_example(e, max_chars, fields) for e in examples) # type: ignore - - final_result = "\n".join(map(_format_wrong_examples_node, examples_formatted.keys(), examples_formatted.values())) - return final_result - - -def _format_pipeline_node(node: str, calculated_metrics: dict): - node_metrics: dict = {} - for metric_mode, metrics in calculated_metrics.items(): - for metric, value in metrics.get(node, {}).items(): - node_metrics[f"{metric}{metric_mode}"] = value - - def format_node_metric(metric, value): - return f" | {metric}: {value:5.3}" - - node_metrics_formatted = "\n".join(sorted(map(format_node_metric, node_metrics.keys(), node_metrics.values()))) - node_metrics_formatted = f"{node_metrics_formatted}\n" if len(node_metrics_formatted) > 0 else "" - s = ( - f" {node}\n" - f" |\n" - f"{node_metrics_formatted}" - f" |" - ) - return s - - -def _format_pipeline_overview(calculated_metrics: dict, graph: DiGraph): - pipeline_overview = "\n".join(_format_pipeline_node(node, calculated_metrics) for node in graph.nodes) - s = ( - f"================== Evaluation Report ==================\n" - f"=======================================================\n" - f" Pipeline Overview\n" - f"=======================================================\n" - f"{pipeline_overview}\n" - f" Output\n" - f"=======================================================\n" - ) - return s diff --git a/haystack/schema.py b/haystack/schema.py deleted file mode 100644 index 9bb4417873..0000000000 --- a/haystack/schema.py +++ /dev/null @@ -1,1632 +0,0 @@ -from __future__ import annotations - -import ast -import csv -import hashlib -import inspect -import json -import logging -import time -from dataclasses import asdict -from pathlib import Path -from typing import Any, Dict, List, Literal, Optional, Union -from uuid import uuid4 - -import numpy as np -import pandas as pd -from numpy import ndarray -from pandas import DataFrame -from pydantic import BaseConfig, Field - -# We are using Pydantic dataclasses instead of vanilla Python's -# See #1598 for the reasons behind this choice & performance considerations -from pydantic.dataclasses import dataclass -from pydantic.json import pydantic_encoder - -from haystack.mmh3 import hash128 - -logger = logging.getLogger(__name__) - - -BaseConfig.arbitrary_types_allowed = True - - -#: Types of content_types supported -ContentTypes = Literal["text", "table", "image", "audio"] -FilterType = Dict[str, Union[Dict[str, Any], List[Any], str, int, float, bool]] - -LABEL_DATETIME_FORMAT: str = "%Y-%m-%d %H:%M:%S" - - -@dataclass -class Document: - id: str - content: Union[str, DataFrame] - content_type: ContentTypes = Field(default="text") - meta: Dict[str, Any] = Field(default={}) - id_hash_keys: List[str] = Field(default=["content"]) - score: Optional[float] = None - embedding: Optional[ndarray] = None - - # We use a custom init here as we want some custom logic. The annotations above are however still needed in order - # to use some dataclass magic like "asdict()". See https://www.python.org/dev/peps/pep-0557/#custom-init-method - # They also help in annotating which object attributes will always be present (e.g. "id") even though they - # don't need to passed by the user in init and are rather initialized automatically in the init - def __init__( - self, - content: Union[str, DataFrame], - content_type: ContentTypes = "text", - id: Optional[str] = None, - score: Optional[float] = None, - meta: Optional[Dict[str, Any]] = None, - embedding: Optional[ndarray] = None, - id_hash_keys: Optional[List[str]] = None, - ): - """ - One of the core data classes in Haystack. It's used to represent documents / passages in a standardized way within Haystack. - Documents are stored in DocumentStores, are returned by Retrievers, are the input for Readers and are used in - many other places that manipulate or interact with document-level data. - Note: There can be multiple Documents originating from one file (e.g. PDF), if you split the text - into smaller passages. We'll have one Document per passage in this case. - Each document has a unique ID. This can be supplied by the user or generated automatically. - It's particularly helpful for handling of duplicates and referencing documents in other objects (e.g. Labels) - There's an easy option to convert from/to dicts via `from_dict()` and `to_dict`. - :param content: Content of the document. For most cases, this will be text, but it can be a table or image. - :param content_type: One of "text", "table", "image" or "audio". Haystack components can use this to adjust their - handling of Documents and check compatibility. - :param id: Unique ID for the document. If not supplied by the user, we'll generate one automatically by - creating a hash from the supplied text. This behaviour can be further adjusted by `id_hash_keys`. - :param score: The relevance score of the Document determined by a model (e.g. Retriever or Re-Ranker). - If model's `scale_score` was set to True (default) score is in the unit interval (range of [0,1]), where 1 means extremely relevant. - :param meta: Meta fields for a document like name, url, or author in the form of a custom dict (any keys and values allowed). - :param embedding: Vector encoding of the text - :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's attributes. - To ensure you don't have duplicate documents in your DocumentStore if texts are - not unique, modify the metadata and pass, for example, "meta" to this field (example: ["content", "meta"]). - In this case, the id is generated by using the content and the defined metadata. - If you specify a custom ID for the `id` parameter, the `id_hash_keys` parameter is - ignored and the custom ID is used. - - Note that you can use even nested fields of the `meta` as id_hash_keys. For example, if you - have a key in `meta` called `url` and you want to use it as part of the id, you can pass - this parameter as `["meta.url"]`. Haystack supports a maximum depth of 1. For example, if you - use `meta.url.path`, it looks for the `url.path` key in the `meta` dict, for example `meta['url.path']`. - - - """ - - if content is None: - raise ValueError("Can't create 'Document': Mandatory 'content' field is None") - - self.content = content - self.content_type = content_type - self.score = score - self.meta = meta or {} - - allowed_hash_key_attributes = ["content", "content_type", "score", "meta", "embedding"] - - if id_hash_keys is not None and not all( - key in allowed_hash_key_attributes or key.startswith("meta.") for key in id_hash_keys - ): - raise ValueError( - f"You passed custom strings {id_hash_keys} to id_hash_keys which is deprecated. Supply instead a " - f"list of Document's attribute names (like {', '.join(allowed_hash_key_attributes)}) or " - f"a key of meta with a maximum depth of 1 (like meta.url). " - "See [Custom id hashing on documentstore level](https://github.com/deepset-ai/haystack/pull/1910) and " - "[Allow more flexible Document id hashing](https://github.com/deepset-ai/haystack/issues/4317) for details" - ) - # We store id_hash_keys to be able to clone documents, for example when splitting them during pre-processing - self.id_hash_keys = id_hash_keys or ["content"] - - if embedding is not None: - embedding = np.asarray(embedding) - self.embedding = embedding - - # Create a unique ID (either new one, or one from user input) - if id is not None: - self.id: str = str(id) - else: - self.id: str = self._get_id(id_hash_keys=id_hash_keys) - - def _get_id(self, id_hash_keys: Optional[List[str]] = None): - """ - Generate the id of a document by creating the hash of strings. By default the content of a document is - used to generate the hash. There are two ways of modifying the generated id of a document. Either static keys - or a selection of the content. - :param id_hash_keys: Optional list of fields that should be dynamically used to generate the hash. - """ - - if id_hash_keys is None: - return "{:02x}".format(hash128(str(self.content))) - - final_hash_key = "" - for attr in id_hash_keys: - if attr.startswith("meta."): - meta_key = attr.split(".", maxsplit=1)[1] - if meta_key in self.meta: - final_hash_key += ":" + str(self.meta[meta_key]) - else: - final_hash_key += ":" + str(getattr(self, attr)) - - if final_hash_key == "": - raise ValueError( - "Can't create 'Document': 'id_hash_keys' must contain at least one of ['content', 'meta'] or be set to None." - ) - - return "{:02x}".format(hash128(final_hash_key)) - - def to_dict(self, field_map: Optional[Dict[str, Any]] = None) -> Dict: - """ - Convert Document to dict. An optional field_map can be supplied to change the names of the keys in the - resulting dict. This way you can work with standardized Document objects in Haystack, but adjust the format that - they are serialized / stored in other places (e.g. elasticsearch) - Example: - - ```python - doc = Document(content="some text", content_type="text") - doc.to_dict(field_map={"custom_content_field": "content"}) - - # Returns {"custom_content_field": "some text", content_type": "text"} - ``` - - :param field_map: Dict with keys being the custom target keys and values being the standard Document attributes - :return: dict with content of the Document - """ - if not field_map: - field_map = {} - - inv_field_map = {v: k for k, v in field_map.items()} - _doc: Dict[str, str] = {} - for k, v in self.__dict__.items(): - # Exclude internal fields (Pydantic, ...) fields from the conversion process - if k.startswith("__"): - continue - # Convert pd.DataFrame to list of rows for serialization - if k == "content" and self.content_type == "table" and isinstance(self.content, DataFrame): - v = dataframe_to_list(self.content) - k = k if k not in inv_field_map else inv_field_map[k] - _doc[k] = v - return _doc - - @classmethod - def from_dict(cls, dict: Dict[str, Any], field_map: Optional[Dict[str, Any]] = None) -> Document: - """ - Create Document from dict. An optional `field_map` parameter can be supplied to adjust for custom names of the keys in the - input dict. This way you can work with standardized Document objects in Haystack, but adjust the format that - they are serialized / stored in other places (e.g. elasticsearch). - - Example: - - ```python - my_dict = {"custom_content_field": "some text", "content_type": "text"} - Document.from_dict(my_dict, field_map={"custom_content_field": "content"}) - ``` - - :param field_map: Dict with keys being the custom target keys and values being the standard Document attributes - :return: A Document object - """ - if not field_map: - field_map = {} - - _doc = dict.copy() - init_args = ["content", "content_type", "id", "score", "id_hash_keys", "question", "meta", "embedding"] - if "meta" not in _doc.keys(): - _doc["meta"] = {} - # copy additional fields into "meta" - for k, v in _doc.items(): - # Exclude internal fields (Pydantic, ...) fields from the conversion process - if k.startswith("__"): - continue - if k not in init_args and k not in field_map: - _doc["meta"][k] = v - # remove additional fields from top level - _new_doc = {} - for k, v in _doc.items(): - if k in init_args: - _new_doc[k] = v - elif k in field_map: - k = field_map[k] - _new_doc[k] = v - - # Convert list of rows to DataFrame - if _new_doc.get("content_type", None) == "table" and isinstance(_new_doc["content"], list): - _new_doc["content"] = dataframe_from_list(_new_doc["content"]) - - return cls(**_new_doc) - - def to_json(self, field_map: Optional[Dict[str, Any]] = None) -> str: - if not field_map: - field_map = {} - dictionary = self.to_dict(field_map=field_map) - return json.dumps(dictionary, cls=NumpyEncoder) - - @classmethod - def from_json(cls, data: Union[str, Dict[str, Any]], field_map: Optional[Dict[str, Any]] = None) -> Document: - if not field_map: - field_map = {} - if isinstance(data, str): - dict_data = json.loads(data) - else: - dict_data = data - return cls.from_dict(dict_data, field_map=field_map) - - def __eq__(self, other): - content = getattr(other, "content", None) - if isinstance(content, pd.DataFrame): - is_content_equal = content.equals(self.content) - else: - is_content_equal = content == self.content - return ( - isinstance(other, self.__class__) - and is_content_equal - and getattr(other, "content_type", None) == self.content_type - and getattr(other, "id", None) == self.id - and getattr(other, "id_hash_keys", None) == self.id_hash_keys - and getattr(other, "score", None) == self.score - and getattr(other, "meta", None) == self.meta - and np.array_equal(getattr(other, "embedding", None), self.embedding) - ) - - def __repr__(self): - doc_dict = self.to_dict() - embedding = doc_dict.get("embedding", None) - if embedding is not None: - doc_dict["embedding"] = f"" - return f"" - - def __str__(self): - # In some cases, self.content is None (therefore not subscriptable) - if self.content is None: - return f"" - return f" 100 else ''}'>" - - def __lt__(self, other): - """Enable sorting of Documents by score""" - return self.score < other.score - - -@dataclass -class Span: - start: int - end: int - """ - Defining a sequence of characters (Text span) or cells (Table span) via start and end index. - For extractive QA: Character where answer starts/ends - - :param start: Position where the span starts - :param end: Position where the span ends - """ - - def __contains__(self, value): - """ - Checks for inclusion of the given value into the interval defined by Span. - ``` - assert 10 in Span(5, 15) # True - assert 20 in Span(1, 15) # False - ``` - Includes the left edge, but not the right edge. - ``` - assert 5 in Span(5, 15) # True - assert 15 in Span(5, 15) # False - ``` - Works for numbers and all values that can be safely converted into floats. - ``` - assert 10.0 in Span(5, 15) # True - assert "10" in Span(5, 15) # True - ``` - It also works for Span objects, returning True only if the given - Span is fully contained into the original Span. - As for numerical values, the left edge is included, the right edge is not. - ``` - assert Span(10, 11) in Span(5, 15) # True - assert Span(5, 10) in Span(5, 15) # True - assert Span(10, 15) in Span(5, 15) # False - assert Span(5, 15) in Span(5, 15) # False - assert Span(5, 14) in Span(5, 15) # True - assert Span(0, 1) in Span(5, 15) # False - assert Span(0, 10) in Span(5, 15) # False - assert Span(10, 20) in Span(5, 15) # False - ``` - """ - if isinstance(value, Span): - return self.start <= value.start and self.end > value.end - try: - value = float(value) - return self.start <= value < self.end - except Exception as e: - raise ValueError( - f"Cannot use 'in' with a value of type {type(value)}. Use numeric values or Span objects." - ) from e - - -@dataclass -class TableCell: - row: int - col: int - """ - Defining a table cell via the row and column index. - - :param row: Row index of the cell - :param col: Column index of the cell - """ - - -@dataclass -class Answer: - answer: str - type: Literal["generative", "extractive", "other"] = "extractive" - score: Optional[float] = None - context: Optional[Union[str, DataFrame]] = None - offsets_in_document: Optional[Union[List[Span], List[TableCell]]] = None - offsets_in_context: Optional[Union[List[Span], List[TableCell]]] = None - document_ids: Optional[List[str]] = None - meta: Optional[Dict[str, Any]] = None - - """ - The fundamental object in Haystack to represent any type of Answers (e.g. extractive QA, generative QA or TableQA). - For example, it's used within some Nodes like the Reader, but also in the REST API. - - :param answer: The answer string. If there's no possible answer (aka "no_answer" or "is_impossible) this will be an empty string. - :param type: One of ("generative", "extractive", "other"): Whether this answer comes from an extractive model - (i.e. we can locate an exact answer string in one of the documents) or from a generative model - (i.e. no pointer to a specific document, no offsets ...). - :param score: The relevance score of the Answer determined by a model (e.g. Reader or Generator). - In the range of [0,1], where 1 means extremely relevant. - :param context: The related content that was used to create the answer (i.e. a text passage, part of a table, image ...) - :param offsets_in_document: List of `Span` objects with start and end positions of the answer **in the - document** (as stored in the document store). - For extractive QA: Character where answer starts => `Answer.offsets_in_document[0].start - For TableQA: Cell where the answer starts (counted from top left to bottom right of table) => `Answer.offsets_in_document[0].start - (Note that in TableQA there can be multiple cell ranges that are relevant for the answer, thus there can be multiple `Spans` here) - :param offsets_in_context: List of `Span` objects with start and end positions of the answer **in the - context** (i.e. the surrounding text/table of a certain window size). - For extractive QA: Character where answer starts => `Answer.offsets_in_document[0].start - For TableQA: Cell where the answer starts (counted from top left to bottom right of table) => `Answer.offsets_in_document[0].start - (Note that in TableQA there can be multiple cell ranges that are relevant for the answer, thus there can be multiple `Spans` here) - :param document_ids: IDs of the documents the answer came from (if any). - For extractive QA, this will be a list of length 1. - For generative QA, this will be a list of length > 0. - :param meta: Dict that can be used to associate any kind of custom meta data with the answer. - In extractive QA, this will carry the meta data of the document where the answer was found. - """ - - def __post_init__(self): - # In case offsets are passed as dicts rather than Span or TableCell objects we convert them here - # For example, this is used when instantiating an object via from_json() - if self.offsets_in_document is not None: - self.offsets_in_document = self._from_dict_offsets(self.offsets_in_document) - - if self.offsets_in_context is not None: - self.offsets_in_context = self._from_dict_offsets(self.offsets_in_context) - - if self.meta is None: - self.meta = {} - - # In case the context is a list of lists for a table document that is instantiated by from_json() or from_dict() - if isinstance(self.context, list): - self.context = dataframe_from_list(self.context) - - def __lt__(self, other): - """Enable sorting of Answers by score""" - return self.score < other.score - - def __str__(self): - # self.context might be None (therefore not subscriptable) - if self.context is None: - return f"" - return f" 50 else ''}'>" - - def __repr__(self): - return f"" - - def to_dict(self) -> Dict: - return asdict(self, dict_factory=_dict_factory) - - @classmethod - def from_dict(cls, dict: Dict) -> Answer: - # backwards compatibility: `document_id: Optional[str]` was changed to `document_ids: Optional[List[str]]` - if "document_id" in dict: - dict = dict.copy() - document_id = dict.pop("document_id") - dict["document_ids"] = [document_id] if document_id is not None else None - return cls(**dict) - - def to_json(self): - return json.dumps(self.to_dict(), cls=NumpyEncoder) - - @classmethod - def from_json(cls, data: Union[str, Dict[str, Any]]): - if isinstance(data, str): - dict_data = json.loads(data) - else: - dict_data = data - return cls.from_dict(dict_data) - - @staticmethod - def _from_dict_offsets(offsets): - converted_offsets = [] - for e in offsets: - if isinstance(e, dict): - if "row" in e: # is a TableCell - converted_offsets.append(TableCell(**e)) - else: - converted_offsets.append(Span(**e)) - else: - converted_offsets.append(e) - return converted_offsets - - def __eq__(self, other): - context = getattr(other, "context", None) - if isinstance(context, pd.DataFrame): - is_content_equal = context.equals(self.context) - else: - is_content_equal = context == self.context - return ( - isinstance(other, self.__class__) - and is_content_equal - and getattr(other, "answer", None) == self.answer - and getattr(other, "type", None) == self.type - and getattr(other, "score", None) == self.score - and getattr(other, "offsets_in_document", None) == self.offsets_in_document - and getattr(other, "offsets_in_context", None) == self.offsets_in_context - and getattr(other, "document_ids", None) == self.document_ids - and getattr(other, "meta", None) == self.meta - ) - - -@dataclass -class Label: - id: str - query: str - document: Document - is_correct_answer: bool - is_correct_document: bool - origin: Literal["user-feedback", "gold-label"] - answer: Optional[Answer] = None - pipeline_id: Optional[str] = None - created_at: Optional[str] = None - updated_at: Optional[str] = None - meta: Optional[dict] = None - # Note that filters cannot be of type Optional[FilterType] as assignments like `filters = {"name": "file_name"}` - # won't work due to Dict's covariance. See https://github.com/python/mypy/issues/9418. - filters: Optional[Dict[str, Any]] = None - - # We use a custom init here as we want some custom logic. The annotations above are however still needed in order - # to use some dataclass magic like "asdict()". See https://www.python.org/dev/peps/pep-0557/#custom-init-method - def __init__( - self, - query: str, - document: Document, - is_correct_answer: bool, - is_correct_document: bool, - origin: Literal["user-feedback", "gold-label"], - answer: Optional[Answer], - id: Optional[str] = None, - pipeline_id: Optional[str] = None, - created_at: Optional[str] = None, - updated_at: Optional[str] = None, - meta: Optional[dict] = None, - filters: Optional[Dict[str, Any]] = None, - ): - """ - Object used to represent label/feedback in a standardized way within Haystack. - This includes labels from dataset like SQuAD, annotations from labeling tools, - or, user-feedback from the Haystack REST API. - - :param query: the question (or query) for finding answers. - :param document: - :param answer: the answer object. - :param is_correct_answer: whether the sample is positive or negative. - :param is_correct_document: in case of negative sample(is_correct_answer is False), there could be two cases; - incorrect answer but correct document & incorrect document. This flag denotes if - the returned document was correct. - :param origin: the source for the labels. It can be used to later for filtering. - :param id: Unique ID used within the DocumentStore. If not supplied, a uuid will be generated automatically. - :param pipeline_id: pipeline identifier (any str) that was involved for generating this label (in-case of user feedback). - :param created_at: Timestamp of creation with format yyyy-MM-dd HH:mm:ss. - Generate in Python via time.strftime("%Y-%m-%d %H:%M:%S"). - :param updated_at: Timestamp of update with format yyyy-MM-dd HH:mm:ss. - Generate in Python via time.strftime("%Y-%m-%d %H:%M:%S") - :param meta: Meta fields like "annotator_name" in the form of a custom dict (any keys and values allowed). - :param filters: filters that should be applied to the query to rule out non-relevant documents. For example, if there are different correct answers - in a DocumentStore depending on the retrieved document and the answer in this label is correct only on condition of the filters. - """ - - # Create a unique ID (either new one, or one from user input) - if id: - self.id = str(id) - else: - self.id = str(uuid4()) - - if created_at is None: - created_at = time.strftime(LABEL_DATETIME_FORMAT) - self.created_at = created_at - - self.updated_at = updated_at - self.query = query - - self.answer = answer - self.document = document - - self.is_correct_answer = is_correct_answer - self.is_correct_document = is_correct_document - self.origin = origin - - # TODO autofill answer.document_id if Document is provided - - self.pipeline_id = pipeline_id - if not meta: - self.meta = {} - else: - self.meta = meta - self.filters = filters - - @property - def no_answer(self) -> Optional[bool]: - no_answer = None - if self.answer is not None: - no_answer = self.answer.answer is None or self.answer.answer.strip() == "" - return no_answer - - def to_dict(self): - return asdict(self, dict_factory=_dict_factory) - - @classmethod - def from_dict(cls, dict: Dict): - answer = dict.get("answer") - if answer and isinstance(answer, Dict): - dict["answer"] = Answer.from_dict(dict["answer"]) - doc = dict.get("document") - if isinstance(doc, Dict): - dict["document"] = Document.from_dict(dict["document"]) - return cls(**dict) - - def to_json(self): - return json.dumps(self.to_dict(), cls=NumpyEncoder) - - @classmethod - def from_json(cls, data: Union[str, Dict[str, Any]]): - if isinstance(data, str): - dict_data = json.loads(data) - else: - dict_data = data - return cls.from_dict(dict_data) - - # define __eq__ and __hash__ functions to deduplicate Label Objects - def __eq__(self, other): - return ( - isinstance(other, self.__class__) - and getattr(other, "query", None) == self.query - and getattr(other, "answer", None) == self.answer - and getattr(other, "is_correct_answer", None) == self.is_correct_answer - and getattr(other, "is_correct_document", None) == self.is_correct_document - and getattr(other, "origin", None) == self.origin - and getattr(other, "document", None) == self.document - and getattr(other, "no_answer", None) == self.no_answer - and getattr(other, "pipeline_id", None) == self.pipeline_id - ) - - def __hash__(self): - return hash( - self.query - + str(self.answer) - + str(self.is_correct_answer) - + str(self.is_correct_document) - + str(self.origin) - + str(self.document) - + str(self.no_answer) - + str(self.pipeline_id) - ) - - def __repr__(self): - return f"" - - def __str__(self): - return f"" - - -def is_positive_label(label): - return (label.is_correct_answer and label.is_correct_document) or ( - label.answer is None and label.is_correct_document - ) - - -class MultiLabel: - def __init__(self, labels: List[Label], drop_negative_labels: bool = False, drop_no_answers: bool = False): - """ - There are often multiple `Labels` associated with a single query. For example, there can be multiple annotated - answers for one question or multiple documents contain the information you want for a query. - This class is "syntactic sugar" that simplifies the work with such a list of related Labels. - It stores the original labels in MultiLabel.labels and provides additional aggregated attributes that are - automatically created at init time. For example, MultiLabel.no_answer allows you to easily access if any of the - underlying Labels provided a text answer and therefore demonstrates that there is indeed a possible answer. - - :param labels: A list of labels that belong to a similar query and shall be "grouped" together - :param drop_negative_labels: Whether to drop negative labels from that group (e.g. thumbs down feedback from UI) - :param drop_no_answers: Whether to drop labels that specify the answer is impossible - """ - # drop duplicate labels and remove negative labels if needed. - labels = list(dict.fromkeys(labels)) - if drop_negative_labels: - labels = [l for l in labels if is_positive_label(l)] - if drop_no_answers: - labels = [l for l in labels if l.no_answer is False] - - self._labels = labels - self._query = self._aggregate_labels(key="query", must_be_single_value=True)[0] - self._filters = self._aggregate_labels(key="filters", must_be_single_value=True)[0] - self.id = hashlib.md5((self.query + json.dumps(self.filters, sort_keys=True)).encode()).hexdigest() - - # Currently no_answer is only true if all labels are "no_answers", we could later introduce a param here to let - # users decided which aggregation logic they want - self._no_answer = all(l.no_answer for l in self._labels) - - # Answer strings and offsets cleaned for no_answers: - # If there are only no_answers, offsets are empty and answers will be a single empty string - # which equals the no_answers representation of reader nodes. - if self._no_answer: - self._answers = [""] - self._offsets_in_documents: List[dict] = [] - self._offsets_in_contexts: List[dict] = [] - else: - answered = [l.answer for l in self._labels if not l.no_answer and l.answer is not None] - self._answers = [answer.answer for answer in answered] - self._offsets_in_documents = [] - self._offsets_in_contexts = [] - for answer in answered: - if answer.offsets_in_document is not None: - for span in answer.offsets_in_document: - self._offsets_in_documents.append(self._to_dict_offsets(span)) - if answer.offsets_in_context is not None: - for span in answer.offsets_in_context: - self._offsets_in_contexts.append(self._to_dict_offsets(span)) - - # There are two options here to represent document_ids: - # taking the id from the document of each label or taking the document_id of each label's answer. - # We take the former as labels without answers are allowed. - # - # For no_answer cases document_store.add_eval_data() currently adds all documents coming from the SQuAD paragraph's context - # as separate no_answer labels, and thus with document.id but without answer.document_id. - # If we do not exclude them from document_ids this would be problematic for retriever evaluation as they do not contain the answer. - # Hence, we exclude them here as well. - self._document_ids = [l.document.id for l in self._labels if not l.no_answer] - self._contexts = [str(l.document.content) for l in self._labels if not l.no_answer] - - @staticmethod - def _to_dict_offsets(offset: Union[Span, TableCell]) -> Dict: - if isinstance(offset, TableCell): - return {"row": offset.row, "col": offset.col} - else: - return {"start": offset.start, "end": offset.end} - - @property - def labels(self): - return self._labels - - @property - def query(self): - return self._query - - @property - def filters(self): - return self._filters - - @property - def document_ids(self): - return self._document_ids - - @property - def contexts(self): - return self._contexts - - @property - def no_answer(self): - return self._no_answer - - @property - def answers(self): - return self._answers - - @property - def offsets_in_documents(self): - return self._offsets_in_documents - - @property - def offsets_in_contexts(self): - return self._offsets_in_contexts - - def _aggregate_labels(self, key, must_be_single_value=True) -> List[Any]: - if any(isinstance(getattr(l, key), dict) for l in self.labels): - # dict is not hashable so we collect unique filters via looping through all labels - unique_values = [] - for l in self.labels: - if l.filters not in unique_values: - unique_values.append(l.filters) - else: - unique_values = list({getattr(l, key) for l in self.labels}) - if must_be_single_value and len(unique_values) > 1: - raise ValueError( - f"Tried to combine attribute '{key}' of Labels, but found multiple different values: {unique_values}" - ) - return unique_values - - def to_dict(self): - # convert internal attribute names to property names - result = {k[1:] if k[0] == "_" else k: v for k, v in vars(self).items()} - # convert Label object to dict - result["labels"] = [label.to_dict() for label in result["labels"]] - return result - - @classmethod - def from_dict(cls, dict: Dict): - # exclude extra arguments - inputs = {k: v for k, v in dict.items() if k in inspect.signature(cls).parameters} - inputs["labels"] = [Label.from_dict(label) for label in inputs["labels"]] - return cls(**inputs) - - def to_json(self): - return json.dumps(self.to_dict(), default=pydantic_encoder) - - @classmethod - def from_json(cls, data: Union[str, Dict[str, Any]]): - if isinstance(data, str): - dict_data = json.loads(data) - else: - dict_data = data - return cls.from_dict(dict_data) - - def __eq__(self, other): - return isinstance(other, self.__class__) and self.labels == other.labels - - def __repr__(self): - return f"" - - def __str__(self): - return f"" - - -def _pydantic_dataclass_from_dict(dict: Dict, pydantic_dataclass_type) -> Any: - """ - Constructs a pydantic dataclass from a dict incl. other nested dataclasses. - This allows simple de-serialization of pydantic dataclasses from json. - :param dict: Dict containing all attributes and values for the dataclass. - :param pydantic_dataclass_type: The class of the dataclass that should be constructed (e.g. Document) - """ - base_model = pydantic_dataclass_type.__pydantic_model__.parse_obj(dict) - base_mode_fields = base_model.__fields__ - - values = {} - for base_model_field_name in base_mode_fields.keys(): - value = getattr(base_model, base_model_field_name) - values[base_model_field_name] = value - - dataclass_object = pydantic_dataclass_type(**values) - return dataclass_object - - -def _dict_factory(data): - """Meant to be as the dict_factory for `asdict`. This function is called within `asdict` to convert a list of tuples - into a dictionary object. This handles the conversion of pandas Dataframes into a list of lists. - - :param data: list of (key, value) pairs - """ - - def convert_value(v): - if isinstance(v, pd.DataFrame): - return dataframe_to_list(v) - return v - - return {k: convert_value(v) for k, v in data} - - -class NumpyEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, np.ndarray): - return obj.tolist() - return json.JSONEncoder.default(self, obj) - - -def dataframe_to_list(df: pd.DataFrame) -> List[List]: - return [df.columns.tolist()] + df.values.tolist() - - -def dataframe_from_list(list_df: List[List]) -> pd.DataFrame: - return pd.DataFrame(columns=list_df[0], data=list_df[1:]) - - -class EvaluationResult: - def __init__(self, node_results: Optional[Dict[str, DataFrame]] = None) -> None: - """ - A convenience class to store, pass, and interact with results of a pipeline evaluation run (for example `pipeline.eval()`). - Detailed results are stored as one dataframe per node. This class makes them more accessible and provides - convenience methods to work with them. - For example, you can calculate eval metrics, get detailed reports, or simulate different top_k settings: - - ```python - eval_results = pipeline.eval(...) - - # derive detailed metrics - eval_results.calculate_metrics() - - # show summary of incorrect queries - eval_results.wrong_examples() - ``` - - Each row of the underlying DataFrames contains either an answer or a document that has been retrieved during evaluation. - Rows are enriched with basic information like rank, query, type, or node. - Additional answer or document-specific evaluation information, like gold labels - and metrics showing whether the row matches the gold labels, are included, too. - The DataFrames have the following schema: - - multilabel_id: The ID of the multilabel, which is unique for the pair of query and filters. - - query: The actual query string. - - filters: The filters used with the query. - - gold_answers (answers only): The expected answers. - - answer (answers only): The actual answer. - - context: The content of the document (the surrounding context of the answer for QA). - - exact_match (answers only): A metric showing if the answer exactly matches the gold label. - - f1 (answers only): A metric showing how well the answer overlaps with the gold label on a token basis. - - sas (answers only, optional): A metric showing how well the answer matches the gold label on a semantic basis. - - exact_match_context_scope (answers only): exact_match with enforced context match. - - f1_context_scope (answers only): f1 with enforced context scope match. - - sas_context_scope (answers only): sas with enforced context scope match. - - exact_match_document_scope (answers only): exact_match with enforced document scope match. - - f1_document_scope (answers only): f1 with enforced document scope match. - - sas_document_scope (answers only): sas with enforced document scope match. - - exact_match_document_id_and_context_scope: (answers only): exact_match with enforced document and context scope match. - - f1_document_id_and_context_scope (answers only): f1 with enforced document and context scope match. - - sas_document_id_and_context_scope (answers only): sas with enforced document and context scope match. - - gold_contexts: The contents of the gold documents. - - gold_id_match (documents only): A metric showing whether one of the gold document IDs matches the document. - - context_match (documents only): A metric showing whether one of the gold contexts matches the document content. - - answer_match (documents only): A metric showing whether the document contains the answer. - - gold_id_or_answer_match (documents only): A Boolean operation specifying that there should be either `'gold_id_match' OR 'answer_match'`. - - gold_id_and_answer_match (documents only): A Boolean operation specifying that there should be both `'gold_id_match' AND 'answer_match'`. - - gold_id_or_context_match (documents only): A Boolean operation specifying that there should be either `'gold_id_match' OR 'context_match'`. - - gold_id_and_context_match (documents only): A Boolean operation specifying that there should be both `'gold_id_match' AND 'context_match'`. - - gold_id_and_context_and_answer_match (documents only): A Boolean operation specifying that there should be `'gold_id_match' AND 'context_match' AND 'answer_match'`. - - context_and_answer_match (documents only): A Boolean operation specifying that there should be both `'context_match' AND 'answer_match'`. - - rank: A rank or 1-based-position in the result list. - - document_id: The ID of the document that has been retrieved or that contained the answer. - - gold_document_ids: The IDs of the documents to be retrieved. - - custom_document_id: The custom ID of the document (specified by `custom_document_id_field`) that has been retrieved or that contained the answer. - - gold_custom_document_ids: The custom documents IDs (specified by `custom_document_id_field`) to be retrieved. - - offsets_in_document (answers only): The position or offsets within the document where the answer was found. - - gold_offsets_in_documents (answers only): The position or offsets of the gold answer within the document. - - gold_answers_exact_match (answers only): exact_match values per gold_answer. - - gold_answers_f1 (answers only): f1 values per gold_answer. - - gold_answers_sas (answers only): sas values per gold answer. - - gold_documents_id_match: The document ID match per gold label (if `custom_document_id_field` has been specified, custom IDs are used). - - gold_contexts_similarity: Context similarity per gold label. - - gold_answers_match (documents only): Specifies whether the document contains an answer per gold label. - - type: Possible values: 'answer' or 'document'. - - node: The node name - - eval_mode: Specifies whether the evaluation was executed in integrated or isolated mode. - Check pipeline.eval()'s add_isolated_node_eval parameter for more information. - - :param node_results: The evaluation Dataframes per pipeline node. - """ - self.node_results: Dict[str, DataFrame] = {} if node_results is None else node_results - - def __getitem__(self, key: str): - return self.node_results.__getitem__(key) - - def __delitem__(self, key: str): - self.node_results.__delitem__(key) - - def __setitem__(self, key: str, value: DataFrame): - self.node_results.__setitem__(key, value) - - def __contains__(self, key: str): - return self.node_results.keys().__contains__(key) - - def __len__(self): - return self.node_results.__len__() - - def append(self, key: str, value: DataFrame): - if value is not None and len(value) > 0: - if key in self.node_results: - self.node_results[key] = pd.concat([self.node_results[key], value]).reset_index(drop=True) - else: - self.node_results[key] = value - - def calculate_metrics( - self, - simulated_top_k_reader: int = -1, - simulated_top_k_retriever: int = -1, - document_scope: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "document_id_or_answer", - ] = "document_id_or_answer", - eval_mode: Literal["integrated", "isolated"] = "integrated", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - ) -> Dict[str, Dict[str, float]]: - """ - Calculates proper metrics for each node. - - For Nodes that return Documents, the default metrics are: - - mrr (`Mean Reciprocal Rank `_) - - map (`Mean Average Precision `_) - - ndcg (`Normalized Discounted Cumulative Gain `_) - - precision (Precision: How many of the returned documents were relevant?) - - recall_multi_hit (Recall according to Information Retrieval definition: How many of the relevant documents were retrieved per query?) - - recall_single_hit (Recall for Question Answering: How many of the queries returned at least one relevant document?) - - For Nodes that return answers, the default metrics are: - - exact_match (How many of the queries returned the exact answer?) - - f1 (How well do the returned results overlap with any gold answer on a token basis?) - - sas, if a SAS model has been provided when calling `pipeline.eval()` (How semantically similar is the prediction to the gold answers?) - - During the eval run, you can simulate lower top_k values for Reader and Retriever than the actual values. - For example, you can calculate `top_1_f1` for Reader nodes by setting `simulated_top_k_reader=1`. - - If you applied `simulated_top_k_retriever` to a Reader node, you should treat the results with caution as they can differ from an actual eval run with a corresponding `top_k_retriever` heavily. - - :param simulated_top_k_reader: Simulates the `top_k` parameter of the Reader. - :param simulated_top_k_retriever: Simulates the `top_k` parameter of the Retriever. - Note: There might be a discrepancy between simulated Reader metrics and an actual Pipeline run with Retriever `top_k`. - :param eval_mode: The input the Node was evaluated on. - Usually a Node gets evaluated on the prediction provided by its predecessor Nodes in the Pipeline (`value='integrated'`). - However, as the quality of the Node can heavily depend on the Node's input and thus the predecessor's quality, - you might want to simulate a perfect predecessor in order to get an independent upper bound of the quality of your Node. - For example, when evaluating the Reader, use `value='isolated'` to simulate a perfect Retriever in an ExtractiveQAPipeline. - Possible values are: `integrated`, `isolated`. - The default value is `integrated`. - :param document_scope: A criterion for deciding whether documents are relevant or not. - You can select between: - - 'document_id': Specifies that the document ID must match. You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - A typical use case is Document Retrieval. - - 'context': Specifies that the content of the document must match. Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - A typical use case is Document-Independent Passage Retrieval. - - 'document_id_and_context': A Boolean operation specifying that both `'document_id' AND 'context'` must match. - A typical use case is Document-Specific Passage Retrieval. - - 'document_id_or_context': A Boolean operation specifying that either `'document_id' OR 'context'` must match. - A typical use case is Document Retrieval having sparse context labels. - - 'answer': Specifies that the document contents must include the answer. The selected `answer_scope` is enforced automatically. - A typical use case is Question Answering. - - 'document_id_or_answer' (default): A Boolean operation specifying that either `'document_id' OR 'answer'` must match. - This is intended to be a proper default value in order to support both main use cases: - - Document Retrieval - - Question Answering - The default value is 'document_id_or_answer'. - :param answer_scope: Specifies the scope in which a matching answer is considered correct. - You can select between: - - 'any' (default): Any matching answer is considered correct. - - 'context': The answer is only considered correct if its context matches as well. - Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - - 'document_id': The answer is only considered correct if its document ID matches as well. - You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - - 'document_id_and_context': The answer is only considered correct if its document ID and its context match as well. - The default value is 'any'. - In Question Answering, to enforce that the retrieved document is considered correct whenever the answer is correct, set `document_scope` to 'answer' or 'document_id_or_answer'. - """ - return { - node: self._calculate_node_metrics( - df, - simulated_top_k_reader=simulated_top_k_reader, - simulated_top_k_retriever=simulated_top_k_retriever, - document_scope=document_scope, - answer_scope=answer_scope, - eval_mode=eval_mode, - ) - for node, df in self.node_results.items() - } - - def wrong_examples( - self, - node: str, - n: int = 3, - simulated_top_k_reader: int = -1, - simulated_top_k_retriever: int = -1, - document_scope: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "document_id_or_answer", - ] = "document_id_or_answer", - document_metric: str = "recall_single_hit", - answer_metric: str = "f1", - document_metric_threshold: float = 0.5, - answer_metric_threshold: float = 0.5, - eval_mode: Literal["integrated", "isolated"] = "integrated", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - ) -> List[Dict]: - """ - Returns the worst performing queries. - Worst performing queries are calculated based on the metric - that is either a document metric or an answer metric according to the node type. - - Lower top_k values for reader and retriever than the actual values during the eval run can be simulated. - See calculate_metrics() for more information. - - :param simulated_top_k_reader: simulates top_k param of reader - :param simulated_top_k_retriever: simulates top_k param of retriever. - remarks: there might be a discrepancy between simulated reader metrics and an actual pipeline run with retriever top_k - :param document_metric: the document metric worst queries are calculated with. - values can be: 'recall_single_hit', 'recall_multi_hit', 'mrr', 'map', 'precision' - :param answer_metric: the answer metric worst queries are calculated with. - values can be: 'f1', 'exact_match' and 'sas' if the evaluation was made using a SAS model. - :param document_metric_threshold: the threshold for the document metric (only samples below selected metric - threshold will be considered) - :param answer_metric_threshold: the threshold for the answer metric (only samples below selected metric - threshold will be considered) - :param eval_mode: the input on which the node was evaluated on. - Usually nodes get evaluated on the prediction provided by its predecessor nodes in the pipeline (value='integrated'). - However, as the quality of the node itself can heavily depend on the node's input and thus the predecessor's quality, - you might want to simulate a perfect predecessor in order to get an independent upper bound of the quality of your node. - For example when evaluating the reader use value='isolated' to simulate a perfect retriever in an ExtractiveQAPipeline. - Values can be 'integrated', 'isolated'. - Default value is 'integrated'. - :param document_scope: A criterion for deciding whether documents are relevant or not. - You can select between: - - 'document_id': Specifies that the document ID must match. You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - A typical use case is Document Retrieval. - - 'context': Specifies that the content of the document must match. Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - A typical use case is Document-Independent Passage Retrieval. - - 'document_id_and_context': A Boolean operation specifying that both `'document_id' AND 'context'` must match. - A typical use case is Document-Specific Passage Retrieval. - - 'document_id_or_context': A Boolean operation specifying that either `'document_id' OR 'context'` must match. - A typical use case is Document Retrieval having sparse context labels. - - 'answer': Specifies that the document contents must include the answer. The selected `answer_scope` is enforced automatically. - A typical use case is Question Answering. - - 'document_id_or_answer' (default): A Boolean operation specifying that either `'document_id' OR 'answer'` must match. - This is intended to be a proper default value in order to support both main use cases: - - Document Retrieval - - Question Answering - The default value is 'document_id_or_answer'. - :param answer_scope: Specifies the scope in which a matching answer is considered correct. - You can select between: - - 'any' (default): Any matching answer is considered correct. - - 'context': The answer is only considered correct if its context matches as well. - Uses fuzzy matching (see `pipeline.eval()`'s `context_matching_...` params). - - 'document_id': The answer is only considered correct if its document ID matches as well. - You can specify a custom document ID through `pipeline.eval()`'s `custom_document_id_field` param. - - 'document_id_and_context': The answer is only considered correct if its document ID and its context match as well. - The default value is 'any'. - In Question Answering, to enforce that the retrieved document is considered correct whenever the answer is correct, set `document_scope` to 'answer' or 'document_id_or_answer'. - """ - node_df = self.node_results[node] - node_df = self._filter_eval_mode(node_df, eval_mode) - - answers = node_df[node_df["type"] == "answer"] - if len(answers) > 0: - metrics_df = self._build_answer_metrics_df( - answers, - simulated_top_k_reader=simulated_top_k_reader, - simulated_top_k_retriever=simulated_top_k_retriever, - answer_scope=answer_scope, - ) - worst_df = metrics_df.sort_values(by=[answer_metric]).head(n) - wrong_examples = [] - for multilabel_id, metrics in worst_df.iterrows(): - query_answers = answers[answers["multilabel_id"] == multilabel_id] - if answer_metric not in metrics: - logger.warning( - "You specified an answer_metric=%s not available in calculated metrics=%s." - "Skipping collection of worst performing samples.", - answer_metric, - metrics.keys(), - ) - break - if metrics[answer_metric] <= answer_metric_threshold: - query_dict = { - "multilabel_id": query_answers["multilabel_id"].iloc[0], - "query": query_answers["query"].iloc[0], - "filters": query_answers["filters"].iloc[0], - "metrics": metrics.to_dict(), - "answers": query_answers.drop( - ["node", "query", "type", "gold_answers", "gold_offsets_in_documents", "gold_document_ids"], - axis=1, - ).to_dict(orient="records"), - "gold_answers": query_answers["gold_answers"].iloc[0], - "gold_document_ids": query_answers["gold_document_ids"].iloc[0], - } - wrong_examples.append(query_dict) - return wrong_examples - - documents = node_df[node_df["type"] == "document"] - if len(documents) > 0: - document_relevance_criterion = self._get_document_relevance_criterion( - document_scope=document_scope, answer_scope=answer_scope - ) - metrics_df = self._build_document_metrics_df( - documents, - simulated_top_k_retriever=simulated_top_k_retriever, - document_relevance_criterion=document_relevance_criterion, - ) - worst_df = metrics_df.sort_values(by=[document_metric]).head(n) - wrong_examples = [] - for multilabel_id, metrics in worst_df.iterrows(): - if document_metric not in metrics: - logger.warning( - "You specified a document_metric=%s not available in calculated metrics=%s." - "Skipping collection of worst performing samples.", - document_metric, - metrics.keys(), - ) - break - if metrics[document_metric] <= document_metric_threshold: - query_documents = documents[documents["multilabel_id"] == multilabel_id] - query_dict = { - "multilabel_id": query_documents["multilabel_id"].iloc[0], - "query": query_documents["query"].iloc[0], - "filters": query_documents["filters"].iloc[0], - "metrics": metrics.to_dict(), - "documents": query_documents.drop( - ["node", "query", "multilabel_id", "filters", "type", "gold_document_ids", "gold_contexts"], - axis=1, - ).to_dict(orient="records"), - "gold_document_ids": query_documents["gold_document_ids"].iloc[0], - } - wrong_examples.append(query_dict) - return wrong_examples - - return [] - - def _get_document_relevance_criterion( - self, - document_scope: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "document_id_or_answer", - ] = "document_id_or_answer", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - ) -> Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "context_and_answer", - "document_id_and_answer", - "document_id_and_context_and_answer", - "document_id_or_answer", - ]: - """ - Combines document_scope and answer_scope to create the document_relevance_criterion. - """ - answer_scope_to_doc_relevance_crit = { - "context": "context_and_answer", - "document_id": "document_id_and_answer", - "document_id_and_context": "document_id_and_context_and_answer", - } - - document_relevance_criterion: str = document_scope - if document_scope in ["answer", "document_id_or_answer"]: - document_relevance_criterion = answer_scope_to_doc_relevance_crit.get(answer_scope, document_scope) - elif answer_scope in answer_scope_to_doc_relevance_crit.keys(): - logger.warning( - "You specified a non-answer document_scope together with a non-default answer_scope. " - "This may result in inconsistencies between answer and document metrics. " - "To enforce the same definition of correctness for both, document_scope must be one of 'answer', 'document_id_or_answer'." - ) - - return document_relevance_criterion # type: ignore[return-value] - - def _calculate_node_metrics( - self, - df: DataFrame, - simulated_top_k_reader: int = -1, - simulated_top_k_retriever: int = -1, - document_scope: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "document_id_or_answer", - ] = "document_id_or_answer", - eval_mode: str = "integrated", - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - ) -> Dict[str, float]: - df = self._filter_eval_mode(df, eval_mode) - - answer_metrics = self._calculate_answer_metrics( - df, - simulated_top_k_reader=simulated_top_k_reader, - simulated_top_k_retriever=simulated_top_k_retriever, - answer_scope=answer_scope, - ) - - document_relevance_criterion = self._get_document_relevance_criterion( - document_scope=document_scope, answer_scope=answer_scope - ) - document_metrics = self._calculate_document_metrics( - df, - simulated_top_k_retriever=simulated_top_k_retriever, - document_relevance_criterion=document_relevance_criterion, - ) - - return {**answer_metrics, **document_metrics} - - def _filter_eval_mode(self, df: DataFrame, eval_mode: str) -> DataFrame: - if "eval_mode" in df.columns: - df = df[df["eval_mode"] == eval_mode] - else: - logger.warning("eval dataframe has no eval_mode column. eval_mode param will be ignored.") - return df - - def _calculate_answer_metrics( - self, - df: DataFrame, - simulated_top_k_reader: int = -1, - simulated_top_k_retriever: int = -1, - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - ) -> Dict[str, float]: - answers = df[df["type"] == "answer"] - if len(answers) == 0: - return {} - - metrics_df = self._build_answer_metrics_df( - answers, - simulated_top_k_reader=simulated_top_k_reader, - simulated_top_k_retriever=simulated_top_k_retriever, - answer_scope=answer_scope, - ) - num_examples_for_eval = len(answers["multilabel_id"].unique()) - result = {metric: metrics_df[metric].mean().tolist() for metric in metrics_df.columns} - result["num_examples_for_eval"] = float(num_examples_for_eval) # formatter requires float - return result - - def _build_answer_metrics_df( - self, - answers: DataFrame, - simulated_top_k_reader: int = -1, - simulated_top_k_retriever: int = -1, - answer_scope: Literal["any", "context", "document_id", "document_id_and_context"] = "any", - ) -> DataFrame: - """ - Builds a dataframe containing answer metrics (columns) per multilabel (index). - Answer metrics are: - - exact_match (Did the query exactly return any gold answer? -> 1.0 or 0.0) - - f1 (How well does the best matching returned results overlap with any gold answer on token basis?) - - sas if a SAS model has been provided during pipeline.eval() (How semantically similar is the prediction to the gold answers?) - """ - multilabel_ids = answers["multilabel_id"].unique() - # simulate top k retriever - if simulated_top_k_retriever != -1: - documents = self._get_documents_df() - - top_k_documents = documents[documents["rank"] <= simulated_top_k_retriever] - simulated_answers = [] - for multilabel_id in multilabel_ids: - top_k_document_ids = top_k_documents[top_k_documents["multilabel_id"] == multilabel_id][ - "document_id" - ].unique() - query_answers = answers[answers["multilabel_id"] == multilabel_id] - # consider only the answers within simulated_top_k_retriever documents - - simulated_query_answers = query_answers[ - query_answers["document_ids"].apply( - lambda document_ids, top_k_document_ids=top_k_document_ids: all( - document_id in top_k_document_ids for document_id in document_ids - ) - ) - ] - # simulate top k reader - if simulated_top_k_reader != -1: - # consider only the simulated_top_k_reader answers within simulated_query_answers - simulated_query_answers = simulated_query_answers.nsmallest(simulated_top_k_reader, "rank") - simulated_query_answers["rank"] = np.arange(1, len(simulated_query_answers) + 1) - simulated_answers.append(simulated_query_answers) - answers = pd.concat(simulated_answers) - # simulate top k reader - elif simulated_top_k_reader != -1: - answers = answers[answers["rank"] <= simulated_top_k_reader] - - # build metrics df - answer_metrics = ["exact_match", "f1", "sas"] - df_records = [] - - for multilabel_id in multilabel_ids: - query_df = answers[answers["multilabel_id"] == multilabel_id] - metric_to_scoped_col = { - metric: f"{metric}_{answer_scope}_scope" if answer_scope != "any" else metric - for metric in answer_metrics - if metric in query_df.columns - } - query_metrics = { - metric: query_df[col].max() if any(query_df) else 0.0 for metric, col in metric_to_scoped_col.items() - } - df_records.append(query_metrics) - - metrics_df = DataFrame.from_records(df_records, index=multilabel_ids) - return metrics_df - - def _get_documents_df(self): - document_dfs = [ - node_df for node_df in self.node_results.values() if len(node_df[node_df["type"] == "document"]) > 0 - ] - if len(document_dfs) != 1: - raise ValueError("cannot detect retriever dataframe") - documents_df = document_dfs[0] - documents_df = documents_df[documents_df["type"] == "document"] - return documents_df - - def _calculate_document_metrics( - self, - df: DataFrame, - simulated_top_k_retriever: int = -1, - document_relevance_criterion: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "context_and_answer", - "document_id_and_answer", - "document_id_and_context_and_answer", - "document_id_or_answer", - ] = "document_id_or_answer", - ) -> Dict[str, float]: - documents = df[df["type"] == "document"] - if len(documents) == 0: - return {} - - metrics_df = self._build_document_metrics_df( - documents, - simulated_top_k_retriever=simulated_top_k_retriever, - document_relevance_criterion=document_relevance_criterion, - ) - - return {metric: metrics_df[metric].mean().tolist() for metric in metrics_df.columns} - - def _build_document_metrics_df( - self, - documents: DataFrame, - simulated_top_k_retriever: int = -1, - document_relevance_criterion: Literal[ - "document_id", - "context", - "document_id_and_context", - "document_id_or_context", - "answer", - "context_and_answer", - "document_id_and_answer", - "document_id_and_context_and_answer", - "document_id_or_answer", - ] = "document_id_or_answer", - ) -> DataFrame: - """ - Builds a dataframe containing document metrics (columns) per pair of query and gold document ids (index). - Document metrics are: - - mrr (Mean Reciprocal Rank: see https://en.wikipedia.org/wiki/Mean_reciprocal_rank) - - map (Mean Average Precision: see https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)#Mean_average_precision) - - precision (Precision: How many of the returned documents were relevant?) - - recall_multi_hit (Recall according to Information Retrieval definition: How many of the relevant documents were retrieved per query?) - - recall_single_hit (Recall for Question Answering: Did the query return at least one relevant document? -> 1.0 or 0.0) - - :param documents: document eval dataframe - :param simulated_top_k_retriever: simulates top_k param of retriever. - :param document_relevance_criterion: criterion for deciding whether documents are relevant or not. - You can select between: - - 'document_id': Document's id or custom id must match. - Typical use case: Document Retrieval - - 'context': Document's content must match. - Typical use case: Document-independent Passage Retrieval - - 'document_id_and_context': boolean operation `'document_id' AND 'context'`. - Typical use case: Document-specific Passage Retrieval - - 'document_id_or_context': boolean operation `'document_id' OR 'context'`. - Typical use case: Document Retrieval having sparse context labels - - 'answer': Document's content must include the answer. - Typical use case: Question Answering - - 'document_id_or_answer' (default): boolean operation `'document_id' OR 'answer'`. - This is intended to be a proper default value in order to support both main use cases: - - Document Retrieval - - Question Answering - - 'context_and_answer': boolean operation `'context' AND 'answer'`. - Typical use case: Question Answering with context-specific answers (see answer_scope='context') - - 'document_id_and_answer': boolean operation `'document_id' AND 'answer'`. - Typical use case: Question Answering with document-specific answers (see answer_scope='document_id') - - 'document_id_and_context_and_answer': boolean operation `'document_id' AND 'context' and 'answer'`. - Typical use case: Question Answering with document-and-context-specific answers (see answer_scope='document_id_and_context') - Default value is 'document_id_or_answer'. - """ - if simulated_top_k_retriever != -1: - documents = documents[documents["rank"] <= simulated_top_k_retriever] - - # find out which label matched - def find_matched_label_idxs(row) -> List[int]: # pylint: disable=too-many-return-statements - id_matches = [idx for idx, val in enumerate(row["gold_documents_id_match"]) if val == 1.0] - context_matches = [ - idx for idx, val in enumerate(row["gold_contexts_similarity"]) if val > 65.0 - ] # TODO: hardcoded threshold for now, will be param of calculate_metrics - answer_matches = [idx for idx, val in enumerate(row["gold_answers_match"]) if val == 1.0] - if document_relevance_criterion == "document_id": - return id_matches - elif document_relevance_criterion == "context": - return context_matches - elif document_relevance_criterion == "answer": - return answer_matches - elif document_relevance_criterion == "document_id_and_context": - return list(set(id_matches) & set(context_matches)) - elif document_relevance_criterion == "document_id_or_context": - return list(set(id_matches) | set(context_matches)) - elif document_relevance_criterion == "document_id_and_answer": - return list(set(id_matches) & set(answer_matches)) - elif document_relevance_criterion == "document_id_or_answer": - return list(set(id_matches) | set(answer_matches)) - elif document_relevance_criterion == "context_and_answer": - return list(set(context_matches) & set(answer_matches)) - elif document_relevance_criterion == "document_id_and_context_and_answer": - return list(set(id_matches) & set(context_matches) & set(answer_matches)) - else: - raise ValueError(f"document_relevance_criterion '{document_relevance_criterion}' not supported.") - - documents["matched_label_idxs"] = documents.apply(find_matched_label_idxs, axis=1) - - metrics = [] - - for multilabel_id in documents["multilabel_id"].unique(): - query_df = documents[documents["multilabel_id"] == multilabel_id] - - # Note: Metrics are always calculated on document_ids. - # For some document relevance criteria (e.g. context), the gold_document_ids are not enough or not useful at all. - # So, we have to adjust the relevant ids according to the document_relevance_criterion. - relevance_criterion_col = f"{document_relevance_criterion.replace('document_id', 'gold_id')}_match" - relevant_rows = query_df[query_df[relevance_criterion_col] == 1] - - # all labels without no_answers - # we need to match all (except for single hit recall) - gold_document_ids = ( - list(query_df["gold_custom_document_ids"].iloc[0]) - if "gold_custom_document_ids" in query_df - else list(query_df["gold_document_ids"].iloc[0]) - ) - # remove no_answer label - gold_document_ids = [id for id in gold_document_ids if id != "00"] - - num_labels = len(gold_document_ids) - num_matched_labels = len({idx for idxs in relevant_rows["matched_label_idxs"] for idx in idxs}) - num_missing_labels = num_labels - num_matched_labels - - relevance_criterion_ids = list(relevant_rows["document_id"].values) - num_relevants = len(set(relevance_criterion_ids)) + num_missing_labels - - num_retrieved = len(query_df["document_id"]) - num_retrieved_relevants = len(relevant_rows) - rank_retrieved_relevants = relevant_rows["rank"].values - - if num_labels == 0: - # For no_answer queries, we set all metrics to 1.0, to indicate that the retriever cannot improve the pipeline. - # This behavior is different from pytrec_eval, which sets the metrics to 0.0 if there is no relevant document in the evalset. - rr = 1.0 - avg_precision = 1.0 - recall_multi_hit = 1.0 - recall_single_hit = 1.0 - precision = 1.0 - ndcg = 1.0 - elif num_retrieved_relevants == 0: - # Set all metrics to 0.0 if no relevant document has been retrieved to avoid undefined metrics. - rr = 0.0 - avg_precision = 0.0 - recall_multi_hit = 0.0 - recall_single_hit = 0.0 - precision = 0.0 - ndcg = 0.0 - else: - # The previous checks ensure: - # - `num_labels` > 0 - # - `num_retrieved_relevants` > 0 - # - `num_relevants` > 0 (`num_relevants` is always >= `num_labels`) - # - `num_retrieved` > 0 (`num_retrieved` is always >= `num_retrieved_relevants`) - # - `len(rank_retrieved_relevants)` > 0 (`len(rank_retrieved_relevants)` is always == `num_retrieved_relevants`) - avp_retrieved_relevants = [ - len(relevant_rows[relevant_rows["rank"] <= rank]) / rank for rank in rank_retrieved_relevants - ] - avg_precision = np.sum(avp_retrieved_relevants) / num_relevants - recall_multi_hit = num_matched_labels / num_labels - recall_single_hit = 1.0 - precision = num_retrieved_relevants / num_retrieved - rr = 1.0 / rank_retrieved_relevants.min() - dcg = np.sum([1.0 / np.log2(rank + 1) for rank in rank_retrieved_relevants]) - idcg = np.sum([1.0 / np.log2(rank + 1) for rank in range(1, num_relevants + 1)]) - ndcg = dcg / idcg - - metrics.append( - { - "recall_multi_hit": recall_multi_hit, - "recall_single_hit": recall_single_hit, - "precision": precision, - "map": avg_precision, - "mrr": rr, - "ndcg": ndcg, - } - ) - - metrics_df = DataFrame.from_records(metrics, index=documents["multilabel_id"].unique()) - return metrics_df - - def save(self, out_dir: Union[str, Path], **to_csv_kwargs): - """ - Saves the evaluation result. - The result of each node is saved in a separate csv with file name {node_name}.csv to the out_dir folder. - - :param out_dir: Path to the target folder the csvs will be saved. - :param to_csv_kwargs: kwargs to be passed to DataFrame.to_csv(). See https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_csv.html. - This method uses different default values than DataFrame.to_csv() for the following parameters: - index=False, quoting=csv.QUOTE_NONNUMERIC (to avoid problems with \r chars) - """ - out_dir = out_dir if isinstance(out_dir, Path) else Path(out_dir) - logger.info("Saving evaluation results to %s", out_dir) - if not out_dir.exists(): - out_dir.mkdir(parents=True) - for node_name, df in self.node_results.items(): - target_path = out_dir / f"{node_name}.csv" - default_to_csv_kwargs = { - "index": False, - "quoting": csv.QUOTE_NONNUMERIC, # avoids problems with \r chars in texts by enclosing all string values in quotes - } - to_csv_kwargs = {**default_to_csv_kwargs, **to_csv_kwargs} - df.to_csv(target_path, **to_csv_kwargs) - - @classmethod - def load(cls, load_dir: Union[str, Path], **read_csv_kwargs): - """ - Loads the evaluation result from disk. Expects one csv file per node. See save() for further information. - - :param load_dir: The directory containing the csv files. - :param read_csv_kwargs: kwargs to be passed to pd.read_csv(). See https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html. - This method uses different default values than pd.read_csv() for the following parameters: - header=0, converters=CONVERTERS - where CONVERTERS is a dictionary mapping all array typed columns to ast.literal_eval. - """ - load_dir = load_dir if isinstance(load_dir, Path) else Path(load_dir) - csv_files = [file for file in load_dir.iterdir() if file.is_file() and file.suffix == ".csv"] - cols_to_convert = [ - "filters", - "gold_document_ids", - "gold_custom_document_ids", - "gold_contexts", - "gold_answers", - "gold_documents_id_match", - "gold_offsets_in_documents", - "gold_offsets_in_contexts", - "gold_answers_exact_match", - "gold_answers_f1", - "gold_answers_sas", - "gold_answers_match", - "gold_contexts_similarity", - "offsets_in_document", - "offsets_in_context", - "document_ids", - "custom_document_ids", - "gold_document_contents", - ] - - def safe_literal_eval(x: str) -> Any: - if x == "": - return None - return ast.literal_eval(x) - - converters = dict.fromkeys(cols_to_convert, safe_literal_eval) - default_read_csv_kwargs = {"converters": converters, "header": 0} - read_csv_kwargs = {**default_read_csv_kwargs, **read_csv_kwargs} - node_results = {file.stem: pd.read_csv(file, **read_csv_kwargs) for file in csv_files} - # backward compatibility mappings - for df in node_results.values(): - df.replace(to_replace=np.nan, value=None, inplace=True) - df.rename(columns={"gold_document_contents": "gold_contexts", "content": "context"}, inplace=True) - # convert single document_id to list - if "answer" in df.columns and "document_id" in df.columns and not "document_ids" in df.columns: - df["document_ids"] = df["document_id"].apply(lambda x: [x] if x not in [None, "None"] else []) - df.drop(columns=["document_id"], inplace=True) - if ( - "answer" in df.columns - and "custom_document_id" in df.columns - and not "custom_document_ids" in df.columns - ): - df["custom_document_ids"] = df["custom_document_id"].apply( - lambda x: [x] if x not in [None, "None"] else [] - ) - df.drop(columns=["custom_document_id"], inplace=True) - result = cls(node_results) - return result diff --git a/haystack/silenceable_tqdm.py b/haystack/silenceable_tqdm.py deleted file mode 100644 index 7d0c552138..0000000000 --- a/haystack/silenceable_tqdm.py +++ /dev/null @@ -1,40 +0,0 @@ -import os -import tqdm - - -class SilenceableTqdm(tqdm.tqdm): - """ - Wrapper for tqdm that disables all progress bars if HAYSTACK_PROGRESS_BARS is set to a falsey value - ("0", "False", "FALSE", "false"). - - Note: this check is done every time a tqdm iterator is initialized, so normally for each method run. Therefore - progress bars can be enabled and disabled at runtime, but not during a specific iteration. - """ - - def __init__(self, *args, **kwargs): - """ - Passes `disable=True` to tqdm if `self.no_progress_bars` is set to True. - """ - if self.no_progress_bars: - kwargs["disable"] = True - - super().__init__(*args, **kwargs) - - @property - def no_progress_bars(self): - """ - Reads the HAYSTACK_PROGRESS_BARS env var to check if the progress bars should be disabled. - """ - return os.getenv("HAYSTACK_PROGRESS_BARS", "1") in ["0", "False", "FALSE", "false"] - - @property - def disable(self): - return self.no_progress_bars or self._disable - - @disable.setter - def disable(self, value): - self._disable = value - - -tqdm.std.tqdm = SilenceableTqdm -tqdm.tqdm = SilenceableTqdm diff --git a/haystack/telemetry.py b/haystack/telemetry.py deleted file mode 100644 index db4c0f7167..0000000000 --- a/haystack/telemetry.py +++ /dev/null @@ -1,223 +0,0 @@ -import os -from typing import Any, Dict, Optional, List, Union -import uuid -import logging -from pathlib import Path -import json - -import yaml -import posthog - -from haystack.environment import collect_static_system_specs, collect_dynamic_system_specs - -HAYSTACK_TELEMETRY_ENABLED = "HAYSTACK_TELEMETRY_ENABLED" -HAYSTACK_EXECUTION_CONTEXT = "HAYSTACK_EXECUTION_CONTEXT" -HAYSTACK_DOCKER_CONTAINER = "HAYSTACK_DOCKER_CONTAINER" -CONFIG_PATH = Path("~/.haystack/config.yaml").expanduser() -SEND_EVENT_EVERY_N_RUNS = 100 - - -logger = logging.getLogger(__name__) - - -class Telemetry: - """ - Haystack reports anonymous usage statistics to support continuous software improvements for all its users. - - You can opt-out of sharing usage statistics by manually setting the environment - variable `HAYSTACK_TELEMETRY_ENABLED` as described for different operating systems on the - [documentation page](https://docs.haystack.deepset.ai/docs/telemetry#how-can-i-opt-out). - - Check out the documentation for more details: [Telemetry](https://docs.haystack.deepset.ai/docs/telemetry). - """ - - def __init__(self): - """ - Initializes the telemetry. Loads the user_id from the config file, - or creates a new id and saves it if the file is not found. - - It also collects system information which cannot change across the lifecycle - of the process (for example `is_containerized()`). - """ - posthog.api_key = "phc_C44vUK9R1J6HYVdfJarTEPqVAoRPJzMXzFcj8PIrJgP" - posthog.host = "https://eu.posthog.com" - - # disable posthog logging - for module_name in ["posthog", "backoff"]: - logging.getLogger(module_name).setLevel(logging.CRITICAL) - # Prevent module from sending errors to stderr when an exception is encountered during an emit() call - logging.getLogger(module_name).addHandler(logging.NullHandler()) - logging.getLogger(module_name).propagate = False - - self.user_id = None - - if CONFIG_PATH.exists(): - # Load the config file - try: - with open(CONFIG_PATH, "r", encoding="utf-8") as config_file: - config = yaml.safe_load(config_file) - if "user_id" in config: - self.user_id = config["user_id"] - except Exception as e: - logger.debug("Telemetry could not read the config file %s", CONFIG_PATH, exc_info=e) - else: - # Create the config file - logger.info( - "Haystack sends anonymous usage data to understand the actual usage and steer dev efforts " - "towards features that are most meaningful to users. You can opt-out at anytime by manually " - "setting the environment variable HAYSTACK_TELEMETRY_ENABLED as described for different " - "operating systems in the [documentation page](https://docs.haystack.deepset.ai/docs/telemetry#how-can-i-opt-out). " - "More information at [Telemetry](https://docs.haystack.deepset.ai/docs/telemetry)." - ) - CONFIG_PATH.parents[0].mkdir(parents=True, exist_ok=True) - self.user_id = str(uuid.uuid4()) - try: - with open(CONFIG_PATH, "w") as outfile: - yaml.dump({"user_id": self.user_id}, outfile, default_flow_style=False) - except Exception as e: - logger.debug("Telemetry could not write config file to %s", CONFIG_PATH, exc_info=e) - - self.event_properties = collect_static_system_specs() - - def send_event(self, event_name: str, event_properties: Optional[Dict[str, Any]] = None): - """ - Sends a telemetry event. - - :param event_name: The name of the event to show in PostHog. - :param event_properties: Additional event metadata. These are merged with the - system metadata collected in __init__, so take care not to overwrite them. - """ - event_properties = event_properties or {} - dynamic_specs = collect_dynamic_system_specs() - try: - posthog.capture( - distinct_id=self.user_id, - event=event_name, - # loads/dumps to sort the keys - properties=json.loads( - json.dumps({**self.event_properties, **dynamic_specs, **event_properties}, sort_keys=True) - ), - ) - except Exception as e: - logger.debug("Telemetry couldn't make a POST request to PostHog.", exc_info=e) - - -def tutorial_running(tutorial_id: int): - """ - Can be called when a tutorial is executed so that the tutorial_id is used to identify the tutorial and send an event. - :param tutorial_id: ID number of the tutorial - """ - send_event(event_name="Tutorial", event_properties={"tutorial.id": tutorial_id}) - - -def send_pipeline_event( # type: ignore - pipeline: "Pipeline", # type: ignore - query: Optional[str] = None, - queries: Optional[List[str]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union["MultiLabel", List["MultiLabel"]]] = None, # type: ignore - documents: Optional[Union[List["Document"], List[List["Document"]]]] = None, # type: ignore - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, -): - """ - Sends a telemetry event about the execution of a pipeline, if telemetry is enabled. - - :param pipeline: the pipeline that is running - :param query: the value of the `query` input of the pipeline, if any - :param queries: the value of the `queries` input of the pipeline, if any - :param file_paths: the value of the `file_paths` input of the pipeline, if any - :param labels: the value of the `labels` input of the pipeline, if any - :param documents: the value of the `documents` input of the pipeline, if any - :param meta: the value of the `meta` input of the pipeline, if any - :param params: the value of the `params` input of the pipeline, if any - :param debug: the value of the `debug` input of the pipeline, if any - """ - try: - if telemetry: - # Check if it's the public demo - exec_context = os.environ.get(HAYSTACK_EXECUTION_CONTEXT, "") - if exec_context == "public_demo": - event_properties: Dict[str, Optional[Union[str, bool, int, Dict[str, Any]]]] = { - "pipeline.is_public_demo": True, - "pipeline.run_parameters.query": query, - "pipeline.run_parameters.params": params, - } - telemetry.send_event(event_name="Public Demo", event_properties=event_properties) - return - - # If pipeline config has not changed, send an event every SEND_EVENT_EVERY_N_RUNS runs - if pipeline.last_config_hash == pipeline.config_hash and pipeline.runs % SEND_EVENT_EVERY_N_RUNS == 0: - event_properties = {"pipeline.config_hash": pipeline.config_hash, "pipeline.runs": pipeline.runs} - telemetry.send_event(event_name="Pipeline", event_properties=event_properties) - return - pipeline.last_config_hash = pipeline.config_hash - pipeline.runs = 1 - - event_properties = { - "pipeline.classname": pipeline.__class__.__name__, - "pipeline.config_hash": pipeline.config_hash, - "pipeline.runs": pipeline.runs, - } - - # Add document store - docstore = pipeline.get_document_store() - if docstore: - event_properties["pipeline.document_store"] = docstore.__class__.__name__ - - # Add an entry for each node class and classify the pipeline by its root node - for node in pipeline.graph.nodes: - node_type = pipeline.graph.nodes.get(node)["component"].__class__.__name__ - if node_type == "RootNode": - event_properties["pipeline.type"] = node - else: - event_properties["pipeline.nodes." + node_type] = ( - event_properties.get("pipeline.nodes." + node_type, 0) + 1 # type: ignore - ) - - # Inputs of the run() or run_batch() call - if isinstance(labels, list): - labels_len = len(labels) - else: - labels_len = 1 if labels else 0 - if documents and isinstance(documents, list) and isinstance(documents[0], list): - documents_len = [len(docs) if isinstance(docs, list) else 0 for docs in documents] - elif isinstance(documents, list): - documents_len = [len(documents)] - else: - documents_len = [0] - if meta and isinstance(meta, list): - meta_len = len(meta) - else: - meta_len = 1 - event_properties["pipeline.run_parameters.queries"] = len(queries) if queries else bool(query) - event_properties["pipeline.run_parameters.file_paths"] = len(file_paths or []) - event_properties["pipeline.run_parameters.labels"] = labels_len - event_properties["pipeline.run_parameters.documents"] = documents_len # type: ignore - event_properties["pipeline.run_parameters.meta"] = meta_len - event_properties["pipeline.run_parameters.params"] = bool(params) - event_properties["pipeline.run_parameters.debug"] = bool(debug) - - telemetry.send_event(event_name="Pipeline", event_properties=event_properties) - except Exception as e: - # Never let telemetry break things - logger.debug("There was an issue sending a 'Pipeline' telemetry event", exc_info=e) - - -def send_event(event_name: str, event_properties: Optional[Dict[str, Any]] = None): - """ - Send a telemetry event, if telemetry is enabled. - """ - try: - if telemetry: - telemetry.send_event(event_name=event_name, event_properties=event_properties) - except Exception as e: - # Never let telemetry break things - logger.debug("There was an issue sending a '%s' telemetry event", event_name, exc_info=e) - - -if os.environ.get("HAYSTACK_TELEMETRY_ENABLED", "True") == "False": - telemetry = None # type: ignore -else: - telemetry = Telemetry() diff --git a/haystack/testing/__init__.py b/haystack/testing/__init__.py deleted file mode 100644 index 4bbf2c4040..0000000000 --- a/haystack/testing/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .document_store import DocumentStoreBaseTestAbstract diff --git a/haystack/testing/document_store.py b/haystack/testing/document_store.py deleted file mode 100644 index 9e2f2ad928..0000000000 --- a/haystack/testing/document_store.py +++ /dev/null @@ -1,567 +0,0 @@ -# pylint: disable=too-many-public-methods -import sys - -import pytest -import numpy as np - -from haystack.schema import Document, Label, Answer, Span -from haystack.errors import DuplicateDocumentError -from haystack.document_stores import BaseDocumentStore - - -@pytest.mark.document_store -class DocumentStoreBaseTestAbstract: - """ - This is a base class to test abstract methods from DocumentStoreBase to be inherited by any Document Store - testsuite. It doesn't have the `Test` prefix in the name so that its methods won't be collected for this - class but only for its subclasses. - """ - - @pytest.fixture - def documents(self): - documents = [] - for i in range(3): - documents.append( - Document( - content=f"A Foo Document {i}", - meta={"name": f"name_{i}", "year": "2020", "month": "01", "numbers": [2, 4]}, - embedding=np.random.rand(768).astype(np.float32), - ) - ) - - documents.append( - Document( - content=f"A Bar Document {i}", - meta={"name": f"name_{i}", "year": "2021", "month": "02", "numbers": [-2, -4]}, - embedding=np.random.rand(768).astype(np.float32), - ) - ) - - documents.append( - Document( - content=f"Document {i} without embeddings", - meta={"name": f"name_{i}", "no_embedding": True, "month": "03"}, - ) - ) - - return documents - - @pytest.fixture - def labels(self, documents): - labels = [] - for i, d in enumerate(documents): - labels.append( - Label( - query=f"query_{i}", - document=d, - is_correct_document=True, - is_correct_answer=False, - # create a mix set of labels - origin="user-feedback" if i % 2 else "gold-label", - answer=None if not i else Answer(f"the answer is {i}", document_ids=[d.id]), - meta={"name": f"label_{i}", "year": f"{2020 + i}"}, - ) - ) - return labels - - # - # Integration tests - # - - @pytest.mark.integration - def test_write_documents(self, ds, documents): - ds.write_documents(documents) - docs = ds.get_all_documents() - assert len(docs) == len(documents) - expected_ids = {doc.id for doc in documents} - ids = {doc.id for doc in docs} - assert ids == expected_ids - - @pytest.mark.integration - def test_write_labels(self, ds, labels): - ds.write_labels(labels) - assert ds.get_all_labels() == labels - - @pytest.mark.integration - def test_write_with_duplicate_doc_ids(self, ds): - duplicate_documents = [ - Document(content="Doc1", id_hash_keys=["content"], meta={"key1": "value1"}), - Document(content="Doc1", id_hash_keys=["content"], meta={"key1": "value1"}), - ] - ds.write_documents(duplicate_documents, duplicate_documents="skip") - results = ds.get_all_documents() - assert len(results) == 1 - assert results[0] == duplicate_documents[0] - with pytest.raises(Exception): - ds.write_documents(duplicate_documents, duplicate_documents="fail") - - @pytest.mark.integration - def test_get_embedding_count(self, ds, documents): - """ - We expect 6 docs with embeddings because only 6 documents in the documents fixture for this class contain - embeddings. - """ - ds.write_documents(documents) - assert ds.get_embedding_count() == 6 - - @pytest.mark.skip - @pytest.mark.integration - def test_get_all_documents_without_filters(self, ds, documents): - ds.write_documents(documents) - out = ds.get_all_documents() - assert out == documents - - @pytest.mark.integration - def test_get_all_documents_without_embeddings(self, ds, documents): - ds.write_documents(documents) - out = ds.get_all_documents(return_embedding=False) - for doc in out: - assert doc.embedding is None - - @pytest.mark.integration - def test_get_all_document_filter_duplicate_text_value(self, ds): - documents = [ - Document(content="duplicated", meta={"meta_field": "0"}, id_hash_keys=["meta"]), - Document(content="duplicated", meta={"meta_field": "1", "name": "file.txt"}, id_hash_keys=["meta"]), - Document(content="Doc2", meta={"name": "file_2.txt"}, id_hash_keys=["meta"]), - ] - ds.write_documents(documents) - documents = ds.get_all_documents(filters={"meta_field": ["1"]}) - assert len(documents) == 1 - assert documents[0].content == "duplicated" - assert documents[0].meta["name"] == "file.txt" - - documents = ds.get_all_documents(filters={"meta_field": ["0"]}) - assert len(documents) == 1 - assert documents[0].content == "duplicated" - assert documents[0].meta.get("name") is None - - documents = ds.get_all_documents(filters={"name": ["file_2.txt"]}) - assert len(documents) == 1 - assert documents[0].content == "Doc2" - assert documents[0].meta.get("meta_field") is None - - @pytest.mark.integration - def test_get_all_documents_with_correct_filters(self, ds, documents): - ds.write_documents(documents) - result = ds.get_all_documents(filters={"year": ["2020"]}) - assert len(result) == 3 - - documents = ds.get_all_documents(filters={"year": ["2020", "2021"]}) - assert len(documents) == 6 - - @pytest.mark.integration - def test_get_all_documents_with_incorrect_filter_name(self, ds, documents): - ds.write_documents(documents) - result = ds.get_all_documents(filters={"non_existing_meta_field": ["whatever"]}) - assert len(result) == 0 - - @pytest.mark.integration - def test_get_all_documents_with_incorrect_filter_value(self, ds, documents): - ds.write_documents(documents) - result = ds.get_all_documents(filters={"year": ["nope"]}) - assert len(result) == 0 - - @pytest.mark.integration - def test_eq_filters(self, ds, documents): - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$eq": "2020"}}) - assert len(result) == 3 - result = ds.get_all_documents(filters={"year": "2020"}) - assert len(result) == 3 - - @pytest.mark.integration - def test_in_filters(self, ds, documents): - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$in": ["2020", "2021", "n.a."]}}) - assert len(result) == 6 - result = ds.get_all_documents(filters={"year": ["2020", "2021", "n.a."]}) - assert len(result) == 6 - - @pytest.mark.integration - def test_ne_filters(self, ds, documents): - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$ne": "2020"}}) - assert len(result) == 6 - - @pytest.mark.integration - def test_nin_filters(self, ds, documents): - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$nin": ["2020", "2021", "n.a."]}}) - assert len(result) == 3 - - @pytest.mark.integration - def test_comparison_filters(self, ds, documents): - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"numbers": {"$gt": 0.0}}) - assert len(result) == 3 - - result = ds.get_all_documents(filters={"numbers": {"$gte": -2.0}}) - assert len(result) == 6 - - result = ds.get_all_documents(filters={"numbers": {"$lt": 0.0}}) - assert len(result) == 3 - - result = ds.get_all_documents(filters={"numbers": {"$lte": 2.0}}) - assert len(result) == 6 - - @pytest.mark.integration - def test_compound_filters(self, ds, documents): - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$lte": "2021", "$gte": "2020"}}) - assert len(result) == 6 - - @pytest.mark.integration - def test_simplified_filters(self, ds, documents): - ds.write_documents(documents) - - filters = {"$and": {"year": {"$lte": "2021", "$gte": "2020"}, "name": {"$in": ["name_0", "name_1"]}}} - result = ds.get_all_documents(filters=filters) - assert len(result) == 4 - - filters_simplified = {"year": {"$lte": "2021", "$gte": "2020"}, "name": ["name_0", "name_1"]} - result = ds.get_all_documents(filters=filters_simplified) - assert len(result) == 4 - - @pytest.mark.integration - def test_nested_condition_filters(self, ds, documents): - ds.write_documents(documents) - filters = { - "$and": { - "year": {"$lte": "2021", "$gte": "2020"}, - "$or": {"name": {"$in": ["name_0", "name_1"]}, "numbers": {"$lt": 5.0}}, - } - } - result = ds.get_all_documents(filters=filters) - assert len(result) == 6 - - filters_simplified = { - "year": {"$lte": "2021", "$gte": "2020"}, - "$or": {"name": {"$in": ["name_0", "name_2"]}, "numbers": {"$lt": 5.0}}, - } - result = ds.get_all_documents(filters=filters_simplified) - assert len(result) == 6 - - filters = { - "$and": { - "year": {"$lte": "2021", "$gte": "2020"}, - "$or": { - "name": {"$in": ["name_0", "name_1"]}, - "$and": {"numbers": {"$lt": 5.0}, "$not": {"month": {"$eq": "01"}}}, - }, - } - } - result = ds.get_all_documents(filters=filters) - assert len(result) == 5 - - filters_simplified = { - "year": {"$lte": "2021", "$gte": "2020"}, - "$or": {"name": ["name_0", "name_1"], "$and": {"numbers": {"$lt": 5.0}, "$not": {"month": {"$eq": "01"}}}}, - } - result = ds.get_all_documents(filters=filters_simplified) - assert len(result) == 5 - - @pytest.mark.integration - def test_nested_condition_not_filters(self, ds, documents): - """ - Test nested logical operations within "$not", important as we apply De Morgan's laws in WeaviateDocumentstore - """ - ds.write_documents(documents) - filters = { - "$not": { - "$or": { - "$and": {"numbers": {"$lt": 5.0}, "month": {"$ne": "01"}}, - "$not": {"year": {"$lte": "2021", "$gte": "2020"}}, - } - } - } - result = ds.get_all_documents(filters=filters) - assert len(result) == 3 - - docs_meta = result[0].meta["numbers"] - assert [2, 4] == docs_meta - - # Test same logical operator twice on same level - - filters = { - "$or": [ - {"$and": {"name": {"$in": ["name_0", "name_1"]}, "year": {"$gte": "2020"}}}, - {"$and": {"name": {"$in": ["name_0", "name_1"]}, "year": {"$lt": "2021"}}}, - ] - } - result = ds.get_all_documents(filters=filters) - docs_meta = [doc.meta["name"] for doc in result] - assert len(result) == 4 - assert "name_0" in docs_meta - assert "name_2" not in docs_meta - - @pytest.mark.integration - def test_get_document_by_id(self, ds, documents): - ds.write_documents(documents) - doc = ds.get_document_by_id(documents[0].id) - assert doc.id == documents[0].id - assert doc.content == documents[0].content - - @pytest.mark.integration - def test_get_documents_by_id(self, ds, documents): - ds.write_documents(documents) - ids = [doc.id for doc in documents] - result = {doc.id for doc in ds.get_documents_by_id(ids, batch_size=2)} - assert set(ids) == result - - @pytest.mark.integration - def test_get_document_count(self, ds, documents): - ds.write_documents(documents) - assert ds.get_document_count() == len(documents) - assert ds.get_document_count(filters={"year": ["2020"]}) == 3 - assert ds.get_document_count(filters={"month": ["02"]}) == 3 - - @pytest.mark.integration - def test_get_all_documents_generator(self, ds, documents): - ds.write_documents(documents) - assert len(list(ds.get_all_documents_generator(batch_size=2))) == 9 - - @pytest.mark.integration - def test_duplicate_documents_skip(self, ds, documents): - ds.write_documents(documents) - - updated_docs = [] - for d in documents: - updated_d = Document.from_dict(d.to_dict()) - updated_d.meta["name"] = "Updated" - updated_docs.append(updated_d) - - ds.write_documents(updated_docs, duplicate_documents="skip") - for d in ds.get_all_documents(): - assert d.meta.get("name") != "Updated" - - @pytest.mark.integration - def test_duplicate_documents_overwrite(self, ds, documents): - ds.write_documents(documents) - - updated_docs = [] - for d in documents: - updated_d = Document.from_dict(d.to_dict()) - updated_d.meta["name"] = "Updated" - updated_docs.append(updated_d) - - ds.write_documents(updated_docs, duplicate_documents="overwrite") - for doc in ds.get_all_documents(): - assert doc.meta["name"] == "Updated" - - @pytest.mark.integration - def test_duplicate_documents_fail(self, ds, documents): - ds.write_documents(documents) - - updated_docs = [] - for d in documents: - updated_d = Document.from_dict(d.to_dict()) - updated_d.meta["name"] = "Updated" - updated_docs.append(updated_d) - - with pytest.raises(DuplicateDocumentError): - ds.write_documents(updated_docs, duplicate_documents="fail") - - @pytest.mark.integration - def test_write_document_meta(self, ds): - ds.write_documents( - [ - {"content": "dict_without_meta", "id": "1"}, - {"content": "dict_with_meta", "meta_field": "test2", "id": "2"}, - Document(content="document_object_without_meta", id="3"), - Document(content="document_object_with_meta", meta={"meta_field": "test4"}, id="4"), - ] - ) - assert not ds.get_document_by_id("1").meta - assert ds.get_document_by_id("2").meta["meta_field"] == "test2" - assert not ds.get_document_by_id("3").meta - assert ds.get_document_by_id("4").meta["meta_field"] == "test4" - - @pytest.mark.integration - def test_delete_documents(self, ds, documents): - ds.write_documents(documents) - ds.delete_documents() - assert ds.get_document_count() == 0 - - @pytest.mark.integration - def test_delete_documents_with_filters(self, ds, documents): - ds.write_documents(documents) - ds.delete_documents(filters={"year": ["2020", "2021"]}) - documents = ds.get_all_documents() - assert ds.get_document_count() == 3 - - @pytest.mark.integration - def test_delete_documents_by_id(self, ds, documents): - ds.write_documents(documents) - docs_to_delete = ds.get_all_documents(filters={"year": ["2020"]}) - ds.delete_documents(ids=[doc.id for doc in docs_to_delete]) - assert ds.get_document_count() == 6 - - @pytest.mark.integration - def test_delete_documents_by_id_with_filters(self, ds, documents): - ds.write_documents(documents) - docs_to_delete = ds.get_all_documents(filters={"year": ["2020"]}) - # this should delete only 1 document out of the 3 ids passed - ds.delete_documents(ids=[doc.id for doc in docs_to_delete], filters={"name": ["name_0"]}) - assert ds.get_document_count() == 8 - - @pytest.mark.integration - def test_write_get_all_labels(self, ds, labels): - ds.write_labels(labels) - ds.write_labels(labels[:3], index="custom_index") - assert len(ds.get_all_labels()) == 9 - assert len(ds.get_all_labels(index="custom_index")) == 3 - # remove the index we created in this test - ds.delete_index("custom_index") - - @pytest.mark.integration - def test_delete_labels(self, ds, labels): - ds.write_labels(labels) - ds.write_labels(labels[:3], index="custom_index") - ds.delete_labels() - ds.delete_labels(index="custom_index") - assert len(ds.get_all_labels()) == 0 - assert len(ds.get_all_labels(index="custom_index")) == 0 - # remove the index we created in this test - ds.delete_index("custom_index") - - @pytest.mark.integration - def test_write_labels_duplicate(self, ds, labels): - # create a duplicate - dupe = Label.from_dict(labels[0].to_dict()) - - ds.write_labels(labels + [dupe]) - - # ensure the duplicate was discarded - assert len(ds.get_all_labels()) == len(labels) - - @pytest.mark.integration - def test_delete_labels_by_id(self, ds, labels): - ds.write_labels(labels) - ds.delete_labels(ids=[labels[0].id]) - assert len(ds.get_all_labels()) == len(labels) - 1 - - @pytest.mark.integration - def test_delete_labels_by_filter(self, ds, labels): - ds.write_labels(labels) - ds.delete_labels(filters={"query": "query_1"}) - assert len(ds.get_all_labels()) == len(labels) - 1 - - @pytest.mark.integration - def test_delete_labels_by_filter_id(self, ds, labels): - ds.write_labels(labels) - - # ids and filters are ANDed, the following should have no effect - ds.delete_labels(ids=[labels[0].id], filters={"query": "query_9"}) - assert len(ds.get_all_labels()) == len(labels) - - # - ds.delete_labels(ids=[labels[0].id], filters={"query": "query_0"}) - assert len(ds.get_all_labels()) == len(labels) - 1 - - @pytest.mark.integration - def test_get_label_count(self, ds, labels): - ds.write_labels(labels) - assert ds.get_label_count() == len(labels) - - @pytest.mark.integration - def test_delete_index(self, ds, documents): - ds.write_documents(documents, index="custom_index") - assert ds.get_document_count(index="custom_index") == len(documents) - ds.delete_index(index="custom_index") - with pytest.raises(Exception): - ds.get_document_count(index="custom_index") - - @pytest.mark.integration - def test_delete_index_does_not_raise_if_not_exists(self, ds): - ds.delete_index(index="unknown_index") - - @pytest.mark.integration - def test_update_meta(self, ds, documents): - ds.write_documents(documents) - doc = documents[0] - ds.update_document_meta(doc.id, meta={"year": "2099", "month": "12"}) - doc = ds.get_document_by_id(doc.id) - assert doc.meta["year"] == "2099" - assert doc.meta["month"] == "12" - - @pytest.mark.integration - def test_labels_with_long_texts(self, ds, documents): - label = Label( - query="question1", - answer=Answer( - answer="answer", - type="extractive", - score=0.0, - context="something " * 10_000, - offsets_in_document=[Span(start=12, end=14)], - offsets_in_context=[Span(start=12, end=14)], - ), - is_correct_answer=True, - is_correct_document=True, - document=Document(content="something " * 10_000, id="123"), - origin="gold-label", - ) - ds.write_labels(labels=[label]) - labels = ds.get_all_labels() - assert len(labels) == 1 - assert label == labels[0] - - @pytest.mark.integration - @pytest.mark.skipif(sys.platform == "win32", reason="_get_documents_meta() fails with 'too many SQL variables'") - def test_get_all_documents_large_quantities(self, ds): - # Test to exclude situations like Weaviate not returning more than 100 docs by default - # https://github.com/deepset-ai/haystack/issues/1893 - docs_to_write = [ - {"meta": {"name": f"name_{i}"}, "content": f"text_{i}", "embedding": np.random.rand(768).astype(np.float32)} - for i in range(1000) - ] - ds.write_documents(docs_to_write) - documents = ds.get_all_documents() - assert all(isinstance(d, Document) for d in documents) - assert len(documents) == len(docs_to_write) - - @pytest.mark.integration - def test_custom_embedding_field(self, ds): - ds.embedding_field = "custom_embedding_field" - doc_to_write = {"content": "test", "custom_embedding_field": np.random.rand(768).astype(np.float32)} - ds.write_documents([doc_to_write]) - documents = ds.get_all_documents(return_embedding=True) - assert len(documents) == 1 - assert documents[0].content == "test" - # Some document stores normalize the embedding on save, let's just compare the length - assert doc_to_write["custom_embedding_field"].shape == documents[0].embedding.shape - - @pytest.mark.skip(reason="This currently fails for Weaviate and Pinecone") - @pytest.mark.integration - @pytest.mark.parametrize("batch_size", [None, 20]) - def test_add_eval_data(self, ds, batch_size, samples_path): - # add eval data (SQUAD format) - ds.add_eval_data( - filename=samples_path / "squad" / "small.json", - doc_index=ds.index, - label_index=ds.label_index, - batch_size=batch_size, - ) - assert ds.get_document_count() == 87 - assert ds.get_label_count() == 1214 - - # - # Unit tests - # - - @pytest.mark.unit - def test_normalize_embeddings_diff_shapes(self): - VEC_1 = np.array([0.1, 0.2, 0.3], dtype="float32") - BaseDocumentStore.normalize_embedding(VEC_1) - assert np.linalg.norm(VEC_1) - 1 < 0.01 - - VEC_1 = np.array([0.1, 0.2, 0.3], dtype="float32").reshape(1, -1) - BaseDocumentStore.normalize_embedding(VEC_1) - assert np.linalg.norm(VEC_1) - 1 < 0.01 diff --git a/haystack/utils/__init__.py b/haystack/utils/__init__.py deleted file mode 100644 index 15a9794082..0000000000 --- a/haystack/utils/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -from haystack.utils.reflection import args_to_kwargs -from haystack.utils.requests_utils import request_with_retry -from haystack.utils.preprocessing import convert_files_to_docs, tika_convert_files_to_docs -from haystack.utils.import_utils import fetch_archive_from_http -from haystack.utils.cleaning import clean_wiki_text -from haystack.utils.doc_store import launch_es, launch_opensearch, launch_weaviate, stop_opensearch, stop_service -from haystack.utils.deepsetcloud import DeepsetCloud, DeepsetCloudError, DeepsetCloudExperiments -from haystack.utils.export_utils import ( - print_answers, - print_documents, - print_questions, - export_answers_to_csv, - convert_labels_to_squad, -) -from haystack.utils.squad_data import SquadData -from haystack.utils.context_matching import calculate_context_similarity, match_context, match_contexts -from haystack.utils.experiment_tracking import ( - Tracker, - NoTrackingHead, - BaseTrackingHead, - MLflowTrackingHead, - StdoutTrackingHead, -) -from haystack.utils.early_stopping import EarlyStopping -from haystack.utils.labels import aggregate_labels -from haystack.utils.batching import get_batches_from_generator -from haystack.utils.getting_started import build_pipeline, add_example_data diff --git a/haystack/utils/augment_squad.py b/haystack/utils/augment_squad.py deleted file mode 100644 index 98fb892ef9..0000000000 --- a/haystack/utils/augment_squad.py +++ /dev/null @@ -1,312 +0,0 @@ -""" -Script to perform data augmentation on a SQuAD like dataset to increase training data. -It follows the approach oultined in the TinyBERT paper: https://arxiv.org/pdf/1909.10351.pdf. -It takes a SQuAD like dataset as input and writes the augmented dataset to a new file in the same format. -There are no answer labels in the augmented dataset and every question is marked impossible. -This isn't a problem for distillation. However, this means that the augmented dataset is not suitable for training -a model on its own. -Usage: - python augment_squad.py --squad_path --output_path \ - --multiplication_factor --word_possibilities \ - --replace_probability --glove_path \ - --batch_size --device --tokenizer --model -Arguments: - squad_path: Path to the input dataset. Must have the same structure as the official squad json. - output_path: Path to the output dataset. - multiplication_factor: Number of times to augment the dataset. - word_possibilities: Number of possible words to replace a word with. - replace_probability: Probability of replacing a word with a different word. - glove_path: Path to the GloVe vectors. If it does not exist, it will be downloaded. - batch_size: Batch size for MLM model. - device: Device to use for MLM model. Usually either "cpu:0" or "cuda:0". - tokenizer: Huggingface tokenizer identifier. - model: Huggingface MLM model identifier. -""" - -from typing import Tuple, List, Union - -import json -import random -import argparse -import logging -from pathlib import Path -from zipfile import ZipFile -from copy import copy, deepcopy - -import torch -from torch.nn import functional as F -from transformers import AutoModelForMaskedLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizerBase -import requests -import numpy as np -from tqdm import tqdm - - -logger = logging.getLogger(__name__) - - -def load_glove( - glove_path: Path = Path("glove.txt"), - vocab_size: int = 100_000, - device: Union[str, torch.device] = torch.device("cpu:0"), - timeout: Union[float, Tuple[float, float]] = 10.0, -) -> Tuple[dict, dict, torch.Tensor]: - """ - Loads the GloVe vectors and returns a mapping from words to their GloVe vector indices and the other way around. - :param timeout: How many seconds to wait for the server to send data before giving up, - as a float, or a :ref:`(connect timeout, read timeout) ` tuple. - Defaults to 10 seconds. - """ - - if not glove_path.exists(): # download and extract glove if necessary - logger.info("Provided glove file not found. Downloading it instead.") - glove_path.parent.mkdir(parents=True, exist_ok=True) - zip_path = glove_path.parent / (glove_path.name + ".zip") - request = requests.get( - "https://nlp.stanford.edu/data/glove.42B.300d.zip", allow_redirects=True, timeout=timeout - ) - with zip_path.open("wb") as downloaded_file: - downloaded_file.write(request.content) - with ZipFile(zip_path, "r") as zip_file: - glove_file = zip_file.namelist()[0] - with glove_path.open("wb") as g: - g.write(zip_file.read(glove_file)) - - word_id_mapping = {} - id_word_mapping = {} - vector_list = [] - with open(glove_path, "r") as f: - for i, line in enumerate(f): - if i == vocab_size: # limit vocab size - break - split = line.split() - word_id_mapping[split[0]] = i - id_word_mapping[i] = split[0] - vector_list.append(torch.tensor([float(x) for x in split[1:]])) - vectors = torch.stack(vector_list) - with torch.inference_mode(): - vectors = vectors.to(device) - vectors = F.normalize(vectors, dim=1) - return word_id_mapping, id_word_mapping, vectors - - -def tokenize_and_extract_words(text: str, tokenizer: PreTrainedTokenizerBase) -> Tuple[torch.Tensor, List[str], dict]: - # tokenizes text and returns, in addition to the tokens, indices and mapping of the words that were not split into subwords - # this is important as MLM is not used for subwords - words = tokenizer.basic_tokenizer.tokenize(text) - - subwords = [tokenizer.wordpiece_tokenizer.tokenize(word) for word in words] - - word_subword_mapping = {} - - j = 0 - for i, subwords_ in enumerate(subwords): - j += len(subwords_) - if j >= 510: # sequence length may not be longer than 512 (1 cls + 510 tokens + 1 sep) - break - if len(subwords_) == 1: - word_subword_mapping[i] = j - - subwords = [subword for subwords_ in subwords for subword in subwords_] # flatten list of lists - - input_ids = tokenizer.convert_tokens_to_ids(subwords[:510]) - input_ids.insert(0, tokenizer.cls_token_id) - input_ids.append(tokenizer.sep_token_id) - - return input_ids, words, word_subword_mapping - - -def get_replacements( - glove_word_id_mapping: dict, - glove_id_word_mapping: dict, - glove_vectors: np.ndarray, - model: PreTrainedModel, - tokenizer: PreTrainedTokenizerBase, - text: str, - word_possibilities: int = 20, - batch_size: int = 16, - device: torch.device = torch.device("cpu:0"), -) -> List[List[str]]: - """Returns a list of possible replacements for each word in the text.""" - input_ids, words, word_subword_mapping = tokenize_and_extract_words(text, tokenizer) - - # masks words which were not split into subwords by the tokenizer - inputs = [] - for subword_index in word_subword_mapping.values(): - input_ids_ = copy(input_ids) - input_ids_[subword_index] = tokenizer.mask_token_id - inputs.append((input_ids_, subword_index)) - - # doing batched forward pass - with torch.inference_mode(): - prediction_list = [] - while len(inputs) != 0: - batch_list, token_indices = tuple(zip(*inputs[:batch_size])) - batch = torch.tensor(batch_list) - batch = batch.to(device) - logits = model(input_ids=batch)["logits"] - relevant_logits = logits[torch.arange(batch.shape[0]), token_indices] - ranking = torch.topk(relevant_logits, word_possibilities, dim=1) - prediction_list.append(ranking.indices.cpu()) - inputs = inputs[batch_size:] - predictions = torch.cat(prediction_list, dim=0) - - # creating list of possible replacements for each word - possible_words = [] - - batch_index = 0 - for i, word in enumerate(words): - if i in word_subword_mapping: # word was not split into subwords so we can use MLM output - subword_index = word_subword_mapping[i] - ranking = predictions[batch_index] # type: ignore [assignment] - possible_words_ = [word] - for token in ranking: - word = tokenizer.convert_ids_to_tokens([token])[0] - if not word.startswith("##"): - possible_words_.append(word) - - possible_words.append(possible_words_) - - batch_index += 1 - elif word in glove_word_id_mapping: # word was split into subwords so we use glove instead - word_id = glove_word_id_mapping[word] - glove_vector = glove_vectors[word_id] - with torch.inference_mode(): - word_similarities = torch.mm(glove_vectors, glove_vector.unsqueeze(1)).squeeze(1) # type: ignore [arg-type] - ranking = torch.argsort(word_similarities, descending=True)[: word_possibilities + 1] # type: ignore [assignment] - possible_words.append([glove_id_word_mapping[int(id_)] for id_ in ranking.cpu()]) # type: ignore [attr-defined] - else: # word was not in glove either so we can't find any replacements - possible_words.append([word]) - - return possible_words - - -def augment( - word_id_mapping: dict, - id_word_mapping: dict, - vectors: np.ndarray, - model: PreTrainedModel, - tokenizer: PreTrainedTokenizerBase, - text: str, - multiplication_factor: int = 20, - word_possibilities: int = 20, - replace_probability: float = 0.4, - batch_size: int = 16, - device: Union[str, torch.device] = torch.device("cpu:0"), -) -> List[str]: - device = torch.device(device) - # returns a list of different augmented versions of the text - replacements = get_replacements( - glove_word_id_mapping=word_id_mapping, - glove_id_word_mapping=id_word_mapping, - glove_vectors=vectors, - model=model, - tokenizer=tokenizer, - text=text, - word_possibilities=word_possibilities, - batch_size=batch_size, - device=device, - ) - new_texts = [] - for _ in range(multiplication_factor): - new_text = [] - for possible_words in replacements: - if len(possible_words) == 1: - new_text.append(possible_words[0]) - continue - if random.random() < replace_probability: - new_text.append(random.choice(possible_words[1:])) - else: - new_text.append(possible_words[0]) - new_texts.append(" ".join(new_text)) - return new_texts - - -def augment_squad( - squad_path: Path, - output_path: Path, - glove_path: Path = Path("glove.txt"), - model: str = "bert-base-uncased", - tokenizer: str = "bert-base-uncased", - multiplication_factor: int = 20, - word_possibilities: int = 20, - replace_probability: float = 0.4, - device: Union[str, torch.device] = "cpu:0", - batch_size: int = 16, -): - """Loads a squad dataset, augments the contexts, and saves the result in SQuAD format.""" - device = torch.device(device) - # loading model and tokenizer - transformers_model = AutoModelForMaskedLM.from_pretrained(model) - transformers_model.to(device) - transformers_tokenizer = AutoTokenizer.from_pretrained(tokenizer, use_fast=False) - # load glove for words that do not have one distinct token, but are split into subwords - word_id_mapping, id_word_mapping, vectors = load_glove(glove_path=glove_path, device=device) - - # load squad dataset - with open(squad_path, "r") as f: - squad = json.load(f) - - topics = [] - - for topic in tqdm(squad["data"]): - paragraphs = [] - for paragraph in topic["paragraphs"]: - # make every question unanswerable as answer strings will probably not match and aren't relevant for distillation - for question in paragraph["qas"]: - question["answers"] = [] - context = paragraph["context"] - contexts = augment( - word_id_mapping=word_id_mapping, - id_word_mapping=id_word_mapping, - vectors=vectors, # type: ignore [arg-type] - model=transformers_model, - tokenizer=transformers_tokenizer, - text=context, - multiplication_factor=multiplication_factor, - word_possibilities=word_possibilities, - replace_probability=replace_probability, - device=device, - batch_size=batch_size, - ) - paragraphs_ = [] - for context in contexts: - new_paragraph = deepcopy(paragraph) - new_paragraph["context"] = context - paragraphs_.append(new_paragraph) - paragraphs += paragraphs_ - topic["paragraphs"] = paragraphs - topics.append(topic) - squad["topics"] = topics - - # save new dataset - with open(output_path, "w") as f: - json.dump(squad, f) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--squad_path", type=Path, required=True, help="Path to the squad json file") - parser.add_argument("--output_path", type=Path, required=True, help="Path to save augmented dataaset") - parser.add_argument( - "--multiplication_factor", type=int, default=20, help="Factor by which dataset size is multiplied" - ) - parser.add_argument( - "--word_possibilities", - type=int, - default=5, - help="Number of possible words to choose from when replacing a word", - ) - parser.add_argument("--replace_probability", type=float, default=0.4, help="Probability of replacing a word") - parser.add_argument("--glove_path", type=Path, default="glove.txt", help="Path to the glove file") - parser.add_argument("--batch_size", type=int, default=16, help="Batch size for forward pass") - parser.add_argument("--device", type=str, default="cuda:0", help="Device to use") - parser.add_argument( - "--model", type=str, default="bert-base-uncased", help="Huggingface model identifier for MLM model" - ) - parser.add_argument( - "--tokenizer", type=str, default="bert-base-uncased", help="Huggingface tokenizer identifier for MLM model" - ) - - args = parser.parse_args() - - augment_squad(**vars(args)) diff --git a/haystack/utils/batching.py b/haystack/utils/batching.py deleted file mode 100644 index a1e1c2c117..0000000000 --- a/haystack/utils/batching.py +++ /dev/null @@ -1,12 +0,0 @@ -from itertools import islice - - -def get_batches_from_generator(iterable, n): - """ - Batch elements of an iterable into fixed-length chunks or blocks. - """ - it = iter(iterable) - x = tuple(islice(it, n)) - while x: - yield x - x = tuple(islice(it, n)) diff --git a/haystack/utils/cleaning.py b/haystack/utils/cleaning.py deleted file mode 100644 index 43d1ca29fa..0000000000 --- a/haystack/utils/cleaning.py +++ /dev/null @@ -1,27 +0,0 @@ -import re - - -def clean_wiki_text(text: str) -> str: - """ - Clean wikipedia text by removing multiple new lines, removing extremely short lines, - adding paragraph breaks and removing empty paragraphs - """ - # get rid of multiple new lines - while "\n\n" in text: - text = text.replace("\n\n", "\n") - - # remove extremely short lines - lines = text.split("\n") - cleaned = [] - for l in lines: - if len(l) > 30 or (l[:2] == "==" and l[-2:] == "=="): - cleaned.append(l) - text = "\n".join(cleaned) - - # add paragraphs (identified by wiki section title which is always in format "==Some Title==") - text = text.replace("\n==", "\n\n\n==") - - # remove empty paragrahps - text = re.sub(r"(==.*==\n\n\n)", "", text) - - return text diff --git a/haystack/utils/context_matching.py b/haystack/utils/context_matching.py deleted file mode 100644 index 80cfb1bd0b..0000000000 --- a/haystack/utils/context_matching.py +++ /dev/null @@ -1,225 +0,0 @@ -from typing import Generator, Iterable, Optional, Tuple, List, Union - -import re -import logging -from itertools import groupby -from multiprocessing.pool import Pool -from collections import namedtuple - -from tqdm import tqdm - -from haystack.lazy_imports import LazyImport - -logger = logging.getLogger(__file__) - - -with LazyImport("Run 'pip install farm-haystack[metrics]' or 'pip install rapidfuzz'") as rapidfuzz_import: - from rapidfuzz import fuzz - - -_CandidateScore = namedtuple("_CandidateScore", ["context_id", "candidate_id", "score"]) - - -def _score_candidate(args: Tuple[Union[str, Tuple[object, str]], Tuple[object, str], int, bool]): - context, candidate, min_length, boost_split_overlaps = args - candidate_id, candidate_text = candidate - context_id, context_text = (None, context) if isinstance(context, str) else context - score = calculate_context_similarity( - context=context_text, candidate=candidate_text, min_length=min_length, boost_split_overlaps=boost_split_overlaps - ) - return _CandidateScore(context_id=context_id, candidate_id=candidate_id, score=score) - - -def normalize_white_space_and_case(str: str) -> str: - return re.sub(r"\s+", " ", str).lower().strip() - - -def _no_processor(str: str) -> str: - return str - - -def calculate_context_similarity( - context: str, candidate: str, min_length: int = 100, boost_split_overlaps: bool = True -) -> float: - """ - Calculates the text similarity score of context and candidate. - The score's value ranges between 0.0 and 100.0. - - :param context: The context to match. - :param candidate: The candidate to match the context. - :param min_length: The minimum string length context and candidate need to have in order to be scored. - Returns 0.0 otherwise. - :param boost_split_overlaps: Whether to boost split overlaps (e.g. [AB] <-> [BC]) that result from different preprocessing params. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries - we cut the context on the same side, recalculate the score and take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - """ - rapidfuzz_import.check() - # we need to handle short contexts/contents (e.g single word) - # as they produce high scores by matching if the chars of the word are contained in the other one - # this has to be done after normalizing - context = normalize_white_space_and_case(context) - candidate = normalize_white_space_and_case(candidate) - context_len = len(context) - candidate_len = len(candidate) - if candidate_len < min_length or context_len < min_length: - return 0.0 - - if context_len < candidate_len: - shorter = context - longer = candidate - shorter_len = context_len - longer_len = candidate_len - else: - shorter = candidate - longer = context - shorter_len = candidate_len - longer_len = context_len - - score_alignment = fuzz.partial_ratio_alignment(shorter, longer, processor=_no_processor) - score = score_alignment.score # type: ignore [union-attr] - - # Special handling for split overlaps (e.g. [AB] <-> [BC]): - # If we detect that the score is near a half match and the best fitting part of longer is at its boundaries - # we cut the shorter on the same side, recalculate the score and take the mean of both. - # Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total - if boost_split_overlaps and 40 <= score < 65: - cut_shorter_left = score_alignment.dest_start == 0 # type: ignore [union-attr] - cut_shorter_right = score_alignment.dest_end == longer_len # type: ignore [union-attr] - cut_len = shorter_len // 2 - - if cut_shorter_left: - cut_score = fuzz.partial_ratio(shorter[cut_len:], longer, processor=_no_processor) - if cut_score > score: - score = (score + cut_score) / 2 - if cut_shorter_right: - cut_score = fuzz.partial_ratio(shorter[:-cut_len], longer, processor=_no_processor) - if cut_score > score: - score = (score + cut_score) / 2 - - return score - - -def match_context( - context: str, - candidates: Generator[Tuple[str, str], None, None], - threshold: float = 65.0, - show_progress: bool = False, - num_processes: Optional[int] = None, - chunksize: int = 1, - min_length: int = 100, - boost_split_overlaps: bool = True, -) -> List[Tuple[str, float]]: - """ - Matches the context against multiple candidates. Candidates consist of a tuple of an id and its text. - - Returns a sorted list of the candidate ids and its scores filtered by the threshold in descending order. - - :param context: The context to match. - :param candidates: The candidates to match the context. - A candidate consists of a tuple of candidate id and candidate text. - :param threshold: Score threshold that candidates must surpass to be included into the result list. - :param show_progress: Whether to show the progress of matching all candidates. - :param num_processes: The number of processes to be used for matching in parallel. - :param chunksize: The chunksize used during parallel processing. - If not specified chunksize is 1. - For very long iterables using a large value for chunksize can make the job complete much faster than using the default value of 1. - :param min_length: The minimum string length context and candidate need to have in order to be scored. - Returns 0.0 otherwise. - :param boost_split_overlaps: Whether to boost split overlaps (e.g. [AB] <-> [BC]) that result from different preprocessing params. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries - we cut the context on the same side, recalculate the score and take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - """ - pool: Optional[Pool] = None - try: - score_candidate_args = ((context, candidate, min_length, boost_split_overlaps) for candidate in candidates) - if num_processes is None or num_processes > 1: - pool = Pool(processes=num_processes) - candidate_scores: Iterable = pool.imap_unordered( - _score_candidate, score_candidate_args, chunksize=chunksize - ) - else: - candidate_scores = map(_score_candidate, score_candidate_args) - - if show_progress: - candidate_scores = tqdm(candidate_scores) - - matches = (candidate for candidate in candidate_scores if candidate.score > threshold) - sorted_matches = sorted(matches, key=lambda candidate: candidate.score, reverse=True) - match_list = [(candidate_score.candidate_id, candidate_score.score) for candidate_score in sorted_matches] - - return match_list - - finally: - if pool: - pool.close() - pool.join() - - -def match_contexts( - contexts: List[str], - candidates: Generator[Tuple[str, str], None, None], - threshold: float = 65.0, - show_progress: bool = False, - num_processes: Optional[int] = None, - chunksize: int = 1, - min_length: int = 100, - boost_split_overlaps: bool = True, -) -> List[List[Tuple[str, float]]]: - """ - Matches the contexts against multiple candidates. Candidates consist of a tuple of an id and its string text. - This method iterates over candidates only once. - - Returns for each context a sorted list of the candidate ids and its scores filtered by the threshold in descending order. - - :param contexts: The contexts to match. - :param candidates: The candidates to match the context. - A candidate consists of a tuple of candidate id and candidate text. - :param threshold: Score threshold that candidates must surpass to be included into the result list. - :param show_progress: Whether to show the progress of matching all candidates. - :param num_processes: The number of processes to be used for matching in parallel. - :param chunksize: The chunksize used during parallel processing. - If not specified chunksize is 1. - For very long iterables using a large value for chunksize can make the job complete much faster than using the default value of 1. - :param min_length: The minimum string length context and candidate need to have in order to be scored. - Returns 0.0 otherwise. - :param boost_split_overlaps: Whether to boost split overlaps (e.g. [AB] <-> [BC]) that result from different preprocessing params. - If we detect that the score is near a half match and the matching part of the candidate is at its boundaries - we cut the context on the same side, recalculate the score and take the mean of both. - Thus [AB] <-> [BC] (score ~50) gets recalculated with B <-> B (score ~100) scoring ~75 in total. - """ - pool: Optional[Pool] = None - try: - score_candidate_args = ( - (context, candidate, min_length, boost_split_overlaps) - for candidate in candidates - for context in enumerate(contexts) - ) - - if num_processes is None or num_processes > 1: - pool = Pool(processes=num_processes) - candidate_scores: Iterable = pool.imap_unordered( - _score_candidate, score_candidate_args, chunksize=chunksize - ) - else: - candidate_scores = map(_score_candidate, score_candidate_args) - - if show_progress: - candidate_scores = tqdm(candidate_scores) - - match_lists: List[List[Tuple[str, float]]] = [] - matches = (candidate for candidate in candidate_scores if candidate.score > threshold) - group_sorted_matches = sorted(matches, key=lambda candidate: candidate.context_id) - grouped_matches = groupby(group_sorted_matches, key=lambda candidate: candidate.context_id) - for context_id, group in grouped_matches: - sorted_group = sorted(group, key=lambda candidate: candidate.score, reverse=True) - match_list = [(candiate_score.candidate_id, candiate_score.score) for candiate_score in sorted_group] - match_lists.insert(context_id, match_list) - - return match_lists - - finally: - if pool: - pool.close() - pool.join() diff --git a/haystack/utils/deepsetcloud.py b/haystack/utils/deepsetcloud.py deleted file mode 100644 index dfe1bc09f5..0000000000 --- a/haystack/utils/deepsetcloud.py +++ /dev/null @@ -1,1767 +0,0 @@ -import json -import logging -import os -import time -from enum import Enum -from mimetypes import guess_type -from pathlib import Path -from typing import Any, Dict, Generator, List, Literal, Optional, Tuple, Union - -import pandas as pd -import requests -import yaml -from tqdm import tqdm - -from haystack.schema import Answer, Document, EvaluationResult, FilterType, Label - -DEFAULT_API_ENDPOINT = "https://api.cloud.deepset.ai/api/v1" - - -class PipelineStatus(Enum): - UNDEPLOYED: str = "UNDEPLOYED" - DEPLOYED_UNHEALTHY: str = "DEPLOYED_UNHEALTHY" - DEPLOYED: str = "DEPLOYED" - DEPLOYMENT_IN_PROGRESS: str = "DEPLOYMENT_IN_PROGRESS" - UNDEPLOYMENT_IN_PROGRESS: str = "UNDEPLOYMENT_IN_PROGRESS" - DEPLOYMENT_SCHEDULED: str = "DEPLOYMENT_SCHEDULED" - UNDEPLOYMENT_SCHEDULED: str = "UNDEPLOYMENT_SCHEDULED" - DEPLOYMENT_FAILED: str = "DEPLOYMENT_FAILED" - UNDEPLOYMENT_FAILED: str = "UNDEPLOYMENT_FAILED" - UNKNOWN: str = "UNKNOWN" - - @classmethod - def from_str(cls, status_string: str) -> "PipelineStatus": - return cls.__dict__.get(status_string, PipelineStatus.UNKNOWN) - - -SATISFIED_STATES_KEY = "satisfied_states" -FAILED_STATES_KEY = "failed_states" -VALID_INITIAL_STATES_KEY = "valid_initial_states" -VALID_TRANSITIONING_STATES_KEY = "valid_transitioning_states" -PIPELINE_STATE_TRANSITION_INFOS: Dict[PipelineStatus, Dict[str, List[PipelineStatus]]] = { - PipelineStatus.UNDEPLOYED: { - SATISFIED_STATES_KEY: [PipelineStatus.UNDEPLOYED], - FAILED_STATES_KEY: [PipelineStatus.UNDEPLOYMENT_FAILED], - VALID_INITIAL_STATES_KEY: [ - PipelineStatus.DEPLOYED, - PipelineStatus.DEPLOYMENT_FAILED, - PipelineStatus.UNDEPLOYMENT_FAILED, - ], - VALID_TRANSITIONING_STATES_KEY: [ - PipelineStatus.UNDEPLOYMENT_SCHEDULED, - PipelineStatus.UNDEPLOYMENT_IN_PROGRESS, - ], - }, - PipelineStatus.DEPLOYED: { - SATISFIED_STATES_KEY: [PipelineStatus.DEPLOYED, PipelineStatus.DEPLOYED_UNHEALTHY], - FAILED_STATES_KEY: [PipelineStatus.DEPLOYMENT_FAILED], - VALID_INITIAL_STATES_KEY: [ - PipelineStatus.UNDEPLOYED, - PipelineStatus.DEPLOYMENT_FAILED, - PipelineStatus.UNDEPLOYMENT_FAILED, - ], - VALID_TRANSITIONING_STATES_KEY: [PipelineStatus.DEPLOYMENT_SCHEDULED, PipelineStatus.DEPLOYMENT_IN_PROGRESS], - }, -} - -logger = logging.getLogger(__name__) - - -class BearerAuth(requests.auth.AuthBase): - def __init__(self, token): - self.token = token - - def __call__(self, r): - r.headers["authorization"] = "Bearer " + self.token - return r - - -class DeepsetCloudError(Exception): - """Raised when there is an error communicating with deepset Cloud""" - - -class DeepsetCloudClient: - def __init__(self, api_key: Optional[str] = None, api_endpoint: Optional[str] = None): - """ - A client to communicate with deepset Cloud. - - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - self.api_key = api_key or os.getenv("DEEPSET_CLOUD_API_KEY") - if self.api_key is None: - raise DeepsetCloudError( - "No api_key specified. Please set api_key param or DEEPSET_CLOUD_API_KEY environment variable." - ) - - self.api_endpoint = api_endpoint or os.getenv("DEEPSET_CLOUD_API_ENDPOINT", DEFAULT_API_ENDPOINT) - - def get( - self, - url: str, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - raise_on_error: bool = True, - ): - return self._execute_request( - method="GET", - url=url, - query_params=query_params, - headers=headers, - stream=stream, - raise_on_error=raise_on_error, - ) - - def get_with_auto_paging( - self, - url: str, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - raise_on_error: bool = True, - auto_paging_page_size: Optional[int] = None, - ) -> Generator: - return self._execute_auto_paging_request( - method="GET", - url=url, - query_params=query_params, - headers=headers, - stream=stream, - raise_on_error=raise_on_error, - auto_paging_page_size=auto_paging_page_size, - ) - - def post( - self, - url: str, - json: Optional[Dict] = None, - data: Optional[Any] = None, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - files: Optional[Any] = None, - raise_on_error: bool = True, - ): - if json is None: - json = {} - return self._execute_request( - method="POST", - url=url, - query_params=query_params, - json=json, - data=data, - stream=stream, - files=files, - headers=headers, - raise_on_error=raise_on_error, - ) - - def post_with_auto_paging( - self, - url: str, - json: Optional[Dict] = None, - data: Optional[Any] = None, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - raise_on_error: bool = True, - auto_paging_page_size: Optional[int] = None, - ): - if json is None: - json = {} - return self._execute_auto_paging_request( - method="POST", - url=url, - query_params=query_params, - json=json, - data=data, - stream=stream, - headers=headers, - raise_on_error=raise_on_error, - auto_paging_page_size=auto_paging_page_size, - ) - - def put( - self, - url: str, - json: Optional[dict] = None, - data: Optional[Any] = None, - query_params: Optional[dict] = None, - stream: bool = False, - headers: Optional[dict] = None, - raise_on_error: bool = True, - ): - return self._execute_request( - method="PUT", - url=url, - query_params=query_params, - json=json, - data=data, - stream=stream, - headers=headers, - raise_on_error=raise_on_error, - ) - - def put_with_auto_paging( - self, - url: str, - json: Optional[Dict] = None, - data: Optional[Any] = None, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - raise_on_error: bool = True, - auto_paging_page_size: Optional[int] = None, - ): - if json is None: - json = {} - return self._execute_auto_paging_request( - method="PUT", - url=url, - query_params=query_params, - json=json, - data=data, - stream=stream, - headers=headers, - raise_on_error=raise_on_error, - auto_paging_page_size=auto_paging_page_size, - ) - - def delete( - self, - url: str, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - raise_on_error: bool = True, - ): - return self._execute_request( - method="DELETE", - url=url, - query_params=query_params, - headers=headers, - stream=stream, - raise_on_error=raise_on_error, - ) - - def patch( - self, - url: str, - json: Optional[dict] = None, - data: Optional[Any] = None, - query_params: Optional[dict] = None, - stream: bool = False, - headers: Optional[dict] = None, - raise_on_error: bool = True, - ): - return self._execute_request( - method="PATCH", - url=url, - query_params=query_params, - json=json, - data=data, - stream=stream, - headers=headers, - raise_on_error=raise_on_error, - ) - - def _execute_auto_paging_request( - self, - method: Literal["GET", "POST", "PUT", "HEAD", "DELETE"], - url: str, - json: Optional[dict] = None, - data: Optional[Any] = None, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - raise_on_error: bool = True, - auto_paging_page_size: Optional[int] = None, - ) -> Generator: - query_params = query_params.copy() if query_params is not None else {} - if auto_paging_page_size: - query_params["limit"] = auto_paging_page_size - page_number = 1 - has_more = True - while has_more: - query_params["page_number"] = page_number - payload = self._execute_request( - method=method, - url=url, - json=json, - data=data, - query_params=query_params, - headers=headers, - stream=stream, - raise_on_error=raise_on_error, - ).json() - yield from payload["data"] - has_more = payload["has_more"] - page_number += 1 - - def _execute_request( - self, - method: Literal["GET", "POST", "PUT", "HEAD", "DELETE", "PATCH"], - url: str, - json: Optional[dict] = None, - data: Optional[Any] = None, - query_params: Optional[dict] = None, - headers: Optional[dict] = None, - stream: bool = False, - files: Optional[Any] = None, - raise_on_error: bool = True, - timeout: Union[float, Tuple[float, float]] = 10.0, - ): - if json is not None: - json = self._remove_null_values(json) - response = requests.request( - method=method, - url=url, - json=json, - data=data, - params=query_params, - headers=headers, - auth=BearerAuth(self.api_key), - stream=stream, - files=files, - timeout=timeout, - ) - if raise_on_error and response.status_code > 299: - raise DeepsetCloudError( - f"{method} {url} failed: HTTP {response.status_code} - {response.reason}\n{response.content.decode()}" - ) - return response - - def build_workspace_url(self, workspace: Optional[str] = None): - api_endpoint = f"{self.api_endpoint}".rstrip("/") - url = f"{api_endpoint}/workspaces/{workspace}" - return url - - def _remove_null_values(self, body: dict) -> dict: - return {k: v for k, v in body.items() if v is not None} - - -class IndexClient: - def __init__(self, client: DeepsetCloudClient, workspace: Optional[str] = None, index: Optional[str] = None): - """ - A client to communicate with deepset Cloud indexes. - - :param client: deepset Cloud client - :param workspace: Specifies the name of the workspace for which you want to create the client. - :param index: index in deepset Cloud workspace - - """ - self.client = client - self.workspace = workspace - self.index = index - - def info(self, workspace: Optional[str] = None, index: Optional[str] = None, headers: Optional[dict] = None): - index_url = self._build_index_url(workspace=workspace, index=index) - try: - response = self.client.get(url=index_url, headers=headers) - return response.json() - except Exception as ie: - raise DeepsetCloudError(f"Could not connect to deepset Cloud:\n{ie}") from ie - - def query( - self, - query: Optional[str] = None, - filters: Optional[FilterType] = None, - top_k: int = 10, - custom_query: Optional[str] = None, - query_emb: Optional[List[float]] = None, - return_embedding: Optional[bool] = None, - workspace: Optional[str] = None, - index: Optional[str] = None, - all_terms_must_match: Optional[bool] = None, - scale_score: bool = True, - headers: Optional[dict] = None, - use_prefiltering: Optional[bool] = None, - ) -> List[dict]: - index_url = self._build_index_url(workspace=workspace, index=index) - query_url = f"{index_url}/documents-query" - request = { - "query": query, - "filters": filters, - "top_k": top_k, - "custom_query": custom_query, - "query_emb": query_emb, - "return_embedding": return_embedding, - "all_terms_must_match": all_terms_must_match, - "scale_score": scale_score, - "use_prefiltering": use_prefiltering, - } - response = self.client.post(url=query_url, json=request, headers=headers) - return response.json() - - def stream_documents( - self, - return_embedding: Optional[bool] = False, - filters: Optional[FilterType] = None, - workspace: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[dict] = None, - ): - index_url = self._build_index_url(workspace=workspace, index=index) - query_url = f"{index_url}/documents-stream" - request = {"return_embedding": return_embedding, "filters": filters} - response = self.client.post(url=query_url, json=request, headers=headers, stream=True) - return response.iter_lines() - - def get_document( - self, id: str, workspace: Optional[str] = None, index: Optional[str] = None, headers: Optional[dict] = None - ): - index_url = self._build_index_url(workspace=workspace, index=index) - document_url = f"{index_url}/documents/{id}" - response = self.client.get(url=document_url, headers=headers, raise_on_error=False) - doc: Optional[dict] = None - if response.status_code == 200: - doc = response.json() - else: - logger.warning( - "Document %s could not be fetched from deepset Cloud: HTTP %s - %s\n%s", - id, - response.status_code, - response.reason, - response.content.decode(), - ) - return doc - - def count_documents( - self, - filters: Optional[FilterType] = None, - only_documents_without_embedding: Optional[bool] = False, - workspace: Optional[str] = None, - index: Optional[str] = None, - headers: Optional[dict] = None, - ) -> dict: - index_url = self._build_index_url(workspace=workspace, index=index) - count_url = f"{index_url}/documents-count" - request = {"filters": filters, "only_documents_without_embedding": only_documents_without_embedding} - response = self.client.post(url=count_url, json=request, headers=headers) - return response.json() - - def _build_index_url(self, workspace: Optional[str] = None, index: Optional[str] = None): - if workspace is None: - workspace = self.workspace - if index is None: - index = self.index - workspace_url = self.client.build_workspace_url(workspace) - return f"{workspace_url}/indexes/{index}" - - -class PipelineClient: - def __init__( - self, client: DeepsetCloudClient, workspace: Optional[str] = None, pipeline_config_name: Optional[str] = None - ): - """ - A client to communicate with deepset Cloud pipelines. - - :param client: deepset Cloud client - :param workspace: Specifies the name of the workspace for which you want to create the client. - :param pipeline_config_name: Name of the pipeline_config in deepset Cloud workspace. - - """ - self.client = client - self.workspace = workspace - self.pipeline_config_name = pipeline_config_name - - def get_pipeline_config( - self, - workspace: Optional[str] = None, - pipeline_config_name: Optional[str] = None, - headers: Optional[dict] = None, - ) -> dict: - """ - Gets the config from a pipeline on deepset Cloud. - - :param pipeline_config_name: Name of the pipeline_config in deepset Cloud workspace. - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call. - """ - pipeline_url = self._build_pipeline_url(workspace=workspace, pipeline_config_name=pipeline_config_name) - pipeline_config_url = f"{pipeline_url}/json" - response = self.client.get(url=pipeline_config_url, headers=headers).json() - return response - - def get_pipeline_config_info( - self, - workspace: Optional[str] = None, - pipeline_config_name: Optional[str] = None, - headers: Optional[dict] = None, - ) -> Optional[dict]: - """ - Gets information about a pipeline on deepset Cloud. - - :param pipeline_config_name: Name of the pipeline_config in deepset Cloud workspace. - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call. - """ - pipeline_url = self._build_pipeline_url(workspace=workspace, pipeline_config_name=pipeline_config_name) - response = self.client.get(url=pipeline_url, headers=headers, raise_on_error=False) - if response.status_code == 200: - return response.json() - elif response.status_code == 404: - return None - else: - raise DeepsetCloudError( - f"GET {pipeline_url} failed: HTTP {response.status_code} - {response.reason}\n{response.content.decode()}" - ) - - def list_pipeline_configs(self, workspace: Optional[str] = None, headers: Optional[dict] = None) -> Generator: - """ - Lists all pipelines available on deepset Cloud. - - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call. - - Returns: - Generator of dictionaries: List[dict] - each dictionary: { - "name": str -> `pipeline_config_name` to be used in `load_from_deepset_cloud()`, - "..." -> additional pipeline meta information - } - example: - - ```python - [{'name': 'my_super_nice_pipeline_config', - 'pipeline_id': '2184e0c1-c6ec-40a1-9b28-5d2768e5efa2', - 'status': 'DEPLOYED', - 'created_at': '2022-02-01T09:57:03.803991+00:00', - 'deleted': False, - 'is_default': False, - 'indexing': {'status': 'IN_PROGRESS', - 'pending_file_count': 3, - 'total_file_count': 31}}] - ``` - - """ - workspace_url = self._build_workspace_url(workspace) - pipelines_url = f"{workspace_url}/pipelines" - generator = self.client.get_with_auto_paging(url=pipelines_url, headers=headers) - return generator - - def save_pipeline_config( - self, - config: dict, - pipeline_config_name: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - ): - """ - Saves a pipeline config to deepset Cloud. - - :param config: The pipeline config to save. - :param pipeline_config_name: Name of the pipeline_config in deepset Cloud workspace. - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call. - """ - workspace_url = self._build_workspace_url(workspace=workspace) - pipelines_url = f"{workspace_url}/pipelines" - response = self.client.post( - url=pipelines_url, json={"name": pipeline_config_name, "config": yaml.dump(config)}, headers=headers - ).json() - if "name" not in response or response["name"] != pipeline_config_name: - logger.warning("Unexpected response from saving pipeline config: %s", response) - - def update_pipeline_config( - self, - config: dict, - pipeline_config_name: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - ): - """ - Updates a pipeline config on deepset Cloud. - - :param config: The pipeline config to save. - :param pipeline_config_name: Name of the pipeline_config in deepset Cloud workspace. - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call. - """ - pipeline_url = self._build_pipeline_url(workspace=workspace, pipeline_config_name=pipeline_config_name) - yaml_url = f"{pipeline_url}/yaml" - response = self.client.put(url=yaml_url, data=yaml.dump(config), headers=headers).json() - if "name" not in response or response["name"] != pipeline_config_name: - logger.warning("Unexpected response from updating pipeline config: %s", response) - - def deploy( - self, - pipeline_config_name: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - timeout: int = 60, - show_curl_message: bool = True, - ): - """ - Deploys the pipelines of a pipeline config on deepset Cloud. - Blocks until pipelines are successfully deployed, deployment failed or timeout exceeds. - If pipelines are already deployed no action will be taken and an info will be logged. - If timeout exceeds a TimeoutError will be raised. - If deployment fails a DeepsetCloudError will be raised. - - :param pipeline_config_name: Name of the config file inside the deepset Cloud workspace. - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call. - :param timeout: The time in seconds to wait until deployment completes. - If the timeout is exceeded an error will be raised. - :param show_curl_message: Whether to print an additional message after successful deployment showing how to query the pipeline using curl. - """ - status, changed = self._transition_pipeline_state( - target_state=PipelineStatus.DEPLOYED, - timeout=timeout, - pipeline_config_name=pipeline_config_name, - workspace=workspace, - headers=headers, - ) - - if workspace is None: - workspace = self.workspace - if pipeline_config_name is None: - pipeline_config_name = self.pipeline_config_name - - pipeline_url = f"{self.client.api_endpoint}/workspaces/{workspace}/pipelines/{pipeline_config_name}/search" - - if status == PipelineStatus.DEPLOYED: - if changed: - logger.info("Pipeline config '%s' successfully deployed.", pipeline_config_name) - else: - logger.info("Pipeline config '%s' is already deployed.", pipeline_config_name) - logger.info( - "Search endpoint for pipeline config '%s' is up and running for you under %s", - pipeline_config_name, - pipeline_url, - ) - if show_curl_message: - curl_cmd = ( - f"curl -X 'POST' \\\n" - f" '{pipeline_url}' \\\n" - f" -H 'accept: application/json' \\\n" - f" -H 'Authorization: Bearer ' \\\n" - f" -H 'Content-Type: application/json' \\\n" - f" -d '{{\n" - f' "queries": [\n' - f' "Is there an answer to this question?"\n' - f" ]\n" - f"}}'" - ) - logger.info("Try it out using the following curl command:\n%s", curl_cmd) - - elif status == PipelineStatus.DEPLOYMENT_FAILED: - raise DeepsetCloudError( - f"Deployment of pipeline config '{pipeline_config_name}' failed. " - "This might be caused by an exception in deepset Cloud or a runtime error in the pipeline. " - "You can try to run this pipeline locally first." - ) - elif status in [PipelineStatus.UNDEPLOYMENT_IN_PROGRESS, PipelineStatus.UNDEPLOYMENT_SCHEDULED]: - raise DeepsetCloudError( - f"Deployment of pipeline config '{pipeline_config_name}' aborted. Undeployment was requested." - ) - elif status == PipelineStatus.UNDEPLOYED: - raise DeepsetCloudError(f"Deployment of pipeline config '{pipeline_config_name}' failed.") - else: - raise DeepsetCloudError( - f"Deployment of pipeline config '{pipeline_config_name} ended in unexpected status: {status.value}" - ) - - def undeploy( - self, - pipeline_config_name: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - timeout: int = 60, - ): - """ - Undeploys the pipelines of a pipeline config on deepset Cloud. - Blocks until pipelines are successfully undeployed, undeployment failed or timeout exceeds. - If pipelines are already undeployed no action will be taken and an info will be logged. - If timeout exceeds a TimeoutError will be raised. - If deployment fails a DeepsetCloudError will be raised. - - :param pipeline_config_name: Name of the config file inside the deepset Cloud workspace. - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call - :param timeout: The time in seconds to wait until undeployment completes. - If the timeout is exceeded an error will be raised. - """ - status, changed = self._transition_pipeline_state( - target_state=PipelineStatus.UNDEPLOYED, - timeout=timeout, - pipeline_config_name=pipeline_config_name, - workspace=workspace, - headers=headers, - ) - - if status == PipelineStatus.UNDEPLOYED: - if changed: - logger.info("Pipeline config '%s' successfully undeployed.", pipeline_config_name) - else: - logger.info("Pipeline config '%s' is already undeployed.", pipeline_config_name) - elif status in [PipelineStatus.DEPLOYMENT_IN_PROGRESS, PipelineStatus.DEPLOYMENT_SCHEDULED]: - raise DeepsetCloudError( - f"Undeployment of pipeline config '{pipeline_config_name}' aborted. Deployment was requested." - ) - elif status in [PipelineStatus.DEPLOYED, PipelineStatus.DEPLOYED_UNHEALTHY]: - raise DeepsetCloudError(f"Undeployment of pipeline config '{pipeline_config_name}' failed.") - else: - raise DeepsetCloudError( - f"Undeployment of pipeline config '{pipeline_config_name} ended in unexpected status: {status.value}" - ) - - def _transition_pipeline_state( - self, - target_state: Literal[PipelineStatus.DEPLOYED, PipelineStatus.UNDEPLOYED], - timeout: int = 60, - pipeline_config_name: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - ) -> Tuple[PipelineStatus, bool]: - """ - Transitions the pipeline config state to desired target_state on deepset Cloud. - - :param target_state: The target state of the Pipeline config. - :param pipeline_config_name: Name of the config file inside the deepset Cloud workspace. - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param headers: Headers to pass to the API call - :param timeout: The time in seconds to wait until undeployment completes. - If the timeout is exceeded an error will be raised. - """ - pipeline_info = self.get_pipeline_config_info( - pipeline_config_name=pipeline_config_name, workspace=workspace, headers=headers - ) - if pipeline_info is None: - raise DeepsetCloudError(f"Pipeline config '{pipeline_config_name}' does not exist.") - - transition_info = PIPELINE_STATE_TRANSITION_INFOS[target_state] - satisfied_states = transition_info[SATISFIED_STATES_KEY] - failed_states = transition_info[FAILED_STATES_KEY] - valid_transitioning_states = transition_info[VALID_TRANSITIONING_STATES_KEY] - valid_initial_states = transition_info[VALID_INITIAL_STATES_KEY] - - status = PipelineStatus.from_str(pipeline_info["status"]) - if status in satisfied_states: - return status, False - - if status not in valid_initial_states: - raise DeepsetCloudError( - f"Pipeline config '{pipeline_config_name}' is in invalid state '{status.value}' to be transitioned to '{target_state.value}'." - ) - - if status in failed_states: - logger.warning( - f"Pipeline config '{pipeline_config_name}' is in a failed state '{status}'. This might be caused by a previous error during (un)deployment. " - + f"Trying to transition from '{status}' to '{target_state}'..." - ) - - if target_state == PipelineStatus.DEPLOYED: - res = self._deploy(pipeline_config_name=pipeline_config_name, workspace=workspace, headers=headers) - status = PipelineStatus.from_str(res["status"]) - elif target_state == PipelineStatus.UNDEPLOYED: - res = self._undeploy(pipeline_config_name=pipeline_config_name, workspace=workspace, headers=headers) - status = PipelineStatus.from_str(res["status"]) - else: - raise NotImplementedError(f"Transitioning to state '{target_state.value}' is not implemented.") - - start_time = time.time() - while status in valid_transitioning_states: - if time.time() - start_time > timeout: - raise TimeoutError( - f"Transitioning of '{pipeline_config_name}' to state '{target_state.value}' timed out." - ) - pipeline_info = self.get_pipeline_config_info( - pipeline_config_name=pipeline_config_name, workspace=workspace, headers=headers - ) - if pipeline_info is None: - raise DeepsetCloudError(f"Pipeline config '{pipeline_config_name}' does not exist anymore.") - status = PipelineStatus.from_str(pipeline_info["status"]) - if status in valid_transitioning_states: - logger.info("Current status of '%s' is: '%s'", pipeline_config_name, status) - time.sleep(5) - - return status, True - - def _deploy( - self, - pipeline_config_name: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - ) -> dict: - pipeline_url = self._build_pipeline_url(workspace=workspace, pipeline_config_name=pipeline_config_name) - deploy_url = f"{pipeline_url}/deploy" - response = self.client.post(url=deploy_url, headers=headers).json() - return response - - def _undeploy( - self, - pipeline_config_name: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - ) -> dict: - pipeline_url = self._build_pipeline_url(workspace=workspace, pipeline_config_name=pipeline_config_name) - undeploy_url = f"{pipeline_url}/undeploy" - response = self.client.post(url=undeploy_url, headers=headers).json() - return response - - def _build_pipeline_url(self, workspace: Optional[str] = None, pipeline_config_name: Optional[str] = None): - if pipeline_config_name is None: - pipeline_config_name = self.pipeline_config_name - workspace_url = self._build_workspace_url(workspace) - return f"{workspace_url}/pipelines/{pipeline_config_name}" - - def _build_workspace_url(self, workspace: Optional[str] = None): - if workspace is None: - workspace = self.workspace - return self.client.build_workspace_url(workspace) - - -class EvaluationSetClient: - def __init__( - self, client: DeepsetCloudClient, workspace: Optional[str] = None, evaluation_set: Optional[str] = None - ): - """ - A client to communicate with deepset Cloud evaluation sets and labels. - - :param client: deepset Cloud client - :param workspace: Specifies the name of the workspace for which you want to create the client. - :param evaluation_set: name of the evaluation set to fall back to - - """ - self.client = client - self.workspace = workspace - self.evaluation_set = evaluation_set - - def get_labels(self, evaluation_set: Optional[str], workspace: Optional[str] = None) -> List[Label]: - """ - Searches for labels for a given evaluation set in deepset cloud. Returns a list of all found labels. - If no labels were found, raises DeepsetCloudError. - - :param evaluation_set: name of the evaluation set for which labels should be fetched - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationSetClient's default workspace (self.workspace) is used. - - :return: list of Label - """ - url = f"{self._build_workspace_url(workspace=workspace)}/evaluation_sets/{evaluation_set}" - response = self.client.get(url=url, raise_on_error=False) - if response.status_code >= 400: - raise DeepsetCloudError(f"No evaluation set found with the name {evaluation_set}") - - labels = response.json() - - return [ - Label( - query=label_dict["query"], - document=Document(content=label_dict["context"]), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - answer=Answer(label_dict["answer"]), - id=label_dict["label_id"], - pipeline_id=None, - created_at=None, - updated_at=None, - meta=label_dict["meta"], - filters={}, - ) - for label_dict in labels - ] - - def get_labels_count(self, evaluation_set: Optional[str] = None, workspace: Optional[str] = None) -> int: - """ - Counts labels for a given evaluation set in deepset cloud. - - :param evaluation_set: Optional evaluation set in deepset Cloud - If set to None, the EvaluationSetClient's default evaluation set (self.evaluation_set) is used. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationSetClient's default workspace (self.workspace) is used. - - :return: Number of labels for the given (or defaulting) index - """ - if not evaluation_set: - evaluation_set = self.evaluation_set - - evaluation_set_response = self.get_evaluation_set(evaluation_set=evaluation_set, workspace=workspace) - if evaluation_set_response is None: - raise DeepsetCloudError(f"No evaluation set found with the name {evaluation_set}") - - return evaluation_set_response["total_labels"] - - def get_evaluation_sets(self, workspace: Optional[str] = None) -> List[dict]: - """ - Searches for all evaluation set names in the given workspace in deepset Cloud. - - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationSetClient's default workspace (self.workspace) is used. - - :return: List of dictionaries that represent deepset Cloud evaluation sets. - These contain ("name", "evaluation_set_id", "created_at", "matched_labels", "total_labels") as fields. - """ - evaluation_sets_response = self._get_evaluation_sets(workspace=workspace) - - return list(evaluation_sets_response) - - def _get_evaluation_sets(self, workspace: Optional[str] = None) -> Generator: - url = self._build_workspace_url(workspace=workspace) - evaluation_set_url = f"{url}/evaluation_sets" - return self.client.get_with_auto_paging(url=evaluation_set_url) - - def upload_evaluation_set(self, file_path: Path, workspace: Optional[str] = None): - """ - Uploads an evaluation set. - The name of file that you uploaded becomes the name of the evaluation set in deepset Cloud. - When using Haystack annotation tool make sure to choose CSV as export format. The resulting file matches the expected format. - - Currently, deepset Cloud only supports CSV files (having "," as delimiter) with the following columns: - - question (or query): the labelled question or query (required) - - text: the answer to the question or relevant text to the query (required) - - context: the surrounding words of the text (should be more than 100 characters) (optional) - - file_name: the name of the file within the workspace that contains the text (optional) - - answer_start: the character position within the file that marks the start of the text (optional) - - answer_end: the character position within the file that marks the end of the text (optional) - - :param file_path: Path to the evaluation set file to be uploaded. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationSetClient's default workspace (self.workspace) is used. - """ - workspace_url = self._build_workspace_url(workspace) - target_url = f"{workspace_url}/evaluation_sets/import" - try: - mime_type = guess_type(str(file_path))[0] - with open(file_path, "rb") as file: - self.client.post(url=target_url, files={"file": (file_path.name, file, mime_type)}) - logger.info( - "Successfully uploaded evaluation set file %s. You can access it now under evaluation set '%s'.", - file_path, - file_path.name, - ) - except DeepsetCloudError as e: - logger.error("Error uploading evaluation set file %s: %s", file_path, e.args) - - def get_evaluation_set( - self, evaluation_set: Optional[str] = None, workspace: Optional[str] = None - ) -> Optional[Dict[str, Any]]: - """ - Returns information about the evaluation set. - - :param evaluation_set: Name of the evaluation set in deepset Cloud. - If set to None, the EvaluationSetClient's default evaluation set (self.evaluation_set) is used. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationSetClient's default workspace (self.workspace) is used. - - :return: Dictionary that represents deepset Cloud evaluation sets. - These contain ("name", "evaluation_set_id", "created_at", "matched_labels", "total_labels") as fields. - """ - url = self._build_workspace_url(workspace=workspace) - evaluation_set_url = f"{url}/evaluation_sets" - - # evaluation_sets resource uses ids instead of names, - # so we have to query by name (which works as a contains filter) and take the first entry with matching name - query_params = {} - if evaluation_set is not None: - query_params["name"] = evaluation_set - - matches = [ - entry - for entry in self.client.get_with_auto_paging(url=evaluation_set_url, query_params=query_params) - if entry["name"] == evaluation_set - ] - if any(matches): - return matches[0] - return None - - def _build_workspace_url(self, workspace: Optional[str] = None): - if workspace is None: - workspace = self.workspace - return self.client.build_workspace_url(workspace) - - -class FileClient: - def __init__(self, client: DeepsetCloudClient, workspace: Optional[str] = None): - """ - A client to manage files on deepset Cloud. - - :param client: deepset Cloud client - :param workspace: Specifies the name of the workspace for which you want to create the client. - """ - self.client = client - self.workspace = workspace - - def upload_files( - self, - file_paths: List[Path], - metas: Optional[List[Dict]] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - ): - """ - Uploads files to the deepset Cloud workspace. - - :param file_paths: File paths to upload (for example .txt or .pdf files) - :param metas: Metadata of the files to upload - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the FileClient's default workspace is used. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - files_url = f"{workspace_url}/files" - if metas is None: - metas = [{} for _ in file_paths] - - file_ids = [] - for file_path, meta in tqdm(zip(file_paths, metas), total=len(file_paths)): - try: - mime_type = guess_type(str(file_path))[0] - with open(file_path, "rb") as file: - response_file_upload = self.client.post( - url=files_url, - files={"file": (file_path.name, file, mime_type)}, - data={"meta": json.dumps(meta)}, - headers=headers, - ) - file_id = response_file_upload.json().get("file_id") - file_ids.append(file_id) - except Exception: - logger.exception("Error uploading file %s", file_path) - - logger.info("Successfully uploaded %s files.", len(file_ids)) - - def delete_file(self, file_id: str, workspace: Optional[str] = None, headers: Optional[dict] = None): - """ - Delete a file from the deepset Cloud workspace. - - :param file_id: The id of the file to be deleted. Use `list_files` to retrieve the id of a file. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the FileClient's default workspace is used. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - file_url = f"{workspace_url}/files/{file_id}" - self.client.delete(url=file_url, headers=headers) - - def delete_all_files(self, workspace: Optional[str] = None, headers: Optional[dict] = None): - """ - Delete all files from a deepset Cloud workspace. - - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the FileClient's default workspace is used. - :param headers: Headers to pass to the API call. - """ - workspace_url = self._build_workspace_url(workspace) - file_url = f"{workspace_url}/files" - self.client.delete(url=file_url, headers=headers) - - def list_files( - self, - name: Optional[str] = None, - meta_key: Optional[str] = None, - meta_value: Optional[str] = None, - workspace: Optional[str] = None, - headers: Optional[dict] = None, - ) -> Generator: - """ - List all files in the given deepset Cloud workspace. - You can filter by name or by meta values. - - :param name: The name or part of the name of the file. - :param meta_key: The key of the metadata of the file to be filtered for. - :param meta_value: The value of the metadata of the file to be filtered for. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the FileClient's default workspace is used. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - files_url = f"{workspace_url}/files" - query_params = {"name": name, "meta_key": meta_key, "meta_value": meta_value} - generator = self.client.get_with_auto_paging(url=files_url, headers=headers, query_params=query_params) - return generator - - def _build_workspace_url(self, workspace: Optional[str] = None): - if workspace is None: - workspace = self.workspace - return self.client.build_workspace_url(workspace) - - -class EvaluationRunClient: - def __init__(self, client: DeepsetCloudClient, workspace: Optional[str] = None): - """ - A client to manage deepset Cloud evaluation runs. - - :param client: deepset Cloud client - :param workspace: Specifies the name of the workspace for which you want to create the client. - """ - self.client = client - self.workspace = workspace - - def create_eval_run( - self, - eval_run_name: str, - workspace: Optional[str] = None, - pipeline_config_name: Optional[str] = None, - headers: Optional[dict] = None, - evaluation_set: Optional[str] = None, - eval_mode: Literal["integrated", "isolated"] = "integrated", - debug: bool = False, - comment: Optional[str] = None, - tags: Optional[List[str]] = None, - ) -> Dict[str, Any]: - """ - Creates an evaluation run. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param pipeline_config_name: The name of the pipeline to evaluate. - :param evaluation_set: The name of the evaluation set to use. - :param eval_mode: The evaluation mode to use. - :param debug: Whether to enable debug output. - :param comment: Comment to add about to the evaluation run. - :param tags: Tags to add to the evaluation run. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - eval_run_url = f"{workspace_url}/eval_runs" - response = self.client.post( - eval_run_url, - json={ - "pipeline_name": pipeline_config_name, - "evaluation_set_name": evaluation_set, - "debug": debug, - "eval_mode": 0 if eval_mode == "integrated" else 1, - "comment": comment, - "name": eval_run_name, - "tags": tags, - }, - headers=headers, - ) - return response.json()["data"] - - def get_eval_run( - self, eval_run_name: str, workspace: Optional[str] = None, headers: Optional[dict] = None - ) -> Dict[str, Any]: - """ - Gets the evaluation run and shows its parameters and metrics. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - eval_run_url = f"{workspace_url}/eval_runs/{eval_run_name}" - response = self.client.get(eval_run_url, headers=headers) - return response.json() - - def get_eval_runs(self, workspace: Optional[str] = None, headers: Optional[dict] = None) -> List[Dict[str, Any]]: - """ - Gets all evaluation runs and shows its parameters and metrics. - - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - eval_run_url = f"{workspace_url}/eval_runs" - response = self.client.get_with_auto_paging(eval_run_url, headers=headers) - return list(response) - - def delete_eval_run(self, eval_run_name: str, workspace: Optional[str] = None, headers: Optional[dict] = None): - """ - Deletes an evaluation run. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - eval_run_url = f"{workspace_url}/eval_runs/{eval_run_name}" - response = self.client.delete(eval_run_url, headers=headers) - if response.status_code == 204: - logger.info("Evaluation run '%s' deleted.", eval_run_name) - - def start_eval_run(self, eval_run_name: str, workspace: Optional[str] = None, headers: Optional[dict] = None): - """ - Starts an evaluation run. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - eval_run_url = f"{workspace_url}/eval_runs/{eval_run_name}/start" - response = self.client.post(eval_run_url, headers=headers) - if response.status_code == 204: - logger.info("Evaluation run '%s' has been started.", eval_run_name) - - def update_eval_run( - self, - eval_run_name: str, - workspace: Optional[str] = None, - pipeline_config_name: Optional[str] = None, - headers: Optional[dict] = None, - evaluation_set: Optional[str] = None, - eval_mode: Literal["integrated", "isolated", None] = None, - debug: Optional[bool] = None, - comment: Optional[str] = None, - tags: Optional[List[str]] = None, - ) -> Dict[str, Any]: - """ - Updates an evaluation run. - - :param eval_run_name: The name of the evaluation run to update. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the FileClient's default workspace is used. - :param pipeline_config_name: The name of the pipeline to evaluate. - :param evaluation_set: The name of the evaluation set to use. - :param eval_mode: The evaluation mode to use. - :param debug: Whether to enable debug output. - :param comment: Comment to add about to the evaluation run. - :param tags: Tags to add to the evaluation run. - :param headers: Headers to pass to the API call - """ - workspace_url = self._build_workspace_url(workspace) - eval_run_url = f"{workspace_url}/eval_runs/{eval_run_name}" - eval_mode_param = None - if eval_mode is not None: - eval_mode_param = 0 if eval_mode == "integrated" else 1 - response = self.client.patch( - eval_run_url, - json={ - "pipeline_name": pipeline_config_name, - "evaluation_set_name": evaluation_set, - "debug": debug, - "eval_mode": eval_mode_param, - "comment": comment, - "tags": tags, - }, - headers=headers, - ) - return response.json()["data"] - - def get_eval_run_results( - self, eval_run_name: str, workspace: Optional[str] = None, headers: Optional[dict] = None - ) -> Dict[str, Any]: - """ - Collects and returns the predictions of an evaluation run. - - :param eval_run_name: The name of the evaluation run to fetch results for. - :param workspace: Specifies the name of the deepset Cloud workspace where the evaluation run exists. - If set to None, the EvaluationRunClient's default workspace is used. - :param headers: The headers that you want to pass to the API call. - """ - - response = self.get_eval_run(eval_run_name, workspace, headers) - predictions_per_node = {} - for eval_result in response["eval_results"]: - predictions_per_node[eval_result["node_name"]] = self.get_eval_run_predictions( - eval_run_name=eval_run_name, node_name=eval_result["node_name"], workspace=workspace, headers=headers - ) - - return predictions_per_node - - def get_eval_run_predictions( - self, eval_run_name: str, node_name: str, workspace: Optional[str] = None, headers: Optional[dict] = None - ) -> List[Dict[str, Any]]: - """ - Fetches predictions for the evaluation run and a node name you specify. - - :param eval_run_name: The name of the evaluation run to fetch predictions for. - :param node_name: The name of the node to fetch predictions for. - :param workspace: Specifies the name of the deepset Cloud workspace where the evaluation run exists. - If set to None, the EvaluationRunClient's default workspace is used. - :param headers: The headers that you want to pass to the API call. - """ - workspace_url = self._build_workspace_url(workspace) - eval_run_prediction_url = f"{workspace_url}/eval_runs/{eval_run_name}/nodes/{node_name}/predictions" - response = self.client.get_with_auto_paging(eval_run_prediction_url, headers=headers) - return list(response) - - def _build_workspace_url(self, workspace: Optional[str] = None): - if workspace is None: - workspace = self.workspace - return self.client.build_workspace_url(workspace) - - -class DeepsetCloud: - """ - A facade to communicate with deepset Cloud. - """ - - @classmethod - def get_index_client( - cls, - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - workspace: str = "default", - index: Optional[str] = None, - ) -> IndexClient: - """ - Creates a client to communicate with deepset Cloud indexes. - - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - :param workspace: Specifies the name of the workspace for which you want to create the client. - :param index: index in deepset Cloud workspace - - """ - client = DeepsetCloudClient(api_key=api_key, api_endpoint=api_endpoint) - return IndexClient(client=client, workspace=workspace, index=index) - - @classmethod - def get_pipeline_client( - cls, - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - workspace: str = "default", - pipeline_config_name: Optional[str] = None, - ) -> PipelineClient: - """ - Creates a client to communicate with deepset Cloud pipelines. - - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - :param workspace: Specifies the name of the workspace for which you want to create the client. - :param pipeline_config_name: name of the pipeline_config in deepset Cloud workspace - - """ - client = DeepsetCloudClient(api_key=api_key, api_endpoint=api_endpoint) - return PipelineClient(client=client, workspace=workspace, pipeline_config_name=pipeline_config_name) - - @classmethod - def get_evaluation_set_client( - cls, - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - workspace: str = "default", - evaluation_set: str = "default", - ) -> EvaluationSetClient: - """ - Creates a client to communicate with deepset Cloud labels. - - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - :param workspace: Specifies the name of the workspace for which you want to create the client. - :param evaluation_set: name of the evaluation set in deepset Cloud - - """ - client = DeepsetCloudClient(api_key=api_key, api_endpoint=api_endpoint) - return EvaluationSetClient(client=client, workspace=workspace, evaluation_set=evaluation_set) - - @classmethod - def get_eval_run_client( - cls, api_key: Optional[str] = None, api_endpoint: Optional[str] = None, workspace: str = "default" - ) -> EvaluationRunClient: - """ - Creates a client to manage evaluation runs on deepset Cloud. - - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - :param workspace: Specifies the name of the workspace for which you want to create the client. - - """ - client = DeepsetCloudClient(api_key=api_key, api_endpoint=api_endpoint) - return EvaluationRunClient(client=client, workspace=workspace) - - @classmethod - def get_file_client( - cls, api_key: Optional[str] = None, api_endpoint: Optional[str] = None, workspace: str = "default" - ) -> FileClient: - """ - Creates a client to manage files on deepset Cloud. - - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - :param workspace: Specifies the name of the workspace for which you want to create the client. - - """ - client = DeepsetCloudClient(api_key=api_key, api_endpoint=api_endpoint) - return FileClient(client=client, workspace=workspace) - - -class DeepsetCloudExperiments: - """ - A facade to conduct and manage experiments within deepset Cloud. - - To start a new experiment run: - 1. Choose a pipeline to evaluate using `list_pipelines()`. - 2. Choose an evaluation set using `list_evaluation_sets()`. - 3. Create and start a new run using `create_and_start_run()`. - 4. Track the run using `get_run()`. When the run finishes, you can use the `eval_results` key in the returned dictionary to view the metrics. - 5. Inspect the result of a run in detail using `get_run_result()`. - This returns an `EvaluationResult` object containing all the predictions and gold labels in the form of pandas dataframes. - Use `calculate_metrics()` to recalculate metrics using different settings (for example, `top_k`) and `wrong_examples()` to show worst performing queries/labels. - """ - - @classmethod - def list_pipelines( - cls, workspace: str = "default", api_key: Optional[str] = None, api_endpoint: Optional[str] = None - ) -> List[dict]: - """ - Lists all pipelines available on deepset Cloud. - - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - - Returns: - list of dictionaries: List[dict] - each dictionary: { - "name": str -> `pipeline_config_name` to be used in `load_from_deepset_cloud()`, - "..." -> additional pipeline meta information - } - example: - - ```python - [{'name': 'my_super_nice_pipeline_config', - 'pipeline_id': '2184e0c1-c6ec-40a1-9b28-5d2768e5efa2', - 'status': 'DEPLOYED', - 'created_at': '2022-02-01T09:57:03.803991+00:00', - 'deleted': False, - 'is_default': False, - 'indexing': {'status': 'IN_PROGRESS', - 'pending_file_count': 3, - 'total_file_count': 31}}] - ``` - - """ - client = DeepsetCloud.get_pipeline_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - pipeline_config_infos = list(client.list_pipeline_configs()) - return pipeline_config_infos - - @classmethod - def list_evaluation_sets( - cls, workspace: str = "default", api_key: Optional[str] = None, api_endpoint: Optional[str] = None - ) -> List[dict]: - """ - Lists all evaluation sets available on deepset Cloud. - - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - - Returns: - list of dictionaries: List[dict] - each dictionary: { - "name": str -> `evaluation_set` to be used in `create_run()`, - "..." -> additional pipeline meta information - } - example: - - ```python - [{'evaluation_set_id': 'fb084729-57ad-4b57-9f78-ec0eb4d29c9f', - 'name': 'my-question-answering-evaluation-set', - 'created_at': '2022-05-06T09:54:14.830529+00:00', - 'matched_labels': 234, - 'total_labels': 234}] - ``` - """ - client = DeepsetCloud.get_evaluation_set_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - return client.get_evaluation_sets() - - @classmethod - def get_runs( - cls, workspace: str = "default", api_key: Optional[str] = None, api_endpoint: Optional[str] = None - ) -> List[dict]: - """ - Gets all evaluation runs. - - :param workspace: Specifies the name of the workspace on deepset Cloud. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - - Returns: - list of dictionaries: List[dict] - example: - - ```python - [{'eval_run_name': 'my-eval-run-1', - 'parameters': { - 'pipeline_name': 'my-pipeline-1_696bc5d0-ee65-46c1-a308-059507bc353b', - 'evaluation_set_name': 'my-eval-set-name', - 'debug': False, - 'eval_mode': 0 - }, - 'metrics': { - 'isolated_exact_match': 0.45, - 'isolated_f1': 0.89, - 'isolated_sas': 0.91, - 'integrated_exact_match': 0.39, - 'integrated_f1': 0.76, - 'integrated_sas': 0.78, - 'mean_reciprocal_rank': 0.77, - 'mean_average_precision': 0.78, - 'recall_single_hit': 0.91, - 'recall_multi_hit': 0.91, - 'normal_discounted_cummulative_gain': 0.83, - 'precision': 0.52 - }, - 'logs': {}, - 'status': 1, - 'eval_mode': 0, - 'eval_run_labels': [], - 'created_at': '2022-05-24T12:13:16.445857+00:00', - 'comment': 'This is a comment about thiseval run', - 'tags': ['experiment-1', 'experiment-2', 'experiment-3'] - }] - ``` - """ - client = DeepsetCloud.get_eval_run_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - return client.get_eval_runs() - - @classmethod - def create_run( - cls, - eval_run_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - pipeline_config_name: Optional[str] = None, - evaluation_set: Optional[str] = None, - eval_mode: Literal["integrated", "isolated"] = "integrated", - debug: bool = False, - comment: Optional[str] = None, - tags: Optional[List[str]] = None, - ) -> Dict[str, Any]: - """ - Creates an evaluation run. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param pipeline_config_name: The name of the pipeline to evaluate. Use `list_pipelines()` to list all available pipelines. - :param evaluation_set: The name of the evaluation set to use. Use `list_evaluation_sets()` to list all available evaluation sets. - :param eval_mode: The evaluation mode to use. - :param debug: Whether to enable debug output. - :param comment: Comment to add about to the evaluation run. - :param tags: Tags to add to the evaluation run. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - client = DeepsetCloud.get_eval_run_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - return client.create_eval_run( - eval_run_name=eval_run_name, - pipeline_config_name=pipeline_config_name, - evaluation_set=evaluation_set, - eval_mode=eval_mode, - debug=debug, - comment=comment, - tags=tags, - ) - - @classmethod - def update_run( - cls, - eval_run_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - pipeline_config_name: Optional[str] = None, - evaluation_set: Optional[str] = None, - eval_mode: Literal["integrated", "isolated"] = "integrated", - debug: bool = False, - comment: Optional[str] = None, - tags: Optional[List[str]] = None, - ) -> Dict[str, Any]: - """ - Updates an evaluation run. - - :param eval_run_name: The name of the evaluation run to update. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the FileClient's default workspace is used. - :param pipeline_config_name: The name of the pipeline to evaluate. Use `list_pipelines()` to list all available pipelines. - :param evaluation_set: The name of the evaluation set to use. Use `list_evaluation_sets()` to list all available evaluation sets. - :param eval_mode: The evaluation mode to use. - :param debug: Whether to enable debug output. - :param comment: Comment to add about to the evaluation run. - :param tags: Tags to add to the evaluation run. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - client = DeepsetCloud.get_eval_run_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - return client.update_eval_run( - eval_run_name=eval_run_name, - pipeline_config_name=pipeline_config_name, - evaluation_set=evaluation_set, - eval_mode=eval_mode, - debug=debug, - comment=comment, - tags=tags, - ) - - @classmethod - def get_run( - cls, - eval_run_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - ) -> Dict[str, Any]: - """ - Gets the evaluation run and shows its parameters and metrics. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - client = DeepsetCloud.get_eval_run_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - return client.get_eval_run(eval_run_name=eval_run_name) - - @classmethod - def delete_run( - cls, - eval_run_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - ): - """ - Deletes an evaluation run. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - client = DeepsetCloud.get_eval_run_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - return client.delete_eval_run(eval_run_name=eval_run_name) - - @classmethod - def start_run( - cls, - eval_run_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - ): - """ - Starts an evaluation run. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - client = DeepsetCloud.get_eval_run_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - client.start_eval_run(eval_run_name=eval_run_name) - logger.info("You can check run progress by inspecting the `status` field returned from `get_run()`.") - - @classmethod - def create_and_start_run( - cls, - eval_run_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - pipeline_config_name: Optional[str] = None, - evaluation_set: Optional[str] = None, - eval_mode: Literal["integrated", "isolated"] = "integrated", - debug: bool = False, - comment: Optional[str] = None, - tags: Optional[List[str]] = None, - ): - """ - Creates and starts an evaluation run. - - :param eval_run_name: The name of the evaluation run. - :param workspace: Specifies the name of the workspace on deepset Cloud. - If set to None, the EvaluationRunClient's default workspace is used. - :param pipeline_config_name: The name of the pipeline to evaluate. Use `list_pipelines()` to list all available pipelines. - :param evaluation_set: The name of the evaluation set to use. Use `list_evaluation_sets()` to list all available evaluation sets. - :param eval_mode: The evaluation mode to use. - :param debug: Whether to enable debug output. - :param comment: Comment to add about to the evaluation run. - :param tags: Tags to add to the evaluation run. - :param api_key: Secret value of the API key. - If not specified, it's read from DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from DEEPSET_CLOUD_API_ENDPOINT environment variable. - If environment variable is not set, defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - cls.create_run( - eval_run_name=eval_run_name, - workspace=workspace, - api_key=api_key, - api_endpoint=api_endpoint, - pipeline_config_name=pipeline_config_name, - evaluation_set=evaluation_set, - eval_mode=eval_mode, - debug=debug, - comment=comment, - tags=tags, - ) - cls.start_run(eval_run_name=eval_run_name, workspace=workspace, api_key=api_key, api_endpoint=api_endpoint) - - @classmethod - def get_run_result( - cls, - eval_run_name: str, - workspace: str = "default", - api_key: Optional[str] = None, - api_endpoint: Optional[str] = None, - ) -> EvaluationResult: - """ - Fetches the results of an evaluation run and turns them into an EvaluationResult object. - - :param eval_run_name: The name of the evaluation run whose results you want to fetch. - :param workspace: Specifies the name of the deepset Cloud workspace where the evaluation run exists. - If set to None, the EvaluationRunClient's default workspace is used. - :param api_key: Secret value of the API key. - If not specified, it's read from the DEEPSET_CLOUD_API_KEY environment variable. - :param api_endpoint: The URL of the deepset Cloud API. - If not specified, it's read from the DEEPSET_CLOUD_API_ENDPOINT environment variable. - If the environment variable is not set, it defaults to 'https://api.cloud.deepset.ai/api/v1'. - """ - client = DeepsetCloud.get_eval_run_client(api_key=api_key, api_endpoint=api_endpoint, workspace=workspace) - results = client.get_eval_run_results(eval_run_name=eval_run_name, workspace=workspace) - - # cast node results in-memory from json to pandas dataframe - results = {node_name: pd.DataFrame(node_predictions) for node_name, node_predictions in results.items()} - - return EvaluationResult(results) diff --git a/haystack/utils/doc_store.py b/haystack/utils/doc_store.py deleted file mode 100644 index a510931b48..0000000000 --- a/haystack/utils/doc_store.py +++ /dev/null @@ -1,127 +0,0 @@ -import time -import logging -import subprocess -from typing import Optional - - -logger = logging.getLogger(__name__) -ELASTICSEARCH_CONTAINER_NAME = "elasticsearch" -OPENSEARCH_CONTAINER_NAME = "opensearch" -WEAVIATE_CONTAINER_NAME = "weaviate" - - -def launch_es(sleep=15, delete_existing=False, java_opts: Optional[str] = None): - """ - Start an Elasticsearch server via Docker. - """ - - logger.debug("Starting Elasticsearch ...") - if delete_existing: - _ = subprocess.run([f"docker rm --force {ELASTICSEARCH_CONTAINER_NAME}"], shell=True, stdout=subprocess.DEVNULL) - - java_opts_str = f"-e ES_JAVA_OPTS='{java_opts}' " if java_opts is not None else "" - - command = ( - f"docker start {ELASTICSEARCH_CONTAINER_NAME} > /dev/null 2>&1 || docker run -d " - f'-p 9200:9200 -p 9600:9600 -e "discovery.type=single-node" ' - f"{java_opts_str}" - f"--name {ELASTICSEARCH_CONTAINER_NAME} elasticsearch:7.17.6" - ) - - status = subprocess.run([command], shell=True) - if status.returncode: - logger.warning( - "Tried to start Elasticsearch through Docker but this failed. " - "It is likely that there is already an existing Elasticsearch instance running. " - ) - else: - time.sleep(sleep) - - -def launch_opensearch(sleep=15, delete_existing=False, local_port=9200, java_opts: Optional[str] = None): - """ - Start an OpenSearch server via Docker. - """ - logger.debug("Starting OpenSearch...") - # This line is needed since it is not possible to start a new docker container with the name opensearch if there is a stopped image with the same now - # docker rm only succeeds if the container is stopped, not if it is running - if delete_existing: - _ = subprocess.run([f"docker rm --force {OPENSEARCH_CONTAINER_NAME}"], shell=True, stdout=subprocess.DEVNULL) - - java_opts_str = f"-e OPENSEARCH_JAVA_OPTS='{java_opts}' " if java_opts is not None else "" - - command = ( - f"docker start {OPENSEARCH_CONTAINER_NAME} > /dev/null 2>&1 || docker run -d " - f'-p {local_port}:9200 -p 9600:9600 -e "discovery.type=single-node" ' - f"{java_opts_str}" - f"--name {OPENSEARCH_CONTAINER_NAME} opensearchproject/opensearch:1.3.5" - ) - - status = subprocess.run([command], shell=True) - if status.returncode: - logger.warning( - "Tried to start OpenSearch through Docker but this failed. " - "It is likely that there is already an existing OpenSearch instance running. " - ) - else: - time.sleep(sleep) - - -def launch_weaviate(sleep=15, delete_existing=False): - """ - Start a Weaviate server via Docker. - """ - - logger.debug("Starting Weaviate ...") - if delete_existing: - _ = subprocess.run([f"docker rm --force {WEAVIATE_CONTAINER_NAME}"], shell=True, stdout=subprocess.DEVNULL) - status = subprocess.run( - [ - f"docker start {WEAVIATE_CONTAINER_NAME} > /dev/null 2>&1 || docker run -d -p 8080:8080 --env AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED='true' --env PERSISTENCE_DATA_PATH='/var/lib/weaviate' --name {WEAVIATE_CONTAINER_NAME} semitechnologies/weaviate:latest" - ], - shell=True, - ) - if status.returncode: - logger.warning( - "Tried to start Weaviate through Docker but this failed. " - "It is likely that there is already an existing Weaviate instance running. " - ) - else: - time.sleep(sleep) - - -def stop_container(container_name, delete_container=False): - logger.debug("Stopping %s...", container_name) - status = subprocess.run([f"docker stop {container_name}"], shell=True) - if status.returncode: - logger.warning( - "Tried to stop %s but this failed. It is likely that there was no Docker container with the name %s", - container_name, - container_name, - ) - if delete_container: - status = subprocess.run([f"docker rm {container_name}"], shell=True) - - -def stop_opensearch(delete_container=False): - stop_container(OPENSEARCH_CONTAINER_NAME, delete_container) - - -def stop_elasticsearch(delete_container=False): - stop_container(ELASTICSEARCH_CONTAINER_NAME, delete_container) - - -def stop_weaviate(delete_container=False): - stop_container(WEAVIATE_CONTAINER_NAME, delete_container) - - -def stop_service(document_store, delete_container=False): - ds_class = str(type(document_store)) - if "OpenSearchDocumentStore" in ds_class: - stop_opensearch(delete_container) - elif "ElasticsearchDocumentStore" in ds_class: - stop_elasticsearch(delete_container) - elif "WeaviateDocumentStore" in ds_class: - stop_weaviate(delete_container) - else: - logger.warning("No support yet for auto stopping the service behind a %s", type(document_store)) diff --git a/haystack/utils/docker.py b/haystack/utils/docker.py deleted file mode 100644 index 21bb4192df..0000000000 --- a/haystack/utils/docker.py +++ /dev/null @@ -1,50 +0,0 @@ -import logging -from typing import List, Union, Optional -from haystack.nodes._json_schema import load_schema - - -logger = logging.getLogger(__name__) - - -def cache_nltk_model(model: str = "punkt"): - logger.info("Caching %s model...", model) - import nltk - - nltk.download(model) - - -def cache_models(models: Optional[List[str]] = None, use_auth_token: Optional[Union[str, bool]] = None): - """ - Small function that caches models and other data. - Used only in the Dockerfile to include these caches in the images. - - :param models: List of Hugging Face model names to cache - :param use_auth_token: The API token used to download private models from Huggingface. - If this parameter is set to `True`, then the token generated when running - `transformers-cli login` (stored in ~/.huggingface) will be used. - Additional information can be found here - https://huggingface.co/transformers/main_classes/model.html#transformers.PreTrainedModel.from_pretrained - """ - # Backward compat after adding the `model` param - if models is None: - models = ["deepset/roberta-base-squad2"] - - # Cache models - import transformers - - for model_to_cache in models: - logger.info("Caching %s", model_to_cache) - transformers.AutoTokenizer.from_pretrained(model_to_cache, use_auth_token=use_auth_token) - transformers.AutoModel.from_pretrained(model_to_cache, use_auth_token=use_auth_token) - - -def cache_schema(): - """ - Generate and persist Haystack JSON schema. - - The schema is lazily generated at first usage, but this might not work in Docker containers - when the user running Haystack doesn't have write permissions on the Python installation. By - calling this function at Docker image build time, the schema is generated once for all. - """ - # Calling load_schema() will generate the schema as a side effect - load_schema() diff --git a/haystack/utils/early_stopping.py b/haystack/utils/early_stopping.py deleted file mode 100644 index 8bfe74671b..0000000000 --- a/haystack/utils/early_stopping.py +++ /dev/null @@ -1,99 +0,0 @@ -import logging - -from typing import Optional, Tuple, List, Dict, Callable, Union, Literal - - -logger = logging.getLogger(__name__) - - -class EarlyStopping: - """ - An object you can to control early stopping with a Node's `train()` method or a Trainer class. You can use a custom - EarlyStopping class instead as long as it implements the method `check_stopping()` and provides the attribute - `save_dir`. - """ - - def __init__( - self, - head: int = 0, - metric: Union[str, Callable] = "loss", - save_dir: Optional[str] = None, - mode: Literal["min", "max"] = "min", - patience: int = 0, - min_delta: float = 0.001, - min_evals: int = 0, - ): - """ - :param head: The index of the prediction head that you are evaluating to determine the chosen `metric`. - In Haystack, the large majority of the models are trained from the loss signal of a single prediction - head so the default value of 0 should work in most cases. - :param save_dir: The directory where to save the final best model. If you set it to None, the model is not saved. - :param metric: The name of a dev set metric to monitor (default: loss) which is extracted from the prediction - head specified by the variable `head`, or a function that extracts a value from the trainer dev evaluation - result. - For FARMReader training, some available metrics to choose from are "EM", "f1", and "top_n_accuracy". - For DensePassageRetriever training, some available metrics to choose from are "acc", "f1", and "average_rank". - NOTE: This is different from the metric that is specified in the Processor which defines how to calculate - one or more evaluation metric values from the prediction and target sets. The metric variable in this - function specifies the name of one particular metric value, or it is a method to calculate a value from - the result returned by the Processor metric. - :param mode: When set to "min", training stops if the metric does not continue to decrease. When set to "max", - training stops if the metric does not continue to increase. - :param patience: How many evaluations with no improvement to perform before stopping training. - :param min_delta: Minimum difference to the previous best value to count as an improvement. - :param min_evals: Minimum number of evaluations to perform before checking that the evaluation metric is - improving. - """ - self.head = head - self.metric = metric - self.save_dir = save_dir - self.mode = mode - self.patience = patience - self.min_delta = min_delta - self.min_evals = min_evals - # for more complex modes - self.eval_values = [] # type: List - self.n_since_best = None # type: Optional[int] - if mode == "min": - self.best_so_far = 1.0e99 - elif mode == "max": - self.best_so_far = -1.0e99 - else: - raise ValueError("Mode must be 'min' or 'max'") - - def check_stopping(self, eval_result: List[Dict]) -> Tuple[bool, bool, float]: - """ - Provides the evaluation value for the current evaluation. Returns true if stopping should occur. - This saves the model if you provided `self.save_dir` when initializing `EarlyStopping`. - - :param eval_result: The current evaluation result which consists of a list of dictionaries, one for each - prediction head. Each dictionary contains the metrics and reports generated during evaluation. - :return: A tuple (stopprocessing, savemodel, eval_value) indicating if processing should be stopped - and if the current model should get saved and the evaluation value used. - """ - if isinstance(self.metric, str): - eval_value = float(eval_result[self.head][self.metric]) - else: - eval_value = float(self.metric(eval_result)) - self.eval_values.append(eval_value) - - stopprocessing, savemodel = False, False - if len(self.eval_values) <= self.min_evals: - return stopprocessing, savemodel, eval_value - - if self.mode == "min": - delta = self.best_so_far - eval_value - else: - delta = eval_value - self.best_so_far - - if delta > self.min_delta: - self.best_so_far = eval_value - self.n_since_best = 0 - if self.save_dir: - savemodel = True - else: - self.n_since_best += 1 # type: ignore - - if self.n_since_best > self.patience: - stopprocessing = True - return stopprocessing, savemodel, eval_value diff --git a/haystack/utils/experiment_tracking.py b/haystack/utils/experiment_tracking.py deleted file mode 100644 index 2a9f8d1ef4..0000000000 --- a/haystack/utils/experiment_tracking.py +++ /dev/null @@ -1,285 +0,0 @@ -from typing import Optional, Any, Dict, Union - -from abc import ABC, abstractmethod -import logging -from pathlib import Path -import os -import platform -import sys - -from requests.exceptions import ConnectionError - -from haystack import __version__ -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install transformers[torch]'") as transformers_import: - import torch - import transformers - -with LazyImport("Run Run 'pip install farm-haystack[metrics]'") as mlflow_import: - import mlflow # pylint: disable=import-error - - -logger = logging.getLogger(__name__) - - -def flatten_dict(dict_to_flatten: dict, prefix: str = ""): - flat_dict = {} - for k, v in dict_to_flatten.items(): - if isinstance(v, dict): - flat_dict.update(flatten_dict(v, prefix + k + "_")) - else: - flat_dict[prefix + k] = v - return flat_dict - - -class BaseTrackingHead(ABC): - """ - Base class for tracking experiments. - - This class can be extended to implement custom logging backends like MLflow, WandB, or TensorBoard. - """ - - @abstractmethod - def init_experiment( - self, - experiment_name: str, - run_name: Optional[str] = None, - tags: Optional[Dict[str, Any]] = None, - nested: bool = False, - ): - raise NotImplementedError() - - @abstractmethod - def track_metrics(self, metrics: Dict[str, Any], step: int): - raise NotImplementedError() - - @abstractmethod - def track_artifacts(self, dir_path: Union[str, Path], artifact_path: Optional[str] = None): - raise NotImplementedError() - - @abstractmethod - def track_params(self, params: Dict[str, Any]): - raise NotImplementedError() - - @abstractmethod - def end_run(self): - raise NotImplementedError() - - -class NoTrackingHead(BaseTrackingHead): - """ - Null object implementation of a tracking head: i.e. does nothing. - """ - - def init_experiment( - self, - experiment_name: str, - run_name: Optional[str] = None, - tags: Optional[Dict[str, Any]] = None, - nested: bool = False, - ): - pass - - def track_metrics(self, metrics: Dict[str, Any], step: int): - pass - - def track_artifacts(self, dir_path: Union[str, Path], artifact_path: Optional[str] = None): - pass - - def track_params(self, params: Dict[str, Any]): - pass - - def end_run(self): - pass - - -class Tracker: - """ - Facade for tracking experiments. - """ - - tracker: BaseTrackingHead = NoTrackingHead() - - @classmethod - def init_experiment( - cls, - experiment_name: str, - run_name: Optional[str] = None, - tags: Optional[Dict[str, Any]] = None, - nested: bool = False, - ): - cls.tracker.init_experiment(experiment_name=experiment_name, run_name=run_name, tags=tags, nested=nested) - - @classmethod - def track_metrics(cls, metrics: Dict[str, Any], step: int): - cls.tracker.track_metrics(metrics=metrics, step=step) - - @classmethod - def track_artifacts(cls, dir_path: Union[str, Path], artifact_path: Optional[str] = None): - cls.tracker.track_artifacts(dir_path=dir_path, artifact_path=artifact_path) - - @classmethod - def track_params(cls, params: Dict[str, Any]): - cls.tracker.track_params(params=params) - - @classmethod - def end_run(cls): - cls.tracker.end_run() - - @classmethod - def set_tracking_head(cls, tracker: BaseTrackingHead): - cls.tracker = tracker - - -class StdoutTrackingHead(BaseTrackingHead): - """ - Experiment tracking head printing metrics and params to stdout. - Useful for services like AWS SageMaker, where you parse metrics from the actual logs - """ - - def init_experiment( - self, - experiment_name: str, - run_name: Optional[str] = None, - tags: Optional[Dict[str, Any]] = None, - nested: bool = False, - ): - logger.info("\n **** Starting experiment '%s' (Run: %s) ****", experiment_name, run_name) - - def track_metrics(self, metrics: Dict[str, Any], step: int): - logger.info("Logged metrics at step %s: \n %s", step, metrics) - - def track_params(self, params: Dict[str, Any]): - logger.info("Logged parameters: \n %s", params) - - def track_artifacts(self, dir_path: Union[str, Path], artifact_path: Optional[str] = None): - logger.warning("Cannot log artifacts with StdoutLogger: \n %s", dir_path) - - def end_run(self): - logger.info("**** End of Experiment **** ") - - -class MLflowTrackingHead(BaseTrackingHead): - def __init__(self, tracking_uri: str, auto_track_environment: bool = True) -> None: - """ - Experiment tracking head for MLflow. - """ - mlflow_import.check() - super().__init__() - self.tracking_uri = tracking_uri - self.auto_track_environment = auto_track_environment - - def init_experiment( - self, - experiment_name: str, - run_name: Optional[str] = None, - tags: Optional[Dict[str, Any]] = None, - nested: bool = False, - ): - try: - mlflow.set_tracking_uri(self.tracking_uri) - mlflow.set_experiment(experiment_name) - mlflow.start_run(run_name=run_name, nested=nested, tags=tags) - logger.info( - "Tracking run %s of experiment %s by mlflow under %s", run_name, experiment_name, self.tracking_uri - ) - if self.auto_track_environment: - mlflow.log_params(flatten_dict({"environment": get_or_create_env_meta_data()})) - except ConnectionError: - raise Exception( - f"MLflow cannot connect to the remote server at {self.tracking_uri}.\n" - f"MLflow also supports logging runs locally to files. Set the MLflowTrackingHead " - f"tracking_uri to an empty string to use that." - ) - - def track_metrics(self, metrics: Dict[str, Any], step: int): - try: - metrics = flatten_dict(metrics) - mlflow.log_metrics(metrics, step=step) - except ConnectionError: - logger.warning("ConnectionError in logging metrics to MLflow.") - except Exception as e: - logger.warning("Failed to log metrics: %s", e) - - def track_params(self, params: Dict[str, Any]): - try: - params = flatten_dict(params) - mlflow.log_params(params) - except ConnectionError: - logger.warning("ConnectionError in logging params to MLflow") - except Exception as e: - logger.warning("Failed to log params: %s", e) - - def track_artifacts(self, dir_path: Union[str, Path], artifact_path: Optional[str] = None): - try: - mlflow.log_artifacts(dir_path, artifact_path) - except ConnectionError: - logger.warning("ConnectionError in logging artifacts to MLflow") - except Exception as e: - logger.warning("Failed to log artifacts: %s", e) - - def end_run(self): - mlflow.end_run() - - -env_meta_data: Dict[str, Any] = {} - - -def get_or_create_env_meta_data() -> Dict[str, Any]: - """ - Collects meta data about the setup that is used with Haystack, such as: operating system, python version, - Haystack version, transformers version, pytorch version, number of GPUs, execution environment, and the value - stored in the env variable HAYSTACK_EXECUTION_CONTEXT. - """ - transformers_import.check() - from haystack.telemetry import HAYSTACK_EXECUTION_CONTEXT - - global env_meta_data # pylint: disable=global-statement - has_mps = ( - hasattr(torch.backends, "mps") - and torch.backends.mps.is_available() - and os.getenv("HAYSTACK_MPS_ENABLED", "true") != "false" - ) - if not env_meta_data: - env_meta_data = { - "os_version": platform.release(), - "os_family": platform.system(), - "os_machine": platform.machine(), - "python_version": platform.python_version(), - "haystack_version": __version__, - "transformers_version": transformers.__version__, - "torch_version": torch.__version__, - "torch_cuda_version": torch.version.cuda if torch.cuda.is_available() else 0, - "n_gpu": torch.cuda.device_count() if torch.cuda.is_available() else 1 if has_mps else 0, - "n_cpu": os.cpu_count(), - "context": os.environ.get(HAYSTACK_EXECUTION_CONTEXT), - "execution_env": _get_execution_environment(), - } - return env_meta_data - - -def _get_execution_environment(): - """ - Identifies the execution environment that Haystack is running in. - Options are: colab notebook, kubernetes, CPU/GPU docker container, test environment, jupyter notebook, python script - """ - from haystack.telemetry import HAYSTACK_DOCKER_CONTAINER - - if os.environ.get("CI", "False").lower() == "true": - execution_env = "ci" - elif "google.colab" in sys.modules: - execution_env = "colab" - elif "KUBERNETES_SERVICE_HOST" in os.environ: - execution_env = "kubernetes" - elif HAYSTACK_DOCKER_CONTAINER in os.environ: - execution_env = os.environ.get(HAYSTACK_DOCKER_CONTAINER) - # check if pytest is imported - elif "pytest" in sys.modules: - execution_env = "test" - else: - try: - execution_env = get_ipython().__class__.__name__ # pylint: disable=undefined-variable - except NameError: - execution_env = "script" - return execution_env diff --git a/haystack/utils/export_utils.py b/haystack/utils/export_utils.py deleted file mode 100644 index 182dff0839..0000000000 --- a/haystack/utils/export_utils.py +++ /dev/null @@ -1,223 +0,0 @@ -from typing import Dict, Any, List, Optional - -import json -import pprint -import logging -from collections import defaultdict - -import pandas as pd - -from haystack.schema import Document, Answer - - -logger = logging.getLogger(__name__) - - -def print_answers(results: dict, details: str = "all", max_text_len: Optional[int] = None): - """ - Utility function to print results of Haystack pipelines - :param results: Results that the pipeline returned. - :param details: Defines the level of details to print. Possible values: minimum, medium, all. - :param max_text_len: Specifies the maximum allowed length for a text field. If you don't want to shorten the text, set this value to None. - :return: None - """ - # Defines the fields to keep in the Answer for each detail level - fields_to_keep_by_level = { - "minimum": {Answer: ["answer", "context"]}, - "medium": {Answer: ["answer", "context", "score"]}, - } - - if not "answers" in results.keys(): - raise ValueError( - "The results object does not seem to come from a Reader: " - f"it does not contain the 'answers' key, but only: {results.keys()}. " - "Try print_documents or print_questions." - ) - - pp = pprint.PrettyPrinter(indent=4) - - queries = [] - if "query" in results.keys(): # results came from a `run` call - queries = [results["query"]] - answers_lists = [results["answers"]] - elif "queries" in results.keys(): # results came from a `run_batch` call - queries = results["queries"] - answers_lists = results["answers"] - - for query_idx, answers in enumerate(answers_lists): - # Filter the results by detail level - filtered_answers = [] - if details in fields_to_keep_by_level.keys(): - for ans in answers: - filtered_ans = { - field: getattr(ans, field) - for field in fields_to_keep_by_level[details][type(ans)] - if getattr(ans, field) is not None - } - filtered_answers.append(filtered_ans) - elif details == "all": - filtered_answers = answers - else: - valid_values = ", ".join(fields_to_keep_by_level.keys()) + " and 'all'" - logging.warn("print_answers received details='%s', which was not understood. ", details) - logging.warn("Valid values are %s. Using 'all'.", valid_values) - filtered_answers = answers - - # Shorten long text fields - if max_text_len is not None: - for ans in answers: - if getattr(ans, "context") and len(ans.context) > max_text_len: - ans.context = ans.context[:max_text_len] + "..." - - if len(queries) > 0: - pp.pprint(f"Query: {queries[query_idx]}") - pp.pprint("Answers:") - pp.pprint(filtered_answers) - - -def print_documents( - results: dict, max_text_len: Optional[int] = None, print_name: bool = True, print_meta: bool = False -): - """ - Utility that prints a compressed representation of the documents returned by a pipeline. - :param max_text_len: Shorten the document's content to a maximum number of characters. When set to `None`, the document is not shortened. - :param print_name: Whether to print the document's name from the metadata. - :param print_meta: Whether to print the document's metadata. - """ - print(f"\nQuery: {results['query']}\n") - pp = pprint.PrettyPrinter(indent=4) - - # Verify that the input contains Documents under the `document` key - if any(not isinstance(doc, Document) for doc in results["documents"]): - raise ValueError( - "This results object does not contain `Document` objects under the `documents` key. " - "Please make sure the last node of your pipeline makes proper use of the " - "new Haystack primitive objects, and if you're using Haystack nodes/pipelines only, " - "please report this as a bug." - ) - - for doc in results["documents"]: - content = doc.content - if max_text_len: - content = doc.content[:max_text_len] + ("..." if len(doc.content) > max_text_len else "") - results = {"content": content} - if print_name: - results["name"] = doc.meta.get("name", None) - if print_meta: - results["meta"] = doc.meta - pp.pprint(results) - print() - - -def print_questions(results: dict): - """ - Utility to print the output of a question generating pipeline in a readable format. - """ - if "generated_questions" in results.keys(): - print("\nGenerated questions:") - for result in results["generated_questions"]: - for question in result["questions"]: - print(f" - {question}") - - elif "queries" in results.keys() and "answers" in results.keys(): - print("\nGenerated pairs:") - for query, answers in zip(results["queries"], results["answers"]): - print(f" - Q: {query}") - for answer in answers: - # Verify that the pairs contains Answers under the `answer` key - if not isinstance(answer, Answer): - raise ValueError( - "This results object does not contain `Answer` objects under the `answers` " - "key of the generated question/answer pairs. " - "Please make sure the last node of your pipeline makes proper use of the " - "new Haystack primitive objects, and if you're using Haystack nodes/pipelines only, " - "please report this as a bug." - ) - print(f" A: {answer.answer}") - - else: - raise ValueError( - "This object does not seem to be the output " - "of a question generating pipeline: does not contain neither " - f"'generated_questions' nor 'results', but only: {results.keys()}. " - " Try `print_answers` or `print_documents`." - ) - - -def export_answers_to_csv(agg_results: list, output_file): - """ - Exports answers coming from finder.get_answers() to a CSV file. - :param agg_results: A list of predictions coming from finder.get_answers(). - :param output_file: The name of the output file. - :return: None - """ - if isinstance(agg_results, dict): - agg_results = [agg_results] - - assert "query" in agg_results[0], f"Wrong format used for {agg_results[0]}" - assert "answers" in agg_results[0], f"Wrong format used for {agg_results[0]}" - - data = {} # type: Dict[str, List[Any]] - data["query"] = [] - data["prediction"] = [] - data["prediction_rank"] = [] - data["prediction_context"] = [] - - for res in agg_results: - for i in range(len(res["answers"])): - temp = res["answers"][i] - data["query"].append(res["query"]) - data["prediction"].append(temp.answer) - data["prediction_rank"].append(i + 1) - data["prediction_context"].append(temp.context) - - df = pd.DataFrame(data) - df.to_csv(output_file, index=False) - - -def convert_labels_to_squad(labels_file: str): - """ - Convert the export from the labeling UI to the SQuAD format for training. - - :param labels_file: The path to the file containing labels. - :return: - """ - from haystack.document_stores.sql import DocumentORM # type: ignore[attr-defined] - - with open(labels_file, encoding="utf-8") as label_file: - labels = json.load(label_file) - - labels_grouped_by_documents = defaultdict(list) - for label in labels: - labels_grouped_by_documents[label["document_id"]].append(label) - - labels_in_squad_format = {"data": []} # type: Dict[str, Any] - for document_id, labels in labels_grouped_by_documents.items(): - qas = [] - for label in labels: - doc = DocumentORM.query.get(label["document_id"]) - - assert doc.content[label["start_offset"] : label["end_offset"]] == label["selected_text"] - - qas.append( - { - "question": label["question"], - "id": label["id"], - "question_id": label["question_id"], - "answers": [ - { - "text": label["selected_text"], - "answer_start": label["start_offset"], - "labeller_id": label["labeler_id"], - } - ], - "is_impossible": False, - } - ) - - squad_format_label = {"paragraphs": [{"qas": qas, "context": doc.content, "document_id": document_id}]} - - labels_in_squad_format["data"].append(squad_format_label) - - with open("labels_in_squad_format.json", "w+", encoding="utf-8") as outfile: - json.dump(labels_in_squad_format, outfile) diff --git a/haystack/utils/getting_started.py b/haystack/utils/getting_started.py deleted file mode 100644 index cd54e7169d..0000000000 --- a/haystack/utils/getting_started.py +++ /dev/null @@ -1,84 +0,0 @@ -import logging -import os - -from haystack.utils import convert_files_to_docs -from haystack.utils import fetch_archive_from_http - -logger = logging.getLogger(__name__) - - -def build_pipeline(provider, API_KEY, document_store): - # Importing top-level causes a circular import - from haystack.nodes import AnswerParser, PromptNode, PromptTemplate, BM25Retriever - from haystack.pipelines import Pipeline - - provider = provider.lower() - # A retriever selects the right documents when given a question. - retriever = BM25Retriever(document_store=document_store, top_k=5) - # Load prompt for doing retrieval augmented generation from https://prompthub.deepset.ai/?prompt=deepset%2Fquestion-answering-with-references - question_answering_with_references = PromptTemplate( - prompt="deepset/question-answering-with-references", - output_parser=AnswerParser(reference_pattern=r"Document\[(\d+)\]"), - ) - # Load the LLM model - if provider == "anthropic": - prompt_node = PromptNode( - model_name_or_path="claude-2", api_key=API_KEY, default_prompt_template=question_answering_with_references - ) - elif provider == "cohere": - prompt_node = PromptNode( - model_name_or_path="command", api_key=API_KEY, default_prompt_template=question_answering_with_references - ) - elif provider == "huggingface": - # TODO: swap out for meta-llama/Llama-2-7b-chat-hf or the 40b model once supported in Haystack+HF API free tier - # The tiiuae/falcon-7b-instruct model cannot handle a complex prompt with references, so we use a very simple one - simple_QA = PromptTemplate( - prompt="deepset/question-answering", output_parser=AnswerParser(reference_pattern=r"Document\[(\d+)\]") - ) - prompt_node = PromptNode( - model_name_or_path="tiiuae/falcon-7b-instruct", api_key=API_KEY, default_prompt_template=simple_QA - ) - elif provider == "openai": - prompt_node = PromptNode( - model_name_or_path="gpt-3.5-turbo-0301", - api_key=API_KEY, - default_prompt_template=question_answering_with_references, - ) - else: - logger.error('Given unknown. Please use any of "anthropic", "cohere", "huggingface", or "openai"') - # Compose the query pipeline - query_pipeline = Pipeline() - query_pipeline.add_node(component=retriever, name="retriever", inputs=["Query"]) - query_pipeline.add_node(component=prompt_node, name="prompt_node", inputs=["retriever"]) - - return query_pipeline - - -def add_example_data(document_store, dir): - # Importing top-level causes a circular import - from haystack.nodes import TextConverter, PreProcessor - - if dir == "data/GoT_getting_started": - # Download and add Game of Thrones TXT files - fetch_archive_from_http( - url="https://s3.eu-central-1.amazonaws.com/deepset.ai-farm-qa/datasets/documents/wiki_gameofthrones_txt.zip", - output_dir=dir, - ) - files_to_index = [dir + "/" + f for f in os.listdir(dir)] - converter = TextConverter(remove_numeric_tables=True) - docs = [converter.convert(file_path=file, meta=None)[0] for file in files_to_index] - else: - # Here you can add a local folder with your files(.txt, .pdf, .docx). - # You might need to install additional packages with "pip install farm-haystack[ocr,preprocessing,file-conversion,pdf]". - # For more details, see: https://haystack.deepset.ai/tutorials/08_preprocessing. - # Be aware that some of your data will be sent to external APIs if you use this functionality! - files_to_index = [dir + "/" + f for f in os.listdir(dir)] - logger.info("Adding %s number of files from local disk at %s.", len(files_to_index), dir) - docs = convert_files_to_docs(dir_path=dir) - - preprocessor = PreProcessor( - split_by="word", split_length=200, split_overlap=0, split_respect_sentence_boundary=True - ) - docs_processed = preprocessor.process(docs) - - document_store.write_documents(documents=docs_processed) diff --git a/haystack/utils/import_utils.py b/haystack/utils/import_utils.py deleted file mode 100644 index a1d537ba50..0000000000 --- a/haystack/utils/import_utils.py +++ /dev/null @@ -1,119 +0,0 @@ -import io -import gzip -import tarfile -import zipfile -import logging -import importlib -import importlib.util -from pathlib import Path -from typing import Optional, Dict, Union, Tuple, List -from urllib.parse import urlparse, unquote -from os.path import splitext, basename - -import requests - -from haystack.errors import DatasetsError -from haystack.schema import Document - - -logger = logging.getLogger(__name__) - - -def load_documents_from_hf_datasets(dataset_name: str, split: Optional[str] = "train") -> List[Document]: - """ - Load a list of Haystack Documents from a remote Hugging Face dataset. - - :param dataset_name: A Hugging Face dataset containing Haystack Documents - :param split: The split of the Hugging Face dataset to load from. By default, this is set to "train". - :return: a List of Haystack Documents - """ - try: - from datasets import load_dataset, load_dataset_builder - except ImportError: - raise ImportError( - "Failed to import `datasets`, Run 'pip install \"datasets>=2.6.0\"' " - "to install the datasets library to use this function." - ) - - dataset = load_dataset_builder(dataset_name) - if "content" not in dataset.info.features.keys(): - raise DatasetsError( - f"{dataset_name} does not contain a `content` field which is required by Haystack to " - f"create `Document` objects." - ) - - remote_dataset = load_dataset(dataset_name, split=split) - documents = [Document.from_dict(document) for document in remote_dataset] - - return documents - - -def get_filename_extension_from_url(url: str) -> Tuple[str, str]: - """ - Extracts the filename and file extension from an url. - - :param url: http address - :return: Tuple (filename, file extension) of the file at the url. - """ - parsed = urlparse(url) - root, extension = splitext(parsed.path) - archive_extension = extension[1:] - file_name = unquote(basename(root[1:])) - return file_name, archive_extension - - -def fetch_archive_from_http( - url: str, - output_dir: str, - proxies: Optional[Dict[str, str]] = None, - timeout: Union[float, Tuple[float, float]] = 10.0, -) -> bool: - """ - Fetch an archive (zip, gz or tar.gz) from a url via http and extract content to an output directory. - - :param url: http address - :param output_dir: local path - :param proxies: proxies details as required by requests library - :param timeout: How many seconds to wait for the server to send data before giving up, - as a float, or a :ref:`(connect timeout, read timeout) ` tuple. - Defaults to 10 seconds. - :return: if anything got fetched - """ - # verify & prepare local directory - path = Path(output_dir) - if not path.exists(): - path.mkdir(parents=True) - - is_not_empty = len(list(Path(path).rglob("*"))) > 0 - if is_not_empty: - logger.info("Found data stored in '%s'. Delete this first if you really want to fetch new data.", output_dir) - return False - else: - logger.info("Fetching from %s to '%s'", url, output_dir) - - file_name, archive_extension = get_filename_extension_from_url(url) - request_data = requests.get(url, proxies=proxies, timeout=timeout) - - if archive_extension == "zip": - zip_archive = zipfile.ZipFile(io.BytesIO(request_data.content)) - zip_archive.extractall(output_dir) - elif archive_extension == "gz" and not "tar.gz" in url: - gzip_archive = gzip.GzipFile(fileobj=io.BytesIO(request_data.content)) - file_content = gzip_archive.read() - with open(f"{output_dir}/{file_name}", "wb") as file: - file.write(file_content) - elif archive_extension in ["gz", "bz2", "xz"]: - tar_archive = tarfile.open(fileobj=io.BytesIO(request_data.content), mode="r|*") - tar_archive.extractall(output_dir) - else: - logger.warning( - "Skipped url %s as file type is not supported here. " - "See haystack documentation for support of more file types", - url, - ) - - return True - - -def is_whisper_available(): - return importlib.util.find_spec("whisper") is not None diff --git a/haystack/utils/labels.py b/haystack/utils/labels.py deleted file mode 100644 index c29f658bce..0000000000 --- a/haystack/utils/labels.py +++ /dev/null @@ -1,88 +0,0 @@ -from collections import defaultdict -from typing import Dict, List, Optional, Tuple, Union - -from haystack.schema import Label, MultiLabel - - -def aggregate_labels( - labels: List[Label], - add_closed_domain_filter: bool = False, - add_meta_filters: Optional[Union[str, list]] = None, - drop_negative_labels: bool = False, - drop_no_answers: bool = False, -) -> List[MultiLabel]: - """ - Aggregates Labels into MultiLabel objects (e.g. for evaluation with `Pipeline.eval()`). - - Labels are always aggregated by question and filters defined in the Label objects. - Beyond that you have options to drop certain labels or to dynamically add filters to control the aggregation process. - - Closed domain aggregation: - If the questions are being asked only on the document defined within the Label (i.e. SQuAD style), set `add_closed_domain_filter=True` to aggregate by question, filters and document. - Note that Labels' filters are enriched with the document_id of the Label's document. - Note that you don't need that step - - if your labels already contain the document_id in their filters - - if you're using `Pipeline.eval()`'s `add_isolated_node_eval` feature - - Dynamic metadata aggregation: - If the questions are being asked on a subslice of your document set, that is not defined with the Label's filters but with an additional meta field, - populate `add_meta_filters` with the names of Label meta fields to aggregate by question, filters and your custom meta fields. - Note that Labels' filters are enriched with the specified meta fields defined in the Label. - Remarks: `add_meta_filters` is only intended for dynamic metadata aggregation (e.g. separate evaluations per document type). - For standard questions use-cases, where a question is always asked on multiple files individually, consider setting the Label's filters instead. - For example, if you want to ask a couple of standard questions for each of your products, set filters for "product_id" to your Labels. - Thus you specify that each Label is always only valid for documents with the respective product_id. - - :param labels: List of Labels to aggregate. - :param add_closed_domain_filter: When True, adds a filter for the document ID specified in the label. - Thus, labels are aggregated in a closed domain fashion based on the question text, filters, - and also the id of the document that the label is tied to. See "closed domain aggregation" section for more details. - :param add_meta_filters: The names of the Label meta fields by which to aggregate in addition to question and filters. For example: ["product_id"]. - Note that Labels' filters are enriched with the specified meta fields defined in the Label. - :param drop_negative_labels: When True, labels with incorrect answers and documents are dropped. - :param drop_no_answers: When True, labels with no answers are dropped. - :return: A list of MultiLabel objects. - """ - if add_meta_filters: - if type(add_meta_filters) == str: - add_meta_filters = [add_meta_filters] - else: - add_meta_filters = [] - - # drop no_answers in order to not create empty MultiLabels - if drop_no_answers: - labels = [label for label in labels if label.no_answer is False] - - # add filters for closed domain and dynamic metadata aggregation - for l in labels: - label_filters_to_add = {} - if add_closed_domain_filter: - label_filters_to_add["_id"] = l.document.id - - for meta_key in add_meta_filters: - meta = l.meta or {} - curr_meta = meta.get(meta_key, None) - if curr_meta: - curr_meta = curr_meta if isinstance(curr_meta, list) else [curr_meta] - label_filters_to_add[meta_key] = curr_meta - - if label_filters_to_add: - if l.filters is None: - l.filters = label_filters_to_add - else: - l.filters.update(label_filters_to_add) - - # Filters define the scope a label is valid for the query, so we group the labels by query and filters. - grouped_labels: Dict[Tuple, List[Label]] = defaultdict(list) - for l in labels: - label_filter_keys = [f"{k}={v}" for k, v in l.filters.items()] if l.filters else [] - group_keys: list = [l.query] + label_filter_keys - group_key = tuple(group_keys) - grouped_labels[group_key].append(l) - - aggregated_labels = [ - MultiLabel(labels=ls, drop_negative_labels=drop_negative_labels, drop_no_answers=drop_no_answers) - for ls in grouped_labels.values() - ] - - return aggregated_labels diff --git a/haystack/utils/openai_utils.py b/haystack/utils/openai_utils.py deleted file mode 100644 index 25de13e508..0000000000 --- a/haystack/utils/openai_utils.py +++ /dev/null @@ -1,264 +0,0 @@ -"""Utils for using OpenAI API""" -import os -import logging -import platform -import json -from typing import Dict, Union, Tuple, Optional, List, cast - -import httpx -import requests -import tenacity -import tiktoken - -from haystack.errors import OpenAIError, OpenAIRateLimitError, OpenAIUnauthorizedError -from haystack.environment import ( - HAYSTACK_REMOTE_API_BACKOFF_SEC, - HAYSTACK_REMOTE_API_MAX_RETRIES, - HAYSTACK_REMOTE_API_TIMEOUT_SEC, -) - -logger = logging.getLogger(__name__) - -machine = platform.machine().lower() -system = platform.system() - -OPENAI_TIMEOUT = float(os.environ.get(HAYSTACK_REMOTE_API_TIMEOUT_SEC, 30)) -OPENAI_BACKOFF = int(os.environ.get(HAYSTACK_REMOTE_API_BACKOFF_SEC, 10)) -OPENAI_MAX_RETRIES = int(os.environ.get(HAYSTACK_REMOTE_API_MAX_RETRIES, 5)) - -OPENAI_MODERATION_URL = "https://api.openai.com/v1/moderations" - - -def load_openai_tokenizer(tokenizer_name: str): - """Load either the tokenizer from tiktoken (if the library is available) or fallback to the GPT2TokenizerFast - from the transformers library. - - :param tokenizer_name: The name of the tokenizer to load. - """ - - logger.debug("Using tiktoken %s tokenizer", tokenizer_name) - return tiktoken.get_encoding(tokenizer_name) - - -def count_openai_tokens_messages(messages: List[Dict[str, str]], tokenizer) -> int: - """Count the number of tokens in `messages` based on the OpenAI `tokenizer` provided. - - :param messages: The messages to be tokenized. - :param tokenizer: An OpenAI tokenizer. - """ - # adapted from https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb - # should be kept up to date - num_tokens = 0 - for message in messages: - num_tokens += 4 # every message follows {role/name}\n{content}\n - for key, value in message.items(): - num_tokens += len(tokenizer.encode(value)) - if key == "name": # if there's a name, the role is omitted - num_tokens += -1 # role is always required and always 1 token - num_tokens += 3 # every reply is primed with assistant<|message|> - return num_tokens - - -def _openai_text_completion_tokenization_details(model_name: str): - """Return the tokenizer name and max tokens limit for a given OpenAI `model_name`. - - :param model_name: Name of the OpenAI model. - """ - tokenizer_name = "gpt2" - max_tokens_limit = 2049 # Based on this ref: https://platform.openai.com/docs/models/gpt-3 - try: - model_tokenizer = tiktoken.encoding_name_for_model(model_name) - except KeyError: - model_tokenizer = None - - if model_tokenizer: - # Based on OpenAI models page, 'davinci' considers have 2049 tokens, - ## therefore, it is better to add `text-davinci` instead to the condition. - ## Ref: https://platform.openai.com/docs/models/gpt-3-5 - ## https://platform.openai.com/docs/models/gpt-3 - if "text-davinci" in model_name: - max_tokens_limit = 4097 - tokenizer_name = model_tokenizer - elif model_name.startswith("gpt-3.5-turbo-16k") or model_name.startswith("gpt-35-turbo-16k"): - max_tokens_limit = 16384 - tokenizer_name = model_tokenizer - elif model_name.startswith("gpt-3"): - max_tokens_limit = 4096 - tokenizer_name = model_tokenizer - # Ref: https://platform.openai.com/docs/models/gpt-4 - elif model_name.startswith("gpt-4-32k"): - max_tokens_limit = 32768 # tokens - tokenizer_name = model_tokenizer - elif model_name.startswith("gpt-4-1106-preview"): - max_tokens_limit = 128000 # tokens - tokenizer_name = model_tokenizer - elif model_name.startswith("gpt-4"): - max_tokens_limit = 8192 # tokens - tokenizer_name = model_tokenizer - else: - tokenizer_name = model_tokenizer - - return tokenizer_name, max_tokens_limit - - -@tenacity.retry( - reraise=True, - retry=tenacity.retry_if_exception_type(OpenAIError) - and tenacity.retry_if_not_exception_type(OpenAIUnauthorizedError), - wait=tenacity.wait_exponential(multiplier=OPENAI_BACKOFF), - stop=tenacity.stop_after_attempt(OPENAI_MAX_RETRIES), -) -def openai_request( - url: str, - headers: Dict, - payload: Dict, - timeout: Optional[Union[float, Tuple[float, float]]] = None, - read_response: Optional[bool] = True, - **kwargs, -): - """Make a request to the OpenAI API given a `url`, `headers`, `payload`, and `timeout`. - - :param url: The URL of the OpenAI API. - :param headers: Dictionary of HTTP Headers to send with the :class:`Request`. - :param payload: The payload to send with the request. - :param timeout: The timeout length of the request. The default is 30s. - :param read_response: Whether to read the response as JSON. The default is True. - """ - if timeout is None: - timeout = OPENAI_TIMEOUT - response = requests.request("POST", url, headers=headers, data=json.dumps(payload), timeout=timeout, **kwargs) - if read_response: - json_response = json.loads(response.text) - - if response.status_code != 200: - openai_error: OpenAIError - if response.status_code == 429: - openai_error = OpenAIRateLimitError(f"API rate limit exceeded: {response.text}") - elif response.status_code == 401: - openai_error = OpenAIUnauthorizedError(f"API key is invalid: {response.text}") - else: - openai_error = OpenAIError( - f"OpenAI returned an error.\n" - f"Status code: {response.status_code}\n" - f"Response body: {response.text}", - status_code=response.status_code, - ) - raise openai_error - if read_response: - return json_response - else: - return response - - -@tenacity.retry( - reraise=True, - retry=tenacity.retry_if_exception_type(OpenAIError) - and tenacity.retry_if_not_exception_type(OpenAIUnauthorizedError), - wait=tenacity.wait_exponential(multiplier=OPENAI_BACKOFF), - stop=tenacity.stop_after_attempt(OPENAI_MAX_RETRIES), -) -async def openai_async_request( - url: str, - headers: Dict, - payload: Dict, - timeout: Union[float, Tuple[float, float]] = OPENAI_TIMEOUT, - read_response: bool = True, - **kwargs, -): - """Make a request to the OpenAI API given a `url`, `headers`, `payload`, and `timeout`. - - See `openai_request`. - """ - async with httpx.AsyncClient() as client: - response = await client.request( - "POST", url, headers=headers, json=payload, timeout=cast(float, timeout), **kwargs - ) - - if read_response: - json_response = json.loads(response.text) - - if response.status_code != 200: - openai_error: OpenAIError - if response.status_code == 429: - openai_error = OpenAIRateLimitError(f"API rate limit exceeded: {response.text}") - elif response.status_code == 401: - openai_error = OpenAIUnauthorizedError(f"API key is invalid: {response.text}") - else: - openai_error = OpenAIError( - f"OpenAI returned an error.\n" - f"Status code: {response.status_code}\n" - f"Response body: {response.text}", - status_code=response.status_code, - ) - raise openai_error - if read_response: - return json_response - else: - return response - - -def check_openai_policy_violation(input: Union[List[str], str], headers: Dict) -> bool: - """ - Calls the moderation endpoint to check if the text(s) violate the policy. - See [OpenAI Moderation API](https://platform.openai.com/docs/guides/moderation) for more details. - Returns true if any of the input is flagged as any of ['sexual', 'hate', 'violence', 'self-harm', 'sexual/minors', 'hate/threatening', 'violence/graphic']. - """ - response = openai_request(url=OPENAI_MODERATION_URL, headers=headers, payload={"input": input}) - results = response["results"] - flagged = any(res["flagged"] for res in results) - if flagged: - for result in results: - if result["flagged"]: - logger.debug( - "OpenAI Moderation API flagged the text '%s' as a potential policy violation of the following categories: %s", - input, - result["categories"], - ) - return flagged - - -async def check_openai_async_policy_violation(input: Union[List[str], str], headers: Dict) -> bool: - """ - Calls the moderation endpoint to check if the text(s) violate the policy. - See [OpenAI Moderation API](https://platform.openai.com/docs/guides/moderation) for more details. - Returns true if any of the input is flagged as any of ['sexual', 'hate', 'violence', 'self-harm', 'sexual/minors', 'hate/threatening', 'violence/graphic']. - """ - response = await openai_async_request(url=OPENAI_MODERATION_URL, headers=headers, payload={"input": input}) - results = response["results"] - flagged = any(res["flagged"] for res in results) - if flagged: - for result in results: - if result["flagged"]: - logger.debug( - "OpenAI Moderation API flagged the text '%s' as a potential policy violation of the following categories: %s", - input, - result["categories"], - ) - return flagged - - -def _check_openai_finish_reason(result: Dict, payload: Dict) -> None: - """Check the `finish_reason` the answers returned by OpenAI completions endpoint. - If the `finish_reason` is `length` or `content_filter`, log a warning to the user. - - :param result: The result returned from the OpenAI API. - :param payload: The payload sent to the OpenAI API. - """ - number_of_truncated_completions = sum(1 for ans in result["choices"] if ans["finish_reason"] == "length") - if number_of_truncated_completions > 0: - logger.warning( - "%s out of the %s completions have been truncated before reaching a natural stopping point. " - "Increase the max_tokens parameter to allow for longer completions.", - number_of_truncated_completions, - payload["n"], - ) - - number_of_content_filtered_completions = sum( - 1 for ans in result["choices"] if ans["finish_reason"] == "content_filter" - ) - if number_of_content_filtered_completions > 0: - logger.warning( - "%s out of the %s completions have omitted content due to a flag from OpenAI content filters.", - number_of_truncated_completions, - payload["n"], - ) diff --git a/haystack/utils/preprocessing.py b/haystack/utils/preprocessing.py deleted file mode 100644 index 9889e855ee..0000000000 --- a/haystack/utils/preprocessing.py +++ /dev/null @@ -1,209 +0,0 @@ -from typing import Callable, Dict, List, Optional - -import re -import logging -from pathlib import Path - -from haystack.schema import Document - - -logger = logging.getLogger(__name__) - - -def convert_files_to_docs( - dir_path: Optional[str] = None, - clean_func: Optional[Callable] = None, - split_paragraphs: bool = False, - encoding: Optional[str] = None, - id_hash_keys: Optional[List[str]] = None, - file_paths: Optional[List[Path]] = None, -) -> List[Document]: - """ - Convert files (.txt, .pdf, .docx) to Documents that can be written to a Document Store. - - Files can be specified by giving a directory path, a list of file paths, or both. If a directory path is given then - all files with the allowed suffixes in the directory's subdirectories will be converted. - - :param dir_path: The path of a directory that contains Files to be converted, including in its subdirectories. - :param clean_func: A custom cleaning function that gets applied to each Document (input: str, output: str). - :param split_paragraphs: Whether to split text by paragraph. - :param encoding: Character encoding to use when converting pdf documents. - :param id_hash_keys: A list of Document attribute names from which the Document ID should be hashed from. - Useful for generating unique IDs even if the Document contents are identical. - To ensure you don't have duplicate Documents in your Document Store if texts are - not unique, you can modify the metadata and pass [`"content"`, `"meta"`] to this field. - If you do this, the Document ID will be generated by using the content and the defined metadata. - :param file_paths: A list of paths of Files to be converted. - """ - # Importing top-level causes a circular import - from haystack.nodes.file_converter import BaseConverter, DocxToTextConverter, PDFToTextConverter, TextConverter - - if dir_path is None and file_paths is None: - raise ValueError("At least one of dir_path or file_paths must be set.") - if file_paths is None: - file_paths = [] - if dir_path is not None: - file_paths = file_paths + list(Path(dir_path).glob("**/*")) - - allowed_suffixes = [".pdf", ".txt", ".docx"] - suffix2converter: Dict[str, BaseConverter] = {} - - suffix2paths: Dict[str, List[Path]] = {} - for path in file_paths: - file_suffix = path.suffix.lower() - if file_suffix in allowed_suffixes: - if file_suffix not in suffix2paths: - suffix2paths[file_suffix] = [] - suffix2paths[file_suffix].append(path) - elif not path.is_dir(): - logger.warning( - "Skipped file %s as type %s is not supported here. " - "See haystack.file_converter for support of more file types", - path, - file_suffix, - ) - - # No need to initialize converter if file type not present - for file_suffix in suffix2paths.keys(): - if file_suffix == ".pdf": - suffix2converter[file_suffix] = PDFToTextConverter() - if file_suffix == ".txt": - suffix2converter[file_suffix] = TextConverter() - if file_suffix == ".docx": - suffix2converter[file_suffix] = DocxToTextConverter() - - documents = [] - for suffix, paths in suffix2paths.items(): - for path in paths: - logger.info("Converting %s", path) - # PDFToTextConverter, TextConverter, and DocxToTextConverter return a list containing a single Document - document = suffix2converter[suffix].convert( - file_path=path, meta=None, encoding=encoding, id_hash_keys=id_hash_keys - )[0] - text = document.content - - if clean_func: - text = clean_func(text) - - if split_paragraphs: - for para in text.split("\n\n"): - if not para.strip(): # skip empty paragraphs - continue - documents.append(Document(content=para, meta={"name": path.name}, id_hash_keys=id_hash_keys)) - else: - documents.append(Document(content=text, meta={"name": path.name}, id_hash_keys=id_hash_keys)) - - return documents - - -def tika_convert_files_to_docs( - dir_path: Optional[str] = None, - clean_func: Optional[Callable] = None, - split_paragraphs: bool = False, - merge_short: bool = True, - merge_lowercase: bool = True, - id_hash_keys: Optional[List[str]] = None, - file_paths: Optional[List[Path]] = None, -) -> List[Document]: - """ - Convert files (.txt, .pdf) to Documents that can be written to a Document Store. - - Files can be specified by giving a directory path, a list of file paths, or both. If a directory path is given then - all files with the allowed suffixes in the directory's subdirectories will be converted. - - :param merge_lowercase: Whether to convert merged paragraphs to lowercase. - :param merge_short: Whether to allow merging of short paragraphs - :param dir_path: The path of a directory that contains Files to be converted, including in its subdirectories. - :param clean_func: A custom cleaning function that gets applied to each doc (input: str, output:str). - :param split_paragraphs: Whether to split text by paragraphs. - :param id_hash_keys: A list of Document attribute names from which the Document ID should be hashed from. - Useful for generating unique IDs even if the Document contents are identical. - To ensure you don't have duplicate Documents in your Document Store if texts are - not unique, you can modify the metadata and pass [`"content"`, `"meta"`] to this field. - If you do this, the Document ID will be generated by using the content and the defined metadata. - :param file_paths: A list of paths of Files to be converted. - """ - try: - from haystack.nodes.file_converter import TikaConverter - except Exception as ex: - logger.error("Tika not installed. Please install tika and try again. Error: %s", ex) - raise ex - converter = TikaConverter() - - if dir_path is None and file_paths is None: - raise ValueError("At least one of dir_path or file_paths must be set.") - if file_paths is None: - file_paths = [] - if dir_path is not None: - file_paths = file_paths + list(Path(dir_path).glob("**/*")) - - allowed_suffixes = [".pdf", ".txt"] - file_paths_to_convert: List[Path] = [] - - for path in file_paths: - file_suffix = path.suffix.lower() - if file_suffix in allowed_suffixes: - file_paths_to_convert.append(path) - elif not path.is_dir(): - logger.warning( - "Skipped file %s as type %s is not supported here. " - "See haystack.file_converter for support of more file types", - path, - file_suffix, - ) - - documents = [] - for path in file_paths_to_convert: - logger.info("Converting %s", path) - # TikaConverter returns a list containing a single Document - document = converter.convert(path)[0] - meta = document.meta or {} - meta["name"] = path.name - text = document.content - pages = text.split("\f") - - if split_paragraphs: - if pages: - paras = pages[0].split("\n\n") - # pop the last paragraph from the first page - last_para = paras.pop(-1) if paras else "" - for page in pages[1:]: - page_paras = page.split("\n\n") - # merge the last paragraph in previous page to the first paragraph in this page - if page_paras: - page_paras[0] = last_para + " " + page_paras[0] - last_para = page_paras.pop(-1) - paras += page_paras - if last_para: - paras.append(last_para) - if paras: - last_para = "" - for para in paras: - para = para.strip() - if not para: - continue - - # this paragraph is less than 10 characters or 2 words - para_is_short = len(para) < 10 or len(re.findall(r"\s+", para)) < 2 - # this paragraph starts with a lower case and last paragraph does not end with a punctuation - para_is_lowercase = ( - para and para[0].islower() and last_para and last_para[-1] not in r'.?!"\'\]\)' - ) - - # merge paragraphs to improve qa - if (merge_short and para_is_short) or (merge_lowercase and para_is_lowercase): - last_para += " " + para - else: - if last_para: - documents.append(Document(content=last_para, meta=meta, id_hash_keys=id_hash_keys)) - last_para = para - # don't forget the last one - if last_para: - documents.append(Document(content=last_para, meta=meta, id_hash_keys=id_hash_keys)) - - else: - if clean_func: - text = clean_func(text) - documents.append(Document(content=text, meta=meta, id_hash_keys=id_hash_keys)) - - return documents diff --git a/haystack/utils/reflection.py b/haystack/utils/reflection.py deleted file mode 100644 index 73d9de673c..0000000000 --- a/haystack/utils/reflection.py +++ /dev/null @@ -1,15 +0,0 @@ -import inspect -import logging -from typing import Any, Dict, Tuple, Callable - -logger = logging.getLogger(__name__) - - -def args_to_kwargs(args: Tuple, func: Callable) -> Dict[str, Any]: - sig = inspect.signature(func) - arg_names = list(sig.parameters.keys()) - # skip self and cls args for instance and class methods - if any(arg_names) and arg_names[0] in ["self", "cls"]: - arg_names = arg_names[1 : 1 + len(args)] - args_as_kwargs = {arg_name: arg for arg, arg_name in zip(args, arg_names)} - return args_as_kwargs diff --git a/haystack/utils/requests_utils.py b/haystack/utils/requests_utils.py deleted file mode 100644 index 245d7737fb..0000000000 --- a/haystack/utils/requests_utils.py +++ /dev/null @@ -1,94 +0,0 @@ -from typing import Optional, List - -import logging - -from tenacity import retry, wait_exponential, retry_if_exception_type, stop_after_attempt, before_log, after_log -import requests - -logger = logging.getLogger(__file__) - - -def request_with_retry( - attempts: int = 3, status_codes_to_retry: Optional[List[int]] = None, **kwargs -) -> requests.Response: - """ - request_with_retry is a simple wrapper function that executes an HTTP request - with a configurable exponential backoff retry on failures. - - All kwargs will be passed to ``requests.request``, so it accepts the same arguments. - - Example Usage: - -------------- - - # Sending an HTTP request with default retry configs - res = request_with_retry(method="GET", url="https://example.com") - - # Sending an HTTP request with custom number of attempts - res = request_with_retry(method="GET", url="https://example.com", attempts=10) - - # Sending an HTTP request with custom HTTP codes to retry - res = request_with_retry(method="GET", url="https://example.com", status_codes_to_retry=[408, 503]) - - # Sending an HTTP request with custom timeout in seconds - res = request_with_retry(method="GET", url="https://example.com", timeout=5) - - # Sending an HTTP request with custom authorization handling - class CustomAuth(requests.auth.AuthBase): - def __call__(self, r): - r.headers["authorization"] = "Basic " - return r - - res = request_with_retry(method="GET", url="https://example.com", auth=CustomAuth()) - - # All of the above combined - res = request_with_retry( - method="GET", - url="https://example.com", - auth=CustomAuth(), - attempts=10, - status_codes_to_retry=[408, 503], - timeout=5 - ) - - # Sending a POST request - res = request_with_retry(method="POST", url="https://example.com", data={"key": "value"}, attempts=10) - - # Retry all 5xx status codes - res = request_with_retry(method="GET", url="https://example.com", status_codes_to_retry=list(range(500, 600))) - - :param attempts: Maximum number of attempts to retry the request, defaults to 3 - :param status_codes_to_retry: List of HTTP status codes that will trigger a retry, defaults to [408, 418, 429, 503]: - - `408: Request Timeout` - - `418` - - `429: Too Many Requests` - - `503: Service Unavailable` - :param **kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response ` object - """ - - if status_codes_to_retry is None: - status_codes_to_retry = [408, 418, 429, 503] - - @retry( - reraise=True, - wait=wait_exponential(), - retry=retry_if_exception_type((requests.HTTPError, TimeoutError)), - stop=stop_after_attempt(attempts), - before=before_log(logger, logging.DEBUG), - after=after_log(logger, logging.DEBUG), - ) - def run(): - timeout = kwargs.pop("timeout", 10) - res = requests.request(**kwargs, timeout=timeout) - - if res.status_code in status_codes_to_retry: - # We raise only for the status codes that must trigger a retry - res.raise_for_status() - - return res - - res = run() - # We raise here too in case the request failed with a status code that - # won't trigger a retry, this way the call will still cause an explicit exception - res.raise_for_status() - return res diff --git a/haystack/utils/scipy_utils.py b/haystack/utils/scipy_utils.py deleted file mode 100644 index 100f746686..0000000000 --- a/haystack/utils/scipy_utils.py +++ /dev/null @@ -1,17 +0,0 @@ -import logging -import numpy as np - -logger = logging.getLogger(__name__) - -try: - from numba import njit # pylint: disable=import-error -except (ImportError, ModuleNotFoundError): - logger.debug("Numba not found, replacing njit() with no-op implementation. Enable it with 'pip install numba'.") - - def njit(f): - return f - - -@njit # (fastmath=True) -def expit(x: float) -> float: - return 1 / (1 + np.exp(-x)) diff --git a/haystack/utils/squad_data.py b/haystack/utils/squad_data.py deleted file mode 100644 index 5e950d4d35..0000000000 --- a/haystack/utils/squad_data.py +++ /dev/null @@ -1,311 +0,0 @@ -from typing import List - -import logging -import json -import random -import pandas as pd -from tqdm import tqdm - -from haystack.mmh3 import hash128 -from haystack.schema import Document, Label, Answer -from haystack.lazy_imports import LazyImport - -with LazyImport("{}") as haystack_modeling: - from haystack.modeling.data_handler.processor import _read_squad_file - -logger = logging.getLogger(__name__) - - -tqdm.pandas() - - -COLUMN_NAMES = ["title", "context", "question", "id", "answer_text", "answer_start", "is_impossible"] - - -class SquadData: - """ - This class is designed to manipulate data that is in SQuAD format - """ - - def __init__(self, squad_data): - """ - :param squad_data: SQuAD format data, either as a dictionary with a `data` key, or just a list of SQuAD documents. - """ - if type(squad_data) == dict: - self.version = squad_data.get("version") - self.data = squad_data["data"] - elif type(squad_data) == list: - self.version = None - self.data = squad_data - self.df = self.to_df(self.data) - - def merge_from_file(self, filename: str): - """Merge the contents of a JSON file in the SQuAD format with the data stored in this object.""" - new_data = json.load(open(filename))["data"] - self.merge(new_data) - - def merge(self, new_data: List): - """ - Merge data in SQuAD format with the data stored in this object. - :param new_data: A list of SQuAD document data. - """ - df_new = self.to_df(new_data) - self.df = pd.concat([df_new, self.df]) - self.data = self.df_to_data(self.df) - - @classmethod - def from_file(cls, filename: str): - """ - Create a SquadData object by providing the name of a JSON file in the SQuAD format. - """ - with open(filename) as f: - data = json.load(f) - return cls(data) - - def save(self, filename: str): - """ - Write the data stored in this object to a JSON file. - """ - with open(filename, "w") as f: - squad_data = {"version": self.version, "data": self.data} - json.dump(squad_data, f, indent=2) - - def to_dpr_dataset(self): - raise NotImplementedError( - "SquadData.to_dpr_dataset() not yet implemented. " - "For now, have a look at the script at haystack/retriever/squad_to_dpr.py" - ) - - def to_document_objs(self): - """ - Export all paragraphs stored in this object to haystack.Document objects. - """ - df_docs = self.df[["title", "context"]] - df_docs = df_docs.drop_duplicates() - record_dicts = df_docs.to_dict("records") - documents = [Document(content=rd["context"], id=rd["title"]) for rd in record_dicts] - return documents - - def to_label_objs(self, answer_type="generative"): - """Export all labels stored in this object to haystack.Label objects""" - df_labels = self.df[["id", "question", "answer_text", "answer_start", "context", "document_id"]] - record_dicts = df_labels.to_dict("records") - labels = [ - Label( - query=record["question"], - answer=Answer(answer=record["answer_text"], answer_type=answer_type), - is_correct_answer=True, - is_correct_document=True, - id=record["id"], - origin=record.get("origin", "gold-label"), - document=Document(content=record.get("context"), id=str(record["document_id"])), - ) - for record in record_dicts - ] - return labels - - @staticmethod - def to_df(data): - """Convert a list of SQuAD document dictionaries into a pandas dataframe (each row is one annotation).""" - flat = [] - for document in data: - title = document.get("title", "") - for paragraph in document["paragraphs"]: - context = paragraph["context"] - document_id = paragraph.get("document_id", "{:02x}".format(hash128(str(context)))) - for question in paragraph["qas"]: - q = question["question"] - id = question["id"] - is_impossible = question.get("is_impossible", False) - # For no_answer samples - if len(question["answers"]) == 0: - flat.append( - { - "title": title, - "context": context, - "question": q, - "id": id, - "answer_text": "", - "answer_start": None, - "is_impossible": is_impossible, - "document_id": document_id, - } - ) - # For span answer samples - else: - for answer in question["answers"]: - answer_text = answer["text"] - answer_start = answer["answer_start"] - flat.append( - { - "title": title, - "context": context, - "question": q, - "id": id, - "answer_text": answer_text, - "answer_start": answer_start, - "is_impossible": is_impossible, - "document_id": document_id, - } - ) - df = pd.DataFrame.from_records(flat) - return df - - def count(self, unit="questions"): - """ - Count the samples in the data. Choose a unit: "paragraphs", "questions", "answers", "no_answers", "span_answers". - """ - c = 0 - for document in self.data: - for paragraph in document["paragraphs"]: - if unit == "paragraphs": - c += 1 - for question in paragraph["qas"]: - if unit == "questions": - c += 1 - # Count no_answers - if len(question["answers"]) == 0: - if unit in ["answers", "no_answers"]: - c += 1 - # Count span answers - else: - for _ in question["answers"]: - if unit in ["answers", "span_answers"]: - c += 1 - return c - - @classmethod - def df_to_data(cls, df): - """ - Convert a data frame into the SQuAD format data (list of SQuAD document dictionaries). - """ - logger.info("Converting data frame to squad format data") - - # Aggregate the answers of each question - logger.info("Aggregating the answers of each question") - df_grouped_answers = df.groupby(["title", "context", "question", "id", "is_impossible"]) - df_aggregated_answers = ( - df[["title", "context", "question", "id", "is_impossible"]].drop_duplicates().reset_index() - ) - answers = df_grouped_answers.progress_apply(cls._aggregate_answers).rename("answers") - answers = pd.DataFrame(answers).reset_index() - df_aggregated_answers = pd.merge(df_aggregated_answers, answers) - - # Aggregate the questions of each passage - logger.info("Aggregating the questions of each paragraphs of each document") - df_grouped_questions = df_aggregated_answers.groupby(["title", "context"]) - df_aggregated_questions = df[["title", "context"]].drop_duplicates().reset_index() - questions = df_grouped_questions.progress_apply(cls._aggregate_questions).rename("qas") - questions = pd.DataFrame(questions).reset_index() - df_aggregated_questions = pd.merge(df_aggregated_questions, questions) - - logger.info("Aggregating the paragraphs of each document") - df_grouped_paragraphs = df_aggregated_questions.groupby(["title"]) - df_aggregated_paragraphs = df[["title"]].drop_duplicates().reset_index() - paragraphs = df_grouped_paragraphs.progress_apply(cls._aggregate_passages).rename("paragraphs") - paragraphs = pd.DataFrame(paragraphs).reset_index() - df_aggregated_paragraphs = pd.merge(df_aggregated_paragraphs, paragraphs) - - df_aggregated_paragraphs = df_aggregated_paragraphs[["title", "paragraphs"]] - ret = df_aggregated_paragraphs.to_dict("records") - - return ret - - @staticmethod - def _aggregate_passages(x): - x = x[["context", "qas"]] - ret = x.to_dict("records") - return ret - - @staticmethod - def _aggregate_questions(x): - x = x[["question", "id", "answers", "is_impossible"]] - ret = x.to_dict("records") - return ret - - @staticmethod - def _aggregate_answers(x): - x = x[["answer_text", "answer_start"]] - x = x.rename(columns={"answer_text": "text"}) - # Span answer - try: - x["answer_start"] = x["answer_start"].astype(int) - ret = x.to_dict("records") - # No answer - except ValueError: - ret = [] - return ret - - def set_data(self, data): - self.data = data - self.df = self.to_df(data) - - def sample_questions(self, n): - """ - Return a sample of n questions in the SQuAD format (a list of SQuAD document dictionaries). - Note that if the same question is asked on multiple different passages, this function treats that - as a single question. - """ - all_questions = self.get_all_questions() - sampled_questions = random.sample(all_questions, n) - df_sampled = self.df[self.df["question"].isin(sampled_questions)] - return self.df_to_data(df_sampled) - - def get_all_paragraphs(self): - """ - Return all paragraph strings. - """ - return self.df["context"].unique().tolist() - - def get_all_questions(self): - """ - Return all question strings. Note that if the same question appears for different paragraphs, this function returns it multiple times. - """ - df_questions = self.df[["title", "context", "question"]] - df_questions = df_questions.drop_duplicates() - questions = df_questions["question"].tolist() - return questions - - def get_all_document_titles(self): - """Return all document title strings.""" - return self.df["title"].unique().tolist() - - -if __name__ == "__main__": - haystack_modeling.check() - - # Download the SQuAD dataset if it isn't at target directory - _read_squad_file("../data/squad20/train-v2.0.json") - - filename1 = "../data/squad20/train-v2.0.json" - filename2 = "../data/squad20/dev-v2.0.json" - - # Load file1 and take a sample of 10000 questions - sd = SquadData.from_file(filename1) - sample1 = sd.sample_questions(n=10000) - - # Set sd to now contain the sample of 10000 questions - sd.set_data(sample1) - - # Merge sd with file2 and take a sample of 100 questions - sd.merge_from_file(filename2) - sample2 = sd.sample_questions(n=100) - sd.set_data(sample2) - - # Save this sample of 100 - sd.save("../data/squad20/sample.json") - - paragraphs = sd.get_all_paragraphs() - questions = sd.get_all_questions() - titles = sd.get_all_document_titles() - - documents = sd.to_document_objs() - labels = sd.to_label_objs() - - n_qs = sd.count(unit="questions") - n_as = sd.count(unit="no_answers") - n_ps = sd.count(unit="paragraphs") - - print(n_qs) - print(n_as) - print(n_ps) diff --git a/haystack/utils/squad_to_dpr.py b/haystack/utils/squad_to_dpr.py deleted file mode 100644 index 25abf76310..0000000000 --- a/haystack/utils/squad_to_dpr.py +++ /dev/null @@ -1,356 +0,0 @@ -""" -Script to convert a SQuAD-like QA-dataset format JSON file to DPR Dense Retriever training format - -Usage: - squad_to_dpr.py --squad_input_filename --dpr_output_filename [options] -Arguments: - SQuAD file path - DPR output folder path - --num_hard_negative_ctxs HNEG Number of hard negative contexts [default: 30:int] - --split_dataset Whether to split the created dataset or not [default: False] - -SQuAD format -{ - version: "Version du dataset" - data:[ - { - title: "Titre de l'article Wikipedia" - paragraphs:[ - { - context: "Paragraph de l'article" - qas:[ - { - id: "Id du pair question-réponse" - question: "Question" - answers:[ - { - "answer_start": "Position de la réponse" - "text": "Réponse" - } - ], - is_impossible: (not in v1) - } - ] - } - ] - } - ] -} - - -DPR format -[ - { - "question": "....", - "answers": ["...", "...", "..."], - "positive_ctxs": [{ - "title": "...", - "text": "...." - }], - "negative_ctxs": ["..."], - "hard_negative_ctxs": ["..."] - }, - ... -] -""" - -from typing import Dict, Iterator, Tuple, List, Union - -import json -import logging -import argparse -import subprocess -from time import sleep -from pathlib import Path -from itertools import islice - -from tqdm import tqdm - -from haystack.document_stores.base import BaseDocumentStore -from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore # keep it here ! -from haystack.document_stores.faiss import FAISSDocumentStore # keep it here ! -from haystack.nodes.retriever.sparse import BM25Retriever # keep it here ! # pylint: disable=unused-import -from haystack.nodes.retriever.dense import DensePassageRetriever # keep it here ! # pylint: disable=unused-import -from haystack.nodes.preprocessor import PreProcessor -from haystack.nodes.retriever.base import BaseRetriever -from haystack.lazy_imports import LazyImport - -with LazyImport("Run 'pip install farm-haystack[elasticsearch]'") as es_import: - from elasticsearch import Elasticsearch - - -logger = logging.getLogger(__name__) - - -class HaystackDocumentStore: - def __init__(self, store_type: str = "ElasticsearchDocumentStore", **kwargs): - es_import.check() - - if store_type not in ["ElasticsearchDocumentStore", "FAISSDocumentStore"]: - raise Exception( - "At the moment we only deal with one of these types: ElasticsearchDocumentStore, FAISSDocumentStore" - ) - - self._store_type = store_type - self._kwargs = kwargs - self._preparation = { - "ElasticsearchDocumentStore": self.__prepare_ElasticsearchDocumentStore, - "FAISSDocumentStore": self.__prepare_FAISSDocumentStore, - } - - def get_document_store(self): - self._preparation[self._store_type]() - return globals()[self._store_type](**self._kwargs) - - @staticmethod - def __prepare_ElasticsearchDocumentStore(): - es = Elasticsearch(["http://localhost:9200/"], verify_certs=True) - if not es.ping(): - logger.info("Starting Elasticsearch ...") - status = subprocess.run( - ['docker run -d -p 9200:9200 -e "discovery.type=single-node" elasticsearch:7.9.2'], shell=True - ) - if status.returncode: - raise Exception("Failed to launch Elasticsearch.") - sleep(30) - - es.indices.delete(index="document", ignore=[400, 404]) - - def __prepare_FAISSDocumentStore(self): - pass - - -class HaystackRetriever: - def __init__(self, document_store: BaseDocumentStore, retriever_type: str, **kwargs): - if retriever_type not in ["BM25Retriever", "DensePassageRetriever", "EmbeddingRetriever"]: - raise Exception("Use one of these types: BM25Retriever", "DensePassageRetriever", "EmbeddingRetriever") - self._retriever_type = retriever_type - self._document_store = document_store - self._kwargs = kwargs - - def get_retriever(self): - return globals()[self._retriever_type](document_store=self._document_store, **self._kwargs) - - -def add_is_impossible(squad_data: dict, json_file_path: Path): - new_path = json_file_path.parent / Path(f"{json_file_path.stem}_impossible.json") - squad_articles = list(squad_data["data"]) # create new list with this list although lists are inmutable :/ - for article in squad_articles: - for paragraph in article["paragraphs"]: - for question in paragraph["qas"]: - question["is_impossible"] = False - - squad_data["data"] = squad_articles - with open(new_path, "w", encoding="utf-8") as filo: - json.dump(squad_data, filo, indent=4, ensure_ascii=False) - - return new_path, squad_data - - -def get_number_of_questions(squad_data: dict): - nb_questions = 0 - for article in squad_data: - for paragraph in article["paragraphs"]: - nb_questions += len(paragraph["qas"]) - return nb_questions - - -def has_is_impossible(squad_data: dict): - for article in squad_data["data"]: - for paragraph in article["paragraphs"]: - for question in paragraph["qas"]: - if "is_impossible" in question: - return True - return False - - -def create_dpr_training_dataset(squad_data: dict, retriever: BaseRetriever, num_hard_negative_ctxs: int = 30): - n_non_added_questions = 0 - n_questions = 0 - for article in tqdm(squad_data, unit="article"): - article_title = article.get("title", "") - for paragraph in article["paragraphs"]: - context = paragraph["context"] - for question in paragraph["qas"]: - if "is_impossible" in question and question["is_impossible"]: - continue - answers = [a["text"] for a in question["answers"]] - hard_negative_ctxs = get_hard_negative_contexts( - retriever=retriever, question=question["question"], answers=answers, n_ctxs=num_hard_negative_ctxs - ) - positive_ctxs = [{"title": article_title, "text": context, "passage_id": ""}] - - if not hard_negative_ctxs or not positive_ctxs: - logger.error( - "No retrieved candidates for article %s, with question %s", article_title, question["question"] - ) - n_non_added_questions += 1 - continue - dict_DPR = { - "question": question["question"], - "answers": answers, - "positive_ctxs": positive_ctxs, - "negative_ctxs": [], - "hard_negative_ctxs": hard_negative_ctxs, - } - n_questions += 1 - yield dict_DPR - - logger.info("Number of skipped questions: %s", n_non_added_questions) - logger.info("Number of added questions: %s", n_questions) - - -def save_dataset(iter_dpr: Iterator, dpr_output_filename: Path, total_nb_questions: int, split_dataset: bool): - if split_dataset: - nb_train_examples = int(total_nb_questions * 0.8) - nb_dev_examples = int(total_nb_questions * 0.1) - - train_iter = islice(iter_dpr, nb_train_examples) - dev_iter = islice(iter_dpr, nb_dev_examples) - - dataset_splits = { - dpr_output_filename.parent / f"{dpr_output_filename.stem}.train.json": train_iter, - dpr_output_filename.parent / f"{dpr_output_filename.stem}.dev.json": dev_iter, - dpr_output_filename.parent / f"{dpr_output_filename.stem}.test.json": iter_dpr, - } - else: - dataset_splits = {dpr_output_filename: iter_dpr} - for path, set_iter in dataset_splits.items(): - with open(path, "w", encoding="utf-8") as json_ds: - json.dump(list(set_iter), json_ds, indent=4, ensure_ascii=False) - - -def get_hard_negative_contexts(retriever: BaseRetriever, question: str, answers: List[str], n_ctxs: int = 30): - list_hard_neg_ctxs = [] - retrieved_docs = retriever.retrieve(query=question, top_k=n_ctxs, index="document") - for retrieved_doc in retrieved_docs: - retrieved_doc_id = retrieved_doc.meta.get("name", "") - retrieved_doc_text = retrieved_doc.content - if any(str(answer).lower() in retrieved_doc_text.lower() for answer in answers): - continue - list_hard_neg_ctxs.append({"title": retrieved_doc_id, "text": retrieved_doc_text, "passage_id": ""}) - - return list_hard_neg_ctxs - - -def load_squad_file(squad_file_path: Path): - if not squad_file_path.exists(): - raise FileNotFoundError - - with open(squad_file_path, encoding="utf-8") as squad_file: - squad_data = json.load(squad_file) - - # squad_data["data"] = squad_data["data"][:10] # sample - - # check it has the is_impossible field - if not has_is_impossible(squad_data=squad_data): - squad_file_path, squad_data = add_is_impossible(squad_data, squad_file_path) - - return squad_file_path, squad_data["data"] - - -def main( - squad_input_filename: Path, - dpr_output_filename: Path, - preprocessor, - document_store_type_config: Tuple[str, Dict] = ("ElasticsearchDocumentStore", {}), - retriever_type_config: Tuple[str, Dict] = ("BM25Retriever", {}), - num_hard_negative_ctxs: int = 30, - split_dataset: bool = False, -): - tqdm.write(f"Using SQuAD-like file {squad_input_filename}") - - # 1. Load squad file data - squad_file_path, squad_data = load_squad_file(squad_file_path=squad_input_filename) - - # 2. Prepare document store - store_factory = HaystackDocumentStore(store_type=document_store_type_config[0], **document_store_type_config[1]) - document_store: Union[ElasticsearchDocumentStore, FAISSDocumentStore] = store_factory.get_document_store() - - # 3. Load data into the document store - document_store.add_eval_data(squad_file_path.as_posix(), doc_index="document", preprocessor=preprocessor) - - # 4. Prepare retriever - retriever_factory = HaystackRetriever( - document_store=document_store, retriever_type=retriever_type_config[0], **retriever_type_config[1] - ) - retriever = retriever_factory.get_retriever() - - # 5. Get embeddings if needed - if retriever_type_config[0] in ["DensePassageRetriever", "EmbeddingRetriever"]: - document_store.update_embeddings(retriever) - - # 6. Find positive and negative contexts and create new dataset - iter_DPR = create_dpr_training_dataset( - squad_data=squad_data, retriever=retriever, num_hard_negative_ctxs=num_hard_negative_ctxs - ) - - # 7. Split (maybe) and save dataset - total_nb_questions = get_number_of_questions(squad_data) - save_dataset( - iter_dpr=iter_DPR, - dpr_output_filename=dpr_output_filename, - total_nb_questions=total_nb_questions, - split_dataset=split_dataset, - ) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Convert a SQuAD JSON format dataset to DPR format.") - parser.add_argument( - "--squad_input_filename", - dest="squad_input_filename", - help="A dataset with a SQuAD JSON format.", - metavar="SQUAD_in", - required=True, - ) - parser.add_argument( - "--dpr_output_filename", - dest="dpr_output_filename", - help="The name of the DPR JSON formatted output file", - metavar="DPR_out", - required=True, - ) - parser.add_argument( - "--num_hard_negative_ctxs", - dest="num_hard_negative_ctxs", - help="Number of hard negative contexts to use", - metavar="num_hard_negative_ctxs", - default=30, - ) - parser.add_argument( - "--split_dataset", - dest="split_dataset", - action="store_true", - help="Whether to split the created dataset or not (default: False)", - ) - - args = parser.parse_args() - - preprocessor = PreProcessor( - split_length=100, - split_overlap=0, - clean_empty_lines=False, - split_respect_sentence_boundary=False, - clean_whitespace=False, - ) - squad_input_filename = Path(args.squad_input_filename) - dpr_output_filename = Path(args.dpr_output_filename) - num_hard_negative_ctxs = args.num_hard_negative_ctxs - split_dataset = args.split_dataset - - retriever_dpr_config = {"use_gpu": True} - store_dpr_config = {"embedding_field": "embedding", "embedding_dim": 768} - - retriever_bm25_config: dict = {} - - main( - squad_input_filename=squad_input_filename, - dpr_output_filename=dpr_output_filename, - preprocessor=preprocessor, - document_store_type_config=("ElasticsearchDocumentStore", store_dpr_config), - # retriever_type_config=("DensePassageRetriever", retriever_dpr_config), # dpr - retriever_type_config=("BM25Retriever", retriever_bm25_config), # bm25 - num_hard_negative_ctxs=num_hard_negative_ctxs, - split_dataset=split_dataset, - ) diff --git a/haystack/utils/torch_utils.py b/haystack/utils/torch_utils.py deleted file mode 100644 index 01aaba8023..0000000000 --- a/haystack/utils/torch_utils.py +++ /dev/null @@ -1,54 +0,0 @@ -from typing import Optional, List, Union -import os - -import torch -from torch.utils.data import Dataset - - -class ListDataset(Dataset): - def __init__(self, original_list): - self.original_list = original_list - - def __len__(self): - return len(self.original_list) - - def __getitem__(self, i): - return self.original_list[i] - - -def ensure_tensor_on_device(inputs: Union[dict, list, tuple, torch.Tensor], device: torch.device): - """Utility function to check that all torch tensors present in `inputs` are sent to the correct device. - - :param inputs: Contains the torch tensors that will be sent to `device`. - :param device: The torch device to send the tensors to. - """ - if isinstance(inputs, dict): - return {name: ensure_tensor_on_device(tensor, device) for name, tensor in inputs.items()} - elif isinstance(inputs, list): - return [ensure_tensor_on_device(item, device) for item in inputs] - elif isinstance(inputs, tuple): - return tuple(ensure_tensor_on_device(item, device) for item in inputs) - elif isinstance(inputs, torch.Tensor): - if device == torch.device("cpu") and inputs.dtype in {torch.float16, torch.bfloat16}: - inputs = inputs.float() - return inputs.to(device) - else: - return inputs - - -def get_devices(devices: Optional[List[Union[str, torch.device]]]) -> List[torch.device]: - """ - Convert a list of device names into a list of Torch devices, - depending on the system's configuration and hardware. - """ - if devices is not None: - return [torch.device(device) for device in devices] - elif torch.cuda.is_available(): - return [torch.device(device) for device in range(torch.cuda.device_count())] - elif ( - hasattr(torch.backends, "mps") - and torch.backends.mps.is_available() - and os.getenv("HAYSTACK_MPS_ENABLED", "true") != "false" - ): - return [torch.device("mps")] - return [torch.device("cpu")] diff --git a/rest_api/LICENSE b/rest_api/LICENSE deleted file mode 100644 index 6fb66d8d5f..0000000000 --- a/rest_api/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 deepset GmbH - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/rest_api/README.md b/rest_api/README.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/rest_api/pyproject.toml b/rest_api/pyproject.toml deleted file mode 100644 index e5eda60e7d..0000000000 --- a/rest_api/pyproject.toml +++ /dev/null @@ -1,79 +0,0 @@ -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[project] -name = "rest-api" -description = 'API server for Haystack (https://github.com/deepset-ai/haystack)' -readme = "README.md" -requires-python = ">=3.7" -license = "Apache-2.0" -keywords = [] -authors = [ - { name = "deepset.ai", email = "malte.pietsch@deepset.ai" }, -] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering :: Artificial Intelligence", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: Implementation :: CPython", -] -dependencies = [ - "farm-haystack", - "fastapi", - "uvicorn<1", - "python-multipart<1", # optional FastAPI dependency for form data - "pynvml", - "psutil" -] -dynamic = ["version"] - -[project.optional-dependencies] -dev = [ - "httpx" -] - -[project.urls] -Documentation = "https://github.com/deepset-ai/haystack/tree/main/rest_api#readme" -Issues = "https://github.com/deepset-ai/haystack/issues" -Source = "https://github.com/deepset-ai/haystack/tree/main/rest_api" - -[tool.hatch.version] -path = "rest_api/__about__.py" - -[tool.hatch.build.targets.sdist] -[tool.hatch.build.targets.wheel] - -[tool.hatch.envs.default] -dependencies = [ - "pytest", - "pytest-cov", -] -[tool.hatch.envs.default.scripts] -cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=rest_api --cov=tests" -no-cov = "cov --no-cov" - -[[tool.hatch.envs.test.matrix]] -python = ["37", "38", "39", "310"] - -[tool.coverage.run] -branch = true -parallel = true -omit = ["rest_api/__about__.py"] - -[tool.coverage.report] -exclude_lines = [ - "no cov", - "if __name__ == .__main__.:", - "if TYPE_CHECKING:", -] - -[tool.black] -line-length = 120 -skip_magic_trailing_comma = true # For compatibility with pydoc>=4.6, check if still needed. diff --git a/rest_api/rest_api/__about__.py b/rest_api/rest_api/__about__.py deleted file mode 100644 index acf60584fa..0000000000 --- a/rest_api/rest_api/__about__.py +++ /dev/null @@ -1,13 +0,0 @@ -import logging - -from pathlib import Path - - -__version__ = "0.0.0" - - -try: - __version__ = open(Path(__file__).parent.parent / "VERSION.txt", "r").read() -except Exception: - logger = logging.getLogger(__name__) - logger.exception("No VERSION.txt found!") diff --git a/rest_api/rest_api/__init__.py b/rest_api/rest_api/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/rest_api/rest_api/application.py b/rest_api/rest_api/application.py deleted file mode 100644 index c7921b2164..0000000000 --- a/rest_api/rest_api/application.py +++ /dev/null @@ -1,25 +0,0 @@ -import logging - -import uvicorn -from rest_api.utils import get_app, get_pipelines - - -logging.basicConfig(format="%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p") -logger = logging.getLogger(__name__) -logging.getLogger("elasticsearch").setLevel(logging.WARNING) -logging.getLogger("haystack").setLevel(logging.INFO) - - -app = get_app() -pipelines = get_pipelines() # Unused here, called to init the pipelines early - - -logger.info("Open http://127.0.0.1:8000/docs to see Swagger API Documentation.") -logger.info( - "Or just try it out directly: curl --request POST --url 'http://127.0.0.1:8000/query' " - '-H "Content-Type: application/json" --data \'{"query": "Who is the father of Arya Stark?"}\'' -) - - -if __name__ == "__main__": - uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/rest_api/rest_api/config.py b/rest_api/rest_api/config.py deleted file mode 100644 index 2211743a2b..0000000000 --- a/rest_api/rest_api/config.py +++ /dev/null @@ -1,16 +0,0 @@ -import os -from pathlib import Path - - -PIPELINE_YAML_PATH = os.getenv( - "PIPELINE_YAML_PATH", str((Path(__file__).parent / "pipeline" / "pipelines.haystack-pipeline.yml").absolute()) -) -QUERY_PIPELINE_NAME = os.getenv("QUERY_PIPELINE_NAME", "query") -INDEXING_PIPELINE_NAME = os.getenv("INDEXING_PIPELINE_NAME", "indexing") - -FILE_UPLOAD_PATH = os.getenv("FILE_UPLOAD_PATH", str((Path(__file__).parent / "file-upload").absolute())) - -LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") -ROOT_PATH = os.getenv("ROOT_PATH", "/") - -CONCURRENT_REQUEST_PER_WORKER = int(os.getenv("CONCURRENT_REQUEST_PER_WORKER", "4")) diff --git a/rest_api/rest_api/controller/__init__.py b/rest_api/rest_api/controller/__init__.py deleted file mode 100644 index 4b066366a9..0000000000 --- a/rest_api/rest_api/controller/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from rest_api.pipeline import custom_component # this import is required for the Custom Components to be registered diff --git a/rest_api/rest_api/controller/document.py b/rest_api/rest_api/controller/document.py deleted file mode 100644 index a1f0bcb211..0000000000 --- a/rest_api/rest_api/controller/document.py +++ /dev/null @@ -1,56 +0,0 @@ -from typing import Optional, List - -import logging - -from fastapi import FastAPI, APIRouter -from haystack.document_stores import BaseDocumentStore -from haystack.schema import Document - -from rest_api.utils import get_app, get_pipelines -from rest_api.config import LOG_LEVEL -from rest_api.schema import FilterRequest - - -logging.getLogger("haystack").setLevel(LOG_LEVEL) -logger = logging.getLogger("haystack") - - -router = APIRouter() -app: FastAPI = get_app() -document_store: BaseDocumentStore = get_pipelines().get("document_store", None) - - -@router.post("/documents/get_by_filters", response_model=List[Document], response_model_exclude_none=True) -def get_documents(filters: FilterRequest, index: Optional[str] = None): - """ - This endpoint allows you to retrieve documents contained in your document store. - You can filter the documents to retrieve by metadata (like the document's name), - or provide an empty JSON object to clear the document store. - - Example of filters: - `'{"filters": {{"name": ["some", "more"], "category": ["only_one"]}}'` - - To get all documents you should provide an empty dict, like: - `'{"filters": {}}'` - """ - docs = document_store.get_all_documents(filters=filters.filters, index=index) - for doc in docs: - doc.embedding = None - return docs - - -@router.post("/documents/delete_by_filters", response_model=bool) -def delete_documents(filters: FilterRequest, index: Optional[str] = None): - """ - This endpoint allows you to delete documents contained in your document store. - You can filter the documents to delete by metadata (like the document's name), - or provide an empty JSON object to clear the document store. - - Example of filters: - `'{"filters": {{"name": ["some", "more"], "category": ["only_one"]}}'` - - To get all documents you should provide an empty dict, like: - `'{"filters": {}}'` - """ - document_store.delete_documents(filters=filters.filters, index=index) - return True diff --git a/rest_api/rest_api/controller/errors/__init__.py b/rest_api/rest_api/controller/errors/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/rest_api/rest_api/controller/errors/http_error.py b/rest_api/rest_api/controller/errors/http_error.py deleted file mode 100644 index c503229358..0000000000 --- a/rest_api/rest_api/controller/errors/http_error.py +++ /dev/null @@ -1,7 +0,0 @@ -from fastapi import HTTPException -from starlette.requests import Request -from starlette.responses import JSONResponse - - -async def http_error_handler(_: Request, exc: HTTPException) -> JSONResponse: - return JSONResponse({"errors": [exc.detail]}, status_code=exc.status_code) diff --git a/rest_api/rest_api/controller/feedback.py b/rest_api/rest_api/controller/feedback.py deleted file mode 100644 index 8e891c6e9b..0000000000 --- a/rest_api/rest_api/controller/feedback.py +++ /dev/null @@ -1,199 +0,0 @@ -from typing import Any, Dict, List, Union, Optional - -import json -import logging - -from fastapi import FastAPI, APIRouter -from haystack.schema import Label, Span -from haystack.document_stores import BaseDocumentStore -from rest_api.schema import FilterRequest, CreateLabelSerialized -from rest_api.utils import get_app, get_pipelines - - -logger = logging.getLogger(__name__) - -router = APIRouter() -app: FastAPI = get_app() -document_store: BaseDocumentStore = get_pipelines().get("document_store", None) - - -@router.post("/feedback") -def post_feedback(feedback: CreateLabelSerialized, index: Optional[str] = None): - """ - With this endpoint, the API user can submit their feedback on an answer for a particular query. This feedback is then written to the label_index of the DocumentStore. - - For example, the user can send feedback on whether the answer was correct and whether the right snippet was identified as the answer. - - Information submitted through this endpoint is used to train the underlying QA model. - """ - - if feedback.origin is None: - feedback.origin = "user-feedback" - - label = Label(**feedback.dict()) - document_store.write_labels([label], index=index) - - -@router.get("/feedback", response_model=List[Label]) -def get_feedback(index: Optional[str] = None): - """ - This endpoint allows the API user to retrieve all the feedback that has been submitted through the `POST /feedback` endpoint. - """ - labels = document_store.get_all_labels(index=index) - return labels - - -@router.delete("/feedback") -def delete_feedback(index: Optional[str] = None): - """ - This endpoint allows the API user to delete all the feedback that has been submitted through the - `POST /feedback` endpoint. - """ - all_labels = document_store.get_all_labels(index=index) - user_label_ids = [label.id for label in all_labels if label.origin == "user-feedback"] - document_store.delete_labels(ids=user_label_ids, index=index) - - -@router.post("/eval-feedback") -def get_feedback_metrics(filters: Optional[FilterRequest] = None, index: Optional[str] = None): - """ - This endpoint returns basic accuracy metrics based on user feedback, for example, the ratio of correct answers or correctly identified documents. - You can filter the output by document or label. - - Example: - - `curl --location --request POST 'http://127.0.0.1:8000/eval-doc-qa-feedback' \ - --header 'Content-Type: application/json' \ - --data-raw '{ "filters": {"document_id": ["XRR3xnEBCYVTkbTystOB"]} }'` - """ - - if filters: - filters_content = filters.filters or {} - filters_content["origin"] = ["user-feedback"] - else: - filters_content = {"origin": ["user-feedback"]} - - labels = document_store.get_all_labels(filters=filters_content, index=index) - - res: Dict[str, Optional[Union[float, int]]] - if len(labels) > 0: - answer_feedback = [1 if l.is_correct_answer else 0 for l in labels] - doc_feedback = [1 if l.is_correct_document else 0 for l in labels] - - answer_accuracy = sum(answer_feedback) / len(answer_feedback) - doc_accuracy = sum(doc_feedback) / len(doc_feedback) - - res = {"answer_accuracy": answer_accuracy, "document_accuracy": doc_accuracy, "n_feedback": len(labels)} - else: - res = {"answer_accuracy": None, "document_accuracy": None, "n_feedback": 0} - return res - - -@router.get("/export-feedback") -def export_feedback( - context_size: int = 100_000, - full_document_context: bool = True, - only_positive_labels: bool = False, - index: Optional[str] = None, -): - """ - This endpoint returns JSON output in the SQuAD format for question/answer pairs that were marked as "relevant" by user feedback through the `POST /feedback` endpoint. - - The context_size param can be used to limit response size for large documents. - """ - if only_positive_labels: - labels = document_store.get_all_labels( - filters={"is_correct_answer": [True], "origin": ["user-feedback"]}, index=index - ) - else: - labels = document_store.get_all_labels(filters={"origin": ["user-feedback"]}, index=index) - # Filter out the labels where the passage is correct but answer is wrong (in SQuAD this matches - # neither a "positive example" nor a negative "is_impossible" one) - labels = [l for l in labels if not (l.is_correct_document is True and l.is_correct_answer is False)] - - export_data = [] - - for label in labels: - answer_text = label.answer.answer if label and label.answer else "" - - offset_start_in_document = 0 - if label.answer and label.answer.offsets_in_document: - if isinstance(label.answer.offsets_in_document[0], Span): - offset_start_in_document = label.answer.offsets_in_document[0].start - else: - offset_start_in_document = label.answer.offsets_in_document[0].row - - if full_document_context: - context = label.document.content - answer_start = offset_start_in_document - else: - text = label.document.content - # the final length of context(including the answer string) is 'context_size'. - # we try to add equal characters for context before and after the answer string. - # if either beginning or end of text is reached, we correspondingly - # append more context characters at the other end of answer string. - context_to_add = int((context_size - len(answer_text)) / 2) - start_pos = max(offset_start_in_document - context_to_add, 0) - additional_context_at_end = max(context_to_add - offset_start_in_document, 0) - end_pos = min(offset_start_in_document + len(answer_text) + context_to_add, len(text) - 1) - additional_context_at_start = max( - offset_start_in_document + len(answer_text) + context_to_add - len(text), 0 - ) - start_pos = max(0, start_pos - additional_context_at_start) - end_pos = min(len(text) - 1, end_pos + additional_context_at_end) - context = text[start_pos:end_pos] - answer_start = offset_start_in_document - start_pos - - squad_label: Dict[str, Any] - if label.is_correct_answer is False and label.is_correct_document is False: # No answer - squad_label = { - "paragraphs": [ - { - "context": context, - "id": label.document.id, - "qas": [{"question": label.query, "id": label.id, "is_impossible": True, "answers": []}], - } - ] - } - else: - squad_label = { - "paragraphs": [ - { - "context": context, - "id": label.document.id, - "qas": [ - { - "question": label.query, - "id": label.id, - "is_impossible": False, - "answers": [{"text": answer_text, "answer_start": answer_start}], - } - ], - } - ] - } - - # quality check - start = squad_label["paragraphs"][0]["qas"][0]["answers"][0]["answer_start"] - answer = squad_label["paragraphs"][0]["qas"][0]["answers"][0]["text"] - context = squad_label["paragraphs"][0]["context"] - if context[start : start + len(answer)] != answer: - logger.error( - "Skipping invalid squad label as string via offsets ('%s') does not match answer string ('%s') ", - context[start : start + len(answer)], - answer, - ) - export_data.append(squad_label) - - export = {"data": export_data} - - feedback_file = "feedback_squad_direct.json" - try: - with open(feedback_file, "w", encoding="utf8") as f: - json.dump(export_data, f, ensure_ascii=False, sort_keys=True, indent=4) - except Exception as e: - # might fail in some docker container environment. - logger.error("Can't write feedback file. filename=%s", feedback_file) - logger.exception(e) - - return export diff --git a/rest_api/rest_api/controller/file_upload.py b/rest_api/rest_api/controller/file_upload.py deleted file mode 100644 index 97b29994eb..0000000000 --- a/rest_api/rest_api/controller/file_upload.py +++ /dev/null @@ -1,99 +0,0 @@ -from typing import Optional, List - -import json -import shutil -import uuid -from pathlib import Path - -from fastapi import FastAPI, APIRouter, UploadFile, File, Form, HTTPException, Depends -from pydantic import BaseModel -from haystack import Pipeline -from haystack.nodes import BaseConverter, PreProcessor - -from rest_api.utils import get_app, get_pipelines -from rest_api.config import FILE_UPLOAD_PATH -from rest_api.controller.utils import as_form - - -router = APIRouter() -app: FastAPI = get_app() -indexing_pipeline: Pipeline = get_pipelines().get("indexing_pipeline", None) - - -@as_form -class FileConverterParams(BaseModel): - remove_numeric_tables: Optional[bool] = None - valid_languages: Optional[List[str]] = None - - -@as_form -class PreprocessorParams(BaseModel): - clean_whitespace: Optional[bool] = None - clean_empty_lines: Optional[bool] = None - clean_header_footer: Optional[bool] = None - split_by: Optional[str] = None - split_length: Optional[int] = None - split_overlap: Optional[int] = None - split_respect_sentence_boundary: Optional[bool] = None - - -class Response(BaseModel): - file_id: str - - -@router.post("/file-upload") -def upload_file( - files: List[UploadFile] = File(...), - # JSON serialized string - meta: Optional[str] = Form("null"), # type: ignore - additional_params: Optional[str] = Form("null"), # type: ignore - fileconverter_params: FileConverterParams = Depends(FileConverterParams.as_form), # type: ignore - preprocessor_params: PreprocessorParams = Depends(PreprocessorParams.as_form), # type: ignore - keep_files: Optional[bool] = False, -): - """ - You can use this endpoint to upload a file for indexing - (see https://docs.haystack.deepset.ai/docs/rest_api#indexing-documents-in-the-haystack-rest-api-documentstore). - - Note: files are removed immediately after being indexed. If you want to keep them, pass the - `keep_files=true` parameter in the request payload. - """ - if not indexing_pipeline: - raise HTTPException(status_code=501, detail="Indexing Pipeline is not configured.") - - file_paths: list = [] - file_metas: list = [] - - meta_form = json.loads(meta) or {} # type: ignore - if not isinstance(meta_form, dict): - raise HTTPException(status_code=500, detail=f"The meta field must be a dict or None, not {type(meta_form)}") - - for file in files: - try: - file_path = Path(FILE_UPLOAD_PATH) / f"{uuid.uuid4().hex}_{file.filename}" - with file_path.open("wb") as buffer: - shutil.copyfileobj(file.file, buffer) - - file_paths.append(file_path) - meta_form["name"] = file.filename - file_metas.append(meta_form) - finally: - file.file.close() - - params = json.loads(additional_params) or {} # type: ignore - - # Find nodes names - converters = indexing_pipeline.get_nodes_by_class(BaseConverter) - preprocessors = indexing_pipeline.get_nodes_by_class(PreProcessor) - - for converter in converters: - params[converter.name] = fileconverter_params.dict() - for preprocessor in preprocessors: - params[preprocessor.name] = preprocessor_params.dict() - - indexing_pipeline.run(file_paths=file_paths, meta=file_metas, params=params) - - # Clean up indexed files - if not keep_files: - for p in file_paths: - p.unlink() diff --git a/rest_api/rest_api/controller/health.py b/rest_api/rest_api/controller/health.py deleted file mode 100644 index a7524f111e..0000000000 --- a/rest_api/rest_api/controller/health.py +++ /dev/null @@ -1,129 +0,0 @@ -from typing import List, Optional - -import logging - -import os -import pynvml -import psutil - -from pydantic import BaseModel, Field, validator - -from fastapi import FastAPI, APIRouter - -import haystack - -from rest_api.utils import get_app -from rest_api.config import LOG_LEVEL - -logging.getLogger("haystack").setLevel(LOG_LEVEL) -logger = logging.getLogger("haystack") - - -router = APIRouter() -app: FastAPI = get_app() - - -class CPUUsage(BaseModel): - used: float = Field(..., description="REST API average CPU usage in percentage") - - @validator("used") - @classmethod - def used_check(cls, v): - return round(v, 2) - - -class MemoryUsage(BaseModel): - used: float = Field(..., description="REST API used memory in percentage") - - @validator("used") - @classmethod - def used_check(cls, v): - return round(v, 2) - - -class GPUUsage(BaseModel): - kernel_usage: float = Field(..., description="GPU kernel usage in percentage") - memory_total: int = Field(..., description="Total GPU memory in megabytes") - memory_used: Optional[int] = Field(..., description="REST API used GPU memory in megabytes") - - @validator("kernel_usage") - @classmethod - def kernel_usage_check(cls, v): - return round(v, 2) - - -class GPUInfo(BaseModel): - index: int = Field(..., description="GPU index") - usage: GPUUsage = Field(..., description="GPU usage details") - - -class HealthResponse(BaseModel): - version: str = Field(..., description="Haystack version") - cpu: CPUUsage = Field(..., description="CPU usage details") - memory: MemoryUsage = Field(..., description="Memory usage details") - gpus: List[GPUInfo] = Field(default_factory=list, description="GPU usage details") - - -def get_cpu_usage() -> CPUUsage: - cpu_count = os.cpu_count() or 1 - p = psutil.Process() - p_cpu_usage = p.cpu_percent() / cpu_count - return CPUUsage(used=p_cpu_usage) - - -def get_memory_usage() -> MemoryUsage: - p = psutil.Process() - p_memory_usage = p.memory_percent() - return MemoryUsage(used=p_memory_usage) - - -def get_gpu_usage() -> List[GPUInfo]: - gpus: List[GPUInfo] = [] - try: - pynvml.nvmlInit() - try: - gpu_count = pynvml.nvmlDeviceGetCount() - for i in range(gpu_count): - handle = pynvml.nvmlDeviceGetHandleByIndex(i) - info = pynvml.nvmlDeviceGetMemoryInfo(handle) - gpu_mem_total = float(info.total) / 1024 / 1024 - gpu_mem_used = None - try: - for proc in pynvml.nvmlDeviceGetComputeRunningProcesses(handle): - if proc.pid == os.getpid(): - gpu_mem_used = float(proc.usedGpuMemory) / 1024 / 1024 - break - except pynvml.NVMLError: - # ignore if nvmlDeviceGetComputeRunningProcesses is not supported - # this can happen for outdated drivers - pass - gpu_info = GPUInfo( - index=i, - usage=GPUUsage( - memory_total=round(gpu_mem_total), - kernel_usage=pynvml.nvmlDeviceGetUtilizationRates(handle).gpu, - memory_used=round(gpu_mem_used) if gpu_mem_used is not None else None, - ), - ) - gpus.append(gpu_info) - except pynvml.NVMLError as e: - logger.warning("Couldn't collect GPU stats: %s", str(e)) - finally: - pynvml.nvmlShutdown() - except pynvml.NVMLError: - # Here we intentionally ignore errors that occur when NVML (NVIDIA Management Library) is not available - # or found. See the original code's comment for more details. - pass - - return gpus - - -@router.get("/health", response_model=HealthResponse, status_code=200) -def get_health_status(): - """ - This endpoint allows external systems to monitor the health of the Haystack REST API. - """ - - return HealthResponse( - version=haystack.__version__, cpu=get_cpu_usage(), memory=get_memory_usage(), gpus=get_gpu_usage() - ) diff --git a/rest_api/rest_api/controller/search.py b/rest_api/rest_api/controller/search.py deleted file mode 100644 index abdeebe1c9..0000000000 --- a/rest_api/rest_api/controller/search.py +++ /dev/null @@ -1,76 +0,0 @@ -from typing import Dict, Any - -import logging -import time -import json - -from pydantic import BaseConfig -from fastapi import FastAPI, APIRouter -import haystack -from haystack import Pipeline - -from rest_api.utils import get_app, get_pipelines -from rest_api.config import LOG_LEVEL -from rest_api.schema import QueryRequest, QueryResponse - - -logging.getLogger("haystack").setLevel(LOG_LEVEL) -logger = logging.getLogger("haystack") - - -BaseConfig.arbitrary_types_allowed = True - - -router = APIRouter() -app: FastAPI = get_app() -query_pipeline: Pipeline = get_pipelines().get("query_pipeline", None) -concurrency_limiter = get_pipelines().get("concurrency_limiter", None) - - -@router.get("/initialized") -def check_status(): - """ - This endpoint can be used during startup to understand if the - server is ready to take any requests, or is still loading. - - The recommended approach is to call this endpoint with a short timeout, - like 500ms, and in case of no reply, consider the server busy. - """ - return True - - -@router.get("/hs_version") -def haystack_version(): - """ - Get the running Haystack version. - """ - return {"hs_version": haystack.__version__} - - -@router.post("/query", response_model=QueryResponse, response_model_exclude_none=True) -def query(request: QueryRequest): - """ - This endpoint receives the question as a string and allows the requester to set - additional parameters that will be passed on to the Haystack pipeline. - """ - with concurrency_limiter.run(): - result = _process_request(query_pipeline, request) - return result - - -def _process_request(pipeline, request) -> Dict[str, Any]: - start_time = time.time() - - params = request.params or {} - result = pipeline.run(query=request.query, params=params, debug=request.debug) - - # Ensure answers and documents exist, even if they're empty lists - if not "documents" in result: - result["documents"] = [] - if not "answers" in result: - result["answers"] = [] - - logger.info( - json.dumps({"request": request, "response": result, "time": f"{(time.time() - start_time):.2f}"}, default=str) - ) - return result diff --git a/rest_api/rest_api/controller/utils.py b/rest_api/rest_api/controller/utils.py deleted file mode 100644 index 49587968ed..0000000000 --- a/rest_api/rest_api/controller/utils.py +++ /dev/null @@ -1,50 +0,0 @@ -from typing import Type, NewType - -import inspect -from contextlib import contextmanager -from threading import Semaphore - -from fastapi import Form, HTTPException -from pydantic import BaseModel - - -class RequestLimiter: - def __init__(self, limit): - self.semaphore = Semaphore(limit) - - @contextmanager - def run(self): - acquired = self.semaphore.acquire(blocking=False) - if not acquired: - raise HTTPException(status_code=503, detail="The server is busy processing requests.") - try: - yield acquired - finally: - self.semaphore.release() - - -StringId = NewType("StringId", str) - - -def as_form(cls: Type[BaseModel]): - """ - Adds an as_form class method to decorated models. The as_form class method - can be used with FastAPI endpoints - """ - new_params = [ - inspect.Parameter( - field.alias, - inspect.Parameter.POSITIONAL_ONLY, - default=(Form(field.default) if not field.required else Form(...)), - ) - for field in cls.__fields__.values() - ] - - async def _as_form(**data): - return cls(**data) - - sig = inspect.signature(_as_form) - sig = sig.replace(parameters=new_params) - _as_form.__signature__ = sig # type: ignore - setattr(cls, "as_form", _as_form) - return cls diff --git a/rest_api/rest_api/pipeline/__init__.py b/rest_api/rest_api/pipeline/__init__.py deleted file mode 100644 index beca14e611..0000000000 --- a/rest_api/rest_api/pipeline/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -from typing import Any, Dict - -import os -import logging -from pathlib import Path - -from haystack.pipelines.base import Pipeline -from haystack.document_stores import FAISSDocumentStore, InMemoryDocumentStore -from haystack.errors import PipelineConfigError - -from rest_api.controller.utils import RequestLimiter - - -logger = logging.getLogger(__name__) - -# Each instance of FAISSDocumentStore creates an in-memory FAISS index, -# the Indexing & Query Pipelines will end up with different indices for each worker. -# The same applies for InMemoryDocumentStore. -SINGLE_PROCESS_DOC_STORES = (FAISSDocumentStore, InMemoryDocumentStore) - - -def _load_pipeline(pipeline_yaml_path, pipeline_name): - # Load pipeline (if available) - try: - pipeline = Pipeline.load_from_yaml(Path(pipeline_yaml_path), pipeline_name=pipeline_name) - logger.info("Loaded pipeline nodes: %s", pipeline.graph.nodes.keys()) - document_store = _get_pipeline_doc_store(pipeline, pipeline_name) - except PipelineConfigError as e: - pipeline, document_store = None, None - logger.error("Error loading %s pipeline from %s. \n %s\n", pipeline_name, pipeline_yaml_path, e.message) - return pipeline, document_store - - -def _get_last_pipeline_component(pipeline): - last_node_name = list(pipeline.graph.nodes.keys())[-1] - return pipeline.get_node(last_node_name) - - -def _get_pipeline_doc_store(pipeline, pipeline_name): - document_store = pipeline.get_document_store() - logger.info("Loading docstore: %s", document_store) - last_node = _get_last_pipeline_component(pipeline) - if pipeline_name and pipeline_name.startswith("indexing") and isinstance(last_node, SINGLE_PROCESS_DOC_STORES): - logger.warning( - "Indexing pipelines with FAISSDocumentStore or InMemoryDocumentStore detected!" - "\n These DocumentStores will not work as expected in indexing pipelines with REST APIs." - ) - return document_store - - -def setup_pipelines() -> Dict[str, Any]: - # Re-import the configuration variables - from rest_api import config # pylint: disable=reimported - - pipelines = {} - - # Load query pipeline & document store - query_pipeline, document_store = _load_pipeline(config.PIPELINE_YAML_PATH, config.QUERY_PIPELINE_NAME) - pipelines["query_pipeline"] = query_pipeline - pipelines["document_store"] = document_store - - # Setup concurrency limiter - concurrency_limiter = RequestLimiter(config.CONCURRENT_REQUEST_PER_WORKER) - logger.info("Concurrent requests per worker: %s", config.CONCURRENT_REQUEST_PER_WORKER) - pipelines["concurrency_limiter"] = concurrency_limiter - - # Load indexing pipeline - index_pipeline, _ = _load_pipeline(config.PIPELINE_YAML_PATH, config.INDEXING_PIPELINE_NAME) - if not index_pipeline: - logger.warning("Indexing Pipeline is not setup. File Upload API will not be available.") - pipelines["indexing_pipeline"] = index_pipeline - - # Create directory for uploaded files - os.makedirs(config.FILE_UPLOAD_PATH, exist_ok=True) - - return pipelines diff --git a/rest_api/rest_api/pipeline/custom_component.py b/rest_api/rest_api/pipeline/custom_component.py deleted file mode 100644 index 9bf032b003..0000000000 --- a/rest_api/rest_api/pipeline/custom_component.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -Pipelines allow putting together Components to build a graph. - -In addition to the standard Haystack Components, custom user-defined Components -can be used in a Pipeline YAML configuration. - -The classes for the Custom Components must be defined in this file. -""" - - -from haystack.nodes.base import BaseComponent - - -class SampleComponent(BaseComponent): - outgoing_edges: int = 1 - - def run(self, **kwargs): - raise NotImplementedError diff --git a/rest_api/rest_api/pipeline/pipeline_empty.haystack-pipeline.yml b/rest_api/rest_api/pipeline/pipeline_empty.haystack-pipeline.yml deleted file mode 100644 index b813b25517..0000000000 --- a/rest_api/rest_api/pipeline/pipeline_empty.haystack-pipeline.yml +++ /dev/null @@ -1,17 +0,0 @@ -# Dummy pipeline, used when the CI needs to load the REST API to extract the OpenAPI specs. DO NOT USE. -version: ignore - -components: - - name: FileTypeClassifier - type: FileTypeClassifier - -pipelines: - - name: query - nodes: - - name: FileTypeClassifier - inputs: [File] - - - name: indexing - nodes: - - name: FileTypeClassifier - inputs: [File] diff --git a/rest_api/rest_api/pipeline/pipelines.haystack-pipeline.yml b/rest_api/rest_api/pipeline/pipelines.haystack-pipeline.yml deleted file mode 100644 index c3935cdc46..0000000000 --- a/rest_api/rest_api/pipeline/pipelines.haystack-pipeline.yml +++ /dev/null @@ -1,53 +0,0 @@ -# To allow your IDE to autocomplete and validate your YAML pipelines, name them as .haystack-pipeline.yml - -version: ignore - -components: # define all the building-blocks for Pipeline - - name: DocumentStore - type: ElasticsearchDocumentStore - params: - host: localhost - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore # params can reference other components defined in the YAML - top_k: 5 - - name: Reader # custom-name for the component; helpful for visualization & debugging - type: FARMReader # Haystack Class name for the component - params: - model_name_or_path: deepset/roberta-base-squad2 - context_window_size: 500 - return_no_answer: true - - name: TextFileConverter - type: TextConverter - - name: PDFFileConverter - type: PDFToTextConverter - - name: Preprocessor - type: PreProcessor - params: - split_by: word - split_length: 1000 - - name: FileTypeClassifier - type: FileTypeClassifier - -pipelines: - - name: query # a sample extractive-qa Pipeline - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - - name: indexing - nodes: - - name: FileTypeClassifier - inputs: [File] - - name: TextFileConverter - inputs: [FileTypeClassifier.output_1] - - name: PDFFileConverter - inputs: [FileTypeClassifier.output_2] - - name: Preprocessor - inputs: [PDFFileConverter, TextFileConverter] - - name: Retriever - inputs: [Preprocessor] - - name: DocumentStore - inputs: [Retriever] diff --git a/rest_api/rest_api/pipeline/pipelines_dpr.haystack-pipeline.yml b/rest_api/rest_api/pipeline/pipelines_dpr.haystack-pipeline.yml deleted file mode 100644 index d8e174a299..0000000000 --- a/rest_api/rest_api/pipeline/pipelines_dpr.haystack-pipeline.yml +++ /dev/null @@ -1,53 +0,0 @@ -# To allow your IDE to autocomplete and validate your YAML pipelines, name them as .haystack-pipeline.yml - -version: ignore - -components: # define all the building-blocks for Pipeline - - name: DocumentStore - type: ElasticsearchDocumentStore # consider using WeaviateDocumentStore for scaling to large number of documents - params: - host: localhost - - name: Retriever - type: DensePassageRetriever - params: - document_store: DocumentStore # params can reference other components defined in the YAML - top_k: 5 - - name: Reader # custom-name for the component; helpful for visualization & debugging - type: FARMReader # Haystack Class name for the component - params: - model_name_or_path: deepset/roberta-base-squad2 - context_window_size: 1000 - return_no_answer: true - - name: TextFileConverter - type: TextConverter - - name: PDFFileConverter - type: PDFToTextConverter - - name: Preprocessor - type: PreProcessor - params: - split_by: word - split_length: 1000 - - name: FileTypeClassifier - type: FileTypeClassifier - -pipelines: - - name: query # a sample extractive-qa Pipeline - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - - name: indexing - nodes: - - name: FileTypeClassifier - inputs: [File] - - name: TextFileConverter - inputs: [FileTypeClassifier.output_1] - - name: PDFFileConverter - inputs: [FileTypeClassifier.output_2] - - name: Preprocessor - inputs: [PDFFileConverter, TextFileConverter] - - name: Retriever - inputs: [Preprocessor] - - name: DocumentStore - inputs: [Retriever] diff --git a/rest_api/rest_api/pipeline/pipelines_faq.haystack-pipeline.yml b/rest_api/rest_api/pipeline/pipelines_faq.haystack-pipeline.yml deleted file mode 100644 index 3473660ff1..0000000000 --- a/rest_api/rest_api/pipeline/pipelines_faq.haystack-pipeline.yml +++ /dev/null @@ -1,40 +0,0 @@ -# To allow your IDE to autocomplete and validate your YAML pipelines, name them as .haystack-pipeline.yml - -version: ignore - -components: # define all the building-blocks for Pipeline - - name: DocumentStore - type: ElasticsearchDocumentStore - params: - host: localhost - embedding_field: question_emb - embedding_dim: 384 - excluded_meta_data: - - question_emb - similarity: cosine - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore # params can reference other components defined in the YAML - embedding_model: sentence-transformers/all-MiniLM-L6-v2 - scale_score: False - - name: Doc2Answers # custom-name for the component; helpful for visualization & debugging - type: Docs2Answers # Haystack Class name for the component - - name: CsvTextConverter - type: CsvTextConverter - -pipelines: - - name: query # a sample extractive-qa Pipeline - nodes: - - name: Retriever - inputs: [Query] - - name: Doc2Answers - inputs: [Retriever] - - name: indexing - nodes: - - name: CsvTextConverter - inputs: [File] - - name: Retriever - inputs: [ CsvTextConverter ] - - name: DocumentStore - inputs: [ Retriever ] diff --git a/rest_api/rest_api/pipeline/pipelines_web_lfqa.haystack-pipeline.yaml b/rest_api/rest_api/pipeline/pipelines_web_lfqa.haystack-pipeline.yaml deleted file mode 100644 index 4126ae1c62..0000000000 --- a/rest_api/rest_api/pipeline/pipelines_web_lfqa.haystack-pipeline.yaml +++ /dev/null @@ -1,42 +0,0 @@ -version: ignore - -components: -- name: Retriever - params: - api_key: RETRIEVER_PARAMS_API_KEY - type: WebRetriever -- name: Shaper - params: - func: join_documents_and_scores - inputs: - documents: documents - outputs: - - documents - type: Shaper -- name: custom-at-query-time - params: - prompt: "\nSynthesize a comprehensive answer from the following most relevant\ - \ paragraphs and the given question.\nProvide a clear and concise response that\ - \ summarizes the key points and information presented in the paragraphs.\nYour\ - \ answer should be in your own words and be no longer than 50 words.\n\n\n Paragraphs:\ - \ {documents} \n\n Question: {query} \n\n Answer:\n" - type: PromptTemplate -- name: PromptNode - params: - api_key: PROMPTNODE_PARAMS_API_KEY - default_prompt_template: custom-at-query-time - max_length: 256 - model_name_or_path: gpt-3.5-turbo - type: PromptNode -pipelines: -- name: query - nodes: - - inputs: - - Query - name: Retriever - - inputs: - - Retriever - name: Shaper - - inputs: - - Shaper - name: PromptNode diff --git a/rest_api/rest_api/schema.py b/rest_api/rest_api/schema.py deleted file mode 100644 index e108763dde..0000000000 --- a/rest_api/rest_api/schema.py +++ /dev/null @@ -1,60 +0,0 @@ -from __future__ import annotations - -from typing import Dict, List, Optional, Union, Literal -import numpy as np -import pandas as pd - -from pydantic import BaseModel, Field, Extra -from pydantic import BaseConfig - -from haystack.schema import Answer, Document - - -BaseConfig.arbitrary_types_allowed = True -BaseConfig.json_encoders = { - np.ndarray: lambda x: x.tolist(), - pd.DataFrame: lambda x: [x.columns.tolist()] + x.values.tolist(), -} - - -PrimitiveType = Union[str, int, float, bool] - - -class RequestBaseModel(BaseModel): - class Config: - # Forbid any extra fields in the request to avoid silent failures - extra = Extra.forbid - - -class QueryRequest(RequestBaseModel): - query: str - params: Optional[dict] = None - debug: Optional[bool] = False - - -class FilterRequest(RequestBaseModel): - filters: Optional[Dict[str, Union[PrimitiveType, List[PrimitiveType], Dict[str, PrimitiveType]]]] = None - - -class CreateLabelSerialized(RequestBaseModel): - id: Optional[str] = None - query: str - document: Document - is_correct_answer: bool - is_correct_document: bool - origin: Literal["user-feedback", "gold-label"] - answer: Optional[Answer] = None - no_answer: Optional[bool] = None - pipeline_id: Optional[str] = None - created_at: Optional[str] = None - updated_at: Optional[str] = None - meta: Optional[dict] = None - filters: Optional[dict] = None - - -class QueryResponse(BaseModel): - query: str - answers: List[Answer] = [] - documents: List[Document] = [] - results: Optional[List[str]] = None - debug: Optional[Dict] = Field(None, alias="_debug") diff --git a/rest_api/rest_api/utils.py b/rest_api/rest_api/utils.py deleted file mode 100644 index d5c566fa6b..0000000000 --- a/rest_api/rest_api/utils.py +++ /dev/null @@ -1,80 +0,0 @@ -from fastapi import FastAPI, HTTPException, APIRouter -from fastapi.routing import APIRoute -from fastapi.openapi.utils import get_openapi -from starlette.middleware.cors import CORSMiddleware -from haystack import __version__ as haystack_version - -from rest_api.pipeline import setup_pipelines -from rest_api.controller.errors.http_error import http_error_handler - - -app = None -pipelines = None - - -def get_app() -> FastAPI: - """ - Initializes the App object and creates the global pipelines as possible. - """ - global app # pylint: disable=global-statement - if app: - return app - - from rest_api.config import ROOT_PATH - - app = FastAPI(title="Haystack REST API", debug=True, version=haystack_version, root_path=ROOT_PATH) - - # Creates the router for the API calls - from rest_api.controller import file_upload, search, feedback, document, health - - router = APIRouter() - router.include_router(search.router, tags=["search"]) - router.include_router(feedback.router, tags=["feedback"]) - router.include_router(file_upload.router, tags=["file-upload"]) - router.include_router(document.router, tags=["document"]) - router.include_router(health.router, tags=["health"]) - - # This middleware enables allow all cross-domain requests to the API from a browser. For production - # deployments, it could be made more restrictive. - app.add_middleware( - CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"] - ) - app.add_exception_handler(HTTPException, http_error_handler) - app.include_router(router) - - # Simplify operation IDs so that generated API clients have simpler function - # names (see https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#using-the-path-operation-function-name-as-the-operationid). - # The operation IDs will be the same as the route names (i.e. the python method names of the endpoints) - # Should be called only after all routes have been added. - for route in app.routes: - if isinstance(route, APIRoute): - route.operation_id = route.name - - return app - - -def get_pipelines(): - global pipelines # pylint: disable=global-statement - if not pipelines: - pipelines = setup_pipelines() - return pipelines - - -def get_openapi_specs() -> dict: - """ - Used to autogenerate OpenAPI specs file to use in the documentation. - - Returns `servers` to specify base URL for OpenAPI Playground (see https://swagger.io/docs/specification/api-host-and-base-path/) - - See `.github/utils/generate_openapi_specs.py` - """ - - app = get_app() - return get_openapi( - title=app.title, - version=app.version, - openapi_version=app.openapi_version, - description=app.description, - routes=app.routes, - servers=[{"url": "http://localhost:8000"}], - ) diff --git a/rest_api/test/__init__.py b/rest_api/test/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/rest_api/test/samples/pdf/sample_pdf_1.pdf b/rest_api/test/samples/pdf/sample_pdf_1.pdf deleted file mode 100644 index 87259b897f83b462f521276bf32d210ea008bcd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44524 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

1p2->@_y0X+Ac~V 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 LF=KrFr&;|4#k|z* diff --git a/rest_api/test/samples/pdf/sample_pdf_2.pdf b/rest_api/test/samples/pdf/sample_pdf_2.pdf deleted file mode 100644 index 6384246e891c59abf174e7225ed7f793e814ed69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26093 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 S4>n+N3&DvwIj^b75&sVaB5i5_ diff --git a/rest_api/test/samples/test.bogus_pipeline.yml b/rest_api/test/samples/test.bogus_pipeline.yml deleted file mode 100644 index 22120c9757..0000000000 --- a/rest_api/test/samples/test.bogus_pipeline.yml +++ /dev/null @@ -1,17 +0,0 @@ -version: 'ignore' - -components: - - name: InMemoryDocumentStore - params: {} - # Wrong DocumentStore Type - type: MyOwnDocumentStore - - name: tfidf_ret - params: - document_store: InMemoryDocumentStore - type: TfidfRetriever -pipelines: - - name: query - nodes: - - inputs: - - Query - name: tfidf_ret diff --git a/rest_api/test/samples/test.docstore-no-params-pipeline.yml b/rest_api/test/samples/test.docstore-no-params-pipeline.yml deleted file mode 100644 index 5379528f5e..0000000000 --- a/rest_api/test/samples/test.docstore-no-params-pipeline.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: 'ignore' - -components: - - name: InMemoryDocumentStore - type: InMemoryDocumentStore - - name: tfidf_ret - params: - document_store: InMemoryDocumentStore - type: TfidfRetriever -pipelines: - - name: query - nodes: - - inputs: - - Query - name: tfidf_ret diff --git a/rest_api/test/samples/test.haystack-pipeline.yml b/rest_api/test/samples/test.haystack-pipeline.yml deleted file mode 100644 index 9b28bb761e..0000000000 --- a/rest_api/test/samples/test.haystack-pipeline.yml +++ /dev/null @@ -1,37 +0,0 @@ -version: 'ignore' - -components: - - name: TestReader - type: MockReader - - name: TestRetriever - type: MockRetriever - params: - document_store: TestDocumentStore - - name: TestDocumentStore - type: MockDocumentStore - - name: TestPreprocessor - type: PreProcessor - params: - clean_whitespace: true - - name: TestPDFConverter - type: MockPDFToTextConverter - params: - remove_numeric_tables: false - - -pipelines: - - name: test-query - nodes: - - name: TestRetriever - inputs: [Query] - - name: TestReader - inputs: [TestRetriever] - - - name: test-indexing - nodes: - - name: TestPDFConverter - inputs: [File] - - name: TestPreprocessor - inputs: [TestPDFConverter] - - name: TestDocumentStore - inputs: [TestPreprocessor] diff --git a/rest_api/test/samples/test.in-memory-haystack-pipeline.yml b/rest_api/test/samples/test.in-memory-haystack-pipeline.yml deleted file mode 100644 index ed03b5645a..0000000000 --- a/rest_api/test/samples/test.in-memory-haystack-pipeline.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: 'ignore' - -components: - - name: InMemoryDocumentStore - type: InMemoryDocumentStore - - name: tfidf_ret - params: - document_store: InMemoryDocumentStore - type: TfidfRetriever - - name: TextFileConverter - type: TextConverter -pipelines: - - name: query - nodes: - - inputs: - - Query - name: tfidf_ret - - name: indexing - nodes: - - name: TextFileConverter - inputs: [ File ] - - name: tfidf_ret - inputs: [ TextFileConverter ] - - name: InMemoryDocumentStore - inputs: [ tfidf_ret ] diff --git a/rest_api/test/test_rest_api.py b/rest_api/test/test_rest_api.py deleted file mode 100644 index 757b9dfb8f..0000000000 --- a/rest_api/test/test_rest_api.py +++ /dev/null @@ -1,626 +0,0 @@ -# mypy: disable_error_code = "empty-body, override, union-attr" - -from typing import Dict, List, Optional, Union, Generator - -import os -from pathlib import Path -from textwrap import dedent -from unittest import mock -from unittest.mock import MagicMock, Mock -import numpy as np -import pandas as pd - -import pytest -from fastapi.testclient import TestClient -import posthog -from haystack import Document, Answer, Pipeline, TableCell -import haystack -from haystack.nodes import BaseReader, BaseRetriever -from haystack.document_stores import BaseDocumentStore -from haystack.errors import PipelineSchemaError -from haystack.schema import Label, FilterType -from haystack.nodes.file_converter import BaseConverter - -from rest_api.pipeline import _load_pipeline -from rest_api.utils import get_app - -# Disable telemetry reports when running tests -posthog.disabled = True - -TEST_QUERY = "Who made the PDF specification?" - - -def test_doc_store_error_for_indexing_pipelines(caplog): - yaml_pipeline_path = Path(__file__).parent.resolve() / "samples" / "test.in-memory-haystack-pipeline.yml" - p, _ = _load_pipeline(yaml_pipeline_path, "indexing") - - assert isinstance(p, Pipeline) - assert "will not work as expected" in caplog.text - - -def test_single_worker_doc_store_success_for_query_pipelines(): - yaml_pipeline_path = Path(__file__).parent.resolve() / "samples" / "test.in-memory-haystack-pipeline.yml" - p, _ = _load_pipeline(yaml_pipeline_path, "query") - assert isinstance(p, Pipeline) - - -def test_check_error_for_pipeline_not_found(): - yaml_pipeline_path = Path(__file__).parent.resolve() / "samples" / "test.in-memory-haystack-pipeline.yml" - p, _ = _load_pipeline(yaml_pipeline_path, "ThisPipelineDoesntExist") - assert p is None - - -def test_overwrite_params_with_env_variables_when_no_params_in_pipeline_yaml(monkeypatch): - yaml_pipeline_path = Path(__file__).parent.resolve() / "samples" / "test.docstore-no-params-pipeline.yml" - monkeypatch.setenv("INMEMORYDOCUMENTSTORE_PARAMS_INDEX", "custom_index") - _, document_store = _load_pipeline(yaml_pipeline_path, None) - assert document_store.index == "custom_index" - - -def test_bad_yaml_pipeline_configuration_error(): - yaml_pipeline_path = Path(__file__).parent.resolve() / "samples" / "test.bogus_pipeline.yml" - with pytest.raises(PipelineSchemaError) as excinfo: - _load_pipeline(yaml_pipeline_path, None) - assert "MyOwnDocumentStore" in str(excinfo.value) - - -class MockReader(BaseReader): - outgoing_edges = 1 - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None): - return {"query": query, "no_ans_gap": None, "answers": [Answer(answer="Adobe Systems")]} - - def predict_batch( - self, - queries: List[str], - documents: Union[List[Document], List[List[Document]]], - top_k: Optional[int] = None, - batch_size: Optional[int] = None, - ): - pass - - -class MockRetriever(BaseRetriever): - outgoing_edges = 1 - - def __init__(self, document_store: BaseDocumentStore): - super().__init__() - self.document_store = document_store - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score=True, - ) -> List[Document]: - if filters and not isinstance(filters, dict): - raise ValueError("You can't do this!") - return self.document_store.get_all_documents(filters=filters) - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score=True, - ): - pass - - -class MockPDFToTextConverter(BaseConverter): - mocker = MagicMock() - - def convert(self, *args, **kwargs): - self.mocker.convert(*args, **kwargs) - return [] - - -class MockDocumentStore(BaseDocumentStore): - mocker = MagicMock() - - def write_documents(self, *args, **kwargs): - pass - - def get_all_documents(self, *args, **kwargs) -> List[Document]: - self.mocker.get_all_documents(*args, **kwargs) - return [ - Document( - content=dedent( - """\ - History and standardization - Format (PDF) Adobe Systems made the PDF specification available free of - charge in 1993. In the early years PDF was popular mainly in desktop - publishing workflows, and competed with a variety of formats such as DjVu, - Envoy, Common Ground Digital Paper, Farallon Replica and even Adobe's - own PostScript format. PDF was a proprietary format controlled by Adobe - until it was released as an open standard on July 1, 2008, and published by - the International Organization for Standardization as ISO 32000-1:2008, at - which time control of the specification passed to an ISO Committee of - volunteer industry experts.""" - ), - meta={"name": "test.txt", "test_key": "test_value", "test_index": "1"}, - ), - Document( - content=dedent( - """\ - In 2008, Adobe published a Public Patent License - to ISO 32000-1 granting royalty-free rights for all patents owned by Adobe - that are necessary to make, use, sell, and distribute PDF-compliant - implementations. PDF 1.7, the sixth edition of the PDF specification that - became ISO 32000-1, includes some proprietary technologies defined only by - Adobe, such as Adobe XML Forms Architecture (XFA) and JavaScript - extension for Acrobat, which are referenced by ISO 32000-1 as normative - and indispensable for the full implementation of the ISO 32000-1 - specification. These proprietary technologies are not standardized and their - specification is published only on Adobe's website. Many of them are also not - supported by popular third-party implementations of PDF.""" - ), - meta={"name": "test.txt", "test_key": "test_value", "test_index": "2"}, - ), - ] - - def get_all_documents_generator(self, *args, **kwargs) -> Generator[Document, None, None]: - pass - - def get_all_labels(self, *args, **kwargs) -> List[Label]: - return self.mocker.get_all_labels(*args, **kwargs) - - def get_document_by_id(self, *args, **kwargs) -> Optional[Document]: - pass - - def get_document_count(self, *args, **kwargs) -> int: - pass - - def query_by_embedding(self, *args, **kwargs) -> List[Document]: - pass - - def get_label_count(self, *args, **kwargs) -> int: - pass - - def write_labels(self, *args, **kwargs): - self.mocker.write_labels(*args, **kwargs) - - def delete_documents(self, *args, **kwargs): - self.mocker.delete_documents(*args, **kwargs) - - def delete_labels(self, *args, **kwargs): - self.mocker.delete_labels(*args, **kwargs) - - def delete_index(self, index: str): - pass - - def _create_document_field_map(self) -> Dict: - pass - - def get_documents_by_id(self, *args, **kwargs) -> List[Document]: - pass - - def update_document_meta(self, *args, **kwargs): - pass - - -@pytest.fixture(scope="function") -def feedback(): - """ - Some test functions change the content of the `feedback` dictionary, let's keep - the default "function" scope so we don't need to deepcopy the dict each time - """ - return { - "id": "123", - "query": "Who made the PDF specification?", - "document": { - "content": "A sample PDF file\n\nHistory and standardization\nFormat (PDF) Adobe Systems made the PDF specification available free of charge in 1993. In the early years PDF was popular mainly in desktop publishing workflows, and competed with a variety of formats such as DjVu, Envoy, Common Ground Digital Paper, Farallon Replica and even Adobe's own PostScript format. PDF was a proprietary format controlled by Adobe until it was released as an open standard on July 1, 2008, and published by the International Organization for Standardization as ISO 32000-1:2008, at which time control of the specification passed to an ISO Committee of volunteer industry experts. In 2008, Adobe published a Public Patent License to ISO 32000-1 granting royalty-free rights for all patents owned by Adobe that are necessary to make, use, sell, and distribute PDF-compliant implementations. PDF 1.7, the sixth edition of the PDF specification that became ISO 32000-1, includes some proprietary technologies defined only by Adobe, such as Adobe XML Forms Architecture (XFA) and JavaScript extension for Acrobat, which are referenced by ISO 32000-1 as normative and indispensable for the full implementation of the ISO 32000-1 specification. These proprietary technologies are not standardized and their specification is published only on Adobes website. Many of them are also not supported by popular third-party implementations of PDF. Column 1", - "content_type": "text", - "score": None, - "id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "embedding": [0.1, 0.2, 0.3], - }, - "answer": { - "answer": "Adobe Systems", - "type": "extractive", - "context": "A sample PDF file\n\nHistory and standardization\nFormat (PDF) Adobe Systems made the PDF specification available free of charge in 1993. In the early ye", - "offsets_in_context": [{"start": 60, "end": 73}], - "offsets_in_document": [{"start": 60, "end": 73}], - "document_ids": ["fc18c987a8312e72a47fb1524f230bb0"], - "meta": {}, - "score": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "pipeline_id": "some-123", - } - - -@pytest.fixture -def client(tmp_path): - yaml_pipeline_path = Path(__file__).parent.resolve() / "samples" / "test.haystack-pipeline.yml" - os.environ["PIPELINE_YAML_PATH"] = str(yaml_pipeline_path) - os.environ["INDEXING_PIPELINE_NAME"] = "test-indexing" - os.environ["QUERY_PIPELINE_NAME"] = "test-query" - os.environ["FILE_UPLOAD_PATH"] = str(tmp_path) - - app = get_app() - client = TestClient(app) - - MockDocumentStore.mocker.reset_mock() - MockPDFToTextConverter.mocker.reset_mock() - - return client - - -def test_get_all_documents(client): - response = client.post(url="/documents/get_by_filters", data='{"filters": {}}') - assert response.status_code == 200 - # Ensure `get_all_documents` was called with the expected `filters` param - MockDocumentStore.mocker.get_all_documents.assert_called_with(filters={}, index=None) - # Ensure results are part of the response body - response_json = response.json() - assert len(response_json) == 2 - - -def test_get_documents_with_filters(client): - response = client.post(url="/documents/get_by_filters", data='{"filters": {"test_index": ["2"]}}') - assert response.status_code == 200 - # Ensure `get_all_documents` was called with the expected `filters` param - MockDocumentStore.mocker.get_all_documents.assert_called_with(filters={"test_index": ["2"]}, index=None) - - -def test_delete_all_documents(client): - response = client.post(url="/documents/delete_by_filters", data='{"filters": {}}') - assert response.status_code == 200 - # Ensure `delete_documents` was called on the Document Store instance - MockDocumentStore.mocker.delete_documents.assert_called_with(filters={}, index=None) - - -def test_delete_documents_with_filters(client): - response = client.post(url="/documents/delete_by_filters", data='{"filters": {"test_index": ["1"]}}') - assert response.status_code == 200 - # Ensure `delete_documents` was called on the Document Store instance with the same params - MockDocumentStore.mocker.delete_documents.assert_called_with(filters={"test_index": ["1"]}, index=None) - - -def test_file_upload(client): - file_to_upload = {"files": (Path(__file__).parent / "samples" / "pdf" / "sample_pdf_1.pdf").open("rb")} - response = client.post(url="/file-upload", files=file_to_upload, data={"meta": '{"test_key": "test_value"}'}) - assert response.status_code == 200 - # Ensure the `convert` method was called with the right keyword params - _, kwargs = MockPDFToTextConverter.mocker.convert.call_args - # Files are renamed with random prefix like 83f4c1f5b2bd43f2af35923b9408076b_sample_pdf_1.pdf - # so we just ensure the original file name is contained in the converted file name - assert "sample_pdf_1.pdf" in str(kwargs["file_path"]) - assert kwargs["meta"]["test_key"] == "test_value" - - -def test_file_upload_with_no_meta(client): - file_to_upload = {"files": (Path(__file__).parent / "samples" / "pdf" / "sample_pdf_1.pdf").open("rb")} - response = client.post(url="/file-upload", files=file_to_upload, data={}) - assert response.status_code == 200 - # Ensure the `convert` method was called with the right keyword params - _, kwargs = MockPDFToTextConverter.mocker.convert.call_args - assert kwargs["meta"] == {"name": "sample_pdf_1.pdf"} - - -def test_file_upload_with_empty_meta(client): - file_to_upload = {"files": (Path(__file__).parent / "samples" / "pdf" / "sample_pdf_1.pdf").open("rb")} - response = client.post(url="/file-upload", files=file_to_upload, data={"meta": ""}) - assert response.status_code == 200 - # Ensure the `convert` method was called with the right keyword params - _, kwargs = MockPDFToTextConverter.mocker.convert.call_args - assert kwargs["meta"] == {"name": "sample_pdf_1.pdf"} - - -def test_file_upload_with_wrong_meta(client): - file_to_upload = {"files": (Path(__file__).parent / "samples" / "pdf" / "sample_pdf_1.pdf").open("rb")} - response = client.post(url="/file-upload", files=file_to_upload, data={"meta": "1"}) - assert response.status_code == 500 - # Ensure the `convert` method was never called - MockPDFToTextConverter.mocker.convert.assert_not_called() - - -def test_file_upload_cleanup_after_indexing(client): - # mock the upload path to use a dedicated temp folder - with mock.patch("rest_api.controller.file_upload.FILE_UPLOAD_PATH", os.environ.get("FILE_UPLOAD_PATH")): - file_to_upload = {"files": (Path(__file__).parent / "samples" / "pdf" / "sample_pdf_1.pdf").open("rb")} - response = client.post(url="/file-upload", files=file_to_upload, data={}) - assert response.status_code == 200 - # ensure upload folder is empty - uploaded_files = os.listdir(os.environ.get("FILE_UPLOAD_PATH")) - assert len(uploaded_files) == 0 - - -def test_file_upload_keep_files_after_indexing(client): - # mock the upload path to use a dedicated temp folder - with mock.patch("rest_api.controller.file_upload.FILE_UPLOAD_PATH", os.environ.get("FILE_UPLOAD_PATH")): - file_to_upload = {"files": (Path(__file__).parent / "samples" / "pdf" / "sample_pdf_1.pdf").open("rb")} - response = client.post(url="/file-upload", files=file_to_upload, params={"keep_files": "true"}) - assert response.status_code == 200 - # ensure original file was kept - uploaded_files = os.listdir(os.environ.get("FILE_UPLOAD_PATH")) - assert len(uploaded_files) == 1 - - -def test_query_with_no_filter(client): - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = {"query": TEST_QUERY} - response = client.post(url="/query", json={"query": TEST_QUERY}) - assert response.status_code == 200 - # Ensure `run` was called with the expected parameters - mocked_pipeline.run.assert_called_with(query=TEST_QUERY, params={}, debug=False) - - -def test_query_with_one_filter(client): - params = {"TestRetriever": {"filters": {"test_key": ["test_value"]}}} - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = {"query": TEST_QUERY} - response = client.post(url="/query", json={"query": TEST_QUERY, "params": params}) - assert response.status_code == 200 - # Ensure `run` was called with the expected parameters - mocked_pipeline.run.assert_called_with(query=TEST_QUERY, params=params, debug=False) - - -def test_query_with_one_global_filter(client): - params = {"filters": {"test_key": ["test_value"]}} - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = {"query": TEST_QUERY} - response = client.post(url="/query", json={"query": TEST_QUERY, "params": params}) - assert response.status_code == 200 - # Ensure `run` was called with the expected parameters - mocked_pipeline.run.assert_called_with(query=TEST_QUERY, params=params, debug=False) - - -def test_query_with_filter_list(client): - params = {"TestRetriever": {"filters": {"test_key": ["test_value", "another_value"]}}} - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = {"query": TEST_QUERY} - response = client.post(url="/query", json={"query": TEST_QUERY, "params": params}) - assert response.status_code == 200 - # Ensure `run` was called with the expected parameters - mocked_pipeline.run.assert_called_with(query=TEST_QUERY, params=params, debug=False) - - -def test_query_with_no_documents_and_no_answers(client): - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = {"query": TEST_QUERY} - response = client.post(url="/query", json={"query": TEST_QUERY}) - assert response.status_code == 200 - response_json = response.json() - assert response_json["documents"] == [] - assert response_json["answers"] == [] - - -def test_query_with_bool_in_params(client): - """ - Ensure items of params can be other types than dictionary, see - https://github.com/deepset-ai/haystack/issues/2656 - """ - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = {"query": TEST_QUERY} - request_body = { - "query": TEST_QUERY, - "params": {"debug": True, "Retriever": {"top_k": 5}, "Reader": {"top_k": 3}}, - } - response = client.post(url="/query", json=request_body) - assert response.status_code == 200 - response_json = response.json() - assert response_json["documents"] == [] - assert response_json["answers"] == [] - - -def test_query_with_embeddings(client): - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = { - "query": TEST_QUERY, - "documents": [ - Document( - content="test", - content_type="text", - score=0.9, - meta={"test_key": "test_value"}, - embedding=np.array([0.1, 0.2, 0.3]), - ) - ], - } - response = client.post(url="/query", json={"query": TEST_QUERY}) - assert response.status_code == 200 - assert len(response.json()["documents"]) == 1 - assert response.json()["documents"][0]["content"] == "test" - assert response.json()["documents"][0]["content_type"] == "text" - assert response.json()["documents"][0]["embedding"] == [0.1, 0.2, 0.3] - # Ensure `run` was called with the expected parameters - mocked_pipeline.run.assert_called_with(query=TEST_QUERY, params={}, debug=False) - - -def test_query_with_dataframe(client): - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = { - "query": TEST_QUERY, - "documents": [ - Document( - content=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - content_type="table", - score=0.9, - meta={"test_key": "test_value"}, - ) - ], - "answers": [ - Answer( - answer="text_2", - type="extractive", - score=0.95, - context=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - offsets_in_document=[TableCell(1, 0)], - offsets_in_context=[TableCell(1, 0)], - meta={"aggregation_operator": "NONE", "answer_cells": ["text_2"]}, - ) - ], - } - response = client.post(url="/query", json={"query": TEST_QUERY}) - assert response.status_code == 200 - assert len(response.json()["documents"]) == 1 - assert response.json()["documents"][0]["content"] == [["col1", "col2"], ["text_1", 1], ["text_2", 2]] - assert response.json()["documents"][0]["content_type"] == "table" - assert len(response.json()["answers"]) == 1 - assert response.json()["answers"][0]["context"] == [["col1", "col2"], ["text_1", 1], ["text_2", 2]] - assert response.json()["answers"][0]["offsets_in_document"] == [{"row": 1, "col": 0}] - assert response.json()["answers"][0]["offsets_in_context"] == [{"row": 1, "col": 0}] - # Ensure `run` was called with the expected parameters - mocked_pipeline.run.assert_called_with(query=TEST_QUERY, params={}, debug=False) - - -def test_query_with_prompt_node(client): - with mock.patch("rest_api.controller.search.query_pipeline") as mocked_pipeline: - # `run` must return a dictionary containing a `query` key - mocked_pipeline.run.return_value = { - "query": TEST_QUERY, - "documents": [ - Document( - content="test", - content_type="text", - score=0.9, - meta={"test_key": "test_value"}, - embedding=np.array([0.1, 0.2, 0.3]), - ) - ], - "results": ["test"], - } - response = client.post(url="/query", json={"query": TEST_QUERY}) - assert response.status_code == 200 - assert len(response.json()["documents"]) == 1 - assert response.json()["documents"][0]["content"] == "test" - assert response.json()["documents"][0]["content_type"] == "text" - assert response.json()["documents"][0]["embedding"] == [0.1, 0.2, 0.3] - assert len(response.json()["results"]) == 1 - assert response.json()["results"][0] == "test" - # Ensure `run` was called with the expected parameters - mocked_pipeline.run.assert_called_with(query=TEST_QUERY, params={}, debug=False) - - -def test_write_feedback(client, feedback): - response = client.post(url="/feedback", json=feedback) - assert response.status_code == 200 - # Ensure `write_labels` was called on the Document Store instance passing a list - # containing only one label - args, _ = MockDocumentStore.mocker.write_labels.call_args - labels = args[0] - assert len(labels) == 1 - # Ensure all the items that were in `feedback` are also part of - # the stored label (which has several more keys) - label = labels[0] - assert label == Label.from_dict(feedback) - - -def test_write_feedback_without_id(client, feedback): - del feedback["id"] - response = client.post(url="/feedback", json=feedback) - assert response.status_code == 200 - # Ensure `write_labels` was called on the Document Store instance passing a list - # containing only one label - args, _ = MockDocumentStore.mocker.write_labels.call_args - labels = args[0] - assert len(labels) == 1 - # Ensure the `id` was automatically set before storing the label - label = labels[0].to_dict() - assert label["id"] - - -def test_get_feedback(client, feedback): - MockDocumentStore.mocker.get_all_labels.return_value = [Label.from_dict(feedback)] - response = client.get("/feedback") - assert response.status_code == 200 - assert Label.from_dict(response.json()[0]) == Label.from_dict(feedback) - MockDocumentStore.mocker.get_all_labels.assert_called_once() - - -def test_delete_feedback(client, monkeypatch, feedback): - # This label contains `origin=user-feedback` and should be deleted - label_to_delete = Label.from_dict(feedback) - # This other label has a different origin and should NOT be deleted - label_to_keep = Label.from_dict(feedback) - label_to_keep.id = "42" - label_to_keep.origin = "not-from-api" - - # Patch the Document Store so it returns the 2 labels above - def get_all_labels(*args, **kwargs): - return [label_to_delete, label_to_keep] - - monkeypatch.setattr(MockDocumentStore, "get_all_labels", get_all_labels) - - # Call the API and ensure `delete_labels` was called only on the label with id=123 - response = client.delete(url="/feedback") - assert response.status_code == 200 - MockDocumentStore.mocker.delete_labels.assert_called_with(ids=["123"], index=None) - - -def test_export_feedback(client, monkeypatch, feedback): - def get_all_labels(*args, **kwargs): - return [Label.from_dict(feedback)] - - monkeypatch.setattr(MockDocumentStore, "get_all_labels", get_all_labels) - - feedback_urls = [ - "/export-feedback?full_document_context=true", - "/export-feedback?full_document_context=false&context_size=50", - "/export-feedback?full_document_context=false&context_size=50000", - ] - for url in feedback_urls: - response = client.get(url) - response_json = response.json() - context = response_json["data"][0]["paragraphs"][0]["context"] - answer_start = response_json["data"][0]["paragraphs"][0]["qas"][0]["answers"][0]["answer_start"] - answer = response_json["data"][0]["paragraphs"][0]["qas"][0]["answers"][0]["text"] - assert context[answer_start : answer_start + len(answer)] == answer - - -def test_get_feedback_malformed_query(client, feedback): - feedback["unexpected_field"] = "misplaced-value" - response = client.post(url="/feedback", json=feedback) - assert response.status_code == 422 - - -def test_get_health_check(client): - with mock.patch("rest_api.controller.health.os") as os: - os.cpu_count.return_value = 4 - os.getpid.return_value = int(2345) - with mock.patch("rest_api.controller.health.pynvml") as pynvml: - pynvml.nvmlDeviceGetCount.return_value = 2 - pynvml.nvmlDeviceGetHandleByIndex.return_value = "device" - pynvml.nvmlDeviceGetMemoryInfo.return_value = Mock(total=34359738368) - pynvml.nvmlDeviceGetComputeRunningProcesses.return_value = [ - Mock(pid=int(1234), usedGpuMemory=4000000000), - Mock(pid=int(2345), usedGpuMemory=2097152000), - Mock(pid=int(3456), usedGpuMemory=2000000000), - ] - pynvml.nvmlDeviceGetUtilizationRates.return_value = Mock(gpu=45) - with mock.patch("rest_api.controller.health.psutil") as psutil: - psutil.virtual_memory.return_value = Mock(total=34359738368) - psutil.Process.return_value = Mock( - cpu_percent=Mock(return_value=200), memory_percent=Mock(return_value=75) - ) - - response = client.get(url="/health") - assert response.status_code == 200 - assert response.json() == { - "version": haystack.__version__, - "cpu": {"used": 50.0}, - "memory": {"used": 75.0}, - "gpus": [ - {"index": 0, "usage": {"kernel_usage": 45.0, "memory_total": 32768.0, "memory_used": 2000}}, - {"index": 1, "usage": {"kernel_usage": 45.0, "memory_total": 32768.0, "memory_used": 2000}}, - ], - } diff --git a/test/agents/__init__.py b/test/agents/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/agents/test_agent.py b/test/agents/test_agent.py deleted file mode 100644 index df7511bb6a..0000000000 --- a/test/agents/test_agent.py +++ /dev/null @@ -1,435 +0,0 @@ -import logging -import os -import re -from typing import Tuple -from unittest import mock -from unittest.mock import Mock, patch -from test.conftest import MockRetriever, MockPromptNode - -import pytest -from events import Events - -from haystack import BaseComponent, Answer, Document -from haystack.agents import Agent, AgentStep -from haystack.agents.base import Tool, ToolsManager -from haystack.agents.types import AgentTokenStreamingHandler, AgentToolLogger -from haystack.nodes import PromptModel, PromptNode, PromptTemplate -from haystack.pipelines import ExtractiveQAPipeline, DocumentSearchPipeline, BaseStandardPipeline - - -@pytest.mark.unit -def test_add_and_overwrite_tool(caplog): - # Add a Node as a Tool to an Agent - agent = Agent(prompt_node=MockPromptNode()) - retriever = MockRetriever() - agent.add_tool( - Tool( - name="Retriever", - pipeline_or_node=retriever, - description="useful for when you need to " "retrieve documents from your index", - ) - ) - assert len(agent.tm.tools) == 1 - assert agent.has_tool(tool_name="Retriever") - assert isinstance(agent.tm.tools["Retriever"].pipeline_or_node, BaseComponent) - - agent.add_tool( - Tool( - name="Retriever", - pipeline_or_node=retriever, - description="useful for when you need to retrieve documents from your index", - ) - ) - - # Add a Pipeline as a Tool to an Agent and overwrite the previously added Tool - retriever_pipeline = DocumentSearchPipeline(MockRetriever()) - with caplog.at_level(logging.WARNING): - agent.add_tool( - Tool( - name="Retriever", - pipeline_or_node=retriever_pipeline, - description="useful for when you need to retrieve documents from your index", - ) - ) - assert ( - "The agent already has a tool named 'Retriever'. The new tool will overwrite the existing one." in caplog.text - ) - assert len(agent.tm.tools) == 1 - assert agent.has_tool(tool_name="Retriever") - assert isinstance(agent.tm.tools["Retriever"].pipeline_or_node, BaseStandardPipeline) - - -@pytest.mark.unit -def test_max_steps(caplog, monkeypatch): - # Run an Agent and stop because max_steps is reached - agent = Agent(prompt_node=MockPromptNode(), max_steps=3) - retriever = MockRetriever() - agent.add_tool( - Tool( - name="Retriever", - pipeline_or_node=retriever, - description="useful for when you need to retrieve documents from your index", - output_variable="documents", - ) - ) - - # Let the Agent always choose "Retriever" as the Tool with "" as input - def mock_extract_tool_name_and_tool_input(self, pred: str) -> Tuple[str, str]: - return "Retriever", "" - - monkeypatch.setattr(ToolsManager, "extract_tool_name_and_tool_input", mock_extract_tool_name_and_tool_input) - - # Using max_steps as specified in the Agent's init method - with caplog.at_level(logging.WARN, logger="haystack.agents"): - result = agent.run("Where does Christelle live?") - assert result["answers"] == [Answer(answer="", type="generative")] - assert "maximum number of iterations (3)" in caplog.text.lower() - - # Setting max_steps in the Agent's run method - with caplog.at_level(logging.WARN, logger="haystack.agents"): - result = agent.run("Where does Christelle live?", max_steps=2) - assert result["answers"] == [Answer(answer="", type="generative")] - assert "maximum number of iterations (2)" in caplog.text.lower() - - -@pytest.mark.unit -def test_run_tool(): - agent = Agent(prompt_node=MockPromptNode()) - retriever = MockRetriever() - agent.add_tool( - Tool( - name="Retriever", - pipeline_or_node=retriever, - description="useful for when you need to retrieve documents from your index", - output_variable="documents", - ) - ) - pn_response = "need to find out what city he was born.\nTool: Retriever\nTool Input: Where was Jeremy McKinnon born" - - step = AgentStep(prompt_node_response=pn_response) - result = agent.tm.run_tool(step.prompt_node_response) - assert result == "[]" # empty list of documents - - -@pytest.mark.unit -def test_agent_tool_logger(): - agent = Agent(prompt_node=MockPromptNode()) - atl = AgentToolLogger(agent_events=agent.callback_manager, tool_events=agent.tm.callback_manager) - - retriever = MockRetriever() - agent.add_tool( - Tool( - name="Retriever", - pipeline_or_node=retriever, - description="useful for when you need to retrieve documents from your index", - output_variable="documents", - ) - ) - pn_response = "need to find out what city he was born.\nTool: Retriever\nTool Input: Where was Jeremy McKinnon born" - - step = AgentStep(prompt_node_response=pn_response) - agent.tm.run_tool(step.prompt_node_response) - - # Check that the AgentToolLogger collected the tool's output - assert len(atl.logs) == 1 - tool_logging_event = atl.logs[0] - assert tool_logging_event["tool_name"] == "Retriever" - assert tool_logging_event["tool_input"] == "Where was Jeremy McKinnon born" - assert tool_logging_event["tool_output"] == "[]" - - -@pytest.mark.unit -def test_extract_final_answer(): - match_examples = [ - "have the final answer to the question.\nFinal Answer: Florida", - "Final Answer: 42 is the answer", - "Final Answer: 1234", - "Final Answer: Answer", - "Final Answer: This list: one and two and three", - "Final Answer:42", - "Final Answer: ", - "Final Answer: The answer is 99 ", - ] - expected_answers = [ - "Florida", - "42 is the answer", - "1234", - "Answer", - "This list: one and two and three", - "42", - "", - "The answer is 99", - ] - - for example, expected_answer in zip(match_examples, expected_answers): - agent_step = AgentStep(prompt_node_response=example, final_answer_pattern=r"Final Answer\s*:\s*(.*)") - final_answer = agent_step.final_answer(query="irrelevant") - assert final_answer["answers"][0].answer == expected_answer - - -@pytest.mark.unit -def test_final_answer_regex(): - match_examples = [ - "Final Answer: 42 is the answer", - "Final Answer: 1234", - "Final Answer: Answer", - "Final Answer: This list: one and two and three", - "Final Answer:42", - "Final Answer: ", - "Final Answer: The answer is 99 ", - ] - - non_match_examples = ["Final answer: 42 is the answer", "Final Answer", "The final answer is: 100"] - final_answer_pattern = r"Final Answer\s*:\s*(.*)" - for example in match_examples: - match = re.match(final_answer_pattern, example) - assert match is not None - - for example in non_match_examples: - match = re.match(final_answer_pattern, example) - assert match is None - - -@pytest.mark.integration -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -@pytest.mark.parametrize("retriever_with_docs, document_store_with_docs", [("bm25", "memory")], indirect=True) -def test_tool_result_extraction(reader, retriever_with_docs): - # Test that the result of a Tool is correctly extracted as a string - - # Pipeline as a Tool - search = ExtractiveQAPipeline(reader, retriever_with_docs) - t = Tool( - name="Search", - pipeline_or_node=search, - description="useful for when you need to answer " - "questions about where people live. You " - "should ask targeted questions", - output_variable="answers", - ) - result = t.run("Where does Christelle live?") - assert isinstance(result, str) - assert result == "Paris" or result == "Madrid" - - # PromptNode as a Tool - pt = PromptTemplate("Here is a question: {query}, Answer:") - pn = PromptNode(default_prompt_template=pt) - - t = Tool(name="Search", pipeline_or_node=pn, description="N/A", output_variable="results") - result = t.run(tool_input="What is the capital of Germany?") - assert isinstance(result, str) - assert "berlin" in result.lower() - - # Retriever as a Tool - t = Tool( - name="Retriever", - pipeline_or_node=retriever_with_docs, - description="useful for when you need to retrieve documents from your index", - output_variable="documents", - ) - result = t.run(tool_input="Where does Christelle live?") - assert isinstance(result, str) - assert "Christelle" in result - - -@pytest.mark.skip("FIXME") -@pytest.mark.integration -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -@pytest.mark.parametrize("retriever_with_docs, document_store_with_docs", [("bm25", "memory")], indirect=True) -@pytest.mark.skipif( - not os.environ.get("OPENAI_API_KEY", None), - reason="Please export an env var called OPENAI_API_KEY containing the OpenAI API key to run this test.", -) -def test_agent_run(reader, retriever_with_docs, document_store_with_docs): - search = ExtractiveQAPipeline(reader, retriever_with_docs) - prompt_model = PromptModel(model_name_or_path="gpt-3.5-turbo", api_key=os.environ.get("OPENAI_API_KEY")) - prompt_node = PromptNode(model_name_or_path=prompt_model, stop_words=["Observation:"]) - country_finder = PromptNode( - model_name_or_path=prompt_model, - default_prompt_template=PromptTemplate( - "When I give you a name of the city, respond with the country where the city is located.\n" - "City: Rome\nCountry: Italy\n" - "City: Berlin\nCountry: Germany\n" - "City: Belgrade\nCountry: Serbia\n" - "City: {query}?\nCountry: " - ), - ) - - agent = Agent(prompt_node=prompt_node, max_steps=12) - agent.add_tool( - Tool( - name="Search", - pipeline_or_node=search, - description="useful for when you need to answer " - "questions about where people live. You " - "should ask targeted questions", - output_variable="answers", - ) - ) - agent.add_tool( - Tool( - name="CountryFinder", - pipeline_or_node=country_finder, - description="useful for when you need to find the country where a city is located", - ) - ) - - result = agent.run("Where is Madrid?") - country = result["answers"][0].answer - assert "spain" in country.lower() - - result = agent.run("In which country is the city where Christelle lives?") - country = result["answers"][0].answer - assert "france" in country.lower() - - -@pytest.mark.unit -def test_update_hash(): - agent = Agent(prompt_node=MockPromptNode(), prompt_template=mock.Mock()) - assert agent.hash == "d41d8cd98f00b204e9800998ecf8427e" - agent.add_tool( - Tool( - name="Search", - pipeline_or_node=mock.Mock(), - description="useful for when you need to answer " - "questions about where people live. You " - "should ask targeted questions", - output_variable="answers", - ) - ) - assert agent.hash == "d41d8cd98f00b204e9800998ecf8427e" - agent.add_tool( - Tool( - name="Count", - pipeline_or_node=mock.Mock(), - description="useful for when you need to count how many characters are in a word. Ask only with a single word.", - ) - ) - assert agent.hash == "d41d8cd98f00b204e9800998ecf8427e" - agent.update_hash() - assert agent.hash == "5ac8eca2f92c9545adcce3682b80d4c5" - - -@pytest.mark.unit -def test_tool_fails_processing_dict_result(): - tool = Tool(name="name", pipeline_or_node=MockPromptNode(), description="description") - with pytest.raises(ValueError): - tool._process_result({"answer": "answer"}) - - -@pytest.mark.unit -def test_tool_processes_answer_result_and_document_result(): - tool = Tool(name="name", pipeline_or_node=MockPromptNode(), description="description") - assert tool._process_result(Answer(answer="answer")) == "answer" - assert tool._process_result(Document(content="content")) == "content" - - -@pytest.mark.unit -@patch.object(PromptNode, "prompt") -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_default_template_order(mock_model, mock_prompt): - pn = PromptNode("abc") - a = Agent(prompt_node=pn) - assert a.prompt_template.name == "zero-shot-react" - - pn.default_prompt_template = "language-detection" - a = Agent(prompt_node=pn) - assert a.prompt_template.name == "language-detection" - - a = Agent(prompt_node=pn, prompt_template="translation") - assert a.prompt_template.name == "translation" - - -@pytest.mark.unit -def test_agent_with_unknown_prompt_template(): - prompt_node = Mock() - prompt_node.get_prompt_template.return_value = None - with pytest.raises(ValueError, match="Prompt template 'invalid' not found"): - Agent(prompt_node=prompt_node, prompt_template="invalid") - - -@pytest.mark.unit -def test_agent_token_streaming_handler(): - e = Events("on_new_token") - - mock_callback = Mock() - e.on_new_token += mock_callback # register the mock callback to the event - - handler = AgentTokenStreamingHandler(events=e) - result = handler("test") - - assert result == "test" - mock_callback.assert_called_once_with("test") # assert that the mock callback was called with "test" - - -@pytest.mark.unit -def test_agent_prompt_template_parameter_has_transcript(caplog): - mock_prompt_node = Mock(spec=PromptNode) - prompt = PromptTemplate(prompt="I now have {query} as a template parameter but also {transcript}") - mock_prompt_node.get_prompt_template.return_value = prompt - - agent = Agent(prompt_node=mock_prompt_node) - agent.check_prompt_template({"query": "test", "transcript": "some fake transcript"}) - assert "The 'transcript' parameter is missing from the Agent's prompt template" not in caplog.text - - -@pytest.mark.unit -def test_agent_prompt_template_has_no_transcript(caplog): - mock_prompt_node = Mock(spec=PromptNode) - prompt = PromptTemplate(prompt="I only have {query} as a template parameter but I am missing transcript variable") - mock_prompt_node.get_prompt_template.return_value = prompt - agent = Agent(prompt_node=mock_prompt_node) - - # We start with no transcript in the prompt template - assert "transcript" not in prompt.prompt_params - assert "transcript" not in agent.prompt_template.prompt_params - - agent.check_prompt_template({"query": "test", "transcript": "some fake transcript"}) - assert "The 'transcript' parameter is missing from the Agent's prompt template" in caplog.text - - # now let's check again after adding the transcript - # query was there to begin with - assert "query" in agent.prompt_template.prompt_params - # transcript was added automatically for this prompt template and run - assert "transcript" in agent.prompt_template.prompt_params - - -@pytest.mark.unit -def test_agent_prompt_template_unused_parameters(caplog): - caplog.set_level(logging.DEBUG) - mock_prompt_node = Mock(spec=PromptNode) - prompt = PromptTemplate(prompt="I now have {query} and {transcript} as template parameters") - mock_prompt_node.get_prompt_template.return_value = prompt - agent = Agent(prompt_node=mock_prompt_node) - agent.check_prompt_template({"query": "test", "transcript": "some fake transcript", "unused": "test"}) - assert ( - "The Agent's prompt template does not utilize the following parameters provided by the " - "prompt parameter resolver: ['unused']" in caplog.text - ) - - -@pytest.mark.unit -def test_agent_prompt_template_multiple_unused_parameters(caplog): - caplog.set_level(logging.DEBUG) - mock_prompt_node = Mock(spec=PromptNode) - prompt = PromptTemplate(prompt="I now have strange {param_1} and {param_2} as template parameters") - mock_prompt_node.get_prompt_template.return_value = prompt - agent = Agent(prompt_node=mock_prompt_node) - agent.check_prompt_template({"query": "test", "unused": "test"}) - # order of parameters in the list not guaranteed, so we check for preamble of the message - assert ( - "The Agent's prompt template does not utilize the following parameters provided by the " - "prompt parameter resolver" in caplog.text - ) - - -@pytest.mark.unit -def test_agent_prompt_template_missing_parameters(caplog): - # in check_prompt_template we don't check that all prompt template parameters are filled - # prompt template resolution will do that and flag the missing parameters - # in check_prompt_template we check if some template parameters are not used - mock_prompt_node = Mock(spec=PromptNode) - prompt = PromptTemplate(prompt="I now have {query} and {transcript} as template parameters") - mock_prompt_node.get_prompt_template.return_value = prompt - agent = Agent(prompt_node=mock_prompt_node) - agent.check_prompt_template({"transcript": "test"}) - assert not caplog.text diff --git a/test/agents/test_agent_step.py b/test/agents/test_agent_step.py deleted file mode 100644 index 3d0f0cb4e7..0000000000 --- a/test/agents/test_agent_step.py +++ /dev/null @@ -1,109 +0,0 @@ -import pytest - -from haystack import Answer -from haystack.agents import AgentStep -from haystack.errors import AgentError - - -@pytest.fixture -def agent_step(): - return AgentStep( - current_step=1, max_steps=10, final_answer_pattern=None, prompt_node_response="Hello", transcript="Hello" - ) - - -@pytest.mark.unit -def test_create_next_step(agent_step): - # Test normal case - next_step = agent_step.create_next_step(["Hello again"]) - assert next_step.current_step == 2 - assert next_step.prompt_node_response == "Hello again" - assert next_step.transcript == "Hello" - - # Test with invalid prompt_node_response - with pytest.raises(AgentError): - agent_step.create_next_step({}) - - # Test with empty prompt_node_response - with pytest.raises(AgentError): - agent_step.create_next_step([]) - - -@pytest.mark.unit -def test_final_answer(agent_step): - # Test normal case - result = agent_step.final_answer("query") - assert result["query"] == "query" - assert isinstance(result["answers"][0], Answer) - assert result["answers"][0].answer == "Hello" - assert result["answers"][0].type == "generative" - assert result["transcript"] == "Hello" - - # Test with max_steps reached - agent_step.current_step = 11 - result = agent_step.final_answer("query") - assert result["answers"][0].answer == "" - - -@pytest.mark.unit -def test_is_last(): - # Test is last, and it is last because of valid prompt_node_response and default final_answer_pattern - agent_step = AgentStep(current_step=1, max_steps=10, prompt_node_response="Hello", transcript="Hello") - assert agent_step.is_last() - - # Test not last - agent_step.current_step = 1 - agent_step.prompt_node_response = "final answer not satisfying pattern" - agent_step.final_answer_pattern = r"Final Answer\s*:\s*(.*)" - assert not agent_step.is_last() - - # Test border cases for max_steps - agent_step.current_step = 9 - assert not agent_step.is_last() - agent_step.current_step = 10 - assert not agent_step.is_last() - - # Test when last due to max_steps - agent_step.current_step = 11 - assert agent_step.is_last() - - -@pytest.mark.unit -def test_completed(agent_step): - # Test without observation - agent_step.completed(None) - assert agent_step.transcript == "HelloHello" - - # Test with observation, adds Hello from prompt_node_response - agent_step.completed("observation") - assert agent_step.transcript == "HelloHelloHello\nObservation: observation\nThought:" - - -@pytest.mark.unit -def test_repr(agent_step): - assert repr(agent_step) == ( - "AgentStep(current_step=1, max_steps=10, " - "prompt_node_response=Hello, final_answer_pattern=^([\\s\\S]+)$, " - "transcript=Hello)" - ) - - -@pytest.mark.unit -def test_parse_final_answer(agent_step): - # Test when pattern matches - assert agent_step.parse_final_answer() == "Hello" - - # Test when pattern does not match - agent_step.final_answer_pattern = "goodbye" - assert agent_step.parse_final_answer() is None - - -@pytest.mark.unit -def test_format_react_answer(): - step = AgentStep( - final_answer_pattern=r"Final Answer\s*:\s*(.*)", - prompt_node_response="have the final answer to the question.\nFinal Answer: Florida", - ) - formatted_answer = step.final_answer(query="query") - assert formatted_answer["query"] == "query" - assert formatted_answer["answers"] == [Answer(answer="Florida", type="generative")] diff --git a/test/agents/test_conversational_agent.py b/test/agents/test_conversational_agent.py deleted file mode 100644 index 784075e13b..0000000000 --- a/test/agents/test_conversational_agent.py +++ /dev/null @@ -1,105 +0,0 @@ -import pytest -from unittest.mock import MagicMock, patch - -from haystack.errors import AgentError -from haystack.agents.base import Tool -from haystack.agents.conversational import ConversationalAgent -from haystack.agents.memory import ConversationSummaryMemory, ConversationMemory, NoMemory -from haystack.nodes import PromptNode - - -@pytest.fixture -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def prompt_node(mock_model): - prompt_node = PromptNode() - return prompt_node - - -@pytest.mark.unit -def test_init_without_tools(prompt_node): - agent = ConversationalAgent(prompt_node) - - # Test normal case - assert isinstance(agent.memory, ConversationMemory) - assert callable(agent.prompt_parameters_resolver) - assert agent.max_steps == 2 - assert agent.final_answer_pattern == r"^([\s\S]+)$" - assert agent.prompt_template.name == "conversational-agent-without-tools" - - # ConversationalAgent doesn't have tools - assert not agent.tm.tools - - -@pytest.mark.unit -def test_init_with_tools(prompt_node): - agent = ConversationalAgent(prompt_node, tools=[Tool("ExampleTool", lambda x: x, description="Example tool")]) - - # Test normal case - assert isinstance(agent.memory, ConversationMemory) - assert callable(agent.prompt_parameters_resolver) - assert agent.max_steps == 5 - assert agent.final_answer_pattern == r"Final Answer\s*:\s*(.*)" - assert agent.prompt_template.name == "conversational-agent" - assert agent.has_tool("ExampleTool") - - -@pytest.mark.unit -def test_init_with_summary_memory(prompt_node): - # Test with summary memory - agent = ConversationalAgent(prompt_node, memory=ConversationSummaryMemory(prompt_node)) - assert isinstance(agent.memory, ConversationSummaryMemory) - - -@pytest.mark.unit -def test_init_with_no_memory(prompt_node): - # Test with no memory - agent = ConversationalAgent(prompt_node, memory=NoMemory()) - assert isinstance(agent.memory, NoMemory) - - -@pytest.mark.unit -def test_init_with_custom_max_steps(prompt_node): - # Test with custom max step - agent = ConversationalAgent(prompt_node, max_steps=8) - assert agent.max_steps == 8 - - -@pytest.mark.unit -def test_init_with_custom_prompt_template(prompt_node): - # Test with custom prompt template - agent = ConversationalAgent(prompt_node, prompt_template="translation") - assert agent.prompt_template.name == "translation" - - -@pytest.mark.unit -def test_run(prompt_node): - agent = ConversationalAgent(prompt_node) - - # Mock the Agent run method - agent.run = MagicMock(return_value="Hello") - assert agent.run("query") == "Hello" - agent.run.assert_called_once_with("query") - - -@pytest.mark.unit -def test_add_tool(prompt_node): - agent = ConversationalAgent(prompt_node, tools=[Tool("ExampleTool", lambda x: x, description="Example tool")]) - # ConversationalAgent has tools - assert len(agent.tm.tools) == 1 - - # and add more tools if ConversationalAgent is initialized with tools - agent.add_tool(Tool("AnotherTool", lambda x: x, description="Example tool")) - assert len(agent.tm.tools) == 2 - - -@pytest.mark.unit -def test_add_tool_not_allowed(prompt_node): - agent = ConversationalAgent(prompt_node) - # ConversationalAgent has no tools - assert not agent.tm.tools - - # and can't add tools when a ConversationalAgent is initialized without tools - with pytest.raises( - AgentError, match="You cannot add tools after initializing the ConversationalAgent without any tools." - ): - agent.add_tool(Tool("ExampleTool", lambda x: x, description="Example tool")) diff --git a/test/agents/test_memory.py b/test/agents/test_memory.py deleted file mode 100644 index 92bf79d139..0000000000 --- a/test/agents/test_memory.py +++ /dev/null @@ -1,45 +0,0 @@ -import pytest -from typing import Dict, Any -from haystack.agents.memory import NoMemory, ConversationMemory - - -@pytest.mark.unit -def test_no_memory(): - no_mem = NoMemory() - assert no_mem.load() == "" - no_mem.save({"key": "value"}) - no_mem.clear() - - -@pytest.mark.unit -def test_conversation_memory(): - conv_mem = ConversationMemory() - assert conv_mem.load() == "" - data: Dict[str, Any] = {"input": "Hello", "output": "Hi there"} - conv_mem.save(data) - assert conv_mem.load() == "Human: Hello\nAI: Hi there\n" - - data: Dict[str, Any] = {"input": "How are you?", "output": "I'm doing well, thanks."} - conv_mem.save(data) - assert conv_mem.load() == "Human: Hello\nAI: Hi there\nHuman: How are you?\nAI: I'm doing well, thanks.\n" - assert conv_mem.load(window_size=1) == "Human: How are you?\nAI: I'm doing well, thanks.\n" - - conv_mem.clear() - assert conv_mem.load() == "" - - -@pytest.mark.unit -def test_conversation_memory_window_size(): - conv_mem = ConversationMemory() - assert conv_mem.load() == "" - data: Dict[str, Any] = {"input": "Hello", "output": "Hi there"} - conv_mem.save(data) - data: Dict[str, Any] = {"input": "How are you?", "output": "I'm doing well, thanks."} - conv_mem.save(data) - assert conv_mem.load() == "Human: Hello\nAI: Hi there\nHuman: How are you?\nAI: I'm doing well, thanks.\n" - assert conv_mem.load(window_size=1) == "Human: How are you?\nAI: I'm doing well, thanks.\n" - - # clear the memory - conv_mem.clear() - assert conv_mem.load() == "" - assert conv_mem.load(window_size=1) == "" diff --git a/test/agents/test_summary_memory.py b/test/agents/test_summary_memory.py deleted file mode 100644 index f1e3cc9922..0000000000 --- a/test/agents/test_summary_memory.py +++ /dev/null @@ -1,144 +0,0 @@ -from unittest.mock import MagicMock -from haystack.nodes import PromptNode, PromptTemplate -import pytest -from typing import Dict, Any - -from haystack.agents.memory import ConversationSummaryMemory - - -@pytest.fixture -def mocked_prompt_node(): - mock_prompt_node = MagicMock(spec=PromptNode) - mock_prompt_node.default_prompt_template = PromptTemplate("Summarize the conversation: {chat_transcript}") - mock_prompt_node.prompt.return_value = ["This is a summary."] - return mock_prompt_node - - -@pytest.mark.unit -def test_conversation_summary_memory(mocked_prompt_node): - summary = "This is a fake summary definitely." - mocked_prompt_node.prompt.return_value = [summary] - summary_mem = ConversationSummaryMemory(mocked_prompt_node) - - # Test saving and loading without summaries - data1: Dict[str, Any] = {"input": "Hello", "output": "Hi there"} - summary_mem.save(data1) - assert summary_mem.load() == "\nHuman: Hello\nAI: Hi there\n" - assert summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 1 - - data2: Dict[str, Any] = {"input": "How are you?", "output": "I'm doing well, thanks."} - summary_mem.save(data2) - assert summary_mem.load() == "\nHuman: Hello\nAI: Hi there\nHuman: How are you?\nAI: I'm doing well, thanks.\n" - assert summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 2 - - # Test summarization - data3: Dict[str, Any] = {"input": "What's the weather like?", "output": "It's sunny outside."} - summary_mem.save(data3) - assert summary_mem.load() == summary - assert not summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 0 - - summary_mem.clear() - assert summary_mem.load() == "" - - -@pytest.mark.unit -def test_conversation_summary_memory_lower_summary_frequency(mocked_prompt_node): - summary = "This is a fake summary definitely." - mocked_prompt_node.prompt.return_value = [summary] - summary_mem = ConversationSummaryMemory(mocked_prompt_node, summary_frequency=2) - - data1: Dict[str, Any] = {"input": "Hello", "output": "Hi there"} - summary_mem.save(data1) - assert summary_mem.load() == "\nHuman: Hello\nAI: Hi there\n" - assert summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 1 - - # Test summarization - data2: Dict[str, Any] = {"input": "How are you?", "output": "I'm doing well, thanks."} - summary_mem.save(data2) - assert summary_mem.load() == summary - assert not summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 0 - - data3: Dict[str, Any] = {"input": "What's the weather like?", "output": "It's sunny outside."} - summary_mem.save(data3) - assert summary_mem.load() == summary + "\nHuman: What's the weather like?\nAI: It's sunny outside.\n" - assert summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 1 - - summary_mem.clear() - assert summary_mem.load() == "" - - # start over - summary_mem.save(data1) - assert summary_mem.load() == "\nHuman: Hello\nAI: Hi there\n" - assert summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 1 - - # Test summarization - data2: Dict[str, Any] = {"input": "How are you?", "output": "I'm doing well, thanks."} - summary_mem.save(data2) - assert summary_mem.load() == summary - assert not summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 0 - - -@pytest.mark.unit -def test_conversation_summary_is_accumulating(mocked_prompt_node): - # ensure that the summary memory works after being triggered twice - summary = "This is a fake summary definitely." - mocked_prompt_node.prompt.return_value = [summary] - summary_mem = ConversationSummaryMemory(mocked_prompt_node, summary_frequency=2) - - data1: Dict[str, Any] = {"input": "Hello", "output": "Hi there"} - summary_mem.save(data1) - assert summary_mem.load() == "\nHuman: Hello\nAI: Hi there\n" - assert summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 1 - - # Test summarization - data2: Dict[str, Any] = {"input": "How are you?", "output": "I'm doing well, thanks."} - summary_mem.save(data2) - assert summary_mem.load() == summary - assert not summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 0 - - # Add more snippets - new_snippet = "\nHuman: What's the weather like?\nAI: It's sunny outside.\n" - data3: Dict[str, Any] = {"input": "What's the weather like?", "output": "It's sunny outside."} - summary_mem.save(data3) - assert summary_mem.load() == summary + new_snippet - assert summary_mem.has_unsummarized_snippets() - assert summary_mem.unsummarized_snippets() == 1 - - # Trigger summarization again - data3: Dict[str, Any] = {"input": "What's the weather tomorrow?", "output": "It will be sunny."} - summary_mem.save(data3) - - # Ensure that the summary is accumulating - assert summary_mem.load() == summary + summary - assert not summary_mem.has_unsummarized_snippets() - - -@pytest.mark.unit -def test_conversation_summary_memory_with_template(mocked_prompt_node): - pt = PromptTemplate("Summarize the conversation: {chat_transcript}") - summary_mem = ConversationSummaryMemory(mocked_prompt_node, prompt_template=pt) - - data1: Dict[str, Any] = {"input": "Hello", "output": "Hi there"} - summary_mem.save(data1) - assert summary_mem.load() == "\nHuman: Hello\nAI: Hi there\n" - - data2: Dict[str, Any] = {"input": "How are you?", "output": "I'm doing well, thanks."} - summary_mem.save(data2) - assert summary_mem.load() == "\nHuman: Hello\nAI: Hi there\nHuman: How are you?\nAI: I'm doing well, thanks.\n" - - data3: Dict[str, Any] = {"input": "What's the weather like?", "output": "It's sunny outside."} - summary_mem.save(data3) - assert summary_mem.load() == "This is a summary." - - summary_mem.clear() - assert summary_mem.load() == "" diff --git a/test/agents/test_tools_manager.py b/test/agents/test_tools_manager.py deleted file mode 100644 index 1697890c2c..0000000000 --- a/test/agents/test_tools_manager.py +++ /dev/null @@ -1,218 +0,0 @@ -import unittest -from typing import Optional, Union, List, Dict, Any -from unittest import mock - -import pytest - -from haystack import Pipeline, Answer, Document, BaseComponent, MultiLabel -from haystack.agents.base import ToolsManager, Tool - - -@pytest.fixture -def tools_manager(): - tools = [ - Tool(name="ToolA", pipeline_or_node=mock.Mock(), description="Tool A Description"), - Tool(name="ToolB", pipeline_or_node=mock.Mock(), description="Tool B Description"), - ] - return ToolsManager(tools=tools) - - -@pytest.mark.unit -def test_using_callable_as_tool(): - # test that we can also pass a callable as a tool - tool_input = "Haystack" - tool = Tool(name="ToolA", pipeline_or_node=lambda x: x + x, description="Tool A Description") - assert tool.run(tool_input) == tool_input + tool_input - - -@pytest.mark.unit -def test_get_tool_names(tools_manager): - assert tools_manager.get_tool_names() == "ToolA, ToolB" - - -@pytest.mark.unit -def test_get_tools(tools_manager): - tools = tools_manager.get_tools() - assert len(tools) == 2 - assert tools[0].name == "ToolA" - assert tools[1].name == "ToolB" - - -@pytest.mark.unit -def test_get_tool_names_with_descriptions(tools_manager): - expected_output = "ToolA: Tool A Description\n" "ToolB: Tool B Description" - assert tools_manager.get_tool_names_with_descriptions() == expected_output - - -@pytest.mark.unit -def test_extract_tool_name_and_tool_input(tools_manager): - examples = [ - "need to find out what city he was born.\nTool: Search\nTool Input: Where was Jeremy McKinnon born", - "need to find out what city he was born.\n\nTool: Search\n\nTool Input: Where was Jeremy McKinnon born", - 'need to find out what city he was born. Tool: Search Tool Input: "Where was Jeremy McKinnon born"', - ] - for example in examples: - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(example) - assert tool_name == "Search" and tool_input == "Where was Jeremy McKinnon born" - - negative_examples = [ - "need to find out what city he was born.", - "Tool: Search", - "Tool Input: Where was Jeremy McKinnon born", - "need to find out what city he was born. Tool: Search", - "Tool Input: Where was Jeremy McKinnon born", - ] - for example in negative_examples: - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(example) - assert tool_name is None and tool_input is None - - -@pytest.mark.unit -def test_invalid_tool_creation(): - with pytest.raises(ValueError, match="Invalid"): - Tool(name="Tool-A", pipeline_or_node=mock.Mock(), description="Tool A Description") - - -@pytest.mark.unit -def test_tool_invocation(): - # by default for pipelines as tools we look for results key in the output - p = Pipeline() - tool = Tool(name="ToolA", pipeline_or_node=p, description="Tool A Description") - with unittest.mock.patch("haystack.pipelines.Pipeline.run", return_value={"results": "mock"}): - assert tool.run("input") == "mock" - - # now fail if results key is not present - with unittest.mock.patch("haystack.pipelines.Pipeline.run", return_value={"no_results": "mock"}), pytest.raises( - ValueError, match="Tool ToolA returned result" - ): - assert tool.run("input") - - # now try tool with a correct output variable - tool = Tool(name="ToolA", pipeline_or_node=p, description="Tool A Description", output_variable="no_results") - with unittest.mock.patch("haystack.pipelines.Pipeline.run", return_value={"no_results": "mock_no_results"}): - assert tool.run("input") == "mock_no_results" - - # try tool that internally returns an Answer object but we extract the string - tool = Tool(name="ToolA", pipeline_or_node=p, description="Tool A Description") - with unittest.mock.patch("haystack.pipelines.Pipeline.run", return_value=[Answer("mocked_answer")]): - assert tool.run("input") == "mocked_answer" - - # same but for the document - with unittest.mock.patch("haystack.pipelines.Pipeline.run", return_value=[Document("mocked_document")]): - assert tool.run("input") == "mocked_document" - - -@pytest.mark.unit -def test_extract_tool_name_and_tool_multi_line_input(tools_manager): - # new pattern being supported but with backward compatibility for the old - text = ( - "We need to find out the following information:\n" - "1. What city was Jeremy McKinnon born in?\n" - "2. What's the capital of Germany?\n" - "Tool: Search\n" - "Tool Input: Where was Jeremy\n McKinnon born\n and where did he grow up?" - ) - - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(text) - assert tool_name == "Search" and tool_input == "Where was Jeremy\n McKinnon born\n and where did he grow up?" - - # tool input is empty - text2 = ( - "We need to find out the following information:\n" - "1. What city was Jeremy McKinnon born in?\n" - "2. What's the capital of Germany?\n" - "Tool: Search\n" - "Tool Input:" - ) - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(text2) - assert tool_name == "Search" and tool_input == "" - - # Case where the tool name and tool input are provided with extra whitespaces - text3 = " Tool: Search \n Tool Input: What is the tallest building in the world? " - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(text3) - assert tool_name.strip() == "Search" and tool_input.strip() == "What is the tallest building in the world?" - - # Case where the tool name is provided but the tool input line is not provided at all - # Tool input is not optional, so this should return None for both tool name and tool input - text4 = ( - "We need to find out the following information:\n" - "1. Who is the current president of the United States?\n" - "Tool: Search\n" - ) - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(text4) - assert tool_name is None and tool_input is None - - # Case where neither the tool name nor the tool input is provided - text5 = "We need to find out the following information:\n 1. What is the population of India?" - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(text5) - assert tool_name is None and tool_input is None - - # Case where the tool name and tool input are provided with extra whitespaces and new lines - text6 = " Tool: Search \n Tool Input: \nWhat is the tallest \nbuilding in the world? " - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(text6) - assert tool_name.strip() == "Search" and tool_input.strip() == "What is the tallest \nbuilding in the world?" - - -@pytest.mark.unit -def test_extract_tool_name_and_empty_tool_input(tools_manager): - examples = [ - "need to find out what city he was born.\nTool: Search\nTool Input:", - "need to find out what city he was born.\nTool: Search\nTool Input: ", - ] - for example in examples: - tool_name, tool_input = tools_manager.extract_tool_name_and_tool_input(example) - assert tool_name == "Search" and tool_input == "" - - -@pytest.mark.unit -def test_node_as_tool(): - # test that a component can be used as a tool - class ToolComponent(BaseComponent): - outgoing_edges = 1 - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - pass - - def run(self, **kwargs): - return "mocked_output" - - tool = Tool(name="ToolA", pipeline_or_node=ToolComponent(), description="Tool A Description") - assert tool.run("input") == "mocked_output" - - -@pytest.mark.unit -def test_tools_manager_exception(): - # tests exception raising in tools manager - class ToolComponent(BaseComponent): - outgoing_edges = 1 - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - pass - - def run(self, **kwargs): - raise Exception("mocked_exception") - - fake_llm_response = "need to find out what city he was born.\nTool: Search\nTool Input: Where was Jeremy born" - tool = Tool(name="Search", pipeline_or_node=ToolComponent(), description="Search") - tools_manager = ToolsManager(tools=[tool]) - - with pytest.raises(Exception): - tools_manager.run_tool(llm_response=fake_llm_response) diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md deleted file mode 100644 index 361d405056..0000000000 --- a/test/benchmarks/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Benchmarks - -The tooling provided in this directory allows running benchmarks on reader pipelines, retriever pipelines, -and retriever-reader pipelines. - -## Defining configuration - -To run a benchmark, you need to create a configuration file first. This file should be a Pipeline YAML file that -contains both the querying and, optionally, the indexing pipeline, in case the querying pipeline includes a retriever. - -The configuration file should also have a **`benchmark_config`** section that includes the following information: - -- **`labels_file`**: The path to a SQuAD-formatted JSON or CSV file that contains the labels to be benchmarked on. -- **`documents_directory`**: The path to a directory containing files intended to be indexed into the document store. - This is only necessary for retriever and retriever-reader pipelines. -- **`data_url`**: This is optional. If provided, the benchmarking script will download data from this URL and - save it in the **`data/`** directory. - -Here is an example of how a configuration file for a retriever-reader pipeline might look like: - -```yaml -components: - - name: DocumentStore - type: ElasticsearchDocumentStore - - name: TextConverter - type: TextConverter - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/roberta-base-squad2-distilled - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: http://example.com/data.tar.gz - documents_directory: /path/to/documents - labels_file: /path/to/labels.csv -``` - -## Running benchmarks - -Once you have your configuration file, you can run benchmarks by using the **`run.py`** script. - -```bash -python run.py [--output OUTPUT] config -``` - -The script takes the following arguments: - -- `config`: This is the path to your configuration file. -- `--output`: This is an optional path where benchmark results should be saved. If not provided, the script will create a JSON file with the same name as the specified config file. - -## Metrics - -The benchmarks yield the following metrics: - -- Reader pipelines: - - Exact match score - - F1 score - - Total querying time - - Seconds/query -- Retriever pipelines: - - Recall - - Mean-average precision - - Total querying time - - Seconds/query - - Queries/second - - Total indexing time - - Number of indexed Documents/second -- Retriever-Reader pipelines: - - Exact match score - - F1 score - - Total querying time - - Seconds/query - - Total indexing time - - Number of indexed Documents/second - -You can find more details about the performance metrics in our [evaluation guide](https://docs.haystack.deepset.ai/docs/evaluation). diff --git a/test/benchmarks/configs/reader/debertabase.yml b/test/benchmarks/configs/reader/debertabase.yml deleted file mode 100644 index 129aacabd3..0000000000 --- a/test/benchmarks/configs/reader/debertabase.yml +++ /dev/null @@ -1,19 +0,0 @@ -version: ignore - -components: - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-base-squad2 - top_k: 10 - return_no_answer: True - -pipelines: - - name: querying - nodes: - - name: Reader - inputs: [Query] - -benchmark_config: - data_url: https://s3.eu-central-1.amazonaws.com/deepset.ai-farm-downstream/squad20.tar.gz - labels_file: data/squad20/dev-v2.0.json diff --git a/test/benchmarks/configs/reader/debertalarge.yml b/test/benchmarks/configs/reader/debertalarge.yml deleted file mode 100644 index 6936c768cb..0000000000 --- a/test/benchmarks/configs/reader/debertalarge.yml +++ /dev/null @@ -1,19 +0,0 @@ -version: ignore - -components: - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-large-squad2 - top_k: 10 - return_no_answer: True - -pipelines: - - name: querying - nodes: - - name: Reader - inputs: [Query] - -benchmark_config: - data_url: https://s3.eu-central-1.amazonaws.com/deepset.ai-farm-downstream/squad20.tar.gz - labels_file: data/squad20/dev-v2.0.json diff --git a/test/benchmarks/configs/reader/tinyroberta.yml b/test/benchmarks/configs/reader/tinyroberta.yml deleted file mode 100644 index af5b2c7c0b..0000000000 --- a/test/benchmarks/configs/reader/tinyroberta.yml +++ /dev/null @@ -1,19 +0,0 @@ -version: ignore - -components: - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/tinyroberta-squad2 - top_k: 10 - return_no_answer: True - -pipelines: - - name: querying - nodes: - - name: Reader - inputs: [Query] - -benchmark_config: - data_url: https://s3.eu-central-1.amazonaws.com/deepset.ai-farm-downstream/squad20.tar.gz - labels_file: data/squad20/dev-v2.0.json diff --git a/test/benchmarks/configs/retriever/bm25-elasticsearch-100k.yml b/test/benchmarks/configs/retriever/bm25-elasticsearch-100k.yml deleted file mode 100644 index 1500cb50ee..0000000000 --- a/test/benchmarks/configs/retriever/bm25-elasticsearch-100k.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: ElasticsearchDocumentStore - params: - host: elasticsearch - port: 9200 - - name: TextConverter - type: TextConverter - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/bm25-opensearch-100k.yml b/test/benchmarks/configs/retriever/bm25-opensearch-100k.yml deleted file mode 100644 index a798ca532d..0000000000 --- a/test/benchmarks/configs/retriever/bm25-opensearch-100k.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - - name: TextConverter - type: TextConverter - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/bm25-weaviate-100k.yml b/test/benchmarks/configs/retriever/bm25-weaviate-100k.yml deleted file mode 100644 index 0244104931..0000000000 --- a/test/benchmarks/configs/retriever/bm25-weaviate-100k.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: WeaviateDocumentStore - params: - timeout_config: [5, 300] - batch_size: 5000 - host: http://weaviate - port: 8080 - - name: TextConverter - type: TextConverter - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/minilm-elasticsearch-100k.yml b/test/benchmarks/configs/retriever/minilm-elasticsearch-100k.yml deleted file mode 100644 index bc74990bfc..0000000000 --- a/test/benchmarks/configs/retriever/minilm-elasticsearch-100k.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: ElasticsearchDocumentStore - params: - batch_size: 5000 - similarity: cosine - embedding_dim: 384 - host: elasticsearch - port: 9200 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-MiniLM-L6-cos-v1 - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/minilm-opensearch-100k.yml b/test/benchmarks/configs/retriever/minilm-opensearch-100k.yml deleted file mode 100644 index 24875ebaad..0000000000 --- a/test/benchmarks/configs/retriever/minilm-opensearch-100k.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - batch_size: 5000 - similarity: cosine - embedding_dim: 384 - host: opensearch - port: 9200 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-MiniLM-L6-cos-v1 - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/minilm-weaviate-100k.yml b/test/benchmarks/configs/retriever/minilm-weaviate-100k.yml deleted file mode 100644 index 9ea0f10ab2..0000000000 --- a/test/benchmarks/configs/retriever/minilm-weaviate-100k.yml +++ /dev/null @@ -1,39 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: WeaviateDocumentStore - params: - timeout_config: [5, 300] - similarity: cosine - embedding_dim: 384 - batch_size: 5000 - host: http://weaviate - port: 8080 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-MiniLM-L6-cos-v1 - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/mpnetbase-elasticsearch-100k.yml b/test/benchmarks/configs/retriever/mpnetbase-elasticsearch-100k.yml deleted file mode 100644 index 926030ef08..0000000000 --- a/test/benchmarks/configs/retriever/mpnetbase-elasticsearch-100k.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: ElasticsearchDocumentStore - params: - batch_size: 5000 - similarity: dot_product - embedding_dim: 768 - host: elasticsearch - port: 9200 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-mpnet-base-dot-v1 - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/mpnetbase-opensearch-100k.yml b/test/benchmarks/configs/retriever/mpnetbase-opensearch-100k.yml deleted file mode 100644 index df4290afd1..0000000000 --- a/test/benchmarks/configs/retriever/mpnetbase-opensearch-100k.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - batch_size: 5000 - similarity: dot_product - embedding_dim: 768 - host: opensearch - port: 9200 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-mpnet-base-dot-v1 - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever/mpnetbase-weaviate-100k.yml b/test/benchmarks/configs/retriever/mpnetbase-weaviate-100k.yml deleted file mode 100644 index 60efa34b82..0000000000 --- a/test/benchmarks/configs/retriever/mpnetbase-weaviate-100k.yml +++ /dev/null @@ -1,39 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: WeaviateDocumentStore - params: - timeout_config: [5, 300] - similarity: dot_product - embedding_dim: 768 - batch_size: 5000 - host: http://weaviate - port: 8080 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-mpnet-base-dot-v1 - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/msmarco.100_000.tar.bz2 - documents_directory: data/msmarco.100_000/txt - labels_file: data/msmarco.100_000/evalsets/evalset_full.csv diff --git a/test/benchmarks/configs/retriever_reader/bm25-debertabase-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/bm25-debertabase-opensearch-100k.yml deleted file mode 100644 index ba70e81685..0000000000 --- a/test/benchmarks/configs/retriever_reader/bm25-debertabase-opensearch-100k.yml +++ /dev/null @@ -1,43 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - - name: TextConverter - type: TextConverter - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-base-squad2 - preprocessing_batch_size: 1000 - top_k: 10 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/bm25-debertalarge-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/bm25-debertalarge-opensearch-100k.yml deleted file mode 100644 index d5e02ce0b5..0000000000 --- a/test/benchmarks/configs/retriever_reader/bm25-debertalarge-opensearch-100k.yml +++ /dev/null @@ -1,43 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - - name: TextConverter - type: TextConverter - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-large-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/bm25-tinyroberta-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/bm25-tinyroberta-opensearch-100k.yml deleted file mode 100644 index dc90b2749b..0000000000 --- a/test/benchmarks/configs/retriever_reader/bm25-tinyroberta-opensearch-100k.yml +++ /dev/null @@ -1,43 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - - name: TextConverter - type: TextConverter - - name: Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/tinyroberta-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/minilm-debertabase-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/minilm-debertabase-opensearch-100k.yml deleted file mode 100644 index 6401906fef..0000000000 --- a/test/benchmarks/configs/retriever_reader/minilm-debertabase-opensearch-100k.yml +++ /dev/null @@ -1,46 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - similarity: cosine - embedding_dim: 384 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-MiniLM-L6-cos-v1 - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-base-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/minilm-debertalarge-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/minilm-debertalarge-opensearch-100k.yml deleted file mode 100644 index 0e96acbaaf..0000000000 --- a/test/benchmarks/configs/retriever_reader/minilm-debertalarge-opensearch-100k.yml +++ /dev/null @@ -1,46 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - similarity: cosine - embedding_dim: 384 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-MiniLM-L6-cos-v1 - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-large-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/minilm-tinyroberta-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/minilm-tinyroberta-opensearch-100k.yml deleted file mode 100644 index f05cf7002a..0000000000 --- a/test/benchmarks/configs/retriever_reader/minilm-tinyroberta-opensearch-100k.yml +++ /dev/null @@ -1,46 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - similarity: cosine - embedding_dim: 384 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-MiniLM-L6-cos-v1 - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/tinyroberta-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/mpnetbase-debertabase-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/mpnetbase-debertabase-opensearch-100k.yml deleted file mode 100644 index 3fd8b47023..0000000000 --- a/test/benchmarks/configs/retriever_reader/mpnetbase-debertabase-opensearch-100k.yml +++ /dev/null @@ -1,46 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - similarity: dot_product - embedding_dim: 768 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-mpnet-base-dot-v1 - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-base-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/mpnetbase-debertalarge-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/mpnetbase-debertalarge-opensearch-100k.yml deleted file mode 100644 index 3b961844e5..0000000000 --- a/test/benchmarks/configs/retriever_reader/mpnetbase-debertalarge-opensearch-100k.yml +++ /dev/null @@ -1,46 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - similarity: dot_product - embedding_dim: 768 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-mpnet-base-dot-v1 - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/deberta-v3-large-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/configs/retriever_reader/mpnetbase-tinyroberta-opensearch-100k.yml b/test/benchmarks/configs/retriever_reader/mpnetbase-tinyroberta-opensearch-100k.yml deleted file mode 100644 index 4fb270090b..0000000000 --- a/test/benchmarks/configs/retriever_reader/mpnetbase-tinyroberta-opensearch-100k.yml +++ /dev/null @@ -1,46 +0,0 @@ -version: ignore - -components: - - name: DocumentStore - type: OpenSearchDocumentStore - params: - host: opensearch - port: 9200 - batch_size: 1000 - similarity: dot_product - embedding_dim: 768 - - name: TextConverter - type: TextConverter - - name: Retriever - type: EmbeddingRetriever - params: - document_store: DocumentStore - embedding_model: sentence-transformers/multi-qa-mpnet-base-dot-v1 - top_k: 10 - - name: Reader - type: FARMReader - params: - model_name_or_path: deepset/tinyroberta-squad2 - top_k: 10 - preprocessing_batch_size: 1000 - -pipelines: - - name: indexing - nodes: - - name: TextConverter - inputs: [File] - - name: Retriever - inputs: [TextConverter] - - name: DocumentStore - inputs: [Retriever] - - name: querying - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - -benchmark_config: - data_url: https://deepset-test-datasets.s3.eu-central-1.amazonaws.com/squadv2.100_000.tar.bz2 - documents_directory: data/squadv2.100_000/txt - labels_file: data/squadv2.100_000/evalsets/squad_evalset_all.csv diff --git a/test/benchmarks/datadog/metric_handler.py b/test/benchmarks/datadog/metric_handler.py deleted file mode 100644 index d56f8d4929..0000000000 --- a/test/benchmarks/datadog/metric_handler.py +++ /dev/null @@ -1,152 +0,0 @@ -from enum import Enum -from time import time -from typing import Dict, List, Optional - -import datadog -from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type -import logging - -LOGGER = logging.getLogger(__name__) - - -class Tag(Enum): - @classmethod - def values(cls): - return [e.value for e in cls] - - -class NoneTag(Tag): - none = "none_none_none_none-1234" # should not match any other tag - - -class DatasetSizeTags(Tag): - size_100k = "dataset_size:100k" - - -class ReaderModelTags(Tag): - debertabase = "reader:debertabase" - debertalarge = "reader:debertalarge" - tinyroberta = "reader:tinyroberta" - - -class RetrieverModelTags(Tag): - bm25 = "retriever:bm25" - minilm = "retriever:minilm" - mpnetbase = "retriever:mpnetbase" - - -class DocumentStoreModelTags(Tag): - opensearch = "documentstore:opensearch" - elasticsearch = "documentstore:elasticsearch" - weaviate = "documentstore:weaviate" - - -class BenchmarkType(Tag): - retriever = "benchmark_type:retriever" - retriever_reader = "benchmark_type:retriever_reader" - reader = "benchmark_type:reader" - - -class CustomDatadogMetric: - name: str - timestamp: float - value: float - tags: List[Tag] - - def __init__(self, name: str, value: float, tags: Optional[List[Tag]] = None) -> None: - self.timestamp = int(time()) - self.name = name - self.value = value - self.tags = self.validate_tags(tags) if tags is not None else [] - - def validate_tags(self, tags: List[Tag]) -> List[Tag]: - valid_tags: List[Tag] = [] - for tag in tags: - if isinstance( - tag, (DatasetSizeTags, ReaderModelTags, RetrieverModelTags, DocumentStoreModelTags, BenchmarkType) - ): - valid_tags.append(tag) - elif tag != NoneTag.none: - # Log invalid tags as errors - LOGGER.error(f"Tag is not a valid dataset or environment tag: tag={tag}") - - return valid_tags - - -class IndexingDocsPerSecond(CustomDatadogMetric): - def __init__(self, value: float, tags: Optional[List[Tag]] = None) -> None: - name = "haystack.benchmarks.indexing.docs_per_second" - super().__init__(name=name, value=value, tags=tags) - - -class QueryingExactMatchMetric(CustomDatadogMetric): - def __init__(self, value: float, tags: Optional[List[Tag]] = None) -> None: - name = "haystack.benchmarks.querying.exact_match" - super().__init__(name=name, value=value, tags=tags) - - -class QueryingF1Metric(CustomDatadogMetric): - def __init__(self, value: float, tags: Optional[List[Tag]] = None) -> None: - name = "haystack.benchmarks.querying.f1_score" - super().__init__(name=name, value=value, tags=tags) - - -class QueryingRecallMetric(CustomDatadogMetric): - def __init__(self, value: float, tags: Optional[List[Tag]] = None) -> None: - name = "haystack.benchmarks.querying.recall" - super().__init__(name=name, value=value, tags=tags) - - -class QueryingMapMetric(CustomDatadogMetric): - def __init__(self, value: float, tags: Optional[List[Tag]] = None) -> None: - name = "haystack.benchmarks.querying.map" - super().__init__(name=name, value=value, tags=tags) - - -class QueryingSecondsPerQueryMetric(CustomDatadogMetric): - def __init__(self, value: float, tags: Optional[List[Tag]] = None) -> None: - name = "haystack.benchmarks.querying.seconds_per_query" - super().__init__(name=name, value=value, tags=tags) - - -class MetricsAPI: - def __init__(self, datadog_api_key: str, datadog_host: str): - self.datadog_api_key = datadog_api_key - self.datadog_host = datadog_host - - @retry(retry=retry_if_exception_type(ConnectionError), wait=wait_fixed(5), stop=stop_after_attempt(3), reraise=True) - def send_custom_dd_metric(self, metric: CustomDatadogMetric) -> dict: - datadog.initialize(api_key=self.datadog_api_key, api_host=self.datadog_host) - - tags: List[str] = [str(t.value) for t in metric.tags] - post_metric_response: Dict = datadog.api.Metric.send( - metric=metric.name, points=[(metric.timestamp, metric.value)], tags=tags - ) - - if post_metric_response.get("status") != "ok": - LOGGER.error( - f"Could not send custom metric. Retrying. metric_name={metric.name}, metric_value={metric.value}, " - f"status={post_metric_response.get('status')}, error={post_metric_response.get('errors')}, " - f"{post_metric_response}" - ) - raise ConnectionError(f"Could not send custom metric. {post_metric_response}") - else: - LOGGER.info( - f"Sent custom metric. metric_name={metric.name}, metric_value={metric.value}, " - f"status={post_metric_response.get('status')}" - ) - - return post_metric_response - - def send_custom_dd_metrics(self, metrics: List[CustomDatadogMetric]) -> List[Dict]: - responses = [] - for metric in metrics: - try: - response = self.send_custom_dd_metric(metric) - responses.append(response) - except ConnectionError: - LOGGER.error( - f"Could not send custom metric even after retrying. " - f"metric_name={metric.name}, metric_value={metric.value}" - ) - return responses diff --git a/test/benchmarks/datadog/requirements.txt b/test/benchmarks/datadog/requirements.txt deleted file mode 100644 index 3ec93e2859..0000000000 --- a/test/benchmarks/datadog/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -datadog==0.45.0 diff --git a/test/benchmarks/datadog/send_metrics.py b/test/benchmarks/datadog/send_metrics.py deleted file mode 100644 index 54d7346a4d..0000000000 --- a/test/benchmarks/datadog/send_metrics.py +++ /dev/null @@ -1,165 +0,0 @@ -import argparse -import os -import json -from typing import Dict - -from metric_handler import ( - ReaderModelTags, - NoneTag, - RetrieverModelTags, - DocumentStoreModelTags, - BenchmarkType, - LOGGER, - DatasetSizeTags, - IndexingDocsPerSecond, - QueryingExactMatchMetric, - QueryingF1Metric, - QueryingRecallMetric, - QueryingSecondsPerQueryMetric, - QueryingMapMetric, - MetricsAPI, - Tag, -) - - -def parse_benchmark_files(folder_path: str) -> Dict: - metrics = {} - for filename in os.listdir(folder_path): - if filename.endswith(".json"): - file_path = os.path.join(folder_path, filename) - with open(file_path, "r") as file: - data = json.load(file) - indexing_metrics = data.get("indexing", {}) - querying_metrics = data.get("querying") - config = data.get("config") - if indexing_metrics.get("error") is None and querying_metrics.get("error") is None: - metrics[filename.split(".json")[0]] = { - "indexing": indexing_metrics, - "querying": querying_metrics, - "config": config, - } - return metrics - - -def get_reader_tag(config: Dict) -> Tag: - for comp in config["components"]: - if comp["name"] == "Reader": - model = comp["params"]["model_name_or_path"] - - if model == "deepset/tinyroberta-squad2": - return ReaderModelTags.tinyroberta - - if model == "deepset/deberta-v3-base-squad2": - return ReaderModelTags.debertabase - - if model == "deepset/deberta-v3-large-squad2": - return ReaderModelTags.debertalarge - - return NoneTag.none - - -def get_retriever_tag(config: Dict) -> Tag: - for comp in config["components"]: - if comp["name"] == "Retriever": - if comp["type"] == "BM25Retriever": - return RetrieverModelTags.bm25 - - model = comp["params"]["embedding_model"] - if "minilm" in model.lower(): - return RetrieverModelTags.minilm - - if "mpnet-base" in model.lower(): - return RetrieverModelTags.mpnetbase - - return NoneTag.none - - -def get_documentstore_tag(config: Dict) -> Tag: - for comp in config["components"]: - if comp["name"] == "DocumentStore": - if comp["type"] == "ElasticsearchDocumentStore": - return DocumentStoreModelTags.elasticsearch - - if comp["type"] == "WeaviateDocumentStore": - return DocumentStoreModelTags.weaviate - - if comp["type"] == "OpenSearchDocumentStore": - return DocumentStoreModelTags.opensearch - - return NoneTag.none - - -def get_benchmark_type_tag(reader_tag, retriever_tag, document_store_tag): - if reader_tag != NoneTag.none and retriever_tag != NoneTag.none and document_store_tag != NoneTag.none: - return BenchmarkType.retriever_reader - elif retriever_tag != NoneTag.none and document_store_tag != NoneTag.none: - return BenchmarkType.retriever - elif reader_tag != NoneTag.none and retriever_tag == NoneTag.none: - return BenchmarkType.reader - - LOGGER.warn( - f"Did not find benchmark_type for the combination of tags, retriever={retriever_tag}, reader={reader_tag}, " - f"document_store={document_store_tag}" - ) - return NoneTag.none - - -def collect_metrics_from_json_files(folder_path): - benchmark_metrics = parse_benchmark_files(folder_path) - metrics_to_send_to_dd = [] - for metrics in benchmark_metrics.values(): - indexing_metrics = metrics["indexing"] - querying_metrics = metrics["querying"] - config = metrics["config"] - - docs_per_second = indexing_metrics.get("docs_per_second") - - exact_match = querying_metrics.get("exact_match") - f1_score = querying_metrics.get("f1") - recall = querying_metrics.get("recall") - seconds_per_query = querying_metrics.get("seconds_per_query") - map_query = querying_metrics.get("map") - - size_tag = DatasetSizeTags.size_100k - reader_tag = get_reader_tag(config) - retriever_tag = get_retriever_tag(config) - document_store_tag = get_documentstore_tag(config) - benchmark_type_tag = get_benchmark_type_tag(reader_tag, retriever_tag, document_store_tag) - - tags = [size_tag, reader_tag, retriever_tag, document_store_tag, benchmark_type_tag] - - if docs_per_second: - metrics_to_send_to_dd.append(IndexingDocsPerSecond(docs_per_second, tags)) - - if exact_match or exact_match == 0: - metrics_to_send_to_dd.append(QueryingExactMatchMetric(exact_match, tags)) - - if f1_score or f1_score == 0: - metrics_to_send_to_dd.append(QueryingF1Metric(f1_score, tags)) - - if recall or recall == 0: - metrics_to_send_to_dd.append(QueryingRecallMetric(recall, tags)) - - if seconds_per_query: - metrics_to_send_to_dd.append(QueryingSecondsPerQueryMetric(seconds_per_query, tags)) - - if map_query or map_query == 0: - metrics_to_send_to_dd.append(QueryingMapMetric(map_query, tags)) - - return metrics_to_send_to_dd - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("folder_path", type=str, help="Path to the folder with benchmark results") - parser.add_argument("datadog_api_key", type=str, help="Datadog API key") - parser.add_argument("datadog_api_host", type=str, help="Datadog API host") - args = parser.parse_args() - - folder_path = args.folder_path - datadog_api_key = args.datadog_api_key - datadog_api_host = args.datadog_api_host - - metrics_to_send_to_dd = collect_metrics_from_json_files(folder_path) - api = MetricsAPI(datadog_api_key=datadog_api_key, datadog_host=datadog_api_host) - api.send_custom_dd_metrics(metrics_to_send_to_dd) diff --git a/test/benchmarks/distillation_config.json b/test/benchmarks/distillation_config.json deleted file mode 100644 index 193cf00f48..0000000000 --- a/test/benchmarks/distillation_config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "student_model": { - "model_name_or_path": "roberta-base", - "batch_size": 80 - }, - "teacher_model": { - "model_name_or_path": "deepset/roberta-large-squad2", - "batch_size": 512 - }, - "distillation_settings": { - "distillation_loss": "kl_div", - "distillation_loss_weight": [0.75, 1], - "temperature": [5, 10] - }, - "training_settings": { - "n_epochs": 2, - "max_seq_len": 384, - "learning_rate": 3e-5 - }, - "dataset": "squad2", - "download_folder": "dataset/squad2", - "evaluate_teacher": true, - "evaluate_student_without_distillation": true, - "evaluate_student_with_distillation": true -} diff --git a/test/benchmarks/model_distillation.py b/test/benchmarks/model_distillation.py deleted file mode 100644 index b59daca81e..0000000000 --- a/test/benchmarks/model_distillation.py +++ /dev/null @@ -1,155 +0,0 @@ -from haystack.nodes import FARMReader -import json -import requests -from pathlib import Path - -from typing import Union, List -import logging - -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) - -download_links = { - "squad2": { - "train": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json", - "test": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json", - }, - "squad": { - "train": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", - "test": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", - }, -} - - -# loading json config file -def load_config(path: str) -> dict: - with open(path, "r") as f: - return json.load(f) - - -# returns all possible combinations of hyperparameters for grid search -def combine_config(configs: dict) -> List[dict]: - combinations_list = [[]] - for config_key, config in configs.items(): - if not isinstance(config, list): - config = [config] - current_combinations = combinations_list - combinations_list = [] - for item in config: - combinations_list += [c + [(config_key, item)] for c in current_combinations] - - combinations = [] - for combination in combinations_list: - combinations.append(dict(combination)) - - return combinations - - -def download_file(url: str, path: Path): - request = requests.get(url, allow_redirects=True) - with path.open("wb") as f: - f.write(request.content) - - -def download_dataset(dataset: Union[dict, str], download_folder: Path): - train_file = "train.json" - test_file = "test.json" - # checking if dataset is already downloaded - if download_folder.exists(): - assert download_folder.is_dir() - if (download_folder / train_file).is_file() and (download_folder / test_file).is_file(): - return train_file, test_file - if type(dataset) is str: # check if dataset needs to be looked up - dataset = download_links[dataset] - train = dataset["train"] - test = dataset["test"] - download_folder.mkdir(parents=True, exist_ok=True) - download_file(train, download_folder / train_file) - download_file(test, download_folder / test_file) - return train_file, test_file - - -def eval(model: FARMReader, download_folder: Path, test_file: str): - return model.eval_on_file(data_dir=download_folder, test_filename=test_file) - - -def train_student(student: dict, download_folder: Path, train_file: str, test_file: str, **kwargs) -> dict: - # loading student model - model = FARMReader(model_name_or_path=student["model_name_or_path"]) - # training student model - model.train( - data_dir=download_folder, train_filename=train_file, batch_size=student["batch_size"], caching=True, **kwargs - ) - return eval(model, download_folder, test_file) - - -def train_student_with_distillation( - student: dict, teacher: dict, download_folder: Path, train_file: str, test_file: str, **kwargs -) -> dict: - # loading student and teacher models - student_model = FARMReader(model_name_or_path=student["model_name_or_path"]) - teacher_model = FARMReader(model_name_or_path=teacher["model_name_or_path"]) - # distilling - student_model.distil_from( - teacher_model, - data_dir=download_folder, - train_filename=train_file, - student_batch_size=student["batch_size"], - teacher_batch_size=teacher["batch_size"], - caching=True, - **kwargs, - ) - return eval(student_model, download_folder, test_file) - - -def main(): - # loading config - parent = Path(__file__).parent.resolve() - config = load_config(parent / "distillation_config.json") - download_folder = parent / config["download_folder"] - student = config["student_model"] - teacher = config["teacher_model"] - - distillation_settings = config["distillation_settings"] - training_settings = config["training_settings"] - - # loading dataset - logger.info("Downloading dataset") - train_file, test_file = download_dataset(config["dataset"], download_folder) - - results = [] - descriptions = [] - - for current_config in combine_config(distillation_settings): - descriptions.append(f"Results of student with distillation (config: {current_config}") - # distillation training - logger.info("Training student with distillation (config: %s)", current_config) - results.append( - train_student_with_distillation( - student, teacher, download_folder, train_file, test_file, **current_config, **training_settings - ) - ) - - # baseline - if config["evaluate_student_without_distillation"]: - logger.info("Training student without distillation as a baseline") - descriptions.append("Results of student without distillation") - results.append(train_student(student, download_folder, train_file, test_file, **training_settings)) - - if config["evaluate_teacher"]: - # evaluating teacher as upper bound for performance - logger.info("Evaluating teacher") - descriptions.append("Results of teacher") - results.append(eval(FARMReader(model_name_or_path=teacher["model_name_or_path"]), download_folder, test_file)) - - # printing evaluation results - logger.info("Evaluation results:") - for result, description in zip(results, descriptions): - logger.info(description) - logger.info("EM: %s", result["EM"]) - logger.info("F1: %s", result["f1"]) - logger.info("Top n accuracy: %s", result["top_n_accuracy"]) - - -if __name__ == "__main__": - main() diff --git a/test/benchmarks/nq_to_squad.py b/test/benchmarks/nq_to_squad.py deleted file mode 100644 index 41d90c0b26..0000000000 --- a/test/benchmarks/nq_to_squad.py +++ /dev/null @@ -1,296 +0,0 @@ -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -r""" -DEEPSET DOCSTRING: - -A modified version of the script from here: -https://github.com/google/retrieval-qa-eval/blob/main/nq_to_squad.py -Edits have been made by deepset in order to create a dev set for Haystack benchmarking. -Input should be the official NQ dev set (v1.0-simplified-nq-dev-all.jsonl.gz) - -Expected numbers are: -Converted 7830 NQ records into 5678 SQuAD records. -Removed samples: yes/no: 177 multi_short: 648 non_para 1192 long_ans_only: 130 errors: 5 -Removed annotations: long_answer: 4610 short_answer: 953 no_answer: ~1006 -where: -multi_short - annotations where there are multiple disjoint short answers -non_para - where the annotation occurs in an html element that is not a paragraph - - -ORIGINAL DOCSTRING: - -Convert the Natural Questions dataset into SQuAD JSON format. - -To use this utility, first follow the directions at the URL below to download -the complete training dataset. - - https://ai.google.com/research/NaturalQuestions/download - -Next, run this program, specifying the data you wish to convert. For instance, -the invocation: - - python nq_to_squad.py\ - --data_pattern=/usr/local/data/tnq/v1.0/train/*.gz\ - --output_file=/usr/local/data/tnq/v1.0/train.json - -will process all training data and write the results into `train.json`. This -file can, in turn, be provided to squad_eval.py using the --squad argument. -""" - -import argparse -import glob -import gzip -import json -import logging -import os -import re - - -logger = logging.getLogger(__name__) - - -# Dropped samples -n_yn = 0 -n_ms = 0 -n_non_p = 0 -n_long_ans_only = 0 -n_error = 0 - -# Dropped annotations -n_long_ans = 0 -n_no_ans = 0 -n_short = 0 - - -def clean_text(start_token, end_token, doc_tokens, doc_bytes, ignore_final_whitespace=True): - """Remove HTML tags from a text span and reconstruct proper spacing.""" - text = "" - for index in range(start_token, end_token): - token = doc_tokens[index] - if token["html_token"]: - continue - text += token["token"] - # Add a single space between two tokens iff there is at least one - # whitespace character between them (outside of an HTML tag). For example: - # - # token1 token2 ==> Add space. - # token1 token2 ==> Add space. - # token1token2 ==> No space. - # token1token2 ==> No space. - # token12token2 ==> No space. - next_token = token - last_index = end_token if ignore_final_whitespace else end_token + 1 - for next_token in doc_tokens[index + 1 : last_index]: - if not next_token["html_token"]: - break - chars = doc_bytes[token["end_byte"] : next_token["start_byte"]].decode("utf-8") - # Since some HTML tags are missing from the token list, we count '<' and - # '>' to detect if we're inside a tag. - unclosed_brackets = 0 - for char in chars: - if char == "<": - unclosed_brackets += 1 - elif char == ">": - unclosed_brackets -= 1 - elif unclosed_brackets == 0 and re.match(r"\s", char): - # Add a single space after this token. - text += " " - break - return text - - -def get_anno_type(annotation): - long_answer = annotation["long_answer"] - short_answers = annotation["short_answers"] - yes_no_answer = annotation["yes_no_answer"] - - if len(short_answers) > 1: - return "multi_short" - elif yes_no_answer != "NONE": - return yes_no_answer - elif len(short_answers) == 1: - return "short_answer" - elif len(short_answers) == 0: - if long_answer["start_token"] == -1: - return "no_answer" - else: - return "long_answer" - - -def reduce_annotations(anno_types, answers): - """ - In cases where there is annotator disagreement, this fn picks either only the short_answers or only the no_answers, - depending on which is more numerous, with a bias towards picking short_answers. - - Note: By this stage, all long_answer annotations and all samples with yes/no answer have been removed. - This leaves just no_answer and short_answers""" - for at in set(anno_types): - assert at in ("no_answer", "short_answer") - if anno_types.count("short_answer") >= anno_types.count("no_answer"): - majority = "short_answer" - is_impossible = False - else: - majority = "no_answer" - is_impossible = True - answers = [a for at, a in zip(anno_types, answers) if at == majority] - reduction = len(anno_types) - len(answers) - assert reduction < 3 - if not is_impossible: - global n_no_ans - n_no_ans += reduction - else: - global n_short - n_short += reduction - answers = [] - return answers, is_impossible - - -def nq_to_squad(record): - """Convert a Natural Questions record to SQuAD format.""" - - doc_bytes = record["document_html"].encode("utf-8") - doc_tokens = record["document_tokens"] - - question_text = record["question_text"] - question_text = question_text[0].upper() + question_text[1:] + "?" - - answers = [] - anno_types = [] - for annotation in record["annotations"]: - anno_type = get_anno_type(annotation) - long_answer = annotation["long_answer"] - short_answers = annotation["short_answers"] - - if anno_type.lower() in ["yes", "no"]: - global n_yn - n_yn += 1 - return - - # Skip examples that don't have exactly one short answer. - # Note: Consider including multi-span short answers. - if anno_type == "multi_short": - global n_ms - n_ms += 1 - return - - elif anno_type == "short_answer": - short_answer = short_answers[0] - # Skip examples corresponding to HTML blocks other than

. - long_answer_html_tag = doc_tokens[long_answer["start_token"]]["token"] - if long_answer_html_tag != "

": - global n_non_p - n_non_p += 1 - return - answer = clean_text(short_answer["start_token"], short_answer["end_token"], doc_tokens, doc_bytes) - before_answer = clean_text( - 0, short_answer["start_token"], doc_tokens, doc_bytes, ignore_final_whitespace=False - ) - - elif anno_type == "no_answer": - answer = "" - before_answer = "" - - # Throw out long answer annotations - elif anno_type == "long_answer": - global n_long_ans - n_long_ans += 1 - continue - - anno_types.append(anno_type) - answer = {"answer_start": len(before_answer), "text": answer} - answers.append(answer) - - if len(answers) == 0: - global n_long_ans_only - n_long_ans_only += 1 - return - - answers, is_impossible = reduce_annotations(anno_types, answers) - - paragraph = clean_text(0, len(doc_tokens), doc_tokens, doc_bytes) - - return { - "title": record["document_title"], - "paragraphs": [ - { - "context": paragraph, - "qas": [ - { - "answers": answers, - "id": record["example_id"], - "question": question_text, - "is_impossible": is_impossible, - } - ], - } - ], - } - - -def main(): - parser = argparse.ArgumentParser(description="Convert the Natural Questions to SQuAD JSON format.") - parser.add_argument( - "--data_pattern", - dest="data_pattern", - help=("A file pattern to match the Natural Questions " "dataset."), - metavar="PATTERN", - required=True, - ) - parser.add_argument( - "--version", dest="version", help="The version label in the output file.", metavar="LABEL", default="nq-train" - ) - parser.add_argument( - "--output_file", - dest="output_file", - help="The name of the SQuAD JSON formatted output file.", - metavar="FILE", - default="nq_as_squad.json", - ) - args = parser.parse_args() - - root = logging.getLogger() - root.setLevel(logging.DEBUG) - - records = 0 - nq_as_squad = {"version": args.version, "data": []} - - for file in sorted(glob.iglob(args.data_pattern)): - logger.info("opening %s", file) - with gzip.GzipFile(file, "r") as f: - for line in f: - records += 1 - nq_record = json.loads(line) - try: - squad_record = nq_to_squad(nq_record) - except: - squad_record = None - global n_error - n_error += 1 - if squad_record: - nq_as_squad["data"].append(squad_record) - if records % 100 == 0: - logger.info("processed %s records", records) - print("Converted %s NQ records into %s SQuAD records." % (records, len(nq_as_squad["data"]))) - print( - f"Removed samples: yes/no: {n_yn} multi_short: {n_ms} non_para {n_non_p} long_ans_only: {n_long_ans_only} errors: {n_error}" - ) - print(f"Removed annotations: long_answer: {n_long_ans} short_answer: {n_short} no_answer: ~{n_no_ans}") - - with open(args.output_file, "w") as f: - json.dump(nq_as_squad, f, indent=4) - - -if __name__ == "__main__": - main() diff --git a/test/benchmarks/reader.py b/test/benchmarks/reader.py deleted file mode 100644 index a2876123ab..0000000000 --- a/test/benchmarks/reader.py +++ /dev/null @@ -1,70 +0,0 @@ -from time import perf_counter -from typing import Dict -from pathlib import Path -import traceback -import datetime -import logging - -from haystack import Pipeline -from haystack.nodes import BaseReader -from haystack.utils import aggregate_labels -from utils import load_eval_data, get_reader_config - - -def benchmark_reader(pipeline: Pipeline, labels_file: Path) -> Dict: - try: - labels, queries = load_eval_data(labels_file) - eval_labels = aggregate_labels(labels) - eval_queries = [] - eval_docs = [] - for multi_label in eval_labels: - eval_queries.append(multi_label.query) - eval_docs.append([multi_label.labels[0].document]) - - # Run querying - start_time = perf_counter() - # We use run_batch instead of eval_batch because we want to get pure inference time - predictions = pipeline.run_batch(queries=eval_queries, documents=eval_docs, labels=eval_labels, debug=True) - end_time = perf_counter() - querying_time = end_time - start_time - - # Evaluate predictions - eval_result = pipeline._generate_eval_result_from_batch_preds(predictions_batches=predictions) - metrics = eval_result.calculate_metrics()["Reader"] - - reader_type, reader_model, reader_top_k = get_reader_config(pipeline) - results = { - "querying": { - "exact_match": metrics["exact_match"], - "f1": metrics["f1"], - "n_queries": len(eval_labels), - "querying_time": querying_time, - "seconds_per_query": querying_time / len(eval_labels), - "reader": reader_type, - "reader_model": reader_model, - "top_k": reader_top_k, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": None, - } - } - - except Exception: - tb = traceback.format_exc() - logging.error("##### The following Error was raised while running querying run:") - logging.error(tb) - reader_type, reader_model, reader_top_k = get_reader_config(pipeline) - results = { - "reader": { - "exact_match": 0.0, - "f1": 0.0, - "n_queries": 0, - "querying_time": 0.0, - "seconds_per_query": 0.0, - "reader": reader_type, - "reader_model": reader_model, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": str(tb), - } - } - - return results diff --git a/test/benchmarks/retriever.py b/test/benchmarks/retriever.py deleted file mode 100644 index 53d07fb28a..0000000000 --- a/test/benchmarks/retriever.py +++ /dev/null @@ -1,151 +0,0 @@ -from pathlib import Path -from time import perf_counter -import logging -import datetime -import traceback -from typing import Dict - -from haystack.nodes import BaseRetriever -from haystack import Pipeline -from haystack.utils import aggregate_labels - -from utils import load_eval_data, get_retriever_config - - -def benchmark_retriever( - indexing_pipeline: Pipeline, querying_pipeline: Pipeline, documents_directory: Path, eval_set: Path -) -> Dict: - """ - Benchmark indexing and querying on retriever pipelines on a given dataset. - :param indexing_pipeline: Pipeline for indexing documents. - :param querying_pipeline: Pipeline for querying documents. - :param documents_directory: Directory containing files to index. - :param eval_set: Path to evaluation set. - """ - # Indexing - indexing_results = benchmark_indexing(indexing_pipeline, documents_directory) - - # Querying - querying_results = benchmark_querying(querying_pipeline, eval_set) - - results = {"indexing": indexing_results, "querying": querying_results} - - doc_store = indexing_pipeline.get_document_store() - doc_store.delete_index(index="document") - return results - - -def benchmark_indexing(pipeline: Pipeline, documents_directory: Path) -> Dict: - """ - Benchmark indexing. - :param pipeline: Pipeline for indexing documents. - :param documents_directory: Directory containing files to index. - """ - try: - # Indexing Pipelines take a list of file paths as input - file_paths = [str(fp) for fp in documents_directory.iterdir() if fp.is_file() and not fp.name.startswith(".")] - - # Indexing - start_time = perf_counter() - pipeline.run_batch(file_paths=file_paths) - end_time = perf_counter() - - indexing_time = end_time - start_time - n_docs = len(file_paths) - retrievers = pipeline.get_nodes_by_class(BaseRetriever) - retriever_type = retrievers[0].__class__.__name__ if retrievers else "No component of type BaseRetriever found" - doc_store = pipeline.get_document_store() - doc_store_type = doc_store.__class__.__name__ if doc_store else "No DocumentStore found" - results = { - "retriever": retriever_type, - "doc_store": doc_store_type, - "n_docs": n_docs, - "indexing_time": indexing_time, - "docs_per_second": n_docs / indexing_time, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": None, - } - except Exception: - tb = traceback.format_exc() - logging.error("##### The following Error was raised while running indexing run:") - logging.error(tb) - retrievers = pipeline.get_nodes_by_class(BaseRetriever) - retriever_type = retrievers[0].__class__.__name__ if retrievers else "No component of type BaseRetriever found" - doc_store = pipeline.get_document_store() - doc_store_type = doc_store.__class__.__name__ if doc_store else "No DocumentStore found" - results = { - "retriever": retriever_type, - "doc_store": doc_store_type, - "n_docs": 0, - "indexing_time": 0, - "docs_per_second": 0, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": str(tb), - } - - return results - - -def benchmark_querying(pipeline: Pipeline, eval_set: Path) -> Dict: - """ - Benchmark querying. This method should only be called if indexing has already been done. - :param pipeline: Pipeline for querying documents. - :param eval_set: Path to evaluation set. - """ - try: - # Load eval data - labels, _ = load_eval_data(eval_set) - multi_labels = aggregate_labels(labels) - queries = [label.query for label in multi_labels] - - # Run querying - start_time = perf_counter() - predictions = pipeline.run_batch(queries=queries, labels=multi_labels, debug=True) - end_time = perf_counter() - querying_time = end_time - start_time - - # Evaluate predictions - eval_result = pipeline._generate_eval_result_from_batch_preds(predictions_batches=predictions) - metrics = eval_result.calculate_metrics()["Retriever"] - - retriever_type, retriever_top_k = get_retriever_config(pipeline) - doc_store = pipeline.get_document_store() - doc_store_type = doc_store.__class__.__name__ if doc_store else "No DocumentStore found" - results = { - "retriever": retriever_type, - "doc_store": doc_store_type, - "n_docs": doc_store.get_document_count(), - "n_queries": len(labels), - "querying_time": querying_time, - "queries_per_second": len(labels) / querying_time, - "seconds_per_query": querying_time / len(labels), - "recall": metrics["recall_single_hit"], - "map": metrics["map"], - "top_k": retriever_top_k, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": None, - } - - except Exception: - tb = traceback.format_exc() - logging.error("##### The following Error was raised while running querying run:") - logging.error(tb) - retriever_type, retriever_top_k = get_retriever_config(pipeline) - doc_store = pipeline.get_document_store() - doc_store_type = doc_store.__class__.__name__ if doc_store else "No DocumentStore found" - results = { - "retriever": retriever_type, - "doc_store": doc_store_type, - "n_docs": 0, - "n_queries": 0, - "retrieve_time": 0, - "queries_per_second": 0, - "seconds_per_query": 0, - "recall": 0, - "map": 0, - "top_k": retriever_top_k, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": str(tb), - } - - return results diff --git a/test/benchmarks/retriever_reader.py b/test/benchmarks/retriever_reader.py deleted file mode 100644 index e63e7305f2..0000000000 --- a/test/benchmarks/retriever_reader.py +++ /dev/null @@ -1,107 +0,0 @@ -from pathlib import Path -from time import perf_counter -import logging -import datetime -import traceback -from typing import Dict - -from haystack.nodes import BaseRetriever, BaseReader -from haystack import Pipeline -from haystack.utils import aggregate_labels - -from retriever import benchmark_indexing -from utils import load_eval_data, get_reader_config, get_retriever_config - - -def benchmark_retriever_reader( - indexing_pipeline: Pipeline, querying_pipeline: Pipeline, documents_directory: Path, eval_set: Path -) -> Dict: - """ - Benchmark indexing and querying on retriever-reader pipelines on a given dataset. - :param indexing_pipeline: Pipeline for indexing documents. - :param querying_pipeline: Pipeline for querying documents. - :param documents_directory: Directory containing files to index. - :param eval_set: Path to evaluation set. - """ - # Indexing - indexing_results = benchmark_indexing(indexing_pipeline, documents_directory) - - # Querying - querying_results = benchmark_querying(querying_pipeline, eval_set) - - results = {"indexing": indexing_results, "querying": querying_results} - - doc_store = indexing_pipeline.get_document_store() - doc_store.delete_index(index="document") - return results - - -def benchmark_querying(pipeline: Pipeline, eval_set: Path) -> Dict: - """ - Benchmark querying. This method should only be called if indexing has already been done. - :param pipeline: Pipeline for querying documents. - :param eval_set: Path to evaluation set. - """ - try: - # Load eval data - labels, _ = load_eval_data(eval_set) - multi_labels = aggregate_labels(labels) - queries = [label.query for label in multi_labels] - - # Run querying - start_time = perf_counter() - predictions = pipeline.run_batch(queries=queries, labels=multi_labels, debug=True) - end_time = perf_counter() - querying_time = end_time - start_time - - # Evaluate predictions - eval_result = pipeline._generate_eval_result_from_batch_preds(predictions_batches=predictions) - metrics = eval_result.calculate_metrics()["Reader"] - - retriever_type, retriever_top_k = get_retriever_config(pipeline) - doc_store = pipeline.get_document_store() - doc_store_type = doc_store.__class__.__name__ if doc_store else "No DocumentStore found" - reader_type, reader_model, reader_top_k = get_reader_config(pipeline) - - results = { - "exact_match": metrics["exact_match"], - "f1": metrics["f1"], - "querying_time": querying_time, - "seconds_per_query": querying_time / len(labels), - "n_docs": doc_store.get_document_count(), - "n_queries": len(labels), - "retriever": retriever_type, - "retriever_top_k": retriever_top_k, - "doc_store": doc_store_type, - "reader": reader_type, - "reader_model": reader_model, - "reader_top_k": reader_top_k, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": None, - } - except Exception: - tb = traceback.format_exc() - logging.error("##### The following Error was raised while running querying run:") - logging.error(tb) - retriever_type, retriever_top_k = get_retriever_config(pipeline) - doc_store = pipeline.get_document_store() - doc_store_type = doc_store.__class__.__name__ if doc_store else "No DocumentStore found" - reader_type, reader_model, reader_top_k = get_reader_config(pipeline) - results = { - "exact_match": 0, - "f1": 0, - "querying_time": 0, - "seconds_per_query": 0, - "n_docs": 0, - "n_queries": 0, - "retriever": retriever_type, - "retriever_top_k": retriever_top_k, - "doc_store": doc_store_type, - "reader": reader_type, - "reader_model": reader_model, - "reader_top_k": reader_top_k, - "date_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - "error": str(tb), - } - - return results diff --git a/test/benchmarks/run.py b/test/benchmarks/run.py deleted file mode 100644 index 73e7cd33e2..0000000000 --- a/test/benchmarks/run.py +++ /dev/null @@ -1,82 +0,0 @@ -from pathlib import Path -from typing import Dict -import argparse -import json - -import posthog - -from haystack import Pipeline -from haystack.pipelines.config import read_pipeline_config_from_yaml - -from utils import prepare_environment, contains_reader, contains_retriever -from reader import benchmark_reader -from retriever import benchmark_retriever -from retriever_reader import benchmark_retriever_reader - - -# Disable telemetry reports when running benchmarks -posthog.disabled = True - - -def run_benchmark(pipeline_yaml: Path) -> Dict: - """ - Run benchmarking on a given pipeline. Pipeline can be a retriever, reader, or retriever-reader pipeline. - In case of retriever or retriever-reader pipelines, indexing is also benchmarked, so the config file must - contain an indexing pipeline as well. - - :param pipeline_yaml: Path to pipeline YAML config. The config file should contain a benchmark_config section where - the following parameters are specified: - - documents_directory: Directory containing files to index. - - labels_file: Path to evaluation set. - - data_url (optional): URL to download the data from. Downloaded data will be stored in - the directory `data/`. - """ - pipeline_config = read_pipeline_config_from_yaml(pipeline_yaml) - benchmark_config = pipeline_config.pop("benchmark_config", {}) - - # Prepare environment - prepare_environment(pipeline_config, benchmark_config) - labels_file = Path(benchmark_config["labels_file"]) - - querying_pipeline = Pipeline.load_from_config(pipeline_config, pipeline_name="querying") - pipeline_contains_reader = contains_reader(querying_pipeline) - pipeline_contains_retriever = contains_retriever(querying_pipeline) - - # Retriever-Reader pipeline - if pipeline_contains_retriever and pipeline_contains_reader: - documents_dir = Path(benchmark_config["documents_directory"]) - indexing_pipeline = Pipeline.load_from_config(pipeline_config, pipeline_name="indexing") - - results = benchmark_retriever_reader(indexing_pipeline, querying_pipeline, documents_dir, labels_file) - - # Retriever pipeline - elif pipeline_contains_retriever: - documents_dir = Path(benchmark_config["documents_directory"]) - indexing_pipeline = Pipeline.load_from_config(pipeline_config, pipeline_name="indexing") - - results = benchmark_retriever(indexing_pipeline, querying_pipeline, documents_dir, labels_file) - - # Reader pipeline - elif pipeline_contains_reader: - results = benchmark_reader(querying_pipeline, labels_file) - - # Unsupported pipeline type - else: - raise ValueError("Pipeline must be a retriever, reader, or retriever-reader pipeline.") - - pipeline_config["benchmark_config"] = benchmark_config - results["config"] = pipeline_config - return results - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("config", type=str, help="Path to pipeline YAML config.") - parser.add_argument("--output", type=str, help="Path to output file.") - args = parser.parse_args() - - config_file = Path(args.config) - output_file = f"{config_file.stem}_results.json" if args.output is None else args.output - results = run_benchmark(config_file) - with open(output_file, "w") as f: - json.dump(results, f, indent=2) diff --git a/test/benchmarks/templates.py b/test/benchmarks/templates.py deleted file mode 100644 index 674b7da5fe..0000000000 --- a/test/benchmarks/templates.py +++ /dev/null @@ -1,55 +0,0 @@ -READER_TEMPLATE = { - "chart_type": "BarChart", - "title": "Reader Performance", - "subtitle": "Time and Accuracy Benchmarks", - "description": "Performance benchmarks of different Readers that can be used off-the-shelf in Haystack. Some models are geared towards speed, while others are more performance-focused. Accuracy is measured as F1 score and speed as passages/sec (with passages of 384 tokens). Each Reader is benchmarked using the SQuAD v2.0 development set, which contains 11866 question answer pairs. When tokenized using the BERT tokenizer and split using a sliding window approach, these become 12350 passages that are passed into the model. We set max_seq_len=384 and doc_stride=128. These benchmarking tests are run using an AWS p3.2xlarge instance with a Nvidia V100 GPU with this script. Please note that we are using the FARMReader class rather than the TransformersReader class. Also, the F1 measure that is reported here is in fact calculated on token level, rather than word level as is done in the official SQuAD script.", - "bars": "horizontal", - "columns": ["Model", "F1", "Speed (passages/sec)"], - "data": None, -} - -RETRIEVER_TEMPLATE = { - "chart_type": "BarChart", - "title": "Retriever Performance", - "subtitle": "Time and Accuracy Benchmarks", - "description": 'Comparison of the speed and accuracy of different DocumentStore / Retriever combinations on 100k documents. Indexing speed (in docs/sec) refers to how quickly Documents can be inserted into a DocumentStore. Querying speed (in queries/sec) refers to the speed at which the system returns relevant Documents when presented with a query.\n\nThe dataset used is Wikipedia, split into 100 word passages (from here)). \n\nFor querying, we use the Natural Questions development set in combination with the wiki passages. The Document Store is populated with the 100 word passages in which the answer spans occur (i.e. gold passages) as well as a random selection of 100 word passages in which the answer spans do not occur (i.e. negative passages). We take a total of 100k gold and negative passages. Query and document embedding are generated by the "facebook/dpr-question_encoder-single-nq-base" and "facebook/dpr-ctx_encoder-single-nq-base" models. The retriever returns 10 candidates and both the recall and mAP scores are calculated on these 10.\n\nFor FAISS HNSW, we use n_links=128, efSearch=20 and efConstruction=80. We use a cosine similarity function with BM25 retrievers, and dot product with DPR. Both index and query benchmarks are performed on an AWS P3.2xlarge instance which is accelerated by an Nvidia V100 GPU.', - "bars": "horizontal", - "columns": ["Model", "mAP", "Index Speed (docs/sec)", "Query Speed (queries/sec)"], - "series": {"s0": "map", "s1": "time", "s2": "time"}, - "axes": {"label": "map", "time_side": "top", "time_label": "seconds"}, - "data": None, -} - -RETRIEVER_MAP_TEMPLATE = { - "chart_type": "LineChart", - "title": "Retriever Accuracy", - "subtitle": "mAP at different number of docs", - "description": "Here you can see how the mean avg. precision (mAP) of the retriever decays as the number of documents increases. The set up is the same as the above querying benchmark except that a varying number of negative documents are used to fill the document store.", - "columns": [ - "n_docs", - "BM25 / Elasticsearch", - "DPR / Elasticsearch", - "DPR / FAISS (flat)", - "DPR / FAISS (HNSW)", - "Sentence Transformers / Elasticsearch", - ], - "axis": [{"x": "Number of docs", "y": "mAP"}], - "data": None, -} - -RETRIEVER_SPEED_TEMPLATE = { - "chart_type": "LineChart", - "title": "Retriever Speed", - "subtitle": "Query Speed at different number of docs", - "description": "Here you can see how the query speed of different Retriever / DocumentStore combinations scale as the number of documents increases. The set up is the same as the above querying benchmark except that a varying number of negative documents are used to fill the document store.", - "columns": [ - "n_docs", - "BM25 / Elasticsearch", - "DPR / Elasticsearch", - "DPR / FAISS (flat)", - "DPR / FAISS (HNSW)", - "Sentence Transformers / Elasticsearch", - ], - "axis": [{"x": "Number of docs", "y": "Queries/sec"}], - "data": None, -} diff --git a/test/benchmarks/utils.py b/test/benchmarks/utils.py deleted file mode 100644 index 8ef0ae438c..0000000000 --- a/test/benchmarks/utils.py +++ /dev/null @@ -1,187 +0,0 @@ -import os -import tarfile -import tempfile - -import pandas as pd - -from haystack import Label, Document, Answer, Pipeline -from haystack.document_stores import eval_data_from_json -from haystack.nodes import BaseReader, BaseRetriever -from haystack.utils import launch_es, launch_opensearch, launch_weaviate -from haystack.modeling.data_handler.processor import http_get - -import logging -from typing import Dict, Union, Tuple -from pathlib import Path - -logger = logging.getLogger(__name__) - - -def prepare_environment(pipeline_config: Dict, benchmark_config: Dict): - """ - Prepare the environment for running a benchmark. - """ - # Download data if specified in benchmark config - if "data_url" in benchmark_config: - download_from_url(url=benchmark_config["data_url"], target_dir="data/") - n_docs = 0 - if "documents_directory" in benchmark_config: - documents_dir = Path(benchmark_config["documents_directory"]) - n_docs = len( - [ - file_path - for file_path in documents_dir.iterdir() - if file_path.is_file() and not file_path.name.startswith(".") - ] - ) - - # Launch DocumentStore Docker container if needed - if "launch_document_store" in benchmark_config and benchmark_config["launch_document_store"]: - for comp in pipeline_config["components"]: - if comp["type"].endswith("DocumentStore"): - launch_document_store(comp["type"], n_docs=n_docs) - break - - -def launch_document_store(document_store: str, n_docs: int = 0): - """ - Launch a DocumentStore Docker container. - """ - java_opts = None if n_docs < 500000 else "-Xms4096m -Xmx4096m" - if document_store == "ElasticsearchDocumentStore": - launch_es(sleep=30, delete_existing=True, java_opts=java_opts) - elif document_store == "OpenSearchDocumentStore": - launch_opensearch(sleep=30, delete_existing=True, java_opts=java_opts) - elif document_store == "WeaviateDocumentStore": - launch_weaviate(sleep=30, delete_existing=True) - - -def file_previously_downloaded(url_path: Path, target_dir: Union[str, Path]) -> bool: - if ".tar" in url_path.suffixes: - return Path(target_dir, url_path.parent).exists() - return Path(target_dir, url_path.name).exists() - - -def download_from_url(url: str, target_dir: Union[str, Path]) -> None: - """ - Download from a URL to a local file. - - :param url: URL - :param target_dir: Local directory where the URL content will be saved. - """ - url_path = Path(url) - - if file_previously_downloaded(url_path, target_dir): - logger.info(f"Skipping download of {url}, as a previous copy exists") - return - - if not os.path.exists(target_dir): - os.makedirs(target_dir) - - logger.info("Downloading %s to %s", url_path.name, target_dir) - with tempfile.NamedTemporaryFile() as temp_file: - http_get(url=url, temp_file=temp_file) - temp_file.flush() - temp_file.seek(0) - if tarfile.is_tarfile(temp_file.name): - with tarfile.open(temp_file.name) as tar: - tar.extractall(target_dir) - else: - with open(Path(target_dir) / url_path.name, "wb") as file: - file.write(temp_file.read()) - - -def load_eval_data(eval_set_file: Path): - """ - Load evaluation data from a file. - :param eval_set_file: Path to the evaluation data file. - """ - if not os.path.exists(eval_set_file): - raise FileNotFoundError(f"The file {eval_set_file} does not exist.") - elif os.path.isdir(eval_set_file): - raise IsADirectoryError(f"The path {eval_set_file} is a directory, not a file.") - - if eval_set_file.suffix == ".json": - _, labels = eval_data_from_json(str(eval_set_file)) - queries = [label.query for label in labels] - elif eval_set_file.suffix == ".csv": - eval_data = pd.read_csv(eval_set_file) - - labels = [] - queries = [] - for idx, row in eval_data.iterrows(): - query = row["question"] - context = row["context"] - answer = Answer(answer=row["text"]) if "text" in row else None - label = Label( - query=query, - document=Document(context), - answer=answer, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - labels.append(label) - queries.append(query) - else: - raise ValueError( - f"Unsupported file format: {eval_set_file.suffix}. Provide a SQuAD-style .json or a .csv file containing " - f"the columns 'question' and 'context' for Retriever evaluations and additionally 'text' (containing the " - f"answer string) for Reader evaluations." - ) - - return labels, queries - - -def get_reader_config(pipeline: Pipeline) -> Tuple[str, str, Union[int, str]]: - """ - Get the configuration of the Reader component of a pipeline. - :param pipeline: Pipeline - :return: Tuple of Reader type, model name or path, and top_k - """ - readers = pipeline.get_nodes_by_class(BaseReader) - if not readers: - message = "No component of type BaseReader found" - return message, message, message - - reader = readers[0] - reader_type = reader.__class__.__name__ - reader_model = reader.model_name_or_path - reader_top_k = reader.top_k - - return reader_type, reader_model, reader_top_k - - -def get_retriever_config(pipeline: Pipeline) -> Tuple[str, Union[int, str]]: - """ - Get the configuration of the Retriever component of a pipeline. - :param pipeline: Pipeline - :return: Tuple of Retriever type and top_k - """ - retrievers = pipeline.get_nodes_by_class(BaseRetriever) - if not retrievers: - message = "No component of type Retriever found" - return message, message - - retriever = retrievers[0] - retriever_type = retriever.__class__.__name__ - retriever_top_k = retriever.top_k - - return retriever_type, retriever_top_k - - -def contains_reader(pipeline: Pipeline) -> bool: - """ - Check if a pipeline contains a Reader component. - :param pipeline: Pipeline - """ - components = list(pipeline.components.values()) - return any(isinstance(comp, BaseReader) for comp in components) - - -def contains_retriever(pipeline: Pipeline) -> bool: - """ - Check if a pipeline contains a Retriever component. - """ - components = list(pipeline.components.values()) - return any(isinstance(comp, BaseRetriever) for comp in components) diff --git a/test/cli/conftest.py b/test/cli/conftest.py deleted file mode 100644 index 33d1416fb8..0000000000 --- a/test/cli/conftest.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest -from click.testing import CliRunner - - -@pytest.fixture() -def cli_runner(): - yield CliRunner() diff --git a/test/cli/test_prompt_fetch.py b/test/cli/test_prompt_fetch.py deleted file mode 100644 index 56851c84f4..0000000000 --- a/test/cli/test_prompt_fetch.py +++ /dev/null @@ -1,60 +0,0 @@ -from unittest.mock import patch - -import pytest - -from haystack.cli.entry_point import main_cli -from haystack.nodes.prompt.prompt_template import PromptNotFoundError - - -@pytest.mark.unit -@patch("haystack.cli.prompt.fetch.fetch_from_prompthub") -@patch("haystack.cli.prompt.fetch.cache_prompt") -def test_prompt_fetch_no_args(mock_cache, mock_fetch, cli_runner): - response = cli_runner.invoke(main_cli, ["prompt", "fetch"]) - assert response.exit_code == 0 - - mock_fetch.assert_not_called() - mock_cache.assert_not_called() - - -@pytest.mark.unit -@patch("haystack.cli.prompt.fetch.fetch_from_prompthub") -@patch("haystack.cli.prompt.fetch.cache_prompt") -def test_prompt_fetch(mock_cache, mock_fetch, cli_runner): - response = cli_runner.invoke(main_cli, ["prompt", "fetch", "deepset/question-generation"]) - assert response.exit_code == 0 - - mock_fetch.assert_called_once_with("deepset/question-generation") - mock_cache.assert_called_once() - - -@pytest.mark.unit -@patch("haystack.cli.prompt.fetch.fetch_from_prompthub") -@patch("haystack.cli.prompt.fetch.cache_prompt") -def test_prompt_fetch_with_multiple_prompts(mock_cache, mock_fetch, cli_runner): - response = cli_runner.invoke( - main_cli, ["prompt", "fetch", "deepset/question-generation", "deepset/conversational-agent"] - ) - assert response.exit_code == 0 - - assert mock_fetch.call_count == 2 - mock_fetch.assert_any_call("deepset/question-generation") - mock_fetch.assert_any_call("deepset/conversational-agent") - - assert mock_cache.call_count == 2 - - -@pytest.mark.unit -@patch("haystack.cli.prompt.fetch.fetch_from_prompthub") -@patch("haystack.cli.prompt.fetch.cache_prompt") -def test_prompt_fetch_with_unexisting_prompt(mock_cache, mock_fetch, cli_runner): - prompt_name = "deepset/martian-speak" - error_message = f"Prompt template named '{prompt_name}' not available in the Prompt Hub." - mock_fetch.side_effect = PromptNotFoundError(error_message) - - response = cli_runner.invoke(main_cli, ["prompt", "fetch", prompt_name]) - assert response.exit_code == 1 - assert error_message in response.output - - mock_fetch.assert_called_once_with(prompt_name) - mock_cache.assert_not_called() diff --git a/test/document_stores/__init__.py b/test/document_stores/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/document_stores/test_deepsetcloud.py b/test/document_stores/test_deepsetcloud.py deleted file mode 100644 index 86818b5b13..0000000000 --- a/test/document_stores/test_deepsetcloud.py +++ /dev/null @@ -1,422 +0,0 @@ -import logging -import json -from pathlib import Path -from uuid import uuid4 - -import pytest -import responses -import numpy as np - -from responses import matchers - -from haystack.document_stores import DeepsetCloudDocumentStore -from haystack.utils import DeepsetCloudError -from haystack.schema import Document, Label, Answer - - -DC_API_ENDPOINT = "https://dc.example.com/v1" -DC_TEST_INDEX = "document_retrieval_1" -DC_API_KEY = "NO_KEY" - - -@pytest.fixture -def dc_api_mock(request): - """ - This fixture contains responses activation, so either this one or ds() below must be - passed to tests that require mocking. - - If `--mock-dc` was False, responses are never activated and it doesn't matter if the - fixture is passed or not. - """ - if request.config.getoption("--mock-dc"): - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}", - match=[responses.matchers.header_matcher({"authorization": f"Bearer {DC_API_KEY}"})], - json={"indexing": {"status": "INDEXED", "pending_file_count": 0, "total_file_count": 31}}, - status=200, - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines", - match=[responses.matchers.header_matcher({"authorization": f"Bearer {DC_API_KEY}"})], - json={ - "data": [ - { - "name": DC_TEST_INDEX, - "status": "DEPLOYED", - "indexing": {"status": "INDEXED", "pending_file_count": 0, "total_file_count": 31}, - } - ], - "has_more": False, - "total": 1, - }, - ) - - # activate the default mock, same as using the @responses.activate everywhere - with responses.mock as m: - yield m - - -@pytest.mark.document_store -@pytest.mark.integration -@pytest.mark.usefixtures("dc_api_mock") -class TestDeepsetCloudDocumentStore: - # Fixtures - - @pytest.fixture - def ds(self): - """ - We make this fixture depend on `dc_api_mock` so that passing the document store will - activate the mocking and we spare one function parameter. - """ - return DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=DC_TEST_INDEX) - - # Integration tests - - def test_init_with_dot_product(self, ds): - assert ds.return_embedding == False - assert ds.similarity == "dot_product" - - def test_init_with_cosine(self): - document_store = DeepsetCloudDocumentStore( - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - index=DC_TEST_INDEX, - similarity="cosine", - return_embedding=True, - ) - assert document_store.return_embedding == True - assert document_store.similarity == "cosine" - - def test_invalid_token(self): - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines", - match=[matchers.header_matcher({"authorization": "Bearer invalid_token"})], - body="Internal Server Error", - status=500, - ) - - with pytest.raises( - DeepsetCloudError, - match=f"Could not connect to deepset Cloud:\nGET {DC_API_ENDPOINT}/workspaces/default/pipelines failed: HTTP 500 - Internal Server Error", - ): - DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key="invalid_token", index=DC_TEST_INDEX) - - def test_invalid_api_endpoint(self): - responses.add( - method=responses.GET, url=f"{DC_API_ENDPOINT}00/workspaces/default/pipelines", body="Not Found", status=404 - ) - - with pytest.raises( - DeepsetCloudError, - match=f"Could not connect to deepset Cloud:\nGET {DC_API_ENDPOINT}00/workspaces/default/pipelines failed: " - f"HTTP 404 - Not Found\nNot Found", - ): - DeepsetCloudDocumentStore(api_endpoint=f"{DC_API_ENDPOINT}00", api_key=DC_API_KEY, index=DC_TEST_INDEX) - - def test_invalid_index(self, caplog): - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/invalid_index", - body="Not Found", - status=404, - ) - - with caplog.at_level(logging.INFO): - DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index="invalid_index") - assert ( - "You are using a DeepsetCloudDocumentStore with an index that does not exist on deepset Cloud." - in caplog.text - ) - - def test_documents(self, ds, samples_path): - with open(samples_path / "dc" / "documents-stream.response", "r") as f: - documents_stream_response = f.read() - docs = [json.loads(l) for l in documents_stream_response.splitlines()] - filtered_docs = [doc for doc in docs if doc["meta"]["file_id"] == docs[0]["meta"]["file_id"]] - documents_stream_filtered_response = "\n".join([json.dumps(d) for d in filtered_docs]) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}/documents-stream", - body=documents_stream_response, - status=200, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}/documents-stream", - match=[ - matchers.json_params_matcher( - {"filters": {"file_id": [docs[0]["meta"]["file_id"]]}, "return_embedding": False} - ) - ], - body=documents_stream_filtered_response, - status=200, - ) - - for doc in filtered_docs: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}/documents/{doc['id']}", - json=doc, - status=200, - ) - - docs = ds.get_all_documents() - assert len(docs) > 1 - assert isinstance(docs[0], Document) - - first_doc = next(ds.get_all_documents_generator()) - assert isinstance(first_doc, Document) - assert first_doc.meta["file_id"] is not None - - filtered_docs = ds.get_all_documents(filters={"file_id": [first_doc.meta["file_id"]]}) - assert len(filtered_docs) > 0 - assert len(filtered_docs) < len(docs) - - ids = [doc.id for doc in filtered_docs] - single_doc_by_id = ds.get_document_by_id(ids[0]) - assert single_doc_by_id is not None - assert single_doc_by_id.meta["file_id"] == first_doc.meta["file_id"] - - docs_by_id = ds.get_documents_by_id(ids) - assert len(docs_by_id) == len(filtered_docs) - for doc in docs_by_id: - assert doc.meta["file_id"] == first_doc.meta["file_id"] - - def test_query(self, ds, samples_path): - with open(samples_path / "dc" / "query_winterfell.response", "r") as f: - query_winterfell_response = f.read() - query_winterfell_docs = json.loads(query_winterfell_response) - query_winterfell_filtered_docs = [ - doc - for doc in query_winterfell_docs - if doc["meta"]["file_id"] == query_winterfell_docs[0]["meta"]["file_id"] - ] - query_winterfell_filtered_response = json.dumps(query_winterfell_filtered_docs) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}/documents-query", - match=[ - matchers.json_params_matcher( - {"query": "winterfell", "top_k": 50, "all_terms_must_match": False, "scale_score": True} - ) - ], - status=200, - body=query_winterfell_response, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}/documents-query", - match=[ - matchers.json_params_matcher( - { - "query": "winterfell", - "top_k": 50, - "filters": {"file_id": [query_winterfell_docs[0]["meta"]["file_id"]]}, - "all_terms_must_match": False, - "scale_score": True, - } - ) - ], - status=200, - body=query_winterfell_filtered_response, - ) - - docs = ds.query("winterfell", top_k=50) - assert docs is not None - assert len(docs) > 0 - - first_doc = docs[0] - filtered_docs = ds.query("winterfell", top_k=50, filters={"file_id": [first_doc.meta["file_id"]]}) - assert len(filtered_docs) > 0 - assert len(filtered_docs) < len(docs) - - @pytest.mark.parametrize( - "body, expected_count", - [ - ( - { - "data": [ - { - "evaluation_set_id": str(uuid4()), - "name": DC_TEST_INDEX, - "created_at": "2022-03-22T13:40:27.535Z", - "matched_labels": 2, - "total_labels": 10, - } - ], - "has_more": False, - "total": 1, - }, - 10, - ), - ( - { - "data": [ - { - "evaluation_set_id": str(uuid4()), - "name": DC_TEST_INDEX, - "created_at": "2022-03-22T13:40:27.535Z", - "matched_labels": 0, - "total_labels": 0, - } - ], - "has_more": False, - "total": 1, - }, - 0, - ), - ], - ) - def test_count_of_labels_for_evaluation_set(self, ds, body: dict, expected_count: int): - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/evaluation_sets", - status=200, - body=json.dumps(body), - ) - - count = ds.get_label_count(index=DC_TEST_INDEX) - assert count == expected_count - - def test_count_of_labels_for_evaluation_set_raises_DC_error_when_nothing_found(self, ds): - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/evaluation_sets", - status=200, - body=json.dumps({"data": [], "has_more": False, "total": 0}), - ) - - with pytest.raises(DeepsetCloudError, match=f"No evaluation set found with the name {DC_TEST_INDEX}"): - ds.get_label_count(index=DC_TEST_INDEX) - - def test_lists_evaluation_sets(self, ds): - response_evaluation_set = { - "evaluation_set_id": str(uuid4()), - "name": DC_TEST_INDEX, - "created_at": "2022-03-22T13:40:27.535Z", - "matched_labels": 2, - "total_labels": 10, - } - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/evaluation_sets", - status=200, - body=json.dumps({"data": [response_evaluation_set], "has_more": False, "total": 1}), - ) - - evaluation_sets = ds.get_evaluation_sets() - assert evaluation_sets == [response_evaluation_set] - - def test_fetches_labels_for_evaluation_set(self, ds): - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/evaluation_sets/{DC_TEST_INDEX}", - status=200, - body=json.dumps( - [ - { - "label_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "query": "What is berlin?", - "answer": "biggest city in germany", - "answer_start": 0, - "answer_end": 0, - "meta": {}, - "context": "Berlin is the biggest city in germany.", - "external_file_name": "string", - "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "state": "Label matching status", - "candidates": "Candidates that were found in the label <-> file matching", - } - ] - ), - ) - - labels = ds.get_all_labels(index=DC_TEST_INDEX) - assert labels == [ - Label( - query="What is berlin?", - document=Document(content="Berlin is the biggest city in germany."), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - answer=Answer("biggest city in germany"), - id="3fa85f64-5717-4562-b3fc-2c963f66afa6", - pipeline_id=None, - created_at=None, - updated_at=None, - meta={}, - filters={}, - ) - ] - - def test_fetches_labels_for_evaluation_set_raises_deepsetclouderror_when_nothing_found(self, ds): - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/evaluation_sets/{DC_TEST_INDEX}", - status=404, - ) - - with pytest.raises(DeepsetCloudError, match=f"No evaluation set found with the name {DC_TEST_INDEX}"): - ds.get_all_labels(index=DC_TEST_INDEX) - - def test_query_by_embedding(self, ds): - query_emb = np.random.randn(768) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}/documents-query", - match=[ - matchers.json_params_matcher( - { - "query_emb": query_emb.tolist(), - "top_k": 10, - "return_embedding": False, - "scale_score": True, - "use_prefiltering": False, - } - ) - ], - json=[], - status=200, - ) - - emb_docs = ds.query_by_embedding(query_emb) - assert len(emb_docs) == 0 - - def test_get_all_docs_without_index(self): - document_store = DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=None) - assert document_store.get_all_documents() == [] - - def test_get_all_docs_generator_without_index(self): - document_store = DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=None) - assert list(document_store.get_all_documents_generator()) == [] - - def test_get_doc_by_id_without_index(self): - document_store = DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=None) - assert document_store.get_document_by_id(id="some id") == None - - def test_get_docs_by_id_without_index(self): - document_store = DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=None) - assert document_store.get_documents_by_id(ids=["some id"]) == [] - - def test_get_doc_count_without_index(self): - document_store = DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=None) - assert document_store.get_document_count() == 0 - - def test_query_by_emb_without_index(self): - query_emb = np.random.randn(768) - document_store = DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=None) - assert document_store.query_by_embedding(query_emb=query_emb) == [] - - def test_query_without_index(self): - document_store = DeepsetCloudDocumentStore(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, index=None) - assert document_store.query(query="some query") == [] diff --git a/test/document_stores/test_elasticsearch.py b/test/document_stores/test_elasticsearch.py deleted file mode 100644 index adfdeb0a82..0000000000 --- a/test/document_stores/test_elasticsearch.py +++ /dev/null @@ -1,529 +0,0 @@ -import logging -import os -from unittest.mock import MagicMock, patch - -import numpy as np -import pytest -from elasticsearch import Elasticsearch - -from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore, VERSION -from haystack.document_stores.es_converter import elasticsearch_index_to_document_store -from haystack.document_stores.memory import InMemoryDocumentStore -from haystack.nodes import PreProcessor -from haystack.testing import DocumentStoreBaseTestAbstract - -from .test_search_engine import SearchEngineDocumentStoreTestAbstract - - -class TestElasticsearchDocumentStore(DocumentStoreBaseTestAbstract, SearchEngineDocumentStoreTestAbstract): - # Constants - - index_name = __name__ - - @pytest.fixture - def ds(self): - """ - This fixture provides a working document store and takes care of keeping clean - the ES cluster used in the tests. - """ - labels_index_name = f"{self.index_name}_labels" - ds = ElasticsearchDocumentStore( - index=self.index_name, - label_index=labels_index_name, - host=os.environ.get("ELASTICSEARCH_HOST", "localhost"), - create_index=True, - recreate_index=True, - ) - - yield ds - - @pytest.fixture - def mocked_elastic_search_init(self, monkeypatch): - mocked_init = MagicMock(return_value=None) - monkeypatch.setattr(Elasticsearch, "__init__", mocked_init) - return mocked_init - - @pytest.fixture - def mocked_elastic_search_ping(self, monkeypatch): - mocked_ping = MagicMock(return_value=True) - monkeypatch.setattr(Elasticsearch, "ping", mocked_ping) - return mocked_ping - - @pytest.fixture - def mocked_document_store(self): - """ - The fixture provides an instance of a slightly customized - ElasticsearchDocumentStore equipped with a mocked client - """ - - with patch( - f"{ElasticsearchDocumentStore.__module__}.ElasticsearchDocumentStore._init_elastic_client" - ) as mocked_init_client: - if VERSION[0] == 7: - mocked_init_client().info.return_value = {"version": {"number": "7.17.6"}} - else: - mocked_init_client().info.return_value = {"version": {"number": "8.8.0"}} - - class DSMock(ElasticsearchDocumentStore): - # We mock a subclass to avoid messing up the actual class object - pass - - DSMock.client = MagicMock() - yield DSMock() - - @pytest.mark.integration - def test___init__(self): - # defaults - _ = ElasticsearchDocumentStore() - - # list of hosts + single port - _ = ElasticsearchDocumentStore(host=["localhost", "127.0.0.1"], port=9200) - - # list of hosts + list of ports (wrong) - with pytest.raises(Exception): - _ = ElasticsearchDocumentStore(host=["localhost", "127.0.0.1"], port=[9200]) - - # list of hosts + list - _ = ElasticsearchDocumentStore(host=["localhost", "127.0.0.1"], port=[9200, 9200]) - - # only api_key - with pytest.raises(Exception): - _ = ElasticsearchDocumentStore(host=["localhost"], port=[9200], api_key="test") - - # api_key + id - _ = ElasticsearchDocumentStore(host=["localhost"], port=[9200], api_key="test", api_key_id="test") - - @pytest.mark.integration - def test_recreate_index(self, ds, documents, labels): - ds.write_documents(documents) - ds.write_labels(labels) - - # Create another document store on top of the previous one - ds = ElasticsearchDocumentStore(index=ds.index, label_index=ds.label_index, recreate_index=True) - assert len(ds.get_all_documents(index=ds.index)) == 0 - assert len(ds.get_all_labels(index=ds.label_index)) == 0 - - @pytest.mark.integration - def test_eq_filter(self, ds, documents): - ds.write_documents(documents) - - filter = {"name": {"$eq": ["name_0"]}} - filtered_docs = ds.get_all_documents(filters=filter) - assert len(filtered_docs) == 3 - for doc in filtered_docs: - assert doc.meta["name"] == "name_0" - - filter = {"numbers": {"$eq": [2, 4]}} - filtered_docs = ds.query(query=None, filters=filter) - assert len(filtered_docs) == 3 - for doc in filtered_docs: - assert doc.meta["month"] == "01" - assert doc.meta["numbers"] == [2, 4] - - @pytest.mark.integration - def test_custom_fields(self, ds): - index = "haystack_test_custom" - document_store = ElasticsearchDocumentStore( - index=index, - content_field="custom_text_field", - embedding_field="custom_embedding_field", - recreate_index=True, - ) - doc_to_write = {"custom_text_field": "test", "custom_embedding_field": np.random.rand(768).astype(np.float32)} - document_store.write_documents([doc_to_write]) - documents = document_store.get_all_documents(return_embedding=True) - assert len(documents) == 1 - assert documents[0].content == "test" - np.testing.assert_array_equal(doc_to_write["custom_embedding_field"], documents[0].embedding) - document_store.delete_index(index) - - @pytest.mark.integration - def test_query_with_filters_and_missing_embeddings(self, ds, documents): - ds.write_documents(documents) - filters = {"month": {"$in": ["01", "03"]}} - ds.skip_missing_embeddings = False - with pytest.raises(ds._RequestError): - ds.query_by_embedding(np.random.rand(768), filters=filters) - - ds.skip_missing_embeddings = True - documents = ds.query_by_embedding(np.random.rand(768), filters=filters) - assert len(documents) == 3 - - @pytest.mark.integration - def test_synonyms(self, ds): - synonyms = ["i-pod, i pod, ipod", "sea biscuit, sea biscit, seabiscuit", "foo, foo bar, baz"] - synonym_type = "synonym_graph" - - client = ds.client - index = "haystack_synonym_arg" - client.indices.delete(index=index, ignore=[404]) - ElasticsearchDocumentStore(index=index, synonyms=synonyms, synonym_type=synonym_type) - indexed_settings = client.indices.get_settings(index=index) - - assert synonym_type == indexed_settings[index]["settings"]["index"]["analysis"]["filter"]["synonym"]["type"] - assert synonyms == indexed_settings[index]["settings"]["index"]["analysis"]["filter"]["synonym"]["synonyms"] - - @pytest.mark.integration - def test_search_field_mapping(self): - index = "haystack_search_field_mapping" - document_store = ElasticsearchDocumentStore( - index=index, search_fields=["content", "sub_content"], content_field="title" - ) - - document_store.write_documents( - [ - { - "title": "Green tea components", - "meta": { - "content": "The green tea plant contains a range of healthy compounds that make it into the final drink", - "sub_content": "Drink tip", - }, - "id": "1", - }, - { - "title": "Green tea catechin", - "meta": { - "content": "Green tea contains a catechin called epigallocatechin-3-gallate (EGCG).", - "sub_content": "Ingredients tip", - }, - "id": "2", - }, - { - "title": "Minerals in Green tea", - "meta": { - "content": "Green tea also has small amounts of minerals that can benefit your health.", - "sub_content": "Minerals tip", - }, - "id": "3", - }, - { - "title": "Green tea Benefits", - "meta": { - "content": "Green tea does more than just keep you alert, it may also help boost brain function.", - "sub_content": "Health tip", - }, - "id": "4", - }, - ] - ) - - indexed_settings = document_store.client.indices.get_mapping(index=index) - - assert indexed_settings[index]["mappings"]["properties"]["content"]["type"] == "text" - assert indexed_settings[index]["mappings"]["properties"]["sub_content"]["type"] == "text" - document_store.delete_index(index) - - @pytest.mark.integration - def test_existing_alias(self, ds): - client = ds.client - client.indices.delete(index="haystack_existing_alias_1", ignore=[404]) - client.indices.delete(index="haystack_existing_alias_2", ignore=[404]) - client.indices.delete_alias(index="_all", name="haystack_existing_alias", ignore=[404]) - - settings = {"mappings": {"properties": {"content": {"type": "text"}}}} - - client.indices.create(index="haystack_existing_alias_1", **settings) - client.indices.create(index="haystack_existing_alias_2", **settings) - - client.indices.put_alias( - index="haystack_existing_alias_1,haystack_existing_alias_2", name="haystack_existing_alias" - ) - - # To be valid, all indices related to the alias must have content field of type text - ElasticsearchDocumentStore(index="haystack_existing_alias", search_fields=["content"]) - - @pytest.mark.integration - def test_existing_alias_missing_fields(self, ds): - client = ds.client - client.indices.delete(index="haystack_existing_alias_1", ignore=[404]) - client.indices.delete(index="haystack_existing_alias_2", ignore=[404]) - client.indices.delete_alias(index="_all", name="haystack_existing_alias", ignore=[404]) - - right_settings = {"mappings": {"properties": {"content": {"type": "text"}}}} - wrong_settings = {"mappings": {"properties": {"content": {"type": "histogram"}}}} - - client.indices.create(index="haystack_existing_alias_1", **right_settings) - client.indices.create(index="haystack_existing_alias_2", **wrong_settings) - client.indices.put_alias( - index="haystack_existing_alias_1,haystack_existing_alias_2", name="haystack_existing_alias" - ) - - with pytest.raises(Exception): - # wrong field type for "content" in index "haystack_existing_alias_2" - ElasticsearchDocumentStore( - index="haystack_existing_alias", search_fields=["content"], content_field="title" - ) - - @pytest.mark.integration - def test_get_document_count_only_documents_without_embedding_arg(self, ds, documents): - ds.write_documents(documents) - - assert ds.get_document_count() == 9 - assert ds.get_document_count(only_documents_without_embedding=True) == 3 - assert ds.get_document_count(only_documents_without_embedding=True, filters={"month": ["01"]}) == 0 - assert ds.get_document_count(only_documents_without_embedding=True, filters={"month": ["03"]}) == 3 - - @pytest.mark.integration - def test_elasticsearch_brownfield_support(self, ds, documents): - ds.write_documents(documents) - - new_document_store = elasticsearch_index_to_document_store( - document_store=InMemoryDocumentStore(), - original_index_name=ds.index, - original_content_field="content", - original_name_field="name", - included_metadata_fields=["date_field"], - index="test_brownfield_support", - id_hash_keys=["content", "meta"], - ) - - original_documents = ds.get_all_documents() - transferred_documents = new_document_store.get_all_documents(index="test_brownfield_support") - assert len(original_documents) == len(transferred_documents) - assert all("name" in doc.meta for doc in transferred_documents) - assert all(doc.id == doc._get_id(["content", "meta"]) for doc in transferred_documents) - - original_content = {doc.content for doc in original_documents} - transferred_content = {doc.content for doc in transferred_documents} - assert original_content == transferred_content - - # Test transferring docs with PreProcessor - new_document_store = elasticsearch_index_to_document_store( - document_store=InMemoryDocumentStore(), - original_index_name=ds.index, - original_content_field="content", - excluded_metadata_fields=["date_field"], - index="test_brownfield_support_2", - preprocessor=PreProcessor(split_length=1, split_respect_sentence_boundary=False), - ) - transferred_documents = new_document_store.get_all_documents(index="test_brownfield_support_2") - assert all("name" in doc.meta for doc in transferred_documents) - # Check if number of transferred_documents is equal to number of unique words. - assert len(transferred_documents) == len(set(" ".join(original_content).split())) - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 is not supported") - @pytest.mark.unit - def test__init_elastic_client_aws4auth_and_username_raises_warning( - self, caplog, mocked_elastic_search_init, mocked_elastic_search_ping - ): - _init_client_remaining_kwargs = { - "host": "host", - "port": 443, - "password": "pass", - "api_key_id": None, - "api_key": None, - "scheme": "https", - "ca_certs": None, - "verify_certs": True, - "timeout": 10, - "use_system_proxy": False, - } - - with caplog.at_level(logging.WARN, logger="haystack.document_stores.elasticsearch"): - ElasticsearchDocumentStore._init_elastic_client( - username="admin", aws4auth="foo", **_init_client_remaining_kwargs - ) - assert len(caplog.records) == 1 - for r in caplog.records: - assert r.levelname == "WARNING" - - caplog.clear() - with caplog.at_level(logging.WARN, logger="haystack.document_stores.elasticsearch"): - ElasticsearchDocumentStore._init_elastic_client( - username=None, aws4auth="foo", **_init_client_remaining_kwargs - ) - ElasticsearchDocumentStore._init_elastic_client( - username="", aws4auth="foo", **_init_client_remaining_kwargs - ) - assert len(caplog.records) == 0 - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_get_document_by_id_return_embedding_false_es7(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.get_document_by_id("123") - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_get_document_by_id_return_embedding_false_es8(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.get_document_by_id("123") - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - assert kwargs["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_get_document_by_id_excluded_meta_data_has_no_influence_es7(self, mocked_document_store): - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.return_embedding = False - mocked_document_store.get_document_by_id("123") - # assert the resulting body is not affected by the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_get_document_by_id_excluded_meta_data_has_no_influence_es8(self, mocked_document_store): - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.return_embedding = False - mocked_document_store.get_document_by_id("123") - # assert the resulting body is not affected by the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - assert kwargs["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_write_documents_req_for_each_batch(self, mocked_document_store, documents): - mocked_document_store.batch_size = 2 - with patch(f"{ElasticsearchDocumentStore.__module__}.bulk") as mocked_bulk: - mocked_document_store.write_documents(documents) - assert mocked_bulk.call_count == 5 - - @pytest.mark.unit - def test_get_vector_similarity_query(self, mocked_document_store): - """ - Test that the source field of the vector similarity query is correctly formatted for ES 7.6 and above. - We test this to make sure we use the correct syntax for newer ES versions. - """ - vec_sim_query = mocked_document_store._get_vector_similarity_query(np.random.rand(3).astype(np.float32), 10) - assert vec_sim_query["script_score"]["script"]["source"] == "dotProduct(params.query_vector,'embedding') + 1000" - - @pytest.mark.unit - def test_get_vector_similarity_query_es_7_5_and_below(self, mocked_document_store): - """ - Test that the source field of the vector similarity query is correctly formatter for ES 7.5 and below. - We test this to make sure we use the correct syntax for ES versions older than 7.6, as the syntax changed - in 7.6. - """ - # Patch server version to be 7.5.0 - mocked_document_store.server_version = (7, 5, 0) - - vec_sim_query = mocked_document_store._get_vector_similarity_query(np.random.rand(3).astype(np.float32), 10) - assert ( - vec_sim_query["script_score"]["script"]["source"] - == "dotProduct(params.query_vector,doc['embedding']) + 1000" - ) - - # The following tests are overridden only to be able to skip them depending on ES version - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_get_all_documents_return_embedding_true(self, mocked_document_store): - super().test_get_all_documents_return_embedding_true(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_get_all_documents_return_embedding_true_es8(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.client.options().search.return_value = {} - mocked_document_store.get_all_documents(return_embedding=True) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - assert "_source" not in kwargs - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_get_all_documents_return_embedding_false(self, mocked_document_store): - super().test_get_all_documents_return_embedding_false(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_get_all_documents_return_embedding_false_es8(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.client.options().search.return_value = {} - mocked_document_store.get_all_documents(return_embedding=False) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - body = kwargs.get("body", kwargs) - assert body["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_get_all_documents_excluded_meta_data_has_no_influence(self, mocked_document_store): - super().test_get_all_documents_excluded_meta_data_has_no_influence(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_get_all_documents_excluded_meta_data_has_no_influence_es8(self, mocked_document_store): - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.client.options().search.return_value = {} - mocked_document_store.get_all_documents(return_embedding=False) - # assert the resulting body is not affected by the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - body = kwargs.get("body", kwargs) - assert body["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_query_return_embedding_true(self, mocked_document_store): - super().test_query_return_embedding_true(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_query_return_embedding_true_es8(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - assert "_source" not in kwargs - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_query_return_embedding_false(self, mocked_document_store): - super().test_query_return_embedding_false(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_query_return_embedding_false_es8(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - assert kwargs["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_true(self, mocked_document_store): - super().test_query_excluded_meta_data_return_embedding_true(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_true_es8(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.excluded_meta_data = ["foo", "embedding"] - mocked_document_store.query(self.query) - _, kwargs = mocked_document_store.client.options().search.call_args - # we expect "embedding" was removed from the final query - assert kwargs["_source"] == {"excludes": ["foo"]} - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_false(self, mocked_document_store): - super().test_query_excluded_meta_data_return_embedding_false(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_false_es8(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - assert kwargs["_source"] == {"excludes": ["foo", "embedding"]} - - @pytest.mark.skipif(VERSION[0] == 8, reason="Elasticsearch 8 uses a different client call") - @pytest.mark.unit - def test_get_document_by_id_return_embedding_true(self, mocked_document_store): - super().test_get_document_by_id_return_embedding_true(mocked_document_store) - - @pytest.mark.skipif(VERSION[0] == 7, reason="Elasticsearch 7 uses a different client call") - @pytest.mark.unit - def test_get_document_by_id_return_embedding_true_es8(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.get_document_by_id("123") - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.options().search.call_args - assert "_source" not in kwargs diff --git a/test/document_stores/test_faiss.py b/test/document_stores/test_faiss.py deleted file mode 100644 index b2c0171ae0..0000000000 --- a/test/document_stores/test_faiss.py +++ /dev/null @@ -1,330 +0,0 @@ -import faiss -import pytest -import numpy as np - -from haystack.document_stores.faiss import FAISSDocumentStore -from haystack.testing import DocumentStoreBaseTestAbstract - -from haystack.pipelines import Pipeline - -from ..conftest import MockDenseRetriever - - -class TestFAISSDocumentStore(DocumentStoreBaseTestAbstract): - @pytest.fixture - def ds(self, tmp_path): - return FAISSDocumentStore( - sql_url=f"sqlite:///{tmp_path}/haystack_test.db", - return_embedding=True, - isolation_level="AUTOCOMMIT", - progress_bar=False, - similarity="cosine", - ) - - @pytest.fixture - def documents_with_embeddings(self, documents): - # drop documents without embeddings from the original fixture - return [d for d in documents if d.embedding is not None] - - @pytest.mark.unit - def test_index_mutual_exclusive_args(self, tmp_path): - with pytest.raises(ValueError, match="faiss_index_path"): - FAISSDocumentStore( - sql_url=f"sqlite:////{tmp_path/'haystack_test.db'}", - faiss_index_path=f"{tmp_path/'haystack_test'}", - isolation_level="AUTOCOMMIT", - ) - - with pytest.raises(ValueError, match="faiss_index_path"): - FAISSDocumentStore( - f"sqlite:////{tmp_path/'haystack_test.db'}", - faiss_index_path=f"{tmp_path/'haystack_test'}", - isolation_level="AUTOCOMMIT", - ) - - @pytest.mark.integration - def test_delete_index(self, ds, documents): - """Contrary to other Document Stores, FAISSDocumentStore doesn't raise if the index is empty""" - ds.write_documents(documents) - assert ds.get_document_count() == len(documents) - ds.delete_index(ds.index) - assert ds.get_document_count() == 0 - - @pytest.mark.integration - @pytest.mark.parametrize("config_path", [None, "custom_path.json"]) - def test_index_save_and_load(self, ds, documents_with_embeddings, tmp_path, config_path): - if config_path: - config_path = tmp_path / config_path - - ds.write_documents(documents_with_embeddings) - - # test saving the index - ds.save(index_path=tmp_path / "haystack_test_faiss", config_path=config_path) - - # clear existing faiss_index - ds.faiss_indexes[ds.index].reset() - - # test faiss index is cleared - assert ds.faiss_indexes[ds.index].ntotal == 0 - - # test loading the index - new_document_store = FAISSDocumentStore.load( - index_path=tmp_path / "haystack_test_faiss", config_path=config_path - ) - - # check faiss index is restored - assert new_document_store.faiss_indexes[ds.index].ntotal == len(documents_with_embeddings) - # check if documents are restored - assert len(new_document_store.get_all_documents()) == len(documents_with_embeddings) - # Check if the init parameters are kept - assert not new_document_store.progress_bar - - # test saving and loading the loaded faiss index - new_document_store.save(tmp_path / "haystack_test_faiss", config_path=config_path) - reloaded_document_store = FAISSDocumentStore.load(tmp_path / "haystack_test_faiss", config_path=config_path) - - # check faiss index is restored - assert reloaded_document_store.faiss_indexes[ds.index].ntotal == len(documents_with_embeddings) - # check if documents are restored - assert len(reloaded_document_store.get_all_documents()) == len(documents_with_embeddings) - # Check if the init parameters are kept - assert not reloaded_document_store.progress_bar - - # test loading the index via init - new_document_store = FAISSDocumentStore( - faiss_index_path=tmp_path / "haystack_test_faiss", faiss_config_path=config_path - ) - - # check faiss index is restored - assert new_document_store.faiss_indexes[ds.index].ntotal == len(documents_with_embeddings) - # check if documents are restored - assert len(new_document_store.get_all_documents()) == len(documents_with_embeddings) - # Check if the init parameters are kept - assert not new_document_store.progress_bar - - @pytest.mark.integration - @pytest.mark.parametrize("index_buffer_size", [10_000, 2]) - @pytest.mark.parametrize("index_factory", ["Flat", "HNSW", "IVF1,Flat"]) - def test_write_index_docs(self, documents_with_embeddings, tmp_path, index_buffer_size, index_factory): - document_store = FAISSDocumentStore( - sql_url=f"sqlite:///{tmp_path}/test_faiss_retrieving_{index_factory}.db", - faiss_index_factory_str=index_factory, - isolation_level="AUTOCOMMIT", - return_embedding=True, - ) - batch_size = 2 - document_store.index_buffer_size = index_buffer_size - document_store.delete_all_documents(index=document_store.index) - if "ivf" in index_factory.lower(): - document_store.train_index(documents_with_embeddings) - document_store.faiss_indexes[document_store.index].make_direct_map() - - # Write in batches - for i in range(0, len(documents_with_embeddings), batch_size): - document_store.write_documents(documents_with_embeddings[i : i + batch_size]) - - documents_indexed = document_store.get_all_documents() - assert len(documents_indexed) == len(documents_with_embeddings) - assert all(doc.embedding is not None for doc in documents_indexed) - # Check that get_embedding_count works as expected - assert document_store.get_embedding_count() == len(documents_with_embeddings) - - @pytest.mark.integration - def test_write_docs_no_training(self, documents_with_embeddings, tmp_path, caplog): - document_store = FAISSDocumentStore( - sql_url=f"sqlite:///{tmp_path}/test_write_docs_no_training.db", - faiss_index_factory_str="IVF1,Flat", - isolation_level="AUTOCOMMIT", - return_embedding=True, - ) - with pytest.raises(ValueError, match="must be trained before adding vectors"): - document_store.write_documents(documents_with_embeddings) - - @pytest.mark.integration - def test_train_index_from_docs(self, documents_with_embeddings, tmp_path): - document_store = FAISSDocumentStore( - sql_url=f"sqlite:///{tmp_path}/test_faiss_retrieving.db", - faiss_index_factory_str="IVF1,Flat", - isolation_level="AUTOCOMMIT", - return_embedding=True, - ) - document_store.delete_all_documents(index=document_store.index) - - assert not document_store.faiss_indexes[document_store.index].is_trained - document_store.train_index(documents_with_embeddings) - assert document_store.faiss_indexes[document_store.index].is_trained - - @pytest.mark.integration - def test_train_index_from_embeddings(self, documents_with_embeddings, tmp_path): - document_store = FAISSDocumentStore( - sql_url=f"sqlite:///{tmp_path}/test_faiss_retrieving.db", - faiss_index_factory_str="IVF1,Flat", - isolation_level="AUTOCOMMIT", - return_embedding=True, - ) - document_store.delete_all_documents(index=document_store.index) - - embeddings = np.array([doc.embedding for doc in documents_with_embeddings]) - assert not document_store.faiss_indexes[document_store.index].is_trained - document_store.train_index(embeddings=embeddings) - assert document_store.faiss_indexes[document_store.index].is_trained - - @pytest.mark.integration - def test_write_docs_different_indexes(self, ds, documents_with_embeddings): - docs_a = documents_with_embeddings[:2] - docs_b = documents_with_embeddings[2:] - ds.write_documents(docs_a, index="index_a") - ds.write_documents(docs_b, index="index_b") - - docs_from_index_a = ds.get_all_documents(index="index_a", return_embedding=False) - assert len(docs_from_index_a) == len(docs_a) - assert {int(doc.meta["vector_id"]) for doc in docs_from_index_a} == {0, 1} - - docs_from_index_b = ds.get_all_documents(index="index_b", return_embedding=False) - assert len(docs_from_index_b) == len(docs_b) - assert {int(doc.meta["vector_id"]) for doc in docs_from_index_b} == {0, 1, 2, 3} - - @pytest.mark.integration - def test_update_docs_different_indexes(self, ds, documents_with_embeddings): - retriever = MockDenseRetriever(document_store=ds) - - docs_a = documents_with_embeddings[:2] - docs_b = documents_with_embeddings[2:] - ds.write_documents(docs_a, index="index_a") - ds.write_documents(docs_b, index="index_b") - - ds.update_embeddings(retriever=retriever, update_existing_embeddings=True, index="index_a") - ds.update_embeddings(retriever=retriever, update_existing_embeddings=True, index="index_b") - - docs_from_index_a = ds.get_all_documents(index="index_a", return_embedding=False) - assert len(docs_from_index_a) == len(docs_a) - assert {int(doc.meta["vector_id"]) for doc in docs_from_index_a} == {0, 1} - - docs_from_index_b = ds.get_all_documents(index="index_b", return_embedding=False) - assert len(docs_from_index_b) == len(docs_b) - assert {int(doc.meta["vector_id"]) for doc in docs_from_index_b} == {0, 1, 2, 3} - - @pytest.mark.integration - def test_dont_update_existing_embeddings(self, ds, docs): - retriever = MockDenseRetriever(document_store=ds) - first_doc_id = docs[0].id - - for i in range(1, 4): - ds.write_documents(docs[:i]) - ds.update_embeddings(retriever=retriever, update_existing_embeddings=False) - - assert ds.get_document_count() == i - assert ds.get_embedding_count() == i - assert ds.get_document_by_id(id=first_doc_id).meta["vector_id"] == "0" - - # Check if the embeddings of the first document remain unchanged after multiple updates - if i == 1: - first_doc_embedding = ds.get_document_by_id(id=first_doc_id).embedding - else: - assert np.array_equal(ds.get_document_by_id(id=first_doc_id).embedding, first_doc_embedding) - - @pytest.mark.integration - def test_passing_index_from_outside(self, documents_with_embeddings, tmp_path): - d = 768 - nlist = 2 - quantizer = faiss.IndexFlatIP(d) - index = "haystack_test_1" - faiss_index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_INNER_PRODUCT) - faiss_index.set_direct_map_type(faiss.DirectMap.Hashtable) - faiss_index.nprobe = 2 - document_store = FAISSDocumentStore( - sql_url="sqlite:///", faiss_index=faiss_index, index=index, isolation_level="AUTOCOMMIT" - ) - - document_store.delete_documents() - # as it is a IVF index we need to train it before adding docs - document_store.train_index(documents_with_embeddings) - - document_store.write_documents(documents=documents_with_embeddings) - documents_indexed = document_store.get_all_documents() - - # test if vectors ids are associated with docs - for doc in documents_indexed: - assert 0 <= int(doc.meta["vector_id"]) <= 7 - - @pytest.mark.integration - def test_pipeline_with_existing_faiss_docstore(self, ds, documents_with_embeddings, tmp_path): - ds.write_documents(documents_with_embeddings) - ds.save(tmp_path / "existing_faiss_document_store") - pipeline_config = { - "version": "ignore", - "components": [ - { - "name": "DPRRetriever", - "type": "MockDenseRetriever", - "params": {"document_store": "ExistingFAISSDocumentStore"}, - }, - { - "name": "ExistingFAISSDocumentStore", - "type": "FAISSDocumentStore", - "params": {"faiss_index_path": f"{tmp_path / 'existing_faiss_document_store'}"}, - }, - ], - "pipelines": [{"name": "query_pipeline", "nodes": [{"name": "DPRRetriever", "inputs": ["Query"]}]}], - } - pipeline = Pipeline.load_from_config(pipeline_config) - existing_document_store = pipeline.get_document_store() - faiss_index = existing_document_store.faiss_indexes[ds.index] - assert faiss_index.ntotal == len(documents_with_embeddings) - - # See TestSQLDocumentStore about why we have to skip these tests - - @pytest.mark.skip - @pytest.mark.integration - def test_ne_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nin_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_comparison_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nested_condition_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nested_condition_not_filters(self, ds, documents): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_delete_labels_by_filter(self, ds, labels): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_delete_labels_by_filter_id(self, ds, labels): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel_filter_aggregations(self): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel_meta_aggregations(self): - pass - - @pytest.mark.skip(reason="tested in test_write_index_docs") - @pytest.mark.integration - def test_get_embedding_count(self): - pass - - @pytest.mark.skip(reason="can't store embeddings in SQL") - @pytest.mark.integration - def test_custom_embedding_field(self, ds): - pass diff --git a/test/document_stores/test_memory.py b/test/document_stores/test_memory.py deleted file mode 100644 index 1380e37389..0000000000 --- a/test/document_stores/test_memory.py +++ /dev/null @@ -1,122 +0,0 @@ -import logging -from copy import deepcopy - -import pandas as pd -import pytest -from rank_bm25 import BM25 -import numpy as np - -from haystack.document_stores.memory import InMemoryDocumentStore -from haystack.nodes import BM25Retriever -from haystack.schema import Document -from haystack.testing import DocumentStoreBaseTestAbstract - - -class TestInMemoryDocumentStore(DocumentStoreBaseTestAbstract): - @pytest.fixture - def ds(self): - return InMemoryDocumentStore(return_embedding=True, use_bm25=True) - - @pytest.mark.integration - def test_delete_index(self, ds, documents): - """Contrary to other Document Stores, this doesn't raise if the index is empty""" - ds.write_documents(documents, index="custom_index") - assert ds.get_document_count(index="custom_index") == len(documents) - ds.delete_index(index="custom_index") - assert ds.get_document_count(index="custom_index") == 0 - - @pytest.mark.integration - def test_ne_filters(self, ds, documents): - """ - InMemory doesn't include documents if the field is missing, - so we customize this test - """ - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$ne": "2020"}}) - assert len(result) == 3 - - @pytest.mark.integration - def test_get_documents_by_id(self, ds, documents): - """ - The base test uses the batch_size param that's not supported - here, so we override the test case - """ - ds.write_documents(documents) - ids = [doc.id for doc in documents] - result = {doc.id for doc in ds.get_documents_by_id(ids)} - assert set(ids) == result - - @pytest.mark.integration - def test_update_bm25(self, ds, documents): - ds.write_documents(documents) - bm25_representation = ds.bm25[ds.index] - assert isinstance(bm25_representation, BM25) - assert bm25_representation.corpus_size == ds.get_document_count() - - @pytest.mark.integration - def test_update_bm25_table(self, ds): - table_doc = Document( - content=pd.DataFrame(columns=["id", "text"], data=[[0, "This is a test"], ["2", "This is another test"]]), - content_type="table", - ) - ds.write_documents([table_doc]) - bm25_representation = ds.bm25[ds.index] - assert isinstance(bm25_representation, BM25) - assert bm25_representation.corpus_size == ds.get_document_count() - - @pytest.mark.integration - def test_memory_query(self, ds, documents): - ds.write_documents(documents) - query_text = "Bar" - docs = ds.query(query=query_text, top_k=1) - assert len(docs) == 1 - assert "A Bar Document" in docs[0].content - - @pytest.mark.integration - def test_memory_query_batch(self, ds, documents): - ds.write_documents(documents) - query_texts = ["Foo", "Bar"] - docs = ds.query_batch(queries=query_texts, top_k=5) - assert len(docs) == 2 - assert len(docs[0]) == 5 - assert "A Foo Document" in docs[0][0].content - assert len(docs[1]) == 5 - assert "A Bar Document" in docs[1][0].content - - @pytest.mark.integration - def test_memory_query_by_embedding_batch(self, ds, documents): - documents = [doc for doc in documents if doc.embedding is not None] - ds.write_documents(documents) - query_embs = [doc.embedding for doc in documents] - docs_batch = ds.query_by_embedding_batch(query_embs=query_embs, top_k=5) - assert len(docs_batch) == 6 - for docs, query_emb in zip(docs_batch, query_embs): - assert len(docs) == 5 - assert (docs[0].embedding == query_emb).all() - - @pytest.mark.integration - def test_memory_query_by_embedding_docs_wo_embeddings(self, ds, caplog): - # write document but don't update embeddings - ds.write_documents([Document(content="test Document")]) - - query_embedding = np.random.rand(768).astype(np.float32) - - with caplog.at_level(logging.WARNING): - docs = ds.query_by_embedding(query_emb=query_embedding, top_k=1) - assert "Skipping some of your documents that don't have embeddings" in caplog.text - assert len(docs) == 0 - - @pytest.mark.integration - def test_bm25_scores_not_changing_across_queries(self, ds, documents): - """Test that computed scores which are returned to the user should not change when running multiple queries.""" - ds.write_documents(documents) - retriever = BM25Retriever(ds, scale_score=False) - queries = ["What is a Foo Document?", "What is a Bar Document?", "Tell me about a document without embeddings"] - results_direct = [] - results_direct = [retriever.retrieve(query) for query in queries] - results_copied = [deepcopy(retriever.retrieve(query)) for query in queries] - scores_direct = [rd.score for rds in results_direct for rd in rds] - scores_copied = [rc.score for rcs in results_copied for rc in rcs] - - assert scores_direct == scores_copied diff --git a/test/document_stores/test_opensearch.py b/test/document_stores/test_opensearch.py deleted file mode 100644 index 443343123b..0000000000 --- a/test/document_stores/test_opensearch.py +++ /dev/null @@ -1,1301 +0,0 @@ -import os -import logging - -from unittest.mock import MagicMock, patch - -import pytest -import numpy as np - -import opensearchpy - -from haystack.document_stores.opensearch import ( - OpenSearch, - OpenSearchDocumentStore, - RequestsHttpConnection, - Urllib3HttpConnection, - RequestError, - tqdm, -) -from haystack.errors import DocumentStoreError -from haystack.testing import DocumentStoreBaseTestAbstract - -from .test_search_engine import SearchEngineDocumentStoreTestAbstract - - -class TestOpenSearchDocumentStore(DocumentStoreBaseTestAbstract, SearchEngineDocumentStoreTestAbstract): - # Constants - query_emb = np.random.random_sample(size=(2, 2)) - index_name = __name__ - - # Fixtures - - @pytest.fixture - def ds(self): - """ - This fixture provides a working document store and takes care of keeping clean the - OS cluster used in the tests. - """ - labels_index_name = f"{self.index_name}_labels" - ds = OpenSearchDocumentStore( - index=self.index_name, - label_index=labels_index_name, - host=os.environ.get("OPENSEARCH_HOST", "localhost"), - create_index=True, - recreate_index=True, - ) - - yield ds - - @pytest.fixture - def mocked_document_store(self, existing_index): - """ - The fixture provides an instance of a slightly customized - OpenSearchDocumentStore equipped with a mocked client - """ - - class DSMock(OpenSearchDocumentStore): - # We mock a subclass to avoid messing up the actual class object - pass - - opensearch_mock = MagicMock() - opensearch_mock.indices.exists.return_value = True - opensearch_mock.indices.get.return_value = {self.index_name: existing_index} - opensearch_mock.info.return_value = {"version": {"number": "1.3.5"}} - DSMock._init_client = MagicMock() - DSMock._init_client.configure_mock(return_value=opensearch_mock) - dsMock = DSMock() - return dsMock - - @pytest.fixture - def mocked_open_search_init(self, monkeypatch): - mocked_init = MagicMock(return_value=None) - monkeypatch.setattr(OpenSearch, "__init__", mocked_init) - return mocked_init - - @pytest.fixture - def _init_client_params(self): - """ - The fixture provides the required arguments to call OpenSearchDocumentStore._init_client - """ - return { - "host": "localhost", - "port": 9999, - "username": "user", - "password": "pass", - "aws4auth": None, - "scheme": "http", - "ca_certs": "ca_certs", - "verify_certs": True, - "timeout": 42, - "use_system_proxy": True, - } - - @pytest.fixture - def existing_index(self): - return { - "aliases": {}, - "mappings": { - "properties": { - "content": {"type": "text"}, - "embedding": { - "type": "knn_vector", - "dimension": 768, - "method": { - "engine": "nmslib", - "space_type": "innerproduct", - "name": "hnsw", - "parameters": {"ef_construction": 512, "m": 16}, - }, - }, - } - }, - "settings": { - "index": { - "creation_date": "1658337984559", - "number_of_shards": "1", - "number_of_replicas": "1", - "uuid": "jU5KPBtXQHOaIn2Cm2d4jg", - "version": {"created": "135238227"}, - "provided_name": "existing_index", - } - }, - } - - # Integration tests - - @pytest.mark.integration - def test___init__(self): - OpenSearchDocumentStore(index="nmslib_index", create_index=True) - - @pytest.mark.integration - @pytest.mark.parametrize("index_type", ["flat", "hnsw", "ivf", "ivf_pq"]) - def test___init___faiss(self, index_type): - OpenSearchDocumentStore( - index=f"faiss_index_{index_type}", recreate_index=True, knn_engine="faiss", index_type=index_type - ) - - @pytest.mark.integration - def test___init___score_script(self): - OpenSearchDocumentStore(index="score_script_index", create_index=True, knn_engine="score_script") - - @pytest.mark.integration - def test_recreate_index(self, ds, documents, labels): - ds.write_documents(documents) - ds.write_labels(labels) - - # Create another document store on top of the previous one - ds = OpenSearchDocumentStore(index=ds.index, label_index=ds.label_index, recreate_index=True) - assert len(ds.get_all_documents(index=ds.index)) == 0 - assert len(ds.get_all_labels(index=ds.label_index)) == 0 - - @pytest.mark.integration - def test_clone_embedding_field(self, ds, documents): - cloned_field_name = "cloned" - ds.write_documents(documents) - ds.clone_embedding_field(cloned_field_name, "cosine") - for doc in ds.get_all_documents(): - meta = doc.to_dict()["meta"] - if "no_embedding" in meta: - # docs with no embedding should be ignored - assert cloned_field_name not in meta - else: - # docs with an original embedding should have the new one - assert cloned_field_name in meta - - @pytest.mark.integration - @pytest.mark.parametrize("knn_engine", ["nmslib", "faiss", "score_script"]) - def test_query_embedding_with_filters(self, ds: OpenSearchDocumentStore, documents, knn_engine): - # Create another document store on top of the previous one - ds = OpenSearchDocumentStore( - index=ds.index, label_index=ds.label_index, recreate_index=True, knn_engine=knn_engine - ) - ds.write_documents(documents) - results = ds.query_by_embedding( - query_emb=np.random.rand(768).astype(np.float32), filters={"year": "2020"}, top_k=10 - ) - assert len(results) == 3 - - @pytest.mark.integration - @pytest.mark.parametrize("use_ann", [True, False]) - def test_query_embedding_batch_with_filters(self, ds: OpenSearchDocumentStore, documents, use_ann): - ds.embeddings_field_supports_similarity = use_ann - ds.write_documents(documents) - results = ds.query_by_embedding_batch( - query_embs=[np.random.rand(768).astype(np.float32) for _ in range(2)], - filters=[{"year": "2020"} for _ in range(2)], - top_k=10, - ) - assert len(results) == 2 - for result in results: - assert len(result) == 3 - - @pytest.mark.integration - @pytest.mark.parametrize("index_type", ["ivf", "ivf_pq"]) - def test_train_index_from_documents(self, ds: OpenSearchDocumentStore, documents, index_type): - # Create another document store on top of the previous one - ds = OpenSearchDocumentStore( - index=ds.index, - label_index=ds.label_index, - recreate_index=True, - knn_engine="faiss", - index_type=index_type, - knn_parameters={"code_size": 2}, - ) - - # Check that IVF indices use score_script before training - emb_field_settings = ds.client.indices.get(ds.index)[ds.index]["mappings"]["properties"][ds.embedding_field] - assert emb_field_settings == {"type": "knn_vector", "dimension": 768} - - ds.train_index(documents) - # Check that embedding_field_settings have been updated - emb_field_settings = ds.client.indices.get(ds.index)[ds.index]["mappings"]["properties"][ds.embedding_field] - assert emb_field_settings == {"type": "knn_vector", "model_id": f"{ds.index}-ivf"} - - # Check that model uses expected parameters - expected_model_settigns = {"index_type": index_type, "nlist": 4, "nprobes": 1} - if index_type == "ivf_pq": - expected_model_settigns["code_size"] = 2 - expected_model_settigns["m"] = 1 - model_endpoint = f"/_plugins/_knn/models/{ds.index}-ivf" - response = ds.client.transport.perform_request("GET", url=model_endpoint) - model_settings_list = [setting.split(":") for setting in response["description"].split()] - model_settings = {k: (int(v) if v.isnumeric() else v) for k, v in model_settings_list} - assert model_settings == expected_model_settigns - - @pytest.mark.integration - @pytest.mark.parametrize("index_type", ["ivf", "ivf_pq"]) - def test_train_index_from_embeddings(self, ds: OpenSearchDocumentStore, documents, index_type): - # Create another document store on top of the previous one - ds = OpenSearchDocumentStore( - index=ds.index, - label_index=ds.label_index, - recreate_index=True, - knn_engine="faiss", - index_type=index_type, - knn_parameters={"code_size": 2}, - ) - - # Check that IVF indices use HNSW with default settings before training - emb_field_settings = ds.client.indices.get(ds.index)[ds.index]["mappings"]["properties"][ds.embedding_field] - assert emb_field_settings == {"type": "knn_vector", "dimension": 768} - - embeddings = np.array([doc.embedding for doc in documents if doc.embedding is not None]) - ds.train_index(embeddings=embeddings) - # Check that embedding_field_settings have been updated - emb_field_settings = ds.client.indices.get(ds.index)[ds.index]["mappings"]["properties"][ds.embedding_field] - assert emb_field_settings == {"type": "knn_vector", "model_id": f"{ds.index}-ivf"} - - # Check that model uses expected parameters - expected_model_settigns = {"index_type": index_type, "nlist": 4, "nprobes": 1} - if index_type == "ivf_pq": - expected_model_settigns["code_size"] = 2 - expected_model_settigns["m"] = 1 - model_endpoint = f"/_plugins/_knn/models/{ds.index}-ivf" - response = ds.client.transport.perform_request("GET", url=model_endpoint) - model_settings_list = [setting.split(":") for setting in response["description"].split()] - model_settings = {k: (int(v) if v.isnumeric() else v) for k, v in model_settings_list} - assert model_settings == expected_model_settigns - - @pytest.mark.integration - @pytest.mark.parametrize("index_type", ["ivf", "ivf_pq"]) - def test_train_index_with_write_documents(self, ds: OpenSearchDocumentStore, documents, index_type): - # Create another document store on top of the previous one - ds = OpenSearchDocumentStore( - index=ds.index, - label_index=ds.label_index, - recreate_index=True, - knn_engine="faiss", - index_type=index_type, - knn_parameters={"code_size": 2}, - ivf_train_size=6, - ) - - # Check that IVF indices use HNSW with default settings before training - emb_field_settings = ds.client.indices.get(ds.index)[ds.index]["mappings"]["properties"][ds.embedding_field] - assert emb_field_settings == {"type": "knn_vector", "dimension": 768} - - ds.write_documents(documents) - # Check that embedding_field_settings have been updated - emb_field_settings = ds.client.indices.get(ds.index)[ds.index]["mappings"]["properties"][ds.embedding_field] - assert emb_field_settings == {"type": "knn_vector", "model_id": f"{ds.index}-ivf"} - - # Check that model uses expected parameters - expected_model_settigns = {"index_type": index_type, "nlist": 4, "nprobes": 1} - if index_type == "ivf_pq": - expected_model_settigns["code_size"] = 2 - expected_model_settigns["m"] = 1 - model_endpoint = f"/_plugins/_knn/models/{ds.index}-ivf" - response = ds.client.transport.perform_request("GET", url=model_endpoint) - model_settings_list = [setting.split(":") for setting in response["description"].split()] - model_settings = {k: (int(v) if v.isnumeric() else v) for k, v in model_settings_list} - assert model_settings == expected_model_settigns - - # Unit tests - - @pytest.mark.unit - def test___init___api_key_raises_warning(self, mocked_document_store, caplog): - with caplog.at_level(logging.WARN, logger="haystack.document_stores.opensearch"): - mocked_document_store.__init__(api_key="foo") - mocked_document_store.__init__(api_key_id="bar") - mocked_document_store.__init__(api_key="foo", api_key_id="bar") - - assert len(caplog.records) == 3 - for r in caplog.records: - assert r.levelname == "WARNING" - - @pytest.mark.unit - def test__init_client_aws4auth_and_username_raises_warning(self, mocked_open_search_init, caplog): - _init_client_remaining_kwargs = { - "host": "host", - "port": 443, - "password": "pass", - "scheme": "https", - "ca_certs": None, - "verify_certs": True, - "timeout": 10, - "use_system_proxy": False, - } - - with caplog.at_level(logging.WARN, logger="haystack.document_stores.opensearch"): - OpenSearchDocumentStore._init_client(username="admin", aws4auth="foo", **_init_client_remaining_kwargs) - OpenSearchDocumentStore._init_client(username="bar", aws4auth="foo", **_init_client_remaining_kwargs) - assert len(caplog.records) == 2 - for r in caplog.records: - assert r.levelname == "WARNING" - - caplog.clear() - with caplog.at_level(logging.WARN, logger="haystack.document_stores.opensearch"): - OpenSearchDocumentStore._init_client(username=None, aws4auth="foo", **_init_client_remaining_kwargs) - OpenSearchDocumentStore._init_client(username="foo", aws4auth=None, **_init_client_remaining_kwargs) - assert len(caplog.records) == 0 - - @pytest.mark.unit - def test___init___connection_test_fails(self, mocked_document_store): - failing_client = MagicMock() - failing_client.indices.get.side_effect = Exception("The client failed!") - mocked_document_store._init_client.return_value = failing_client - with pytest.raises(ConnectionError): - mocked_document_store.__init__() - - @pytest.mark.unit - def test___init___client_params(self, mocked_open_search_init, _init_client_params): - """ - Ensure the Opensearch-py client was initialized with the right params - """ - OpenSearchDocumentStore._init_client(**_init_client_params) - assert mocked_open_search_init.called - _, kwargs = mocked_open_search_init.call_args - assert kwargs == { - "hosts": [{"host": "localhost", "port": 9999}], - "http_auth": ("user", "pass"), - "scheme": "http", - "ca_certs": "ca_certs", - "verify_certs": True, - "timeout": 42, - "connection_class": RequestsHttpConnection, - } - - @pytest.mark.unit - def test__init_client_use_system_proxy_use_sys_proxy(self, mocked_open_search_init, _init_client_params): - _init_client_params["use_system_proxy"] = False - OpenSearchDocumentStore._init_client(**_init_client_params) - _, kwargs = mocked_open_search_init.call_args - assert kwargs["connection_class"] == Urllib3HttpConnection - - @pytest.mark.unit - def test__init_client_use_system_proxy_dont_use_sys_proxy(self, mocked_open_search_init, _init_client_params): - _init_client_params["use_system_proxy"] = True - OpenSearchDocumentStore._init_client(**_init_client_params) - _, kwargs = mocked_open_search_init.call_args - assert kwargs["connection_class"] == RequestsHttpConnection - - @pytest.mark.unit - def test__init_client_auth_methods_username_password(self, mocked_open_search_init, _init_client_params): - _init_client_params["username"] = "user" - _init_client_params["aws4auth"] = None - OpenSearchDocumentStore._init_client(**_init_client_params) - _, kwargs = mocked_open_search_init.call_args - assert kwargs["http_auth"] == ("user", "pass") - - @pytest.mark.unit - def test__init_client_auth_methods_aws_iam(self, mocked_open_search_init, _init_client_params): - _init_client_params["username"] = "" - _init_client_params["aws4auth"] = "foo" - OpenSearchDocumentStore._init_client(**_init_client_params) - _, kwargs = mocked_open_search_init.call_args - assert kwargs["http_auth"] == "foo" - - @pytest.mark.unit - def test__init_client_auth_methods_no_auth(self, mocked_open_search_init, _init_client_params): - _init_client_params["username"] = "" - _init_client_params["aws4auth"] = None - OpenSearchDocumentStore._init_client(**_init_client_params) - _, kwargs = mocked_open_search_init.call_args - assert "http_auth" not in kwargs - - @pytest.mark.unit - def test_query(self, mocked_document_store): - mocked_document_store.query(query=self.query) - kwargs = mocked_document_store.client.search.call_args.kwargs - assert "index" in kwargs - assert "body" in kwargs - assert "headers" in kwargs - - @pytest.mark.unit - def test_query_return_embedding_false(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["body"]["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_true(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.excluded_meta_data = ["foo", "embedding"] - mocked_document_store.query(self.query) - _, kwargs = mocked_document_store.client.search.call_args - # we expect "embedding" was removed from the final query - assert kwargs["body"]["_source"] == {"excludes": ["foo"]} - - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_false(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["body"]["_source"] == {"excludes": ["foo", "embedding"]} - - @pytest.mark.unit - def test_query_by_embedding_raises_if_missing_field(self, mocked_document_store): - mocked_document_store.embedding_field = "" - with pytest.raises(DocumentStoreError): - mocked_document_store.query_by_embedding(self.query_emb) - - @pytest.mark.unit - def test_query_by_embedding_raises_if_ivf_untrained(self, mocked_document_store): - mocked_document_store.index_type = "ivf" - mocked_document_store.ivf_train_size = 10 - with pytest.raises(DocumentStoreError, match="Index of type 'ivf' is not trained yet."): - mocked_document_store.query_by_embedding(self.query_emb) - - @pytest.mark.unit - def test_query_by_embedding_batch_if_ivf_untrained(self, mocked_document_store): - mocked_document_store.index_type = "ivf" - mocked_document_store.ivf_train_size = 10 - with pytest.raises(DocumentStoreError, match="Index of type 'ivf' is not trained yet."): - mocked_document_store.query_by_embedding_batch([self.query_emb]) - - @pytest.mark.unit - def test_query_by_embedding_filters(self, mocked_document_store): - assert mocked_document_store.knn_engine != "score_script" - expected_filters = {"type": "article", "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}} - mocked_document_store.query_by_embedding(self.query_emb, filters=expected_filters) - # Assert the `search` method on the client was called with the filters we provided - _, kwargs = mocked_document_store.client.search.call_args - actual_filters = kwargs["body"]["query"]["bool"]["filter"] - assert actual_filters["bool"]["must"] == [ - {"term": {"type": "article"}}, - {"range": {"date": {"gte": "2015-01-01", "lt": "2021-01-01"}}}, - ] - - @pytest.mark.unit - def test_query_by_embedding_script_score_filters(self, mocked_document_store): - mocked_document_store.knn_engine = "score_script" - expected_filters = {"type": "article", "date": {"$gte": "2015-01-01", "$lt": "2021-01-01"}} - mocked_document_store.query_by_embedding(self.query_emb, filters=expected_filters) - # Assert the `search` method on the client was called with the filters we provided - _, kwargs = mocked_document_store.client.search.call_args - actual_filters = kwargs["body"]["query"]["script_score"]["query"]["bool"]["filter"] - assert actual_filters["bool"]["must"] == [ - {"term": {"type": "article"}}, - {"range": {"date": {"gte": "2015-01-01", "lt": "2021-01-01"}}}, - ] - - @pytest.mark.unit - def test_query_by_embedding_return_embedding_false(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.query_by_embedding(self.query_emb) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["body"]["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_query_by_embedding_excluded_meta_data_return_embedding_true(self, mocked_document_store): - """ - Test that when `return_embedding==True` the field should NOT be excluded even if it - was added to `excluded_meta_data` - """ - mocked_document_store.return_embedding = True - mocked_document_store.excluded_meta_data = ["foo", "embedding"] - mocked_document_store.query_by_embedding(self.query_emb) - _, kwargs = mocked_document_store.client.search.call_args - # we expect "embedding" was removed from the final query - assert kwargs["body"]["_source"] == {"excludes": ["foo"]} - - @pytest.mark.unit - def test_query_by_embedding_excluded_meta_data_return_embedding_false(self, mocked_document_store): - """ - Test that when `return_embedding==False`, the final query excludes the `embedding` field - even if it wasn't explicitly added to `excluded_meta_data` - """ - mocked_document_store.return_embedding = False - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.query_by_embedding(self.query_emb) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["body"]["_source"] == {"excludes": ["foo", "embedding"]} - - @pytest.mark.unit - def test_query_by_embedding_batch_uses_msearch(self, mocked_document_store): - mocked_document_store.query_by_embedding_batch([self.query_emb for _ in range(10)]) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.msearch.call_args - assert len(kwargs["body"]) == 20 # each search has headers and request - - @pytest.mark.unit - def test__init_indices_with_alias(self, mocked_document_store, caplog): - mocked_document_store.client.indices.exists_alias.return_value = True - - with caplog.at_level(logging.DEBUG, logger="haystack.document_stores.search_engine"): - mocked_document_store._init_indices(self.index_name, "labels", False, False) - - assert f"Index name {self.index_name} is an alias." in caplog.text - - @pytest.mark.unit - def test__validate_and_adjust_document_index_wrong_mapping_raises(self, mocked_document_store, existing_index): - """ - Ensure the method raises if we specify a field in `search_fields` that's not text - """ - existing_index["mappings"]["properties"]["age"] = {"type": "integer"} - mocked_document_store.search_fields = ["age"] - with pytest.raises( - DocumentStoreError, - match=f"The index '{self.index_name}' needs the 'text' type for the search_field 'age' to run full text search, but got type 'integer'.", - ): - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_create_embedding_mapping_if_missing(self, mocked_document_store): - mocked_document_store.embedding_field = "doesnt_have_a_mapping" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - # Assert the expected body was passed to the client - _, kwargs = mocked_document_store.client.indices.put_mapping.call_args - assert kwargs["index"] == self.index_name - assert kwargs["body"]["properties"]["doesnt_have_a_mapping"]["type"] == "knn_vector" - - @pytest.mark.unit - def test__validate_and_adjust_document_index_create_search_field_mapping_if_missing(self, mocked_document_store): - mocked_document_store.search_fields = ["doesnt_have_a_mapping"] - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - # Assert the expected body was passed to the client - _, kwargs = mocked_document_store.client.indices.put_mapping.call_args - assert kwargs["index"] == self.index_name - assert kwargs["body"]["properties"]["doesnt_have_a_mapping"]["type"] == "text" - - @pytest.mark.unit - def test__validate_and_adjust_document_index_with_bad_field_raises(self, mocked_document_store, existing_index): - existing_index["mappings"]["properties"]["age"] = {"type": "integer"} - mocked_document_store.embedding_field = "age" - with pytest.raises( - DocumentStoreError, - match=f"The index '{self.index_name}' needs the 'knn_vector' type for the embedding_field 'age' to run vector search, but got type 'integer'.", - ): - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_but_no_method(self, mocked_document_store, existing_index): - """ - We call the method passing a properly mapped field but without the `method` specified in the mapping - """ - del existing_index["mappings"]["properties"]["embedding"]["method"] - - assert mocked_document_store.space_type == "innerproduct" - with pytest.raises( - DocumentStoreError, - match=rf"Set `similarity` to one of '\['l2'\]' to properly use the embedding field 'embedding' of index '{self.index_name}'. Similarity 'dot_product' is not compatible with embedding field's space type 'l2', it requires 'innerproduct'.", - ): - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - # l2 is default for space_type so it must pass - mocked_document_store.space_type = "l2" - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_similarity(self, mocked_document_store): - mocked_document_store.space_type = "innerproduct" - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_similarity_mismatch(self, mocked_document_store): - mocked_document_store.space_type = "cosinesimil" - - with pytest.raises( - DocumentStoreError, - match=rf"Set `similarity` to one of '\['dot_product'\]' to properly use the embedding field 'embedding' of index '{self.index_name}'. Similarity 'dot_product' is not compatible with embedding field's space type 'innerproduct', it requires 'cosinesimil'.", - ): - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_type_mismatch(self, mocked_document_store): - mocked_document_store.index_type = "hnsw" - - with pytest.raises( - DocumentStoreError, - match=f"The index_type 'hnsw' needs '80' as ef_construction value. Currently, the value for embedding field 'embedding' of index '{self.index_name}' is '512'.", - ): - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_change_knn_engine_to_faiss(self, mocked_document_store): - mocked_document_store.knn_engine = "faiss" - with pytest.raises( - DocumentStoreError, - match=f"Existing embedding field '{mocked_document_store.embedding_field}' of OpenSearch index '{self.index_name}' has knn_engine 'nmslib', but knn_engine was set to 'faiss'.", - ): - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_change_knn_engine_to_score_script(self, mocked_document_store): - mocked_document_store.knn_engine = "score_script" - mocked_document_store.space_type = "cosinesimil" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - @pytest.mark.unit - def test__validate_and_adjust_document_index_adjusts_ef_search_for_hnsw_when_default( - self, mocked_document_store, existing_index - ): - """ - Test adjustment when `knn.algo_param` is missing from the index settings - """ - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["ef_construction"] = 80 - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["m"] = 64 - mocked_document_store.index_type = "hnsw" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - # assert the resulting body contains the adjusted params - _, kwargs = mocked_document_store.client.indices.put_settings.call_args - assert kwargs["body"] == {"knn.algo_param.ef_search": 20} - - @pytest.mark.unit - def test__validate_and_adjust_document_index_adjusts_ef_search_for_hnsw_when_set_different( - self, mocked_document_store, existing_index - ): - """ - Test a value of `knn.algo_param` that needs to be adjusted - """ - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["ef_construction"] = 80 - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["m"] = 64 - existing_index["settings"]["index"]["knn.algo_param"] = {"ef_search": 999} - mocked_document_store.index_type = "hnsw" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - # assert the resulting body is contains the adjusted params - _, kwargs = mocked_document_store.client.indices.put_settings.call_args - assert kwargs["body"] == {"knn.algo_param.ef_search": 20} - - @pytest.mark.unit - def test__validate_and_adjust_document_index_ignores_index_setting_ef_search_for_faiss( - self, mocked_document_store, existing_index - ): - mocked_document_store.knn_engine = "faiss" - existing_index["mappings"]["properties"]["embedding"]["method"]["engine"] = "faiss" - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["ef_construction"] = 512 - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["m"] = 16 - existing_index["settings"]["index"]["knn.algo_param"] = {"ef_search": 999} - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - mocked_document_store.client.indices.put_settings.assert_not_called() - - @pytest.mark.unit - def test__validate_and_adjust_document_index_ignores_parameter_ef_search_for_nmslib( - self, mocked_document_store, existing_index - ): - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["ef_construction"] = 512 - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["m"] = 16 - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["ef_search"] = 999 - existing_index["settings"]["index"]["knn.algo_param"] = {"ef_search": 512} - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - mocked_document_store.client.indices.put_settings.assert_not_called() - - @pytest.mark.unit - def test__validate_and_adjust_document_index_does_not_adjust_ef_search_for_hnsw_when_set_correct( - self, mocked_document_store, existing_index - ): - """ - If params are already set correctly, we should not adjust them. - """ - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["ef_construction"] = 80 - existing_index["mappings"]["properties"]["embedding"]["method"]["parameters"]["m"] = 64 - existing_index["settings"]["index"]["knn.algo_param"] = {"ef_search": 20} - mocked_document_store.index_type = "hnsw" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - mocked_document_store.client.indices.put_settings.assert_not_called() - - @pytest.mark.unit - def test__validate_and_adjust_document_index_adjusts_ef_search_for_flat_when_set_different( - self, mocked_document_store, existing_index - ): - """ - Test a value of `knn.algo_param` that needs to be adjusted - """ - existing_index["settings"]["index"]["knn.algo_param"] = {"ef_search": 999} - mocked_document_store.index_type = "flat" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - - # assert the resulting body is contains the adjusted params - _, kwargs = mocked_document_store.client.indices.put_settings.call_args - assert kwargs["body"] == {"knn.algo_param.ef_search": 512} - - @pytest.mark.unit - def test__validate_and_adjust_document_index_does_not_adjust_ef_search_for_flat_when_default( - self, mocked_document_store - ): - """ - If `knn.algo_param` is missing, default value needs no adjustments - """ - mocked_document_store.index_type = "flat" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - mocked_document_store.client.indices.put_settings.assert_not_called() - - @pytest.mark.unit - def test__validate_and_adjust_document_index_does_not_adjust_ef_search_for_flat_when_set_correct( - self, mocked_document_store, existing_index - ): - """ - If `knn.algo_param` is correct, value needs no adjustments - """ - existing_index["settings"]["index"]["knn.algo_param"] = {"ef_search": 512} - mocked_document_store.index_type = "flat" - - mocked_document_store._validate_and_adjust_document_index(self.index_name) - mocked_document_store.client.indices.put_settings.assert_not_called() - - @pytest.mark.unit - def test__validate_and_adjust_document_index_with_non_existing_index(self, mocked_document_store, caplog): - mocked_document_store.client.indices.get.return_value = {} - with caplog.at_level(logging.WARNING): - mocked_document_store._validate_and_adjust_document_index(self.index_name) - assert f"The index '{self.index_name}' doesn't exist. " in caplog.text - - @pytest.mark.unit - @pytest.mark.parametrize("create_index", [True, False]) - @pytest.mark.parametrize("recreate_index", [True, False]) - def test__init_indices_always_calls_validation_if_no_custom_mapping( - self, mocked_document_store, create_index, recreate_index - ): - mocked_document_store._validate_and_adjust_document_index = MagicMock() - mocked_document_store._init_indices(self.index_name, "label_index", create_index, recreate_index) - - mocked_document_store._validate_and_adjust_document_index.assert_called_once() - - @pytest.mark.unit - @pytest.mark.parametrize("create_index", [True, False]) - @pytest.mark.parametrize("recreate_index", [True, False]) - def test__init_indices_never_calls_validation_if_custom_mapping( - self, mocked_document_store, create_index, recreate_index, caplog - ): - mocked_document_store.custom_mapping = { - "mappings": {"properties": {"embedding": {"type": "dense_vector", "dims": 768}}} - } - mocked_document_store._validate_and_adjust_document_index = MagicMock() - - with caplog.at_level(logging.WARNING): - mocked_document_store._init_indices(self.index_name, "label_index", create_index, recreate_index) - assert "Skipping index validation" in caplog.text - mocked_document_store._validate_and_adjust_document_index.assert_not_called() - - @pytest.mark.unit - def test__init_indices_creates_index_if_not_exists(self, mocked_document_store): - mocked_document_store.client.indices.exists.return_value = False - mocked_document_store._init_indices(self.index_name, "label_index", create_index=True, recreate_index=False) - - mocked_document_store.client.indices.create.assert_called() - - @pytest.mark.unit - def test__init_indices_does_not_create_index_if_exists(self, mocked_document_store): - mocked_document_store._init_indices(self.index_name, "label_index", create_index=True, recreate_index=False) - - mocked_document_store.client.indices.create.assert_not_called() - - @pytest.mark.unit - def test__init_indices_does_not_create_index_if_not_create_index(self, mocked_document_store): - mocked_document_store.client.indices.exists.return_value = False - mocked_document_store._init_indices(self.index_name, "label_index", create_index=False, recreate_index=False) - - mocked_document_store.client.indices.create.assert_not_called() - - @pytest.mark.unit - def test__init_indices_creates_index_if_exists_and_recreate_index(self, mocked_document_store): - # delete_index asks four times: one check for doc index, one check for label index - # + one check for both if ivf model exists - # create_index asks two times: one for doc index, one for label index - mocked_document_store.client.indices.exists.side_effect = [True, False, True, False, False, False] - mocked_document_store._init_indices(self.index_name, "label_index", create_index=True, recreate_index=True) - - mocked_document_store.client.indices.delete.assert_called() - mocked_document_store.client.indices.create.assert_called() - - @pytest.mark.unit - def test__create_document_index_no_index_custom_mapping(self, mocked_document_store): - mocked_document_store.custom_mapping = {"mappings": {"properties": {"a_number": {"type": "integer"}}}} - - mocked_document_store._create_document_index(self.index_name) - _, kwargs = mocked_document_store.client.indices.create.call_args - assert kwargs["body"] == {"mappings": {"properties": {"a_number": {"type": "integer"}}}} - assert mocked_document_store.knn_engine == "nmslib" - assert mocked_document_store.space_type == "innerproduct" - - @pytest.mark.unit - def test__create_document_index_no_index_no_mapping(self, mocked_document_store): - mocked_document_store._create_document_index(self.index_name) - _, kwargs = mocked_document_store.client.indices.create.call_args - assert kwargs["body"] == { - "mappings": { - "dynamic_templates": [ - {"strings": {"mapping": {"type": "keyword"}, "match_mapping_type": "string", "path_match": "*"}} - ], - "properties": { - "content": {"type": "text"}, - "embedding": { - "dimension": 768, - "method": { - "engine": "nmslib", - "name": "hnsw", - "parameters": {"ef_construction": 512, "m": 16}, - "space_type": "innerproduct", - }, - "type": "knn_vector", - }, - "name": {"type": "keyword"}, - }, - }, - "settings": {"analysis": {"analyzer": {"default": {"type": "standard"}}}, "index": {"knn": True}}, - } - assert mocked_document_store.knn_engine == "nmslib" - assert mocked_document_store.space_type == "innerproduct" - - @pytest.mark.unit - def test__create_document_index_no_index_no_mapping_with_synonyms(self, mocked_document_store): - mocked_document_store.search_fields = ["occupation"] - mocked_document_store.synonyms = ["foo"] - - mocked_document_store._create_document_index(self.index_name) - _, kwargs = mocked_document_store.client.indices.create.call_args - assert kwargs["body"] == { - "mappings": { - "properties": { - "name": {"type": "keyword"}, - "content": {"type": "text", "analyzer": "synonym"}, - "occupation": {"type": "text", "analyzer": "synonym"}, - "embedding": { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "innerproduct", - "name": "hnsw", - "engine": "nmslib", - "parameters": {"ef_construction": 512, "m": 16}, - }, - }, - }, - "dynamic_templates": [ - {"strings": {"path_match": "*", "match_mapping_type": "string", "mapping": {"type": "keyword"}}} - ], - }, - "settings": { - "analysis": { - "analyzer": { - "default": {"type": "standard"}, - "synonym": {"tokenizer": "whitespace", "filter": ["lowercase", "synonym"]}, - }, - "filter": {"synonym": {"type": "synonym", "synonyms": ["foo"]}}, - }, - "index": {"knn": True}, - }, - } - assert mocked_document_store.knn_engine == "nmslib" - assert mocked_document_store.space_type == "innerproduct" - - @pytest.mark.unit - def test__create_document_index_no_index_no_mapping_with_embedding_field(self, mocked_document_store): - mocked_document_store.embedding_field = "vec" - mocked_document_store.index_type = "hnsw" - - mocked_document_store._create_document_index(self.index_name) - _, kwargs = mocked_document_store.client.indices.create.call_args - assert kwargs["body"] == { - "mappings": { - "properties": { - "name": {"type": "keyword"}, - "content": {"type": "text"}, - "vec": { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "innerproduct", - "name": "hnsw", - "engine": "nmslib", - "parameters": {"ef_construction": 80, "m": 64}, - }, - }, - }, - "dynamic_templates": [ - {"strings": {"path_match": "*", "match_mapping_type": "string", "mapping": {"type": "keyword"}}} - ], - }, - "settings": { - "analysis": {"analyzer": {"default": {"type": "standard"}}}, - "index": {"knn": True, "knn.algo_param.ef_search": 20}, - }, - } - assert mocked_document_store.knn_engine == "nmslib" - assert mocked_document_store.space_type == "innerproduct" - - @pytest.mark.unit - def test__create_document_index_no_index_no_mapping_faiss(self, mocked_document_store): - mocked_document_store.knn_engine = "faiss" - mocked_document_store._create_document_index(self.index_name) - _, kwargs = mocked_document_store.client.indices.create.call_args - assert kwargs["body"] == { - "mappings": { - "dynamic_templates": [ - {"strings": {"mapping": {"type": "keyword"}, "match_mapping_type": "string", "path_match": "*"}} - ], - "properties": { - "content": {"type": "text"}, - "embedding": { - "dimension": 768, - "method": { - "engine": "faiss", - "name": "hnsw", - "parameters": {"ef_construction": 512, "m": 16}, - "space_type": "innerproduct", - }, - "type": "knn_vector", - }, - "name": {"type": "keyword"}, - }, - }, - "settings": {"analysis": {"analyzer": {"default": {"type": "standard"}}}, "index": {"knn": True}}, - } - - @pytest.mark.unit - def test__create_document_index_client_failure(self, mocked_document_store): - mocked_document_store.client.indices.exists.return_value = False - mocked_document_store.client.indices.create.side_effect = RequestError - - with pytest.raises(RequestError): - mocked_document_store._create_document_index(self.index_name) - - @pytest.mark.unit - def test__get_embedding_field_mapping_flat(self, mocked_document_store): - mocked_document_store.index_type = "flat" - - assert mocked_document_store._get_embedding_field_mapping() == { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "innerproduct", - "name": "hnsw", - "engine": "nmslib", - "parameters": {"ef_construction": 512, "m": 16}, - }, - } - - @pytest.mark.unit - def test__get_embedding_field_mapping_default_hnsw(self, mocked_document_store): - mocked_document_store.index_type = "hnsw" - - assert mocked_document_store._get_embedding_field_mapping() == { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "innerproduct", - "name": "hnsw", - "engine": "nmslib", - "parameters": {"ef_construction": 80, "m": 64}, - }, - } - - @pytest.mark.unit - def test__get_embedding_field_mapping_default_hnsw_faiss(self, mocked_document_store): - mocked_document_store.index_type = "hnsw" - mocked_document_store.knn_engine = "faiss" - - assert mocked_document_store._get_embedding_field_mapping() == { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "innerproduct", - "name": "hnsw", - "engine": "faiss", - "parameters": {"ef_construction": 80, "m": 64, "ef_search": 20}, - }, - } - - @pytest.mark.unit - def test__get_embedding_field_mapping_custom_hnsw(self, mocked_document_store): - mocked_document_store.index_type = "hnsw" - mocked_document_store.knn_parameters = {"ef_construction": 1, "m": 2} - - assert mocked_document_store._get_embedding_field_mapping() == { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "innerproduct", - "engine": "nmslib", - "name": "hnsw", - "parameters": {"ef_construction": 1, "m": 2}, - }, - } - - @pytest.mark.unit - def test__get_embedding_field_mapping_custom_hnsw_faiss(self, mocked_document_store): - mocked_document_store.index_type = "hnsw" - mocked_document_store.knn_engine = "faiss" - mocked_document_store.knn_parameters = {"ef_construction": 1, "m": 2, "ef_search": 3} - - assert mocked_document_store._get_embedding_field_mapping() == { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "innerproduct", - "engine": "faiss", - "name": "hnsw", - "parameters": {"ef_construction": 1, "m": 2, "ef_search": 3}, - }, - } - - @pytest.mark.unit - def test__get_embedding_field_mapping_ivf(self, mocked_document_store): - mocked_document_store.index_type = "ivf" - mocked_document_store.knn_engine = "faiss" - mocked_document_store.client.indices.exists.return_value = False - - # Before training, IVF indices use HNSW with default settings - assert mocked_document_store._get_embedding_field_mapping() == {"type": "knn_vector", "dimension": 768} - - # Assume we have trained the index - mocked_document_store.client.indices.exists.return_value = True - mocked_document_store.client.transport.perform_request.return_value = { - "took": 4, - "timed_out": False, - "_shards": {"total": 1, "successful": 1, "skipped": 0, "failed": 0}, - "hits": { - "total": {"value": 1, "relation": "eq"}, - "max_score": 1.0, - "hits": [ - { - "_index": ".opensearch-knn-models", - "_type": "_doc", - "_id": "document-ivf", - "_score": 1.0, - "_source": { - "model_blob": "", - "engine": "faiss", - "space_type": "innerproduct", - "description": "index_type:ivf nlist:4 nprobes:1", - "model_id": f"{mocked_document_store.index}-ivf", - "state": "created", - "error": "", - "dimension": 768, - "timestamp": "2023-01-25T16:04:21.284398Z", - }, - } - ], - }, - } - assert mocked_document_store._get_embedding_field_mapping() == { - "type": "knn_vector", - "model_id": f"{mocked_document_store.index}-ivf", - } - - @pytest.mark.unit - def test__get_embedding_field_mapping_ivfpq(self, mocked_document_store): - mocked_document_store.index_type = "ivf_pq" - mocked_document_store.knn_engine = "faiss" - mocked_document_store.client.indices.exists.return_value = False - - # Before training, IVF indices use HNSW with default settings - assert mocked_document_store._get_embedding_field_mapping() == {"type": "knn_vector", "dimension": 768} - - # Assume we have trained the index - mocked_document_store.client.indices.exists.return_value = True - mocked_document_store.client.transport.perform_request.return_value = { - "took": 4, - "timed_out": False, - "_shards": {"total": 1, "successful": 1, "skipped": 0, "failed": 0}, - "hits": { - "total": {"value": 1, "relation": "eq"}, - "max_score": 1.0, - "hits": [ - { - "_index": ".opensearch-knn-models", - "_type": "_doc", - "_id": "document-ivf", - "_score": 1.0, - "_source": { - "model_blob": "", - "engine": "faiss", - "space_type": "innerproduct", - "description": "index_type:ivf_pq nlist:4 nprobes:1 m:1 code_size:8", - "model_id": f"{mocked_document_store.index}-ivf", - "state": "created", - "error": "", - "dimension": 768, - "timestamp": "2023-01-25T16:04:21.284398Z", - }, - } - ], - }, - } - assert mocked_document_store._get_embedding_field_mapping() == { - "type": "knn_vector", - "model_id": f"{mocked_document_store.index}-ivf", - } - - @pytest.mark.unit - def test__get_embedding_field_mapping_wrong(self, mocked_document_store, caplog): - mocked_document_store.index_type = "foo" - - with caplog.at_level(logging.ERROR, logger="haystack.document_stores.opensearch"): - retval = mocked_document_store._get_embedding_field_mapping() - - assert "Set index_type to either 'flat', 'hnsw', 'ivf', or 'ivf_pq'" in caplog.text - assert retval == { - "type": "knn_vector", - "dimension": 768, - "method": {"space_type": "innerproduct", "name": "hnsw", "engine": "nmslib"}, - } - - @pytest.mark.unit - def test__create_label_index_already_exists(self, mocked_document_store): - mocked_document_store.client.indices.exists.return_value = True - - mocked_document_store._init_indices("doc_index", "label_index", True, False) - mocked_document_store.client.indices.create.assert_not_called() - - @pytest.mark.unit - def test__create_label_index_client_error(self, mocked_document_store): - mocked_document_store.client.indices.exists.return_value = False - mocked_document_store.client.indices.create.side_effect = RequestError - - with pytest.raises(RequestError): - mocked_document_store._create_label_index("foo") - - @pytest.mark.unit - def test__get_vector_similarity_query_support_true(self, mocked_document_store): - mocked_document_store.embedding_field = "FooField" - assert mocked_document_store.knn_engine != "score_script" - - assert mocked_document_store._get_vector_similarity_query(self.query_emb, 3) == { - "bool": {"must": [{"knn": {"FooField": {"vector": self.query_emb.tolist(), "k": 3}}}]} - } - - @pytest.mark.unit - def test__get_vector_similarity_query_support_false(self, mocked_document_store): - mocked_document_store.embedding_field = "FooField" - mocked_document_store.knn_engine = "score_script" - mocked_document_store.space_type = "innerproduct" - - assert mocked_document_store._get_vector_similarity_query(self.query_emb, 3) == { - "script_score": { - "query": {"match_all": {}}, - "script": { - "source": "knn_score", - "lang": "knn", - "params": { - "field": "FooField", - "query_value": self.query_emb.tolist(), - "space_type": "innerproduct", - }, - }, - } - } - - @pytest.mark.unit - def test__get_raw_similarity_score_dot(self, mocked_document_store): - mocked_document_store.similarity = "dot_product" - assert mocked_document_store._get_raw_similarity_score(2) == 1 - assert mocked_document_store._get_raw_similarity_score(-2) == 1.5 - - @pytest.mark.unit - def test__get_raw_similarity_score_l2(self, mocked_document_store): - mocked_document_store.similarity = "l2" - assert mocked_document_store._get_raw_similarity_score(1) == 0 - - @pytest.mark.unit - def test__get_raw_similarity_score_cosine(self, mocked_document_store): - mocked_document_store.space_type = "cosinesimil" - assert mocked_document_store.knn_engine != "score_script" - assert mocked_document_store._get_raw_similarity_score(1) == 1 - mocked_document_store.knn_engine = "score_script" - assert mocked_document_store._get_raw_similarity_score(1) == 0 - - @pytest.mark.unit - def test_clone_embedding_field_duplicate_mapping(self, mocked_document_store): - mocked_document_store.index = self.index_name - with pytest.raises(Exception, match="embedding already exists with mapping"): - mocked_document_store.clone_embedding_field("embedding", "cosine") - - @pytest.mark.unit - def test_clone_embedding_field_update_mapping(self, mocked_document_store, monkeypatch): - mocked_document_store.index = self.index_name - - # Mock away tqdm and the batch logic so we can test the mapping update alone - mocked_document_store._get_all_documents_in_index = MagicMock(return_value=[]) - monkeypatch.setattr(tqdm, "__new__", MagicMock()) - - mocked_document_store.clone_embedding_field("a_field", "cosine") - _, kwargs = mocked_document_store.client.indices.put_mapping.call_args - assert kwargs["body"]["properties"]["a_field"] == { - "type": "knn_vector", - "dimension": 768, - "method": { - "space_type": "cosinesimil", - "name": "hnsw", - "engine": "nmslib", - "parameters": {"ef_construction": 512, "m": 16}, - }, - } - - @pytest.mark.unit - def test_bulk_write_retries_for_always_failing_insert_is_canceled(self, mocked_document_store, monkeypatch, caplog): - docs_to_write = [ - {"meta": {"name": f"name_{i}"}, "content": f"text_{i}", "embedding": np.random.rand(768).astype(np.float32)} - for i in range(1000) - ] - - with patch("haystack.document_stores.opensearch.bulk") as mocked_bulk: - mocked_bulk.side_effect = opensearchpy.TransportError(429, "Too many requests") - - with pytest.raises(DocumentStoreError, match="Last try of bulk indexing documents failed."): - mocked_document_store._bulk(documents=docs_to_write, _timeout=0, _remaining_tries=3) - - assert mocked_bulk.call_count == 3 # depth first search fails and cancels the whole bulk request - - assert "Too Many Requests" in caplog.text - assert " Splitting the number of documents into two chunks with the same size" in caplog.text - - @pytest.mark.unit - def test_bulk_write_retries_with_backoff_with_smaller_batch_size_on_too_many_requests( - self, mocked_document_store, monkeypatch - ): - docs_to_write = [ - {"meta": {"name": f"name_{i}"}, "content": f"text_{i}", "embedding": np.random.rand(768).astype(np.float32)} - for i in range(1000) - ] - - with patch("haystack.document_stores.opensearch.bulk") as mocked_bulk: - # make bulk insert split documents and request retries s.t. - # 1k => 500 (failed) + 500 (successful) => 250 (successful) + 250 (successful) - # resulting in 5 calls in total - mocked_bulk.side_effect = [ - opensearchpy.TransportError(429, "Too many requests"), - opensearchpy.TransportError(429, "Too many requests"), - None, - None, - None, - ] - mocked_document_store._bulk(documents=docs_to_write, _timeout=0, _remaining_tries=3) - assert mocked_bulk.call_count == 5 - - @pytest.mark.unit - def test_get_document_by_id_return_embedding_false(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.get_document_by_id("123") - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["body"]["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_get_document_by_id_excluded_meta_data_has_no_influence(self, mocked_document_store): - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.return_embedding = False - mocked_document_store.get_document_by_id("123") - # assert the resulting body is not affected by the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["body"]["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_write_documents_req_for_each_batch(self, mocked_document_store, documents): - mocked_document_store.batch_size = 2 - with patch("haystack.document_stores.opensearch.bulk") as mocked_bulk: - mocked_document_store.write_documents(documents) - assert mocked_bulk.call_count == 5 diff --git a/test/document_stores/test_pinecone.py b/test/document_stores/test_pinecone.py deleted file mode 100644 index 6bacb9e48b..0000000000 --- a/test/document_stores/test_pinecone.py +++ /dev/null @@ -1,735 +0,0 @@ -import os -from inspect import getmembers, isclass, isfunction -from typing import Any, Dict, List, Union -from unittest.mock import MagicMock - -import numpy as np -import pytest - -from haystack.document_stores.pinecone import ( - DOCUMENT_WITH_EMBEDDING, - DOCUMENT_WITHOUT_EMBEDDING, - TYPE_METADATA_FIELD, - PineconeDocumentStore, - pinecone, -) -from haystack.errors import FilterError, PineconeDocumentStoreError -from haystack.schema import Document -from haystack.testing import DocumentStoreBaseTestAbstract - -from ..conftest import MockBaseRetriever -from ..mocks import pinecone as pinecone_mock - -# Set metadata fields used during testing for PineconeDocumentStore meta_config -META_FIELDS = ["meta_field", "name", "date", "numeric_field", "odd_document", "doc_type"] - - -class TestPineconeDocumentStore(DocumentStoreBaseTestAbstract): - # Fixtures - - @pytest.fixture - def ds(self, monkeypatch, request) -> PineconeDocumentStore: - """ - This fixture provides an empty document store and takes care of cleaning up after each test - """ - # If it's a unit test, mock Pinecone - if request.config.getoption("--mock-pinecone"): - for fname, function in getmembers(pinecone_mock, isfunction): - monkeypatch.setattr(f"pinecone.{fname}", function, raising=False) - for cname, class_ in getmembers(pinecone_mock, isclass): - monkeypatch.setattr(f"pinecone.{cname}", class_, raising=False) - - return PineconeDocumentStore( - api_key=os.environ.get("PINECONE_API_KEY") or "fake-pinecone-test-key", - embedding_dim=768, - embedding_field="embedding", - index="haystack_tests", - similarity="cosine", - recreate_index=True, - metadata_config={"indexed": META_FIELDS}, - ) - - @pytest.fixture - def doc_store_with_docs(self, ds: PineconeDocumentStore, documents: List[Document]) -> PineconeDocumentStore: - """ - This fixture provides a pre-populated document store and takes care of cleaning up after each test - """ - ds.write_documents(documents) - return ds - - @pytest.fixture - def mocked_ds(self): - class DSMock(PineconeDocumentStore): - pass - - pinecone.init = MagicMock() - pinecone.describe_index = MagicMock() - DSMock._create_index = MagicMock() - mocked_ds = DSMock(api_key="MOCK") - - return mocked_ds - - @pytest.fixture - def docs_all_formats(self) -> List[Union[Document, Dict[str, Any]]]: - return [ - # metafield at the top level for backward compatibility - { - "content": "My name is Paul and I live in New York", - "meta_field": "test-1", - "name": "file_1.txt", - "date": "2019-10-01", - "numeric_field": 5.0, - "odd_document": True, - "year": "2021", - "month": "02", - }, - # "dict" format - { - "content": "My name is Carla and I live in Berlin", - "meta": { - "meta_field": "test-2", - "name": "file_2.txt", - "date": "2020-03-01", - "numeric_field": 5.5, - "odd_document": False, - "year": "2021", - "month": "02", - }, - }, - # Document object - Document( - content="My name is Christelle and I live in Paris", - meta={ - "meta_field": "test-3", - "name": "file_3.txt", - "date": "2018-10-01", - "numeric_field": 4.5, - "odd_document": True, - "year": "2020", - "month": "02", - }, - ), - Document( - content="My name is Camila and I live in Madrid", - meta={ - "meta_field": "test-4", - "name": "file_4.txt", - "date": "2021-02-01", - "numeric_field": 3.0, - "odd_document": False, - "year": "2020", - }, - ), - Document( - content="My name is Matteo and I live in Rome", - meta={ - "meta_field": "test-5", - "name": "file_5.txt", - "date": "2019-01-01", - "numeric_field": 0.0, - "odd_document": True, - "year": "2020", - }, - ), - Document( - content="My name is Adele and I live in London", - meta={ - "meta_field": "test-5", - "name": "file_5.txt", - "date": "2019-01-01", - "numeric_field": 0.0, - "odd_document": True, - "year": "2021", - }, - ), - # Without meta - Document(content="My name is Ahmed and I live in Cairo"), - Document(content="My name is Bruce and I live in Gotham"), - Document(content="My name is Peter and I live in Quahog"), - ] - - @pytest.fixture - def documents(self, docs_all_formats: List[Union[Document, Dict[str, Any]]]) -> List[Document]: - return [Document.from_dict(doc) if isinstance(doc, dict) else doc for doc in docs_all_formats] - - # - # Tests - # - - @pytest.mark.integration - def test_doc_store_wrong_init(self): - """ - This is just a failure check case. - """ - try: - _ = PineconeDocumentStore( - api_key=os.environ.get("PINECONE_API_KEY") or "fake-pinecone-test-key", - embedding_dim=768, - pinecone_index="p_index", - embedding_field="embedding", - index="haystack_tests", - similarity="cosine", - metadata_config={"indexed": META_FIELDS}, - ) - assert False - except PineconeDocumentStoreError as pe: - assert "`pinecone_index` needs to be a `pinecone.Index` object" in pe.message - - @pytest.mark.integration - def test_ne_filters(self, ds, documents): - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$ne": "2020"}}) - assert len(result) == 3 - - @pytest.mark.integration - def test_get_label_count(self, ds, labels): - with pytest.raises(NotImplementedError): - ds.get_label_count() - - # NOTE: the PineconeDocumentStore behaves differently to the others when filters are applied. - # While this should be considered a bug, the relative tests are skipped in the meantime - - @pytest.mark.skip - @pytest.mark.integration - def test_compound_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nin_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_ne_filters(self, ds, documents): # noqa: F811 - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nin_filters(self, ds, documents): # noqa: F811 - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_comparison_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nested_condition_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nested_condition_not_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_delete_documents_by_id_with_filters(self, ds, documents): - pass - - # NOTE: labels metadata are not supported - - @pytest.mark.skip - @pytest.mark.integration - def test_delete_labels_by_filter(self, ds, labels): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_delete_labels_by_filter_id(self, ds, labels): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_simplified_filters(self, ds, documents): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_labels_with_long_texts(self): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel(self): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel_no_answer(self): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel_filter_aggregations(self): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel_meta_aggregations(self): - pass - - # NOTE: Pinecone does not support dates, so it can't do lte or gte on date fields. When a new release introduces this feature, - # the entire family of test_get_all_documents_extended_filter_* tests will become identical to the one present in the - # base document store suite, and can be removed from here. - - @pytest.mark.integration - def test_get_all_documents_extended_filter_eq(self, doc_store_with_docs: PineconeDocumentStore): - eq_docs = doc_store_with_docs.get_all_documents(filters={"meta_field": {"$eq": "test-1"}}) - normal_docs = doc_store_with_docs.get_all_documents(filters={"meta_field": "test-1"}) - assert eq_docs == normal_docs - - @pytest.mark.integration - def test_get_all_documents_extended_filter_in(self, doc_store_with_docs: PineconeDocumentStore): - in_docs = doc_store_with_docs.get_all_documents(filters={"meta_field": {"$in": ["test-1", "test-2", "n.a."]}}) - normal_docs = doc_store_with_docs.get_all_documents(filters={"meta_field": ["test-1", "test-2", "n.a."]}) - assert in_docs == normal_docs - - @pytest.mark.integration - def test_get_all_documents_extended_filter_ne(self, doc_store_with_docs: PineconeDocumentStore): - retrieved_docs = doc_store_with_docs.get_all_documents(filters={"meta_field": {"$ne": "test-1"}}) - assert all(d.meta.get("meta_field", None) != "test-1" for d in retrieved_docs) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_nin(self, doc_store_with_docs: PineconeDocumentStore): - retrieved_docs = doc_store_with_docs.get_all_documents( - filters={"meta_field": {"$nin": ["test-1", "test-2", "n.a."]}} - ) - assert {"test-1", "test-2"}.isdisjoint({d.meta.get("meta_field", None) for d in retrieved_docs}) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_gt(self, doc_store_with_docs: PineconeDocumentStore): - retrieved_docs = doc_store_with_docs.get_all_documents(filters={"numeric_field": {"$gt": 3.0}}) - assert all(d.meta["numeric_field"] > 3.0 for d in retrieved_docs) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_gte(self, doc_store_with_docs: PineconeDocumentStore): - retrieved_docs = doc_store_with_docs.get_all_documents(filters={"numeric_field": {"$gte": 3.0}}) - assert all(d.meta["numeric_field"] >= 3.0 for d in retrieved_docs) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_lt(self, doc_store_with_docs: PineconeDocumentStore): - retrieved_docs = doc_store_with_docs.get_all_documents(filters={"numeric_field": {"$lt": 3.0}}) - assert all(d.meta["numeric_field"] < 3.0 for d in retrieved_docs) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_lte(self, doc_store_with_docs: PineconeDocumentStore): - retrieved_docs = doc_store_with_docs.get_all_documents(filters={"numeric_field": {"$lte": 3.0}}) - assert all(d.meta["numeric_field"] <= 3.0 for d in retrieved_docs) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_dates(self, doc_store_with_docs: PineconeDocumentStore): - filters = {"date": {"$lte": "2020-12-31", "$gte": "2019-01-01"}} - - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_dates_and_other_field_explicit( - self, doc_store_with_docs: PineconeDocumentStore - ): - filters = { - "$and": { - "date": {"$lte": "2020-12-31", "$gte": "2019-01-01"}, - "name": {"$in": ["file_5.txt", "file_3.txt"]}, - } - } - - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_dates_and_other_field_simplified( - self, doc_store_with_docs: PineconeDocumentStore - ): - filters_simplified = { - "date": {"$lte": "2020-12-31", "$gte": "2019-01-01"}, - "name": ["file_5.txt", "file_3.txt"], - } - - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters_simplified) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_dates_and_or_explicit( - self, doc_store_with_docs: PineconeDocumentStore - ): - filters = { - "$and": { - "date": {"$lte": "2020-12-31", "$gte": "2019-01-01"}, - "$or": {"name": {"$in": ["file_5.txt", "file_3.txt"]}, "numeric_field": {"$lte": 5.0}}, - } - } - - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_dates_and_or_simplified( - self, doc_store_with_docs: PineconeDocumentStore - ): - filters_simplified = { - "date": {"$lte": "2020-12-31", "$gte": "2019-01-01"}, - "$or": {"name": ["file_5.txt", "file_3.txt"], "numeric_field": {"$lte": 5.0}}, - } - - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters_simplified) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_dates_and_or_and_not_explicit( - self, doc_store_with_docs: PineconeDocumentStore - ): - filters = { - "$and": { - "date": {"$lte": "2020-12-31", "$gte": "2019-01-01"}, - "$or": { - "name": {"$in": ["file_5.txt", "file_3.txt"]}, - "$and": {"numeric_field": {"$lte": 5.0}, "$not": {"meta_field": {"$eq": "test-2"}}}, - }, - } - } - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_dates_and_or_and_not_simplified( - self, doc_store_with_docs: PineconeDocumentStore - ): - filters_simplified = { - "date": {"$lte": "2020-12-31", "$gte": "2019-01-01"}, - "$or": { - "name": ["file_5.txt", "file_3.txt"], - "$and": {"numeric_field": {"$lte": 5.0}, "$not": {"meta_field": "test-2"}}, - }, - } - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters_simplified) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_nested_not(self, doc_store_with_docs: PineconeDocumentStore): - # Test nested logical operations within "$not", important as we apply De Morgan's laws in Weaviatedocstore - filters = { - "$not": { - "$or": { - "$and": {"numeric_field": {"$gt": 3.0}, "meta_field": {"$ne": "test-3"}}, - "$not": {"date": {"$lt": "2020-01-01"}}, - } - } - } - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]t' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters) - - @pytest.mark.integration - def test_get_all_documents_extended_filter_compound_same_level_not( - self, doc_store_with_docs: PineconeDocumentStore - ): - # Test same logical operator twice on same level, important as we apply De Morgan's laws in Weaviatedocstore - filters = { - "$or": [ - {"$and": {"meta_field": {"$in": ["test-1", "test-2"]}, "date": {"$gte": "2020-01-01"}}}, - {"$and": {"meta_field": {"$in": ["test-3", "test-4"]}, "date": {"$lt": "2020-01-01"}}}, - ] - } - - with pytest.raises(FilterError, match=r"Comparison value for '\$[l|g]te' operation must be a float or int."): - doc_store_with_docs.get_all_documents(filters=filters) - - @pytest.mark.integration - def test_multilayer_dict(self, doc_store_with_docs: PineconeDocumentStore): - # Test that multilayer dict can be upserted - multilayer_meta = { - "parent1": {"parent2": {"parent3": {"child1": 1, "child2": 2}}}, - "meta_field": "multilayer-test", - } - doc = Document( - content="Multilayered dict", meta=multilayer_meta, embedding=np.random.rand(768).astype(np.float32) - ) - - doc_store_with_docs.write_documents([doc]) - retrieved_docs = doc_store_with_docs.get_all_documents(filters={"meta_field": {"$eq": "multilayer-test"}}) - - assert len(retrieved_docs) == 1 - assert retrieved_docs[0].meta == multilayer_meta - - @pytest.mark.unit - def test_skip_validating_empty_embeddings(self, ds: PineconeDocumentStore): - document = Document(id="0", content="test") - retriever = MockBaseRetriever(document_store=ds, mock_document=document) - ds.write_documents(documents=[document]) - ds._validate_embeddings_shape = MagicMock() - - ds.update_embeddings(retriever) - ds._validate_embeddings_shape.assert_called_once() - ds.update_embeddings(retriever, update_existing_embeddings=False) - ds._validate_embeddings_shape.assert_called_once() - - @pytest.mark.integration - def test_get_embedding_count(self, doc_store_with_docs: PineconeDocumentStore): - """ - We expect 1 doc with an embeddings because all documents in already written in doc_store_with_docs contain no - embeddings. - """ - doc = Document( - content="Doc with embedding", - embedding=np.random.rand(768).astype(np.float32), - meta={"meta_field": "test-1"}, - ) - doc_store_with_docs.write_documents([doc]) - assert doc_store_with_docs.get_embedding_count() == 1 - - @pytest.mark.integration - def test_get_embedding_count_with_filters(self, doc_store_with_docs: PineconeDocumentStore): - """ - We expect 1 doc with an embedding and given filters, because there are only two documents with embedding - written in doc_store_with_docs, while only one of them satisfies given filters. - """ - doc_1 = Document( - content="Doc with embedding 1", - embedding=np.random.rand(768).astype(np.float32), - meta={"meta_field": "test-1"}, - ) - doc_2 = Document( - content="Doc with embedding 2", - embedding=np.random.rand(768).astype(np.float32), - meta={"meta_field": "test-2"}, - ) - doc_store_with_docs.write_documents([doc_1, doc_2]) - assert doc_store_with_docs.get_embedding_count(filters={"meta_field": "test-1"}) == 1 - - @pytest.mark.integration - def test_get_embedding_count_with_doc_type_filters(self, doc_store_with_docs: PineconeDocumentStore): - """ - We expect 2 docs with an embedding and given filters, because there are only two documents with embedding - written in doc_store_with_docs and both of them satisfy given filters (`meta_field` filter). - Even though the filters include `doc_type` with value related to documents without embedding (`no-vector`), - we expect this particular filter to be ignored (irrelevant, since documents with embedding have `doc_type` - set to `vector`). - """ - doc_1 = Document( - content="Doc with embedding 1", - embedding=np.random.rand(768).astype(np.float32), - meta={"meta_field": "test-2"}, - ) - doc_2 = Document( - content="Doc with embedding 2", - embedding=np.random.rand(768).astype(np.float32), - meta={"meta_field": "test-2"}, - ) - doc_store_with_docs.write_documents([doc_1, doc_2]) - assert ( - doc_store_with_docs.get_embedding_count( - filters={TYPE_METADATA_FIELD: DOCUMENT_WITHOUT_EMBEDDING, "meta_field": "test-2"} - ) - == 2 - ) - - @pytest.mark.integration - def test_get_document_count_after_write_doc_with_embedding(self, doc_store_with_docs: PineconeDocumentStore): - """ - Tests that get_document_count() returns the correct number of documents in the document store after a document - with an embedding is written to the document store. - """ - # there are 9 docs in doc_store_with_docs (all without embeddings) - initial_document_count = 9 - - # we expect initial_document_count documents without embeddings in doc_store_with_docs - assert doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count - # and also initial_document_count documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count - - # document with embedding is written to doc_store_with_docs - doc = Document(content="Doc with embedding", embedding=np.random.rand(768).astype(np.float32)) - doc_store_with_docs.write_documents([doc]) - - # so we expect initial_document_count + 1 documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count + 1 - - # but we expect initial_document_count documents without embeddings to be unchanged - assert doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count - - @pytest.mark.integration - def test_get_document_count_after_write_doc_without_embedding(self, doc_store_with_docs: PineconeDocumentStore): - """ - Tests that get_document_count() returns the correct number of documents in the document store after a document - without an embedding is written to the document store. - """ - # there are 9 docs in doc_store_with_docs (all without embeddings) - initial_document_count = 9 - - # we expect initial_document_count documents without embeddings in doc_store_with_docs - assert doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count - # and we also expect initial_document_count documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count - - # document without embedding is written to doc_store_with_docs - doc = Document(content="Doc without embedding") - doc_store_with_docs.write_documents([doc]) - - # we now expect initial_document_count + 1 documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count + 1 - - # And we also expect initial_document_count + 1 documents without embeddings, because the document we just - # wrote has no embeddings - assert ( - doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count + 1 - ) - - @pytest.mark.integration - def test_get_document_count_after_delete_doc_with_embedding(self, doc_store_with_docs: PineconeDocumentStore): - """ - Tests that get_document_count() returns the correct number of documents in the document store after a document - with an embedding is deleted from the document store. - """ - # there are 9 docs in doc_store_with_docs (all without embeddings) - initial_document_count = 9 - - # we expect initial_document_count documents without embeddings in doc_store_with_docs - assert doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count - # and also initial_document_count documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count - - # two documents with embedding are written to doc_store_with_docs - doc_1 = Document(content="Doc with embedding 1", embedding=np.random.rand(768).astype(np.float32)) - doc_2 = Document(content="Doc with embedding 2", embedding=np.random.rand(768).astype(np.float32)) - doc_store_with_docs.write_documents([doc_1, doc_2]) - - # total number is initial_document_count + 2 - assert doc_store_with_docs.get_document_count() == initial_document_count + 2 - - # remove one of the documents with embedding - all_embedding_docs = doc_store_with_docs.get_all_documents(type_metadata=DOCUMENT_WITH_EMBEDDING) - - doc_store_with_docs.delete_documents(ids=[all_embedding_docs[0].id]) - - # since we deleted one doc, we expect initial_document_count + 1 documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count + 1 - - # and we expect initial_document_count documents without embeddings - assert doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count - - @pytest.mark.integration - def test_get_document_count_after_delete_doc_without_embedding(self, doc_store_with_docs: PineconeDocumentStore): - """ - Tests that get_document_count() returns the correct number of documents in the document store after a document - without embedding is deleted from the document store. - """ - # there are 9 docs in doc_store_with_docs (all without embeddings) - initial_document_count = 9 - - # therefore we expect initial_document_count documents without embeddings in doc_store_with_docs - assert doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count - # and also initial_document_count documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count - - # two documents without embedding are written to doc_store_with_docs - doc_1 = Document(content="Doc with embedding 1", embedding=None) - doc_2 = Document(content="Doc with embedding 2", embedding=None) - doc_store_with_docs.write_documents([doc_1, doc_2]) - - # total number is initial_document_count + 2 - assert doc_store_with_docs.get_document_count() == initial_document_count + 2 - - # remove one of the documents without embedding - all_non_embedding_docs = doc_store_with_docs.get_all_documents(type_metadata="no-vector") - doc_store_with_docs.delete_documents(ids=[all_non_embedding_docs[0].id]) - - # since we deleted one doc, we expect initial_document_count + 1 documents in total - assert doc_store_with_docs.get_document_count() == initial_document_count + 1 - - # and we expect initial_document_count +1 documents without embeddings as well - assert ( - doc_store_with_docs.get_document_count(only_documents_without_embedding=True) == initial_document_count + 1 - ) - - @pytest.mark.unit - def test_get_all_labels_legacy_document_id(self, ds, monkeypatch): - monkeypatch.setattr( - ds, - "get_all_documents", - MagicMock( - return_value=[ - Document.from_dict( - { - "content": "My name is Carla and I live in Berlin", - "content_type": "text", - "score": None, - "meta": { - "label-id": "d9256445-7b8a-4a33-a558-402ec84d6881", - "query": "query_1", - "label-is-correct-answer": False, - "label-is-correct-document": True, - "label-document-content": "My name is Carla and I live in Berlin", - "label-document-id": "a0747b83aea0b60c4b114b15476dd32d", - "label-no-answer": False, - "label-origin": "user-feedback", - "label-created-at": "2023-02-07 14:46:54", - "label-updated-at": None, - "label-pipeline-id": None, - "label-document-meta-meta_field": "test-2", - "label-document-meta-name": "file_2.txt", - "label-document-meta-date": "2020-03-01", - "label-document-meta-numeric_field": 5.5, - "label-document-meta-odd_document": False, - "label-document-meta-year": "2021", - "label-document-meta-month": "02", - "label-meta-name": "label_1", - "label-meta-year": "2021", - "label-answer-answer": "the answer is 1", - "label-answer-type": "extractive", - "label-answer-score": None, - "label-answer-context": None, - # legacy document_id answer - "label-answer-document-id": "a0747b83aea0b60c4b114b15476dd32d", - "label-answer-offsets-in-document-start": None, - "label-answer-offsets-in-document-end": None, - "label-answer-offsets-in-context-start": None, - "label-answer-offsets-in-context-end": None, - }, - "id_hash_keys": ["content"], - "embedding": None, - "id": "d9256445-7b8a-4a33-a558-402ec84d6881", - } - ) - ] - ), - ) - - labels = ds.get_all_labels() - - assert labels[0].answer.document_ids == ["a0747b83aea0b60c4b114b15476dd32d"] - - @pytest.mark.unit - def test_split_overlap_meta(self, mocked_ds): - """ - Tests that we can upload Docs with a _split_overlap_meta field to Pinecone as a JSON string - and that the field is parsed correctly as dictionary when retrieved. - """ - doc = Document(content="test", meta={"_split_overlap": [{"doc_id": "test_id", "range": (0, 10)}]}, id="test_id") - # Test writing as JSON string - mocked_ds.write_documents([doc]) - call_args = mocked_ds.pinecone_indexes["document"].upsert.call_args.kwargs - assert list(call_args["vectors"])[0][2] == { - "doc_type": "no-vector", - "content": "test", - "content_type": "text", - "_split_overlap": '[{"doc_id": "test_id", "range": [0, 10]}]', - } - # Test retrieving as dict - mocked_ds._get_all_document_ids = MagicMock(return_value=["test_id"]) - mocked_ds.pinecone_indexes["document"].fetch.return_value = { - "vectors": { - "test_id": { - "metadata": { - "_split_overlap": '[{"doc_id": "test_id", "range": [0, 10]}]', - "content": "test", - "content_type": "text", - } - } - } - } - retrieved_docs = mocked_ds.get_all_documents() - assert retrieved_docs[0].meta["_split_overlap"] == [{"doc_id": "test_id", "range": [0, 10]}] diff --git a/test/document_stores/test_search_engine.py b/test/document_stores/test_search_engine.py deleted file mode 100644 index fc819fa7ed..0000000000 --- a/test/document_stores/test_search_engine.py +++ /dev/null @@ -1,266 +0,0 @@ -from typing import Optional -from unittest.mock import MagicMock - -import numpy as np -import pytest -from haystack.document_stores.search_engine import SearchEngineDocumentStore -from haystack.schema import FilterType - - -@pytest.mark.unit -def test_prepare_hosts(): - pass - - -@pytest.mark.document_store -class SearchEngineDocumentStoreTestAbstract: - """ - This is the base class for any Searchengine Document Store testsuite, it doesn't have the `Test` prefix in the name - because we want to run its methods only in subclasses. - """ - - @pytest.fixture - def mocked_get_all_documents_in_index(self, monkeypatch): - method_mock = MagicMock(return_value=None) - monkeypatch.setattr(SearchEngineDocumentStore, "_get_all_documents_in_index", method_mock) - return method_mock - - # Constants - query = "test" - - @pytest.mark.integration - def test___do_bulk(self): - pass - - @pytest.mark.integration - def test___do_scan(self): - pass - - @pytest.mark.integration - def test_query_by_embedding(self): - pass - - @pytest.mark.integration - def test_get_meta_values_by_key(self, ds, documents): - ds.write_documents(documents) - - # test without filters or query - result = ds.get_metadata_values_by_key(key="name") - assert result == [ - {"count": 3, "value": "name_0"}, - {"count": 3, "value": "name_1"}, - {"count": 3, "value": "name_2"}, - ] - - # test with filters but no query - result = ds.get_metadata_values_by_key(key="year", filters={"month": ["01"]}) - assert result == [{"count": 3, "value": "2020"}] - - # test with filters & query - result = ds.get_metadata_values_by_key(key="year", query="Bar") - assert result == [{"count": 3, "value": "2021"}] - - @pytest.mark.unit - def test_query_return_embedding_true(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert "_source" not in kwargs - - @pytest.mark.unit - def test_query_return_embedding_false(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_true(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.excluded_meta_data = ["foo", "embedding"] - mocked_document_store.query(self.query) - _, kwargs = mocked_document_store.client.search.call_args - # we expect "embedding" was removed from the final query - assert kwargs["_source"] == {"excludes": ["foo"]} - - @pytest.mark.unit - def test_query_excluded_meta_data_return_embedding_false(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.query(self.query) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert kwargs["_source"] == {"excludes": ["foo", "embedding"]} - - @pytest.mark.unit - def test_get_all_documents_return_embedding_true(self, mocked_document_store): - mocked_document_store.return_embedding = False - mocked_document_store.client.search.return_value = {} - mocked_document_store.get_all_documents(return_embedding=True) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert "_source" not in kwargs - - @pytest.mark.unit - def test_get_all_documents_return_embedding_false(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.client.search.return_value = {} - mocked_document_store.get_all_documents(return_embedding=False) - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - # starting with elasticsearch client 7.16, scan() uses the query parameter instead of body, - # see https://github.com/elastic/elasticsearch-py/commit/889edc9ad6d728b79fadf790238b79f36449d2e2 - body = kwargs.get("body", kwargs) - assert body["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_get_all_documents_excluded_meta_data_has_no_influence(self, mocked_document_store): - mocked_document_store.excluded_meta_data = ["foo"] - mocked_document_store.client.search.return_value = {} - mocked_document_store.get_all_documents(return_embedding=False) - # assert the resulting body is not affected by the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - # starting with elasticsearch client 7.16, scan() uses the query parameter instead of body, - # see https://github.com/elastic/elasticsearch-py/commit/889edc9ad6d728b79fadf790238b79f36449d2e2 - body = kwargs.get("body", kwargs) - assert body["_source"] == {"excludes": ["embedding"]} - - @pytest.mark.unit - def test_get_document_by_id_return_embedding_true(self, mocked_document_store): - mocked_document_store.return_embedding = True - mocked_document_store.get_document_by_id("123") - # assert the resulting body is consistent with the `excluded_meta_data` value - _, kwargs = mocked_document_store.client.search.call_args - assert "_source" not in kwargs - - @pytest.mark.unit - def test_get_all_labels_legacy_document_id(self, mocked_document_store, mocked_get_all_documents_in_index): - mocked_get_all_documents_in_index.return_value = [ - { - "_id": "123", - "_source": { - "query": "Who made the PDF specification?", - "document": { - "content": "Some content", - "content_type": "text", - "score": None, - "id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "embedding": [0.1, 0.2, 0.3], - }, - "answer": { - "answer": "Adobe Systems", - "type": "extractive", - "context": "Some content", - "offsets_in_context": [{"start": 60, "end": 73}], - "offsets_in_document": [{"start": 60, "end": 73}], - # legacy document_id answer - "document_id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "score": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "pipeline_id": "some-123", - }, - } - ] - labels = mocked_document_store.get_all_labels() - assert labels[0].answer.document_ids == ["fc18c987a8312e72a47fb1524f230bb0"] - - @pytest.mark.unit - def test_query_batch_req_for_each_batch(self, mocked_document_store): - mocked_document_store.batch_size = 2 - mocked_document_store.query_batch([self.query] * 3) - assert mocked_document_store.client.msearch.call_count == 2 - - @pytest.mark.unit - def test_query_by_embedding_batch_req_for_each_batch(self, mocked_document_store): - mocked_document_store.batch_size = 2 - mocked_document_store.query_by_embedding_batch([np.array([1, 2, 3])] * 3) - assert mocked_document_store.client.msearch.call_count == 2 - - @pytest.mark.integration - def test_document_with_version_metadata(self, ds: SearchEngineDocumentStore): - ds.write_documents([{"content": "test", "meta": {"version": "2023.1"}}]) - documents = ds.get_all_documents() - assert documents[0].meta["version"] == "2023.1" - - @pytest.mark.integration - def test_label_with_version_metadata(self, ds: SearchEngineDocumentStore): - ds.write_labels( - [ - { - "query": "test", - "document": {"content": "test"}, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "gold-label", - "meta": {"version": "2023.1"}, - "answer": None, - } - ] - ) - labels = ds.get_all_labels() - assert labels[0].meta["version"] == "2023.1" - - @pytest.mark.integration - @pytest.mark.parametrize( - "query,filters,result_count", - [ - # test happy path - ("tost", {"year": ["2020", "2021", "1990"]}, 4), - # test empty filters - ("test", None, 5), - # test linefeeds in query - ("test\n", {"year": "2021"}, 3), - # test double quote in query - ('test"', {"year": "2021"}, 3), - # test non-matching query - ("toast", None, 0), - ], - ) - def test_custom_query( - self, query: str, filters: Optional[FilterType], result_count: int, ds: SearchEngineDocumentStore - ): - documents = [ - {"id": "1", "content": "test", "meta": {"year": "2019"}}, - {"id": "2", "content": "test", "meta": {"year": "2020"}}, - {"id": "3", "content": "test", "meta": {"year": "2021"}}, - {"id": "4", "content": "test", "meta": {"year": "2021"}}, - {"id": "5", "content": "test", "meta": {"year": "2021"}}, - ] - ds.write_documents(documents) - custom_query = """ - { - "query": { - "bool": { - "must": [{ - "multi_match": { - "query": ${query}, - "fields": ["content"], - "fuzziness": "AUTO" - } - }], - "filter": ${filters} - } - } - } - """ - - results = ds.query(query=query, filters=filters, custom_query=custom_query) - assert len(results) == result_count - - -@pytest.mark.document_store -class TestSearchEngineDocumentStore: - """ - This class tests the concrete methods in SearchEngineDocumentStore - """ - - @pytest.mark.integration - def test__split_document_list(self): - pass diff --git a/test/document_stores/test_sql.py b/test/document_stores/test_sql.py deleted file mode 100644 index b57a98eb9a..0000000000 --- a/test/document_stores/test_sql.py +++ /dev/null @@ -1,179 +0,0 @@ -import json -import logging - -import pytest - -from haystack.document_stores.sql import LabelORM, SQLDocumentStore -from haystack.schema import Document -from haystack.testing import DocumentStoreBaseTestAbstract - - -class TestSQLDocumentStore(DocumentStoreBaseTestAbstract): - # Constants - - index_name = __name__ - - @pytest.fixture - def ds(self, tmp_path): - db_url = f"sqlite:///{tmp_path}/haystack_test.db" - return SQLDocumentStore(url=db_url, index=self.index_name, isolation_level="AUTOCOMMIT") - - @pytest.mark.integration - def test_delete_index(self, ds, documents): - """Contrary to other Document Stores, SQLDocumentStore doesn't raise if the index is empty""" - ds.write_documents(documents, index="custom_index") - assert ds.get_document_count(index="custom_index") == len(documents) - ds.delete_index(index="custom_index") - assert ds.get_document_count(index="custom_index") == 0 - - @pytest.mark.integration - def test_sql_write_different_documents_same_vector_id(self, ds): - doc1 = {"content": "content 1", "name": "doc1", "id": "1", "vector_id": "vector_id"} - doc2 = {"content": "content 2", "name": "doc2", "id": "2", "vector_id": "vector_id"} - - ds.write_documents([doc1], index="index1") - documents_in_index1 = ds.get_all_documents(index="index1") - assert len(documents_in_index1) == 1 - ds.write_documents([doc2], index="index2") - documents_in_index2 = ds.get_all_documents(index="index2") - assert len(documents_in_index2) == 1 - - ds.write_documents([doc1], index="index3") - with pytest.raises(Exception, match=r"(?i)unique"): - ds.write_documents([doc2], index="index3") - - @pytest.mark.integration - def test_sql_get_documents_using_nested_filters_about_classification(self, ds): - documents = [ - Document( - content="That's good. I like it.", - id="1", - meta={ - "classification": { - "label": "LABEL_1", - "score": 0.694, - "details": {"LABEL_1": 0.694, "LABEL_0": 0.306}, - } - }, - ), - Document( - content="That's bad. I don't like it.", - id="2", - meta={ - "classification": { - "label": "LABEL_0", - "score": 0.898, - "details": {"LABEL_0": 0.898, "LABEL_1": 0.102}, - } - }, - ), - ] - ds.write_documents(documents) - - assert ds.get_document_count() == 2 - assert len(ds.get_all_documents(filters={"classification.score": {"$gt": 0.1}})) == 2 - assert len(ds.get_all_documents(filters={"classification.label": ["LABEL_1", "LABEL_0"]})) == 2 - assert len(ds.get_all_documents(filters={"classification.score": {"$gt": 0.8}})) == 1 - assert len(ds.get_all_documents(filters={"classification.label": ["LABEL_1"]})) == 1 - assert len(ds.get_all_documents(filters={"classification.score": {"$gt": 0.95}})) == 0 - assert len(ds.get_all_documents(filters={"classification.label": ["LABEL_100"]})) == 0 - - # NOTE: the SQLDocumentStore marshals metadata values with JSON so querying - # using filters doesn't always work. While this should be considered a bug, - # the relative tests are either customized or skipped while we work on a fix. - - @pytest.mark.integration - def test_ne_filters(self, ds, caplog): - with caplog.at_level(logging.WARNING): - ds.get_all_documents(filters={"year": {"$ne": "2020"}}) - assert "filters won't work on metadata fields" in caplog.text - - @pytest.mark.integration - def test_get_all_labels_legacy_document_id(self, ds): - ds.session.add( - LabelORM( - id="123", - no_answer=False, - document=json.dumps( - { - "content": "Some content", - "content_type": "text", - "score": None, - "id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "embedding": [0.1, 0.2, 0.3], - } - ), - origin="user-feedback", - query="Who made the PDF specification?", - is_correct_answer=True, - is_correct_document=True, - answer=json.dumps( - { - "answer": "Adobe Systems", - "type": "extractive", - "context": "Some content", - "offsets_in_context": [{"start": 60, "end": 73}], - "offsets_in_document": [{"start": 60, "end": 73}], - # legacy document_id answer - "document_id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "score": None, - } - ), - pipeline_id="some-123", - index=ds.label_index, - ) - ) - labels = ds.get_all_labels() - assert labels[0].answer.document_ids == ["fc18c987a8312e72a47fb1524f230bb0"] - - @pytest.mark.skip - @pytest.mark.integration - def test_nin_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_comparison_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nested_condition_filters(self, ds, documents): - pass - - @pytest.mark.skip - @pytest.mark.integration - def test_nested_condition_not_filters(self, ds, documents): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_delete_labels_by_filter(self, ds, labels): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_delete_labels_by_filter_id(self, ds, labels): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel_filter_aggregations(self): - pass - - @pytest.mark.skip(reason="labels metadata are not supported") - @pytest.mark.integration - def test_multilabel_meta_aggregations(self): - pass - - @pytest.mark.skip(reason="embeddings are not supported") - @pytest.mark.integration - def test_get_embedding_count(self): - pass - - @pytest.mark.skip(reason="embeddings are not supported") - @pytest.mark.integration - def test_custom_embedding_field(self, ds): - pass diff --git a/test/document_stores/test_sql_based.py b/test/document_stores/test_sql_based.py deleted file mode 100644 index 9c433fece8..0000000000 --- a/test/document_stores/test_sql_based.py +++ /dev/null @@ -1,274 +0,0 @@ -import pytest -import numpy as np - -from haystack.schema import Document -from haystack.pipelines import DocumentSearchPipeline - -from haystack.pipelines import Pipeline - - -DOCUMENTS = [ - { - "meta": {"name": "name_1", "year": "2020", "month": "01"}, - "content": "text_1", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_2", "year": "2020", "month": "02"}, - "content": "text_2", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_3", "year": "2020", "month": "03"}, - "content": "text_3", - "embedding": np.random.rand(768).astype(np.float64), - }, - { - "meta": {"name": "name_4", "year": "2021", "month": "01"}, - "content": "text_4", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_5", "year": "2021", "month": "02"}, - "content": "text_5", - "embedding": np.random.rand(768).astype(np.float32), - }, - { - "meta": {"name": "name_6", "year": "2021", "month": "03"}, - "content": "text_6", - "embedding": np.random.rand(768).astype(np.float64), - }, -] - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -@pytest.mark.parametrize("batch_size", [4, 6]) -def test_update_docs(document_store, retriever, batch_size): - # initial write - document_store.write_documents(DOCUMENTS) - - document_store.update_embeddings(retriever=retriever, batch_size=batch_size) - documents_indexed = document_store.get_all_documents() - assert len(documents_indexed) == len(DOCUMENTS) - - # test if correct vectors are associated with docs - for doc in documents_indexed: - original_doc = [d for d in DOCUMENTS if d["content"] == doc.content][0] - updated_embedding = retriever.embed_documents([Document.from_dict(original_doc)]) - stored_doc = document_store.get_all_documents(filters={"name": [doc.meta["name"]]})[0] - # compare original input vec with stored one (ignore extra dim added by hnsw) - # original input vec is normalized as faiss only stores normalized vectors - a = updated_embedding / np.linalg.norm(updated_embedding) - assert np.allclose(a[0], stored_doc.embedding, rtol=0.2) # high tolerance was necessary for Milvus 2 - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_update_existing_docs(document_store, retriever): - document_store.duplicate_documents = "overwrite" - old_document = Document(content="text_1") - # initial write - document_store.write_documents([old_document]) - document_store.update_embeddings(retriever=retriever) - old_documents_indexed = document_store.get_all_documents(return_embedding=True) - assert len(old_documents_indexed) == 1 - - # Update document data - new_document = Document(content="text_2") - new_document.id = old_document.id - document_store.write_documents([new_document]) - document_store.update_embeddings(retriever=retriever) - new_documents_indexed = document_store.get_all_documents(return_embedding=True) - assert len(new_documents_indexed) == 1 - - assert old_documents_indexed[0].id == new_documents_indexed[0].id - assert old_documents_indexed[0].content == "text_1" - assert new_documents_indexed[0].content == "text_2" - print(type(old_documents_indexed[0].embedding)) - print(type(new_documents_indexed[0].embedding)) - assert not np.allclose(old_documents_indexed[0].embedding, new_documents_indexed[0].embedding, rtol=0.01) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_update_with_empty_store(document_store, retriever): - # Call update with empty doc store - document_store.update_embeddings(retriever=retriever) - - # initial write - document_store.write_documents(DOCUMENTS) - - documents_indexed = document_store.get_all_documents() - - assert len(documents_indexed) == len(DOCUMENTS) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["embedding"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_finding(document_store, retriever): - document_store.write_documents(DOCUMENTS) - pipe = DocumentSearchPipeline(retriever=retriever) - - prediction = pipe.run(query="How to test this?", params={"Retriever": {"top_k": 1}}) - - assert len(prediction.get("documents", [])) == 1 - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_delete_docs_with_filters_multivalue(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - - document_store.delete_documents(filters={"name": ["name_1", "name_2", "name_3", "name_4"]}) - - documents = document_store.get_all_documents() - assert len(documents) == 2 - assert document_store.get_embedding_count() == 2 - assert {doc.meta["name"] for doc in documents} == {"name_5", "name_6"} - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_delete_docs_with_filters(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - - document_store.delete_documents(filters={"year": ["2020"]}) - - documents = document_store.get_all_documents() - assert len(documents) == 3 - assert document_store.get_embedding_count() == 3 - assert all(doc.meta["year"] == "2021" for doc in documents) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_delete_docs_with_many_filters(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - - document_store.delete_documents(filters={"month": ["01"], "year": ["2020"]}) - - documents = document_store.get_all_documents() - assert len(documents) == 5 - assert document_store.get_embedding_count() == 5 - assert "name_1" not in {doc.meta["name"] for doc in documents} - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_delete_docs_by_id(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - doc_ids = [doc.id for doc in document_store.get_all_documents()] - ids_to_delete = doc_ids[0:3] - - document_store.delete_documents(ids=ids_to_delete) - - documents = document_store.get_all_documents() - assert len(documents) == len(doc_ids) - len(ids_to_delete) - assert document_store.get_embedding_count() == len(doc_ids) - len(ids_to_delete) - - remaining_ids = [doc.id for doc in documents] - assert all(doc_id not in remaining_ids for doc_id in ids_to_delete) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_delete_docs_by_id_with_filters(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - - ids_to_delete = [doc.id for doc in document_store.get_all_documents(filters={"name": ["name_1", "name_2"]})] - ids_not_to_delete = [ - doc.id for doc in document_store.get_all_documents(filters={"name": ["name_3", "name_4", "name_5", "name_6"]}) - ] - - document_store.delete_documents(ids=ids_to_delete, filters={"name": ["name_1", "name_2", "name_3", "name_4"]}) - - documents = document_store.get_all_documents() - assert len(documents) == len(DOCUMENTS) - len(ids_to_delete) - assert document_store.get_embedding_count() == len(DOCUMENTS) - len(ids_to_delete) - - assert all(doc.meta["name"] != "name_1" for doc in documents) - assert all(doc.meta["name"] != "name_2" for doc in documents) - - all_ids_left = [doc.id for doc in documents] - assert all(doc_id in all_ids_left for doc_id in ids_not_to_delete) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_get_docs_with_filters_one_value(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - - documents = document_store.get_all_documents(filters={"year": ["2020"]}) - - assert len(documents) == 3 - assert all(doc.meta["year"] == "2020" for doc in documents) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_get_docs_with_filters_many_values(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - - documents = document_store.get_all_documents(filters={"name": ["name_5", "name_6"]}) - - assert len(documents) == 2 - assert {doc.meta["name"] for doc in documents} == {"name_5", "name_6"} - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_get_docs_with_many_filters(document_store, retriever): - document_store.write_documents(DOCUMENTS) - document_store.update_embeddings(retriever=retriever, batch_size=4) - assert document_store.get_embedding_count() == 6 - - documents = document_store.get_all_documents(filters={"month": ["01"], "year": ["2020"]}) - - assert len(documents) == 1 - assert documents[0].meta["name"] == "name_1" - assert documents[0].meta["month"] == "01" - assert documents[0].meta["year"] == "2020" - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["embedding"], indirect=True) -@pytest.mark.parametrize("document_store", ["faiss"], indirect=True) -def test_pipeline(document_store, retriever): - documents = [ - {"name": "name_1", "content": "text_1", "embedding": np.random.rand(768).astype(np.float32)}, - {"name": "name_2", "content": "text_2", "embedding": np.random.rand(768).astype(np.float32)}, - {"name": "name_3", "content": "text_3", "embedding": np.random.rand(768).astype(np.float64)}, - {"name": "name_4", "content": "text_4", "embedding": np.random.rand(768).astype(np.float32)}, - ] - document_store.write_documents(documents) - pipeline = Pipeline() - pipeline.add_node(component=retriever, name="FAISS", inputs=["Query"]) - output = pipeline.run(query="How to test this?", params={"FAISS": {"top_k": 3}}) - assert len(output["documents"]) == 3 diff --git a/test/document_stores/test_weaviate.py b/test/document_stores/test_weaviate.py deleted file mode 100644 index 050a042b87..0000000000 --- a/test/document_stores/test_weaviate.py +++ /dev/null @@ -1,466 +0,0 @@ -import json -import uuid -from unittest import mock - -import numpy as np -import pytest -import weaviate - -from haystack.document_stores.weaviate import WeaviateDocumentStore -from haystack.schema import Document -from haystack.testing import DocumentStoreBaseTestAbstract - -embedding_dim = 768 - - -def get_uuid(): - return str(uuid.uuid4()) - - -class TestWeaviateDocumentStore(DocumentStoreBaseTestAbstract): - # Constants - - index_name = "DocumentsTest" - - @pytest.fixture - def ds(self): - return WeaviateDocumentStore(index=self.index_name, recreate_index=True, return_embedding=True) - - @pytest.fixture(scope="class") - def documents(self): - documents = [] - for i in range(3): - documents.append( - Document( - id=get_uuid(), - content=f"A Foo Document {i}", - meta={"name": f"name_{i}", "year": "2020", "month": "01", "numbers": [2.0, 4.0]}, - embedding=np.random.rand(768).astype(np.float32), - ) - ) - - documents.append( - Document( - id=get_uuid(), - content=f"A Bar Document {i}", - meta={"name": f"name_{i}", "year": "2021", "month": "02", "numbers": [-2.0, -4.0]}, - embedding=np.random.rand(768).astype(np.float32), - ) - ) - - documents.append( - Document( - id=get_uuid(), - content=f"A Baz Document {i}", - meta={"name": f"name_{i}", "month": "03"}, - embedding=np.random.rand(768).astype(np.float32), - ) - ) - - return documents - - @pytest.fixture() - def mocked_ds(self): - """ - This fixture provides an instance of the WeaviateDocumentStore equipped with a mocked Weaviate client. - """ - with mock.patch("haystack.document_stores.weaviate.client") as mocked_client: - mocked_client.Client().is_ready.return_value = True - mocked_client.Client().schema.contains.return_value = False - yield WeaviateDocumentStore() - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_write_labels(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_delete_labels(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_delete_labels_by_id(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_delete_labels_by_filter(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_delete_labels_by_filter_id(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_get_label_count(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_write_labels_duplicate(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_write_get_all_labels(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_labels_with_long_texts(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_multilabel(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_multilabel_no_answer(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_multilabel_filter_aggregations(self): - pass - - @pytest.mark.skip(reason="Weaviate does not support labels") - @pytest.mark.integration - def test_multilabel_meta_aggregations(self): - pass - - @pytest.mark.integration - def test_ne_filters(self, ds, documents): - """ - Weaviate doesn't include documents if the field is missing, - so we customize this test - """ - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$ne": "2020"}}) - assert len(result) == 3 - - @pytest.mark.integration - def test_nin_filters(self, ds, documents): - """ - Weaviate doesn't include documents if the field is missing, - so we customize this test - """ - ds.write_documents(documents) - - result = ds.get_all_documents(filters={"year": {"$nin": ["2020", "2021", "n.a."]}}) - assert len(result) == 0 - - @pytest.mark.integration - def test_delete_index(self, ds, documents): - """Contrary to other Document Stores, this doesn't raise if the index is empty""" - ds.write_documents(documents, index="custom_index") - assert ds.get_document_count(index="custom_index") == len(documents) - ds.delete_index(index="custom_index") - assert ds.get_document_count(index="custom_index") == 0 - - @pytest.mark.integration - def test_query_by_embedding(self, ds, documents): - ds.write_documents(documents) - - docs = ds.query_by_embedding(np.random.rand(embedding_dim).astype(np.float32)) - assert len(docs) == 9 - - docs = ds.query_by_embedding(np.random.rand(embedding_dim).astype(np.float32), top_k=1) - assert len(docs) == 1 - - docs = ds.query_by_embedding(np.random.rand(embedding_dim).astype(np.float32), filters={"name": ["name_1"]}) - assert len(docs) == 3 - - @pytest.mark.integration - def test_query(self, ds, documents): - ds.write_documents(documents) - - query_text = "Foo" - docs = ds.query(query_text) - assert len(docs) == 3 - - # BM25 retrieval WITH filters is not yet supported as of Weaviate v1.14.1 - # Should be from 1.18: https://github.com/semi-technologies/weaviate/issues/2393 - # docs = ds.query(query_text, filters={"name": ["name_1"]}) - # assert len(docs) == 1 - - docs = ds.query(query=None, filters={"name": ["name_0"]}) - assert len(docs) == 3 - - docs = ds.query(query=None, filters={"content": [query_text.lower()]}) - assert len(docs) == 3 - - docs = ds.query(query=None, filters={"content": ["baz"]}) - assert len(docs) == 3 - - @pytest.mark.integration - def test_get_all_documents_unaffected_by_QUERY_MAXIMUM_RESULTS(self, ds, documents, monkeypatch): - """ - Ensure `get_all_documents` works no matter the value of QUERY_MAXIMUM_RESULTS - see https://github.com/deepset-ai/haystack/issues/2517 - """ - ds.write_documents(documents) - monkeypatch.setattr(ds, "get_document_count", lambda **kwargs: 13_000) - docs = ds.get_all_documents() - assert len(docs) == 9 - - @pytest.mark.integration - def test_deleting_by_id_or_by_filters(self, ds, documents): - ds.write_documents(documents) - # This test verifies that deleting an object by its ID does not first require fetching all documents. This fixes - # a bug, as described in https://github.com/deepset-ai/haystack/issues/2898 - ds.get_all_documents = mock.MagicMock(wraps=ds.get_all_documents) - - assert ds.get_document_count() == 9 - - # Delete a document by its ID. This should bypass the get_all_documents() call - ds.delete_documents(ids=[documents[0].id]) - ds.get_all_documents.assert_not_called() - assert ds.get_document_count() == 8 - - ds.get_all_documents.reset_mock() - # Delete a document with filters. Prove that using the filters will go through get_all_documents() - ds.delete_documents(filters={"name": ["name_0"]}) - ds.get_all_documents.assert_called() - assert ds.get_document_count() == 6 - - @pytest.mark.integration - @pytest.mark.parametrize("similarity", ["cosine", "l2", "dot_product"]) - def test_similarity_existing_index(self, similarity): - """Testing non-matching similarity""" - # create the document_store - WeaviateDocumentStore( - similarity=similarity, index=f"test_similarity_existing_index_{similarity}", recreate_index=True - ) - - # try to connect to the same document store but using the wrong similarity - non_matching_similarity = "l2" if similarity == "cosine" else "cosine" - with pytest.raises(ValueError, match=r"This index already exists in Weaviate with similarity .*"): - WeaviateDocumentStore( - similarity=non_matching_similarity, - index=f"test_similarity_existing_index_{similarity}", - recreate_index=False, - ) - - @pytest.mark.integration - def test_cant_write_id_in_meta(self, ds): - with pytest.raises(ValueError, match='"meta" info contains duplicate key "id"'): - ds.write_documents([Document(content="test", meta={"id": "test-id"})]) - - @pytest.mark.integration - def test_cant_write_top_level_fields_in_meta(self, ds): - with pytest.raises(ValueError, match='"meta" info contains duplicate key "content"'): - ds.write_documents([Document(content="test", meta={"content": "test-id"})]) - - @pytest.mark.integration - def test_get_embedding_count(self, ds, documents): - """ - We expect 9 docs with embeddings because all documents in the documents fixture for this class contain - embeddings. - """ - ds.write_documents(documents) - assert ds.get_embedding_count() == 9 - - @pytest.mark.unit - def test__get_auth_secret(self): - # Test with username and password - secret = WeaviateDocumentStore._get_auth_secret("user", "pass", scope="some_scope") - assert isinstance(secret, weaviate.AuthClientPassword) - - # Test with api key - secret = WeaviateDocumentStore._get_auth_secret(api_key="wcs_api_key") - assert isinstance(secret, weaviate.AuthApiKey) - - # Test with no authentication method - secret = WeaviateDocumentStore._get_auth_secret() - assert secret is None - - @pytest.mark.unit - @pytest.mark.parametrize( - "embedded_options, expected_options", - [ - (None, weaviate.EmbeddedOptions()), - ( - {"hostname": "http://localhost", "port": "8080"}, - weaviate.EmbeddedOptions(hostname="http://localhost", port="8080"), - ), - ], - ) - def test__get_embedded_options(self, embedded_options, expected_options): - options = WeaviateDocumentStore._get_embedded_options(embedded_options) - assert options == expected_options - - @pytest.mark.unit - def test__get_current_properties(self, mocked_ds): - mocked_ds.weaviate_client.schema.get.return_value = json.loads( - """ -{ - "classes": [{ - "class": "Document", - "properties": [ - { - "name": "hasWritten", - "dataType": ["Article"] - }, - { - "name": "hitCounter", - "dataType": ["int"] - } - ] - }] -} """ - ) - # Ensure we dropped the cross-reference property - assert mocked_ds._get_current_properties() == ["hitCounter"] - - @pytest.mark.unit - def test_dict_metadata(self, mocked_ds): - """ - Tests that metadata of type dict is converted to JSON string when writing to Weaviate and converted - back to dict when reading from Weaviate. - """ - doc = Document(content="test", meta={"dict_field": {"key": "value"}}) - # Test writing as JSON string - mocked_ds.write_documents([doc]) - mocked_ds.weaviate_client.batch.add_data_object.assert_called_with( - data_object={ - "content": json.dumps(doc.content), - "content_type": doc.content_type, - "id_hash_keys": doc.id_hash_keys, - "dict_field": json.dumps(doc.meta["dict_field"]), - }, - class_name=mock.ANY, - uuid=mock.ANY, - vector=mock.ANY, - ) - - # Test retrieving as dict - mocked_ds.weaviate_client.query.get().do.return_value = json.loads( - """ - { - "data": { - "Get": { - "Document": [ - { - "content": "\\"test\\"", - "content_type": "text", - "dict_field": "{\\"key\\": \\"value\\"}", - "id_hash_keys": ["content"] - } - ] - } - } - } - """ - ) - mocked_ds.get_document_count = mock.MagicMock(return_value=1) - mocked_ds.weaviate_client.schema.get.return_value = json.loads( - """ - { - "classes": [ - { - "class": "Document", - "description": "Haystack index, it's a class in Weaviate", - "properties": [ - { - "dataType": ["text"], - "description": "Document Content (e.g. the text)", - "name": "content", - "tokenization": "word" - }, - { - "dataType": ["text"], - "description": "JSON dynamic property dict_field", - "name": "dict_field", - "tokenization": "whitespace" - } - ] - } - ] - } - """ - ) - retrieved_docs = mocked_ds.get_all_documents() - assert retrieved_docs[0].meta["dict_field"] == {"key": "value"} - - @pytest.mark.unit - def test_list_of_dict_metadata(self, mocked_ds): - """ - Tests that metadata of type list of dict is converted to list of JSON string when writing to Weaviate and - converted back to list of dict when reading from Weaviate. - """ - doc = Document(content="test", meta={"list_dict_field": [{"key": "value"}, {"key": "value"}]}) - # Test writing as list of JSON strings - mocked_ds.write_documents([doc]) - mocked_ds.weaviate_client.batch.add_data_object.assert_called_with( - data_object={ - "content": json.dumps(doc.content), - "content_type": doc.content_type, - "id_hash_keys": doc.id_hash_keys, - "list_dict_field": [json.dumps(item) for item in doc.meta["list_dict_field"]], - }, - class_name=mock.ANY, - uuid=mock.ANY, - vector=mock.ANY, - ) - - # Test retrieving as list of dict - mocked_ds.weaviate_client.query.get().do.return_value = json.loads( - """ - { - "data": { - "Get": { - "Document": [ - { - "content": "\\"test\\"", - "content_type": "text", - "list_dict_field": ["{\\"key\\": \\"value\\"}", "{\\"key\\": \\"value\\"}"], - "id_hash_keys": ["content"] - } - ] - } - } - } - """ - ) - mocked_ds.get_document_count = mock.MagicMock(return_value=1) - mocked_ds.weaviate_client.schema.get.return_value = json.loads( - """ - { - "classes": [ - { - "class": "Document", - "description": "Haystack index, it's a class in Weaviate", - "properties": [ - { - "dataType": ["text"], - "description": "Document Content (e.g. the text)", - "name": "content", - "tokenization": "word" - }, - { - "dataType": ["text[]"], - "description": "JSON dynamic property dict_field", - "name": "list_dict_field", - "tokenization": "whitespace" - } - ] - } - ] - } - """ - ) - retrieved_docs = mocked_ds.get_all_documents() - assert retrieved_docs[0].meta["list_dict_field"] == [{"key": "value"}, {"key": "value"}] - - @pytest.mark.unit - def test_write_documents_req_for_each_batch(self, mocked_ds, documents): - mocked_ds.batch_size = 2 - mocked_ds.write_documents(documents) - assert mocked_ds.weaviate_client.batch.create_objects.call_count == 5 diff --git a/test/mocks/pinecone.py b/test/mocks/pinecone.py deleted file mode 100644 index e25255f2c2..0000000000 --- a/test/mocks/pinecone.py +++ /dev/null @@ -1,373 +0,0 @@ -import logging -from typing import Any, Dict, List, Optional, Union - -from haystack.schema import FilterType - -logger = logging.getLogger(__name__) - - -# Mock Pinecone instance -CONFIG: dict = {"api_key": None, "environment": None, "indexes": {}} - - -# Mock Pinecone Index Description instance -class IndexDescription: - def __init__( - self, - name: str, - metric: Optional[str] = None, - replicas: Optional[int] = None, - dimension: Optional[int] = None, - shards: Optional[int] = None, - pods: Optional[int] = None, - pod_type: Optional[str] = None, - status: Dict[str, Any] = None, - metadata_config: Optional[dict] = None, - source_collection: Optional[str] = None, - ) -> None: - self.name = name - self.metric = metric - self.replicas = replicas - self.dimension = dimension - self.shards = shards - self.pods = pods - self.pod_type = pod_type - self.status = status - self.metadata_config = metadata_config - self.source_collection = source_collection - - -# Mock Pinecone Index instance -class IndexObject: - def __init__( - self, - index: str, - api_key: Optional[str] = None, - environment: Optional[str] = None, - dimension: Optional[int] = None, - metric: Optional[str] = None, - replicas: Optional[int] = None, - shards: Optional[int] = None, - metadata_config: Optional[dict] = None, - ): - self.index = index - self.api_key = api_key - self.environment = environment - self.dimension = dimension - self.metric = metric - self.replicas = replicas - self.shards = shards - self.metadata_config = metadata_config - self.namespaces: dict = {} - - -# Mock the Pinecone Index class -class Index: - def __init__(self, index: str): - self.index = index - self.index_config = CONFIG["indexes"][index] - - def upsert(self, vectors: List[tuple], namespace: str = ""): - if namespace not in self.index_config.namespaces: - self.index_config.namespaces[namespace] = {} - upsert_count = 0 - for record in vectors: - # Extract info from tuple - _id = record[0] - vector = record[1] - metadata = record[2] - # Checks - assert type(_id) is str - assert type(vector) is list - assert len(vector) == self.index_config.dimension - assert type(metadata) is dict - # Create record (eg document) - new_record: dict = {"id": _id, "values": vector, "metadata": metadata} - self.index_config.namespaces[namespace][_id] = new_record - upsert_count += 1 - return {"upserted_count": upsert_count} - - def update(self, namespace: str, id: str, set_metadata: dict): - # Get existing item metadata - meta = self.index_config.namespaces[namespace][id]["metadata"] - # Add new metadata to existing item metadata - self.index_config.namespaces[namespace][id]["metadata"] = {**meta, **set_metadata} - - def describe_index_stats(self, filter=None): - namespaces = {} - for namespace in self.index_config.namespaces.items(): - records = self.index_config.namespaces[namespace[0]] - if filter: - filtered_records = [] - for record in records.values(): - if self._filter(metadata=record["metadata"], filters=filter, top_level=True): - filtered_records.append(record) - records = filtered_records - namespaces[namespace[0]] = {"vector_count": len(records)} - return {"dimension": self.index_config.dimension, "index_fullness": 0.0, "namespaces": namespaces} - - def query( - self, - vector: List[float], - top_k: int, - namespace: str = "", - include_values: bool = False, - include_metadata: bool = False, - filter: Optional[dict] = None, - ): - return self.query_filter( - vector=vector, - top_k=top_k, - namespace=namespace, - include_values=include_values, - include_metadata=include_metadata, - filter=filter, - ) - - def query_filter( - self, - vector: List[float], - top_k: int, - namespace: str = "", - include_values: bool = False, - include_metadata: bool = False, - filter: Optional[dict] = None, - ): - assert len(vector) == self.index_config.dimension - response: dict = {"matches": []} - if namespace not in self.index_config.namespaces: - return response - else: - records = self.index_config.namespaces[namespace] - namespace_ids = list(records.keys())[:top_k] - - for _id in namespace_ids: - match = {"id": _id} - if include_values: - match["values"] = records[_id]["values"].copy() - if include_metadata: - match["metadata"] = records[_id]["metadata"].copy() - match["score"] = 0.0 - - if filter is None or ( - filter is not None and self._filter(records[_id]["metadata"], filter, top_level=True) - ): - # filter if needed - response["matches"].append(match) - return response - - def fetch(self, ids: List[str], namespace: str = ""): - response: dict = {"namespace": namespace, "vectors": {}} - if namespace not in self.index_config.namespaces: - # If we query an empty/non-existent namespace, Pinecone will just return an empty response - logger.warning("No namespace called '%s'", namespace) - return response - records = self.index_config.namespaces[namespace] - namespace_ids = records.keys() - for _id in namespace_ids: - if _id in ids.copy(): - response["vectors"][_id] = { - "id": _id, - "metadata": records[_id]["metadata"].copy(), - "values": records[_id]["values"].copy(), - } - return response - - def _filter( # noqa: C901,PLR0912 - self, - metadata: dict, - filters: Optional[Union[FilterType, List[Optional[FilterType]]]], - mode: Optional[str] = "$and", - top_level=False, - ) -> dict: - """ - Mock filtering function - """ - # This function has a very high McCabe cyclomatic complexity score of 38 - # (recommended is 10) and contains 55 branches (recommended is 12). - bools = [] - if type(filters) is list: - list_bools = [] - for _filter in filters: - res = self._filter(metadata, _filter, mode=mode) - for key, value in res.items(): - if key == "$and": - list_bools.append(all(value)) - else: - list_bools.append(any(value)) - if mode == "$and": - bools.append(all(list_bools)) - elif mode == "$or": - bools.append(any(list_bools)) - else: - for field, potential_value in filters.items(): - if field in ["$and", "$or"]: - bools.append(self._filter(metadata, potential_value, mode=field)) - mode = field - cond = field - else: - if type(potential_value) is dict: - sub_bool = [] - for cond, value in potential_value.items(): - if len(potential_value.keys()) > 1: - sub_filter = {field: {cond: value}} - bools.append(self._filter(metadata, sub_filter)) - if len(sub_bool) > 1: - if field == "$or": - bools.append(any(sub_bool)) - else: - bools.append(all(sub_bool)) - elif type(potential_value) is list: - cond = "$in" - value = potential_value - else: - cond = "$eq" - value = potential_value - # main chunk of condition checks - if cond == "$eq": - if field in metadata and metadata[field] == value: - bools.append(True) - else: - bools.append(False) - elif cond == "$ne": - if field in metadata and metadata[field] != value: - bools.append(True) - else: - bools.append(False) - elif cond == "$in": - if field in metadata and metadata[field] in value: - bools.append(True) - else: - bools.append(False) - elif cond == "$nin": - if field in metadata and metadata[field] not in value: - bools.append(True) - else: - bools.append(False) - elif cond == "$gt": - if field in metadata and metadata[field] > value: - bools.append(True) - else: - bools.append(False) - elif cond == "$lt": - if field in metadata and metadata[field] < value: - bools.append(True) - else: - bools.append(False) - elif cond == "$gte": - if field in metadata and metadata[field] >= value: - bools.append(True) - else: - bools.append(False) - elif cond == "$lte": - if field in metadata and metadata[field] <= value: - bools.append(True) - else: - bools.append(False) - if top_level: - final = [] - for item in bools: - if type(item) is dict: - for key, value in item.items(): - if key == "$and": - final.append(all(value)) - else: - final.append(any(value)) - else: - final.append(item) - if mode == "$and": - bools = all(final) - else: - bools = any(final) - else: - if mode == "$and": - return {"$and": bools} - else: - return {"$or": bools} - return bools - - def delete( - self, - ids: Optional[List[str]] = None, - namespace: str = "", - filters: Optional[FilterType] = None, - delete_all: bool = False, - ): - if filters: - # Get a filtered list of IDs - matches = self.query(filters=filters, namespace=namespace, include_values=False, include_metadata=False)[ - "vectors" - ] - filter_ids: List[str] = matches.keys() # .keys() returns an object that supports set operators already - elif delete_all: - self.index_config.namespaces[namespace] = {} - - if namespace not in self.index_config.namespaces: - pass - elif ids is not None: - id_list: List[str] = ids - if filters: - # We find the intersect between the IDs and filtered IDs - id_list = set(id_list).intersection(filter_ids) - records = self.index_config.namespaces[namespace] - for _id in list(records.keys()): # list() is needed to be able to del below - if _id in id_list: - del records[_id] - else: - # Delete all - self.index_config.namespaces[namespace] = {} - return {} - - def _get_config(self): - return self.index_config - - -# Mock core Pinecone client functions -def init(api_key: Optional[str] = None, environment: Optional[str] = None): - CONFIG["api_key"] = api_key - CONFIG["environment"] = environment - CONFIG["indexes"] = {} - - -def list_indexes(): - return list(CONFIG["indexes"].keys()) - - -def create_index( - name: str, - dimension: int, - metric: str = "cosine", - replicas: int = 1, - shards: int = 1, - metadata_config: Optional[dict] = None, -): - index_object = IndexObject( - api_key=CONFIG["api_key"], - environment=CONFIG["environment"], - index=name, - dimension=dimension, - metric=metric, - replicas=replicas, - shards=shards, - metadata_config=metadata_config, - ) - CONFIG["indexes"][name] = index_object - - -def delete_index(index: str): - del CONFIG["indexes"][index] - - -def describe_index(index: str): - return IndexDescription( - name=index, - metric="dotproduct", - replicas=1, - dimension=768.0, - shards=1, - pods=1, - pod_type="p1.x1", - status={"ready": True, "state": "Ready"}, - metadata_config=None, - source_collection="", - ) diff --git a/test/modeling/__init__.py b/test/modeling/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/modeling/conftest.py b/test/modeling/conftest.py deleted file mode 100644 index 38084cd9df..0000000000 --- a/test/modeling/conftest.py +++ /dev/null @@ -1,41 +0,0 @@ -import logging - -import pytest -import psutil - -from haystack.modeling.infer import Inferencer, QAInferencer - - -@pytest.fixture -def adaptive_model_qa(num_processes): - """ - PyTest Fixture for a Question Answering Inferencer based on PyTorch. - """ - - model = Inferencer.load( - "deepset/bert-medium-squad2-distilled", - task_type="question_answering", - batch_size=16, - num_processes=num_processes, - gpu=False, - ) - yield model - - # check if all workers (sub processes) are closed - current_process = psutil.Process() - children = current_process.children() - if len(children) != 0: - logging.error("Not all the subprocesses are closed! %s are still running.", len(children)) - - -@pytest.fixture -def bert_base_squad2(request): - model = QAInferencer.load( - "deepset/minilm-uncased-squad2", - task_type="question_answering", - batch_size=4, - num_processes=0, - multithreading_rust=False, - use_fast=True, # TODO parametrize this to test slow as well - ) - return model diff --git a/test/modeling/samples/test_get_tokenizer_from_path/tokenizer_config.json b/test/modeling/samples/test_get_tokenizer_from_path/tokenizer_config.json deleted file mode 100644 index 35442cd50b..0000000000 --- a/test/modeling/samples/test_get_tokenizer_from_path/tokenizer_config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "tokenizer_class": "TestTokenizer" -} diff --git a/test/modeling/test_dataloader.py b/test/modeling/test_dataloader.py deleted file mode 100644 index fc2b95b3af..0000000000 --- a/test/modeling/test_dataloader.py +++ /dev/null @@ -1,47 +0,0 @@ -import pytest - -import torch - -from haystack.modeling.data_handler.dataloader import NamedDataLoader - - -@pytest.fixture -def named_dataloader(): - tensor_names = ["input_ids", "labels"] - return NamedDataLoader(None, 1, tensor_names=tensor_names) - - -@pytest.fixture -def batch(): - # batch containing tensors of different lengths - return [ - (torch.tensor([1, 2, 3]), torch.tensor([[0, 0], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1]])), - (torch.tensor([4, 5, 6]), torch.tensor([[0, 0], [-1, -1], [-1, -1]])), - (torch.tensor([7, 8, 9]), torch.tensor([[0, 0], [-1, -1]])), - ] - - -@pytest.mark.unit -def test_compute_max_number_of_labels(named_dataloader, batch): - tensor_names = ["input_ids", "labels"] - max_num_labels = named_dataloader._compute_max_number_of_labels(batch, tensor_names) - assert max_num_labels == 6 - - -@pytest.mark.unit -def test_collate_fn(named_dataloader, batch): - collated_batch = named_dataloader.collate_fn(batch) - - expected_collated_batch = { - "input_ids": torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), - "labels": torch.tensor( - [ - [[0, 0], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1]], - [[0, 0], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1]], - [[0, 0], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1]], - ] - ), - } - - for key in collated_batch: - assert torch.equal(collated_batch[key], expected_collated_batch[key]) diff --git a/test/modeling/test_feature_extraction.py b/test/modeling/test_feature_extraction.py deleted file mode 100644 index 3e85e7f93e..0000000000 --- a/test/modeling/test_feature_extraction.py +++ /dev/null @@ -1,131 +0,0 @@ -import pytest -from unittest.mock import MagicMock -from unittest import mock -from pathlib import Path - -import haystack -from haystack.errors import ModelingError -from haystack.modeling.model.feature_extraction import FeatureExtractor - - -class MockedAutoTokenizer: - mocker: MagicMock = MagicMock() - - @classmethod - def from_pretrained(cls, *args, **kwargs): - cls.mocker.from_pretrained(*args, **kwargs) - return cls() - - -class MockedAutoConfig: - mocker: MagicMock = MagicMock() - model_type: str = "mocked" - - @classmethod - def from_pretrained(cls, *args, **kwargs): - cls.mocker.from_pretrained(*args, **kwargs) - return cls() - - -@pytest.fixture() -def mock_autotokenizer(monkeypatch): - monkeypatch.setattr( - haystack.modeling.model.feature_extraction, "FEATURE_EXTRACTORS", {"mocked": MockedAutoTokenizer} - ) - monkeypatch.setattr(haystack.modeling.model.feature_extraction, "AutoConfig", MockedAutoConfig) - monkeypatch.setattr(haystack.modeling.model.feature_extraction, "AutoTokenizer", MockedAutoTokenizer) - - -@pytest.mark.unit -def test_get_tokenizer_from_HF(): - with mock.patch("haystack.modeling.model.feature_extraction.AutoConfig") as mocked_ac: - from haystack.modeling.model.feature_extraction import FEATURE_EXTRACTORS - - FEATURE_EXTRACTORS["test"] = mock.MagicMock() - FEATURE_EXTRACTORS["test"].__name__ = "Test" - mocked_ac.from_pretrained.return_value.model_type = "test" - FeatureExtractor(pretrained_model_name_or_path="test-model-name") - FEATURE_EXTRACTORS["test"].from_pretrained.assert_called_with( - pretrained_model_name_or_path="test-model-name", revision=None, use_fast=True, use_auth_token=None - ) - # clean up - FEATURE_EXTRACTORS.pop("test") - - -@pytest.mark.unit -def test_get_tokenizer_from_HF_not_found(): - with mock.patch("haystack.modeling.model.feature_extraction.AutoConfig") as mocked_ac: - mocked_ac.from_pretrained.return_value.model_type = "does_not_exist" - with pytest.raises(ModelingError): - FeatureExtractor(pretrained_model_name_or_path="test-model-name") - - -@pytest.mark.unit -def test_get_tokenizer_from_path_fast(): - here = Path(__file__).resolve().parent - mocked_model_folder = here / "samples/test_get_tokenizer_from_path" - with mock.patch("haystack.modeling.model.feature_extraction.transformers") as mocked_tf: - mocked_tf.TestTokenizerFast.__class__.__name__ = "Test Class" - FeatureExtractor(pretrained_model_name_or_path=mocked_model_folder) - mocked_tf.TestTokenizerFast.from_pretrained.assert_called_with( - pretrained_model_name_or_path=str(mocked_model_folder), revision=None, use_fast=True, use_auth_token=None - ) - - -@pytest.mark.unit -def test_get_tokenizer_from_path(): - here = Path(__file__).resolve().parent - mocked_model_folder = here / "samples/test_get_tokenizer_from_path" - with mock.patch("haystack.modeling.model.feature_extraction.transformers") as mocked_tf: - mocked_tf.TestTokenizer.__class__.__name__ = "Test Class" - FeatureExtractor(pretrained_model_name_or_path=mocked_model_folder) - mocked_tf.TestTokenizerFast.from_pretrained.assert_called_with( - pretrained_model_name_or_path=str(mocked_model_folder), revision=None, use_fast=True, use_auth_token=None - ) - - -@pytest.mark.unit -def test_get_tokenizer_from_path_class_doesnt_exist(): - here = Path(__file__).resolve().parent - mocked_model_folder = here / "samples/test_get_tokenizer_from_path" - with pytest.raises(AttributeError, match="module transformers has no attribute TestTokenizer"): - FeatureExtractor(pretrained_model_name_or_path=mocked_model_folder) - - -@pytest.mark.unit -def test_get_tokenizer_keep_accents(): - here = Path(__file__).resolve().parent - mocked_model_folder = here / "samples/test_get_tokenizer_from_path" - with mock.patch("haystack.modeling.model.feature_extraction.transformers") as mocked_tf: - mocked_tf.TestTokenizer.__class__.__name__ = "Test Class" - FeatureExtractor(pretrained_model_name_or_path=mocked_model_folder, keep_accents=True) - mocked_tf.TestTokenizerFast.from_pretrained.assert_called_with( - pretrained_model_name_or_path=str(mocked_model_folder), - revision=None, - use_fast=True, - use_auth_token=None, - keep_accents=True, - ) - - -FEATURE_EXTRACTORS_TO_TEST = ["bert-base-cased"] - - -@pytest.mark.integration -@pytest.mark.parametrize("model_name", FEATURE_EXTRACTORS_TO_TEST) -def test_load_modify_save_load(tmp_path, model_name: str): - # Load base tokenizer - feature_extractor = FeatureExtractor(pretrained_model_name_or_path=model_name, do_lower_case=False) - - # Add new tokens - feature_extractor.feature_extractor.add_tokens(new_tokens=["neverseentokens"]) - - # Save modified tokenizer - save_dir = tmp_path / "saved_tokenizer" - feature_extractor.feature_extractor.save_pretrained(save_dir) - - # Load modified tokenizer - new_feature_extractor = FeatureExtractor(pretrained_model_name_or_path=save_dir) - - # Assert the new tokenizer still has the added tokens - assert len(new_feature_extractor.feature_extractor) == len(feature_extractor.feature_extractor) diff --git a/test/modeling/test_model_loading.py b/test/modeling/test_model_loading.py deleted file mode 100644 index 859ad23d71..0000000000 --- a/test/modeling/test_model_loading.py +++ /dev/null @@ -1,43 +0,0 @@ -import pytest - -from haystack.modeling.model.language_model import ( - get_language_model, - HFLanguageModel, - HFLanguageModelNoSegmentIds, - HFLanguageModelWithPooler, - DPREncoder, -) - - -@pytest.mark.integration -@pytest.mark.parametrize( - "pretrained_model_name_or_path, lm_class", - [ - ("google/bert_uncased_L-2_H-128_A-2", HFLanguageModel), - ("google/electra-small-generator", HFLanguageModelWithPooler), - ("distilbert-base-uncased", HFLanguageModelNoSegmentIds), - ("deepset/bert-small-mm_retrieval-passage_encoder", DPREncoder), - ], -) -def test_basic_loading(pretrained_model_name_or_path, lm_class, monkeypatch): - monkeypatch.setattr(lm_class, "__init__", lambda self, *a, **k: None) - lm = get_language_model(pretrained_model_name_or_path) - assert isinstance(lm, lm_class) - - -@pytest.mark.unit -def test_basic_loading_unknown_model(): - with pytest.raises(RuntimeError): - get_language_model("model_that_doesnt_exist") - - -@pytest.mark.unit -def test_basic_loading_with_empty_string(): - with pytest.raises(ValueError): - get_language_model("") - - -@pytest.mark.unit -def test_basic_loading_invalid_params(): - with pytest.raises(ValueError): - get_language_model(None) diff --git a/test/modeling/test_prediction_head.py b/test/modeling/test_prediction_head.py deleted file mode 100644 index 368afc5022..0000000000 --- a/test/modeling/test_prediction_head.py +++ /dev/null @@ -1,30 +0,0 @@ -import logging - -from haystack.modeling.model.adaptive_model import AdaptiveModel -from haystack.modeling.model.language_model import get_language_model -from haystack.modeling.model.prediction_head import QuestionAnsweringHead -from haystack.modeling.utils import set_all_seeds, initialize_device_settings - - -def test_prediction_head_load_save(tmp_path, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - - set_all_seeds(seed=42) - devices, n_gpu = initialize_device_settings(use_cuda=False) - lang_model = "bert-base-german-cased" - - language_model = get_language_model(lang_model) - prediction_head = QuestionAnsweringHead() - - model = AdaptiveModel( - language_model=language_model, - prediction_heads=[prediction_head], - embeds_dropout_prob=0.1, - lm_output_types=["per_sequence"], - device=devices[0], - ) - - model.save(tmp_path) - model_loaded = AdaptiveModel.load(tmp_path, device="cpu") - assert model_loaded is not None diff --git a/test/modeling/test_processor.py b/test/modeling/test_processor.py deleted file mode 100644 index db937821e3..0000000000 --- a/test/modeling/test_processor.py +++ /dev/null @@ -1,344 +0,0 @@ -import copy -import logging -from pathlib import Path - -import pytest -from transformers import AutoTokenizer - -from haystack.modeling.data_handler.processor import SquadProcessor, _is_json -import contextlib - - -# during inference (parameter return_baskets = False) we do not convert labels -def test_dataset_from_dicts_qa_inference(samples_path, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - - models = [ - "deepset/roberta-base-squad2", - "deepset/bert-base-cased-squad2", - "deepset/xlm-roberta-large-squad2", - "deepset/minilm-uncased-squad2", - "deepset/electra-base-squad2", - ] - sample_types = ["answer-wrong", "answer-offset-wrong", "noanswer", "vanilla"] - - for model in models: - tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model) - processor = SquadProcessor(tokenizer, max_seq_len=256, data_dir=None) - - for sample_type in sample_types: - dicts = processor.file_to_dicts(samples_path / "qa" / f"{sample_type}.json") - dataset, tensor_names, problematic_sample_ids, baskets = processor.dataset_from_dicts( - dicts, indices=[1], return_baskets=True - ) - assert tensor_names == [ - "input_ids", - "padding_mask", - "segment_ids", - "passage_start_t", - "start_of_word", - "labels", - "id", - "seq_2_start_t", - "span_mask", - ], f"Processing for {model} has changed." - assert len(problematic_sample_ids) == 0, f"Processing for {model} has changed." - assert baskets[0].id_external == "5ad3d560604f3c001a3ff2c8", f"Processing for {model} has changed." - assert baskets[0].id_internal == "1-0", f"Processing for {model} has changed." - - # roberta - if model == "deepset/roberta-base-squad2": - assert ( - len(baskets[0].samples[0].tokenized["passage_tokens"]) == 6 - ), f"Processing for {model} has changed." - assert ( - len(baskets[0].samples[0].tokenized["question_tokens"]) == 7 - ), f"Processing for {model} has changed." - if sample_type == "noanswer": - assert baskets[0].samples[0].features[0]["input_ids"][:13] == [ - 0, - 6179, - 171, - 82, - 697, - 11, - 2201, - 116, - 2, - 2, - 26795, - 2614, - 34, - ], f"Processing for {model} and {sample_type}-testsample has changed." - else: - assert baskets[0].samples[0].features[0]["input_ids"][:13] == [ - 0, - 6179, - 171, - 82, - 697, - 11, - 5459, - 116, - 2, - 2, - 26795, - 2614, - 34, - ], f"Processing for {model} and {sample_type}-testsample has changed." - - # bert - if model == "deepset/bert-base-cased-squad2": - assert ( - len(baskets[0].samples[0].tokenized["passage_tokens"]) == 5 - ), f"Processing for {model} has changed." - assert ( - len(baskets[0].samples[0].tokenized["question_tokens"]) == 7 - ), f"Processing for {model} has changed." - if sample_type == "noanswer": - assert baskets[0].samples[0].features[0]["input_ids"][:10] == [ - 101, - 1731, - 1242, - 1234, - 1686, - 1107, - 2123, - 136, - 102, - 3206, - ], f"Processing for {model} and {sample_type}-testsample has changed." - else: - assert baskets[0].samples[0].features[0]["input_ids"][:10] == [ - 101, - 1731, - 1242, - 1234, - 1686, - 1107, - 3206, - 136, - 102, - 3206, - ], f"Processing for {model} and {sample_type}-testsample has changed." - - # xlm-roberta - if model == "deepset/xlm-roberta-large-squad2": - assert ( - len(baskets[0].samples[0].tokenized["passage_tokens"]) == 7 - ), f"Processing for {model} has changed." - assert ( - len(baskets[0].samples[0].tokenized["question_tokens"]) == 7 - ), f"Processing for {model} has changed." - if sample_type == "noanswer": - assert baskets[0].samples[0].features[0]["input_ids"][:12] == [ - 0, - 11249, - 5941, - 3395, - 6867, - 23, - 7270, - 32, - 2, - 2, - 10271, - 1556, - ], f"Processing for {model} and {sample_type}-testsample has changed." - else: - assert baskets[0].samples[0].features[0]["input_ids"][:12] == [ - 0, - 11249, - 5941, - 3395, - 6867, - 23, - 10271, - 32, - 2, - 2, - 10271, - 1556, - ], f"Processing for {model} and {sample_type}-testsample has changed." - - # minilm and electra have same vocab + tokenizer - if model == "deepset/minilm-uncased-squad2" or model == "deepset/electra-base-squad2": - assert ( - len(baskets[0].samples[0].tokenized["passage_tokens"]) == 5 - ), f"Processing for {model} has changed." - assert ( - len(baskets[0].samples[0].tokenized["question_tokens"]) == 7 - ), f"Processing for {model} has changed." - if sample_type == "noanswer": - assert baskets[0].samples[0].features[0]["input_ids"][:10] == [ - 101, - 2129, - 2116, - 2111, - 2444, - 1999, - 3000, - 1029, - 102, - 4068, - ], f"Processing for {model} and {sample_type}-testsample has changed." - else: - assert baskets[0].samples[0].features[0]["input_ids"][:10] == [ - 101, - 2129, - 2116, - 2111, - 2444, - 1999, - 4068, - 1029, - 102, - 4068, - ], f"Processing for {model} and {sample_type}-testsample has changed." - - -def test_batch_encoding_flatten_rename(): - from haystack.modeling.data_handler.dataset import flatten_rename - - tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") - batch_sentences = ["Hello I'm a single sentence", "And another sentence", "And the very very last one"] - encoded_inputs = tokenizer(batch_sentences, padding=True, truncation=True) - - keys = ["input_ids", "token_type_ids", "attention_mask"] - rename_keys = ["input_ids", "segment_ids", "padding_mask"] - features_flat = flatten_rename(encoded_inputs, keys, rename_keys) - - assert len(features_flat) == 3, "should have three elements in the feature dict list" - for e in features_flat: - for k in rename_keys: - assert k in e, f"feature dict list item {e} in a list should have a key {k}" - - # rename no keys/rename keys - features_flat = flatten_rename(encoded_inputs) - assert len(features_flat) == 3, "should have three elements in the feature dict list" - for e in features_flat: - for k in keys: - assert k in e, f"feature dict list item {e} in a list should have a key {k}" - - # empty input keys - flatten_rename(encoded_inputs, []) - - # empty keys and rename keys - flatten_rename(encoded_inputs, [], []) - - # no encoding_batch provided - flatten_rename(None, [], []) - - # keys and renamed_keys have different sizes - with contextlib.suppress(AssertionError): - flatten_rename(encoded_inputs, [], ["blah"]) - - -def test_dataset_from_dicts_qa_label_conversion(samples_path, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - - models = [ - "deepset/roberta-base-squad2", - "deepset/bert-base-cased-squad2", - "deepset/xlm-roberta-large-squad2", - "deepset/minilm-uncased-squad2", - "deepset/electra-base-squad2", - ] - sample_types = ["answer-wrong", "answer-offset-wrong", "noanswer", "vanilla"] - - for model in models: - tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model) - processor = SquadProcessor(tokenizer, max_seq_len=256, data_dir=None, max_answers=6) - - for sample_type in sample_types: - dicts = processor.file_to_dicts(samples_path / "qa" / f"{sample_type}.json") - dataset, tensor_names, problematic_sample_ids = processor.dataset_from_dicts( - dicts, indices=[1], return_baskets=False - ) - - if sample_type == "answer-wrong" or sample_type == "answer-offset-wrong": - assert len(problematic_sample_ids) == 1, f"Processing labels for {model} has changed." - - if sample_type == "noanswer": - assert list(dataset.tensors[tensor_names.index("labels")].numpy()[0, 0, :]) == [ - 0, - 0, - ], f"Processing labels for {model} has changed." - assert list(dataset.tensors[tensor_names.index("labels")].numpy()[0, 1, :]) == [ - -1, - -1, - ], f"Processing labels for {model} has changed." - - if sample_type == "vanilla": - # roberta - if model == "deepset/roberta-base-squad2": - assert list(dataset.tensors[tensor_names.index("labels")].numpy()[0, 0, :]) == [ - 13, - 13, - ], f"Processing labels for {model} has changed." - assert list(dataset.tensors[tensor_names.index("labels")].numpy()[0, 1, :]) == [ - 13, - 14, - ], f"Processing labels for {model} has changed." - # bert, minilm, electra - if ( - model == "deepset/bert-base-cased-squad2" - or model == "deepset/minilm-uncased-squad2" - or model == "deepset/electra-base-squad2" - ): - assert list(dataset.tensors[tensor_names.index("labels")].numpy()[0, 0, :]) == [ - 11, - 11, - ], f"Processing labels for {model} has changed." - # xlm-roberta - if model == "deepset/xlm-roberta-large-squad2": - assert list(dataset.tensors[tensor_names.index("labels")].numpy()[0, 0, :]) == [ - 12, - 12, - ], f"Processing labels for {model} has changed." - - -@pytest.mark.unit -def test_is_json_identifies_json_objects(): - """Test that _is_json correctly identifies json objects""" - # Paths to json files should be considered json - assert _is_json(Path("processor_config.json")) - # dicts should be considered json - assert _is_json({"a": 1}) - # non-serializable objects should not be considered json - assert not _is_json(AutoTokenizer) - - -@pytest.mark.integration -def test_dataset_from_dicts_auto_determine_max_answers(samples_path, caplog=None): - """ - SquadProcessor should determine the number of answers for the pytorch dataset based on - the maximum number of answers for each question. Vanilla.json has one question with two answers, - so the number of answers should be two. - """ - model = "deepset/roberta-base-squad2" - tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model) - processor = SquadProcessor(tokenizer, max_seq_len=256, data_dir=None) - dicts = processor.file_to_dicts(samples_path / "qa" / "vanilla.json") - dataset, tensor_names, problematic_sample_ids = processor.dataset_from_dicts(dicts, indices=[1]) - assert len(dataset[0][tensor_names.index("labels")]) == 2 - # check that a max_answers will be adjusted when processing a different dataset with the same SquadProcessor - dicts_more_answers = copy.deepcopy(dicts) - dicts_more_answers[0]["qas"][0]["answers"] = dicts_more_answers[0]["qas"][0]["answers"] * 3 - dataset, tensor_names, problematic_sample_ids = processor.dataset_from_dicts(dicts_more_answers, indices=[1]) - assert len(dataset[0][tensor_names.index("labels")]) == 6 - - -@pytest.mark.integration -def test_dataset_from_dicts_truncate_max_answers(samples_path, caplog=None): - """ - Test that it is possible to manually set the number of answers, truncating the answers in the data. - """ - model = "deepset/roberta-base-squad2" - tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model) - processor = SquadProcessor(tokenizer, max_seq_len=256, data_dir=None, max_answers=1) - dicts = processor.file_to_dicts(samples_path / "qa" / "vanilla.json") - dataset, tensor_names, problematic_sample_ids = processor.dataset_from_dicts(dicts, indices=[1]) - assert len(dataset[0][tensor_names.index("labels")]) == 1 diff --git a/test/modeling/test_processor_save_load.py b/test/modeling/test_processor_save_load.py deleted file mode 100644 index 23799dc3f4..0000000000 --- a/test/modeling/test_processor_save_load.py +++ /dev/null @@ -1,46 +0,0 @@ -import logging -from pathlib import Path - -from transformers import AutoTokenizer - -from haystack.modeling.data_handler.processor import SquadProcessor -from haystack.modeling.utils import set_all_seeds -import torch - - -def test_processor_saving_loading(tmp_path, caplog, samples_path): - if caplog is not None: - caplog.set_level(logging.CRITICAL) - - set_all_seeds(seed=42) - lang_model = "roberta-base" - - tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=lang_model, do_lower_case=False) - - processor = SquadProcessor( - tokenizer=tokenizer, - max_seq_len=256, - label_list=["start_token", "end_token"], - train_filename="train-sample.json", - dev_filename="dev-sample.json", - test_filename=None, - data_dir=samples_path / "qa", - ) - - dicts = processor.file_to_dicts(file=samples_path / "qa" / "dev-sample.json") - data, tensor_names, _ = processor.dataset_from_dicts(dicts=dicts, indices=[1]) - - save_dir = tmp_path / Path("testsave/processor") - processor.save(save_dir) - - processor = processor.load_from_dir(save_dir) - dicts = processor.file_to_dicts(file=samples_path / "qa" / "dev-sample.json") - data_loaded, tensor_names_loaded, _ = processor.dataset_from_dicts(dicts, indices=[1]) - - assert tensor_names == tensor_names_loaded - for i in range(len(data.tensors)): - assert torch.all(torch.eq(data.tensors[i], data_loaded.tensors[i])) - - -if __name__ == "__main__": - test_processor_saving_loading(None) diff --git a/test/modeling/test_question_answering.py b/test/modeling/test_question_answering.py deleted file mode 100644 index 8275b623a9..0000000000 --- a/test/modeling/test_question_answering.py +++ /dev/null @@ -1,308 +0,0 @@ -import logging -import pytest -from math import isclose -import numpy as np - -from haystack.modeling.infer import QAInferencer -from haystack.modeling.data_handler.inputs import QAInput, Question - - -DOC_TEXT = """Twilight Princess was released to universal critical acclaim and commercial success. \ -It received perfect scores from major publications such as 1UP.com, Computer and Video Games, \ -Electronic Gaming Monthly, Game Informer, GamesRadar, and GameSpy. On the review aggregators \ -GameRankings and Metacritic, Twilight Princess has average scores of 95% and 95 for the Wii \ -version and scores of 95% and 96 for the GameCube version. GameTrailers in their review called \ -it one of the greatest games ever created.""" - - -@pytest.fixture -def bert_base_squad2(request): - model = QAInferencer.load( - "deepset/minilm-uncased-squad2", - task_type="question_answering", - batch_size=4, - num_processes=0, - multithreading_rust=False, - ) - return model - - -@pytest.fixture() -def span_inference_result(bert_base_squad2): - obj_input = [ - QAInput( - doc_text=DOC_TEXT, questions=Question("Who counted the game among the best ever made?", uid="best_id_ever") - ) - ] - result = bert_base_squad2.inference_from_objects(obj_input, return_json=False)[0] - return result - - -@pytest.fixture() -def no_answer_inference_result(bert_base_squad2, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - obj_input = [ - QAInput( - doc_text="""\ - The majority of the forest is contained within Brazil, with 60% of the rainforest, followed by - Peru with 13%, Colombia with 10%, and with minor amounts in Venezuela, Ecuador, Bolivia, Guyana, - Suriname and French Guiana. States or departments in four nations contain "Amazonas" in their names. - The Amazon represents over half of the planet\'s remaining rainforests, and comprises the largest - and most biodiverse tract of tropical rainforest in the world, with an estimated 390 billion individual - trees divided into 16,000 species.""", - questions=Question( - "The Amazon represents less than half of the planets remaining what?", uid="best_id_ever" - ), - ) - ] - result = bert_base_squad2.inference_from_objects(obj_input, return_json=False)[0] - return result - - -def test_inference_different_inputs(bert_base_squad2): - qa_format_1 = [{"questions": ["Who counted the game among the best ever made?"], "text": DOC_TEXT}] - q = Question(text="Who counted the game among the best ever made?") - qa_format_2 = QAInput(questions=[q], doc_text=DOC_TEXT) - - result1 = bert_base_squad2.inference_from_dicts(dicts=qa_format_1) - result2 = bert_base_squad2.inference_from_objects(objects=[qa_format_2]) - assert result1 == result2 - - -def test_span_inference_result_ranking_by_confidence(bert_base_squad2, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - obj_input = [ - QAInput( - doc_text=DOC_TEXT, questions=Question("Who counted the game among the best ever made?", uid="best_id_ever") - ) - ] - - # by default, result is sorted by confidence and not by score - result_ranked_by_confidence = bert_base_squad2.inference_from_objects(obj_input, return_json=False)[0] - assert all( - result_ranked_by_confidence.prediction[i].confidence >= result_ranked_by_confidence.prediction[i + 1].confidence - for i in range(len(result_ranked_by_confidence.prediction) - 1) - ) - assert not all( - result_ranked_by_confidence.prediction[i].score >= result_ranked_by_confidence.prediction[i + 1].score - for i in range(len(result_ranked_by_confidence.prediction) - 1) - ) - - # ranking can be adjusted so that result is sorted by score - bert_base_squad2.model.prediction_heads[0].use_confidence_scores_for_ranking = False - result_ranked_by_score = bert_base_squad2.inference_from_objects(obj_input, return_json=False)[0] - assert all( - result_ranked_by_score.prediction[i].score >= result_ranked_by_score.prediction[i + 1].score - for i in range(len(result_ranked_by_score.prediction) - 1) - ) - assert not all( - result_ranked_by_score.prediction[i].confidence >= result_ranked_by_score.prediction[i + 1].confidence - for i in range(len(result_ranked_by_score.prediction) - 1) - ) - - -def test_inference_objs(span_inference_result, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - - assert span_inference_result - - -def test_span_performance(span_inference_result, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - - best_pred = span_inference_result.prediction[0] - - assert best_pred.answer == "GameTrailers" - - best_score_gold = 13.4205 - best_score = best_pred.score - assert isclose(best_score, best_score_gold, rel_tol=0.001) - - no_answer_gap_gold = 13.9827 - no_answer_gap = span_inference_result.no_answer_gap - assert isclose(no_answer_gap, no_answer_gap_gold, rel_tol=0.001) - - -def test_no_answer_performance(no_answer_inference_result, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - best_pred = no_answer_inference_result.prediction[0] - - assert best_pred.answer == "no_answer" - - best_score_gold = 12.1445 - best_score = best_pred.score - assert isclose(best_score, best_score_gold, rel_tol=0.001) - - no_answer_gap_gold = -14.4646 - no_answer_gap = no_answer_inference_result.no_answer_gap - assert isclose(no_answer_gap, no_answer_gap_gold, rel_tol=0.001) - - -def test_qa_pred_attributes(span_inference_result, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - - qa_pred = span_inference_result - attributes_gold = [ - "aggregation_level", - "answer_types", - "context", - "context_window_size", - "ground_truth_answer", - "id", - "n_passages", - "no_answer_gap", - "prediction", - "question", - "to_json", - "to_squad_eval", - "token_offsets", - ] - - for ag in attributes_gold: - assert ag in dir(qa_pred) - - -def test_qa_candidate_attributes(span_inference_result, caplog=None): - if caplog: - caplog.set_level(logging.CRITICAL) - - qa_candidate = span_inference_result.prediction[0] - attributes_gold = [ - "aggregation_level", - "answer", - "answer_support", - "answer_type", - "context_window", - "n_passages_in_doc", - "offset_answer_end", - "offset_answer_start", - "offset_answer_support_end", - "offset_answer_support_start", - "offset_context_window_end", - "offset_context_window_start", - "offset_unit", - "passage_id", - "probability", - "score", - "set_answer_string", - "set_context_window", - "to_doc_level", - "to_list", - ] - - for ag in attributes_gold: - assert ag in dir(qa_candidate) - - -def test_id(span_inference_result, no_answer_inference_result): - assert span_inference_result.id == "best_id_ever" - assert no_answer_inference_result.id == "best_id_ever" - - -def test_duplicate_answer_filtering(bert_base_squad2): - qa_input = [ - { - "questions": ["“In what country lies the Normandy?”"], - "text": """The Normans (Norman: Nourmands; French: Normands; Latin: Normanni) were the people who in the 10th and 11th centuries gave their name to Normandy, a region in France. They were descended from Norse (\"Norman\" comes from \"Norseman\") - raiders and pirates from Denmark, Iceland and Norway who, under their leader Rollo, agreed to swear fealty to King Charles III of West Francia. Through generations of assimilation and mixing with the native Frankish and Roman-Gaulish populations, their descendants would gradually merge with the Carolingian-based cultures of West Francia. - The distinct cultural and ethnic identity of the Normans emerged initially in the first half of the 10th century, and it continued to evolve over the succeeding centuries. Weird things happen in Normandy, France.""", - } - ] - - bert_base_squad2.model.prediction_heads[0].n_best = 5 - bert_base_squad2.model.prediction_heads[0].n_best_per_sample = 5 - bert_base_squad2.model.prediction_heads[0].duplicate_filtering = 0 - - result = bert_base_squad2.inference_from_dicts(dicts=qa_input) - offset_answer_starts = [] - offset_answer_ends = [] - for answer in result[0]["predictions"][0]["answers"]: - offset_answer_starts.append(answer["offset_answer_start"]) - offset_answer_ends.append(answer["offset_answer_end"]) - - assert len(offset_answer_starts) == len(set(offset_answer_starts)) - assert len(offset_answer_ends) == len(set(offset_answer_ends)) - - -def test_no_duplicate_answer_filtering(bert_base_squad2): - qa_input = [ - { - "questions": ["“In what country lies the Normandy?”"], - "text": """The Normans (Norman: Nourmands; French: Normands; Latin: Normanni) were the people who in the 10th and 11th centuries gave their name to Normandy, a region in France. They were descended from Norse (\"Norman\" comes from \"Norseman\") - raiders and pirates from Denmark, Iceland and Norway who, under their leader Rollo, agreed to swear fealty to King Charles III of West Francia. Through generations of assimilation and mixing with the native Frankish and Roman-Gaulish populations, their descendants would gradually merge with the Carolingian-based cultures of West Francia. - The distinct cultural and ethnic identity of the Normans emerged initially in the first half of the 10th century, and it continued to evolve over the succeeding centuries. Weird things happen in Normandy, France.""", - } - ] - - bert_base_squad2.model.prediction_heads[0].n_best = 5 - bert_base_squad2.model.prediction_heads[0].n_best_per_sample = 5 - bert_base_squad2.model.prediction_heads[0].duplicate_filtering = -1 - bert_base_squad2.model.prediction_heads[0].no_ans_boost = -100.0 - - result = bert_base_squad2.inference_from_dicts(dicts=qa_input) - offset_answer_starts = [] - offset_answer_ends = [] - for answer in result[0]["predictions"][0]["answers"]: - offset_answer_starts.append(answer["offset_answer_start"]) - offset_answer_ends.append(answer["offset_answer_end"]) - - assert len(offset_answer_starts) != len(set(offset_answer_starts)) - assert len(offset_answer_ends) != len(set(offset_answer_ends)) - - -def test_range_duplicate_answer_filtering(bert_base_squad2): - qa_input = [ - { - "questions": ["“In what country lies the Normandy?”"], - "text": """The Normans (Norman: Nourmands; French: Normands; Latin: Normanni) were the people who in the 10th and 11th centuries gave their name to Normandy, a region in France. They were descended from Norse (\"Norman\" comes from \"Norseman\") - raiders and pirates from Denmark, Iceland and Norway who, under their leader Rollo, agreed to swear fealty to King Charles III of West Francia. Through generations of assimilation and mixing with the native Frankish and Roman-Gaulish populations, their descendants would gradually merge with the Carolingian-based cultures of West Francia. - The distinct cultural and ethnic identity of the Normans emerged initially in the first half of the 10th century, and it continued to evolve over the succeeding centuries. Weird things happen in Normandy, France.""", - } - ] - - bert_base_squad2.model.prediction_heads[0].n_best = 5 - bert_base_squad2.model.prediction_heads[0].n_best_per_sample = 5 - bert_base_squad2.model.prediction_heads[0].duplicate_filtering = 5 - - result = bert_base_squad2.inference_from_dicts(dicts=qa_input) - offset_answer_starts = [] - offset_answer_ends = [] - for answer in result[0]["predictions"][0]["answers"]: - offset_answer_starts.append(answer["offset_answer_start"]) - offset_answer_ends.append(answer["offset_answer_end"]) - - offset_answer_starts.sort() - offset_answer_starts.remove(0) - distances_answer_starts = [j - i for i, j in zip(offset_answer_starts[:-1], offset_answer_starts[1:])] - assert all( - distance > bert_base_squad2.model.prediction_heads[0].duplicate_filtering - for distance in distances_answer_starts - ) - - offset_answer_ends.sort() - offset_answer_ends.remove(0) - distances_answer_ends = [j - i for i, j in zip(offset_answer_ends[:-1], offset_answer_ends[1:])] - assert all( - distance > bert_base_squad2.model.prediction_heads[0].duplicate_filtering for distance in distances_answer_ends - ) - - -def test_qa_confidence(): - inferencer = QAInferencer.load( - "deepset/roberta-base-squad2", task_type="question_answering", batch_size=40, gpu=True - ) - QA_input = [ - { - "questions": ["Who counted the game among the best ever made?"], - "text": "Twilight Princess was released to universal critical acclaim and commercial success. It received perfect scores from major publications such as 1UP.com, Computer and Video Games, Electronic Gaming Monthly, Game Informer, GamesRadar, and GameSpy. On the review aggregators GameRankings and Metacritic, Twilight Princess has average scores of 95% and 95 for the Wii version and scores of 95% and 96 for the GameCube version. GameTrailers in their review called it one of the greatest games ever created.", - } - ] - result = inferencer.inference_from_dicts(dicts=QA_input, return_json=False)[0] - assert np.isclose(result.prediction[0].confidence, 0.990427553653717) - assert result.prediction[0].answer == "GameTrailers" diff --git a/test/nodes/__init__.py b/test/nodes/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/nodes/conftest.py b/test/nodes/conftest.py deleted file mode 100644 index 0d9b156a37..0000000000 --- a/test/nodes/conftest.py +++ /dev/null @@ -1,188 +0,0 @@ -from typing import List -from unittest.mock import patch, Mock -from uuid import UUID - -from numpy import loadtxt - -import pytest - -from haystack.schema import Document -from haystack.nodes import SentenceTransformersRanker, TopPSampler, TransformersDocumentClassifier - - -@pytest.fixture -def docs_with_true_emb(test_rootdir): - return [ - Document( - content="The capital of Germany is the city state of Berlin.", - embedding=loadtxt(test_rootdir / "samples" / "embeddings" / "embedding_1.txt"), - ), - Document( - content="Berlin is the capital and largest city of Germany by both area and population.", - embedding=loadtxt(test_rootdir / "samples" / "embeddings" / "embedding_2.txt"), - ), - ] - - -@pytest.fixture -def docs_with_ids(docs) -> List[Document]: - # Should be already sorted - uuids = [ - UUID("190a2421-7e48-4a49-a639-35a86e202dfb"), - UUID("20ff1706-cb55-4704-8ae8-a3459774c8dc"), - UUID("5078722f-07ae-412d-8ccb-b77224c4bacb"), - UUID("81d8ca45-fad1-4d1c-8028-d818ef33d755"), - UUID("f985789f-1673-4d8f-8d5f-2b8d3a9e8e23"), - ] - uuids.sort() - for doc, uuid in zip(docs, uuids): - doc.id = str(uuid) - return docs - - -@pytest.fixture -def ranker_two_logits(): - return SentenceTransformersRanker(model_name_or_path="deepset/gbert-base-germandpr-reranking") - - -@pytest.fixture -def ranker(): - return SentenceTransformersRanker(model_name_or_path="cross-encoder/ms-marco-MiniLM-L-12-v2") - - -@pytest.fixture -def top_p_sampler(): - return TopPSampler() - - -@pytest.fixture -def document_classifier(): - return TransformersDocumentClassifier( - model_name_or_path="bhadresh-savani/distilbert-base-uncased-emotion", use_gpu=False, top_k=2 - ) - - -@pytest.fixture -def zero_shot_document_classifier(): - return TransformersDocumentClassifier( - model_name_or_path="cross-encoder/nli-distilroberta-base", - use_gpu=False, - task="zero-shot-classification", - labels=["negative", "positive"], - ) - - -@pytest.fixture -def batched_document_classifier(): - return TransformersDocumentClassifier( - model_name_or_path="bhadresh-savani/distilbert-base-uncased-emotion", use_gpu=False, batch_size=16 - ) - - -@pytest.fixture -def indexing_document_classifier(): - return TransformersDocumentClassifier( - model_name_or_path="bhadresh-savani/distilbert-base-uncased-emotion", - use_gpu=False, - batch_size=16, - classification_field="class_field", - ) - - -example_serperdev_response = { - "searchParameters": { - "q": "Who is the boyfriend of Olivia Wilde?", - "gl": "us", - "hl": "en", - "autocorrect": True, - "type": "search", - }, - "organic": [ - { - "title": "Olivia Wilde embraces Jason Sudeikis amid custody battle, Harry Styles split - Page Six", - "link": "https://pagesix.com/2023/01/29/olivia-wilde-hugs-it-out-with-jason-sudeikis-after-harry-styles-split/", - "snippet": "Looks like Olivia Wilde and Jason Sudeikis are starting 2023 on good terms. Amid their highly publicized custody battle – and the actress' ...", - "date": "Jan 29, 2023", - "position": 1, - }, - { - "title": "Olivia Wilde Is 'Quietly Dating' Again Following Harry Styles Split: 'He Makes Her Happy'", - "link": "https://www.yahoo.com/now/olivia-wilde-quietly-dating-again-183844364.html", - "snippet": "Olivia Wilde is “quietly dating again” following her November 2022 split from Harry Styles, a source exclusively tells Life & Style.", - "date": "Feb 10, 2023", - "position": 2, - }, - { - "title": "Olivia Wilde and Harry Styles' Relationship Timeline: The Way They Were - Us Weekly", - "link": "https://www.usmagazine.com/celebrity-news/pictures/olivia-wilde-and-harry-styles-relationship-timeline/", - "snippet": "Olivia Wilde started dating Harry Styles after ending her years-long engagement to Jason Sudeikis — see their relationship timeline.", - "date": "Mar 10, 2023", - "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgTcalNFvptTbYBiDXX55s8yCGfn6F1qbed9DAN16LvynTr9GayK5SPmY&s", - "position": 3, - }, - { - "title": "Olivia Wilde Is 'Ready to Date Again' After Harry Styles Split - Us Weekly", - "link": "https://www.usmagazine.com/celebrity-news/news/olivia-wilde-is-ready-to-date-again-after-harry-styles-split/", - "snippet": "Ready for love! Olivia Wilde is officially back on the dating scene following her split from her ex-boyfriend, Harry Styles.", - "date": "Mar 1, 2023", - "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRCRAeRy5sVE631ZctzbzuOF70xkIOHaTvh2K7dYvdiVBwALiKrIjpscok&s", - "position": 4, - }, - { - "title": "Harry Styles and Olivia Wilde's Definitive Relationship Timeline - Harper's Bazaar", - "link": "https://www.harpersbazaar.com/celebrity/latest/a35172115/harry-styles-olivia-wilde-relationship-timeline/", - "snippet": "November 2020: News breaks about Olivia splitting from fiancé Jason Sudeikis. ... In mid-November, news breaks of Olivia Wilde's split from Jason ...", - "date": "Feb 23, 2023", - "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRRqw3fvZOIGHEepxCc7yFAWYsS_v_1H6X-4nxyFJxdfRuFQw_BrI6JVzI&s", - "position": 5, - }, - { - "title": "Harry Styles and Olivia Wilde's Relationship Timeline - People", - "link": "https://people.com/music/harry-styles-olivia-wilde-relationship-timeline/", - "snippet": "Harry Styles and Olivia Wilde first met on the set of Don't Worry Darling and stepped out as a couple in January 2021. Relive all their biggest relationship ...", - "position": 6, - }, - { - "title": "Jason Sudeikis and Olivia Wilde's Relationship Timeline - People", - "link": "https://people.com/movies/jason-sudeikis-olivia-wilde-relationship-timeline/", - "snippet": "Jason Sudeikis and Olivia Wilde ended their engagement of seven years in 2020. Here's a complete timeline of their relationship.", - "date": "Mar 24, 2023", - "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSleZoXusQyJJe2WMgIuck_cVaJ8AE0_hU2QxsXzYvKANi55UQlv82yAVI&s", - "position": 7, - }, - { - "title": "Olivia Wilde's anger at ex-boyfriend Harry Styles: She resents him and thinks he was using her | Marca", - "link": "https://www.marca.com/en/lifestyle/celebrities/2023/02/23/63f779a4e2704e8d988b4624.html", - "snippet": "The two started dating after Wilde split up with actor Jason Sudeikisin 2020. However, their relationship came to an end last November.", - "date": "Feb 23, 2023", - "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQBgJF2mSnIWCvPrqUqM4WTI9xPNWPyLvHuune85swpB1yE_G8cy_7KRh0&s", - "position": 8, - }, - { - "title": "Olivia Wilde's dating history: Who has the actress dated? | The US Sun", - "link": "https://www.the-sun.com/entertainment/5221040/olivia-wildes-dating-history/", - "snippet": "AMERICAN actress Olivia Wilde started dating Harry Styles in January 2021 after breaking off her engagement the year prior.", - "date": "Nov 19, 2022", - "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTpm8BToVFHJoH6yRggg0fLocLT9mt6lwsnRxFFDNdDGhDydzQiSKZ9__g&s", - "position": 9, - }, - ], - "relatedSearches": [ - {"query": "Harry Styles girlfriends in order"}, - {"query": "Harry Styles and Olivia Wilde engaged"}, - {"query": "Harry Styles and Olivia Wilde wedding"}, - {"query": "Who is Harry Styles married to"}, - {"query": "Jason Sudeikis Olivia Wilde relationship"}, - {"query": "Olivia Wilde and Jason Sudeikis kids"}, - {"query": "Olivia Wilde children"}, - {"query": "Harry Styles and Olivia Wilde age difference"}, - {"query": "Jason Sudeikis Olivia Wilde, Harry Styles"}, - ], -} - - -@pytest.fixture -def mock_web_search(): - with patch("haystack.nodes.search_engine.providers.requests") as mock_run: - mock_run.request.return_value = Mock(status_code=200, json=lambda: example_serperdev_response) - yield mock_run diff --git a/test/nodes/test_connector.py b/test/nodes/test_connector.py deleted file mode 100644 index b346600c0a..0000000000 --- a/test/nodes/test_connector.py +++ /dev/null @@ -1,260 +0,0 @@ -from typing import List - -import json -from pathlib import Path -import re -import hashlib -import os -from unittest.mock import patch - -import pytest - -from selenium.webdriver.common.by import By - -from haystack.nodes.connector.crawler import Crawler -from haystack.schema import Document - - -@pytest.fixture() -def test_url(samples_path): - return (samples_path / "crawler").absolute().as_uri() - - -def content_match(crawler: Crawler, url: str, crawled_page: Path): - """ - :param crawler: the tested Crawler object - :param url: the URL of the expected page - :param crawled_page: the output of Crawler (one element of the paths list) - """ - crawler.driver.get(url) - - body = crawler.driver.find_element(by=By.TAG_NAME, value="body") - - if crawler.extract_hidden_text: - expected_crawled_content = body.get_attribute("textContent") - else: - expected_crawled_content = body.text - - with open(crawled_page, "r") as crawled_file: - page_data = json.load(crawled_file) - return page_data["content"] == expected_crawled_content - - -def content_in_results(crawler: Crawler, url: str, results: List[Path], expected_matches_count=1): - """ - Makes sure there is exactly one matching page in the list of pages returned - by the crawler. - - :param crawler: the tested Crawler object - :param url: the URL of the page to find in the results - :param results: the crawler's output (list of paths) - :param expected_matches_count: how many copies of this page should be present in the results (default 1) - """ - return sum(content_match(crawler, url, path) for path in results) == expected_matches_count - - -@pytest.mark.unit -@patch("haystack.nodes.connector.crawler.webdriver") -def test_crawler_url_none_exception(webdriver): - crawler = Crawler() - with pytest.raises(ValueError): - crawler.crawl() - - -@pytest.mark.integration -def test_crawler(tmp_path): - tmp_dir = tmp_path - url = ["https://haystack.deepset.ai/"] - - crawler = Crawler(output_dir=tmp_dir, file_path_meta_field_name="file_path") - - documents = crawler.crawl(urls=url, crawler_depth=0) - docs_path = [Path(doc.meta["file_path"]) for doc in documents] - - results, _ = crawler.run(urls=url, crawler_depth=0) - docs_result = results["documents"] - - for json_file, document in zip(docs_path, docs_result): - assert isinstance(json_file, Path) - assert isinstance(document, Document) - - with open(json_file.absolute(), "r") as read_file: - file_content = json.load(read_file) - assert file_content["meta"] == document.meta - assert file_content["content"] == document.content - - -@pytest.mark.integration -def test_crawler_depth_0_single_url(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, crawler_depth=0, file_path_meta_field_name="file_path") - documents = crawler.crawl(urls=[test_url + "/index.html"]) - assert len(documents) == 1 - assert content_match(crawler, test_url + "/index.html", documents[0].meta["file_path"]) - - -@pytest.mark.integration -def test_crawler_depth_0_many_urls(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - _urls = [test_url + "/index.html", test_url + "/page1.html"] - documents = crawler.crawl(urls=_urls, crawler_depth=0) - assert len(documents) == 2 - paths = [doc.meta["file_path"] for doc in documents] - assert content_in_results(crawler, test_url + "/index.html", paths) - assert content_in_results(crawler, test_url + "/page1.html", paths) - - -@pytest.mark.integration -def test_crawler_depth_1_single_url(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - documents = crawler.crawl(urls=[test_url + "/index.html"], crawler_depth=1) - assert len(documents) == 3 - paths = [doc.meta["file_path"] for doc in documents] - assert content_in_results(crawler, test_url + "/index.html", paths) - assert content_in_results(crawler, test_url + "/page1.html", paths) - assert content_in_results(crawler, test_url + "/page2.html", paths) - - -@pytest.mark.integration -def test_crawler_output_file_structure(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - documents = crawler.crawl(urls=[test_url + "/index.html"], crawler_depth=0) - path = Path(documents[0].meta["file_path"]) - assert content_match(crawler, test_url + "/index.html", path) - - with open(path.absolute(), "r") as doc_file: - data = json.load(doc_file) - assert "content" in data - assert "meta" in data - assert isinstance(data["content"], str) - assert len(data["content"].split()) > 2 - - -@pytest.mark.integration -def test_crawler_filter_urls(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - - documents = crawler.crawl(urls=[test_url + "/index.html"], filter_urls=["index"], crawler_depth=1) - assert len(documents) == 1 - assert content_match(crawler, test_url + "/index.html", documents[0].meta["file_path"]) - - -@pytest.mark.integration -def test_crawler_extract_hidden_text(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path) - documents, _ = crawler.run(urls=[test_url + "/page_w_hidden_text.html"], extract_hidden_text=True, crawler_depth=0) - crawled_content = documents["documents"][0].content - assert "hidden text" in crawled_content - - documents, _ = crawler.run(urls=[test_url + "/page_w_hidden_text.html"], extract_hidden_text=False, crawler_depth=0) - crawled_content = documents["documents"][0].content - assert "hidden text" not in crawled_content - - -@pytest.mark.integration -def test_crawler_loading_wait_time(test_url, tmp_path, samples_path): - loading_wait_time = 3 - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - documents = crawler.crawl( - urls=[test_url + "/page_dynamic.html"], crawler_depth=1, loading_wait_time=loading_wait_time - ) - - assert len(documents) == 4 - - paths = [doc.meta["file_path"] for doc in documents] - - with open(f"{samples_path.absolute()}/crawler/page_dynamic_result.txt", "r") as dynamic_result: - dynamic_result_text = dynamic_result.readlines() - for path in paths: - with open(path, "r") as crawled_file: - page_data = json.load(crawled_file) - if page_data["meta"]["url"] == test_url + "/page_dynamic.html": - content = page_data["content"].split("\n") - - print(page_data["content"]) - print("------") - - for line in range(len(dynamic_result_text)): - assert dynamic_result_text[line].strip() == content[line].strip() - - assert content_in_results(crawler, test_url + "/index.html", paths) - assert content_in_results(crawler, test_url + "/page1.html", paths) - assert content_in_results(crawler, test_url + "/page2.html", paths) - - -@pytest.mark.integration -def test_crawler_default_naming_function(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - - link = f"{test_url}/page_with_a_very_long_name_to_do_some_tests_Now_let's_add_some_text_just_to_pass_the_129_chars_mark_and_trigger_the_chars_limit_of_the_default_naming_function.html" - file_name_link = re.sub("[<>:'/\\|?*\0 ]", "_", link[:129]) - file_name_hash = hashlib.md5(f"{link}".encode("utf-8")).hexdigest() - expected_crawled_file_path = f"{tmp_path}/{file_name_link}_{file_name_hash[-6:]}.json" - - documents = crawler.crawl(urls=[link], crawler_depth=0) - - path = Path(documents[0].meta["file_path"]) - assert os.path.exists(path) - assert path == Path(expected_crawled_file_path) - - -@pytest.mark.integration -def test_crawler_naming_function(test_url, tmp_path): - crawler = Crawler( - output_dir=tmp_path, - file_path_meta_field_name="file_path", - crawler_naming_function=lambda link, text: re.sub("[<>:'/\\|?*\0 ]", "_", link), - ) - - link = f"{test_url}/page_dynamic.html" - file_name_link = re.sub("[<>:'/\\|?*\0 ]", "_", link) - expected_crawled_file_path = tmp_path / f"{file_name_link}.json" - - documents = crawler.crawl(urls=[test_url + "/page_dynamic.html"], crawler_depth=0) - path = Path(documents[0].meta["file_path"]) - assert os.path.exists(path) - assert path == expected_crawled_file_path - - -@pytest.mark.integration -def test_crawler_not_save_file(test_url): - crawler = Crawler() - documents = crawler.crawl(urls=[test_url + "/index.html"], crawler_depth=0) - assert documents[0].meta.get("file_path", None) is None - - -@pytest.mark.integration -def test_crawler_custom_meta_file_path_name(test_url, tmp_path): - crawler = Crawler() - documents = crawler.crawl( - urls=[test_url + "/index.html"], crawler_depth=0, output_dir=tmp_path, file_path_meta_field_name="custom" - ) - assert documents[0].meta.get("custom", None) is not None - - -@pytest.mark.integration -def test_crawler_depth_2_single_url(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - documents = crawler.crawl(urls=[test_url + "/index.html"], crawler_depth=2) - assert len(documents) == 6 - paths = [doc.meta["file_path"] for doc in documents] - assert content_in_results(crawler, test_url + "/index.html", paths) - assert content_in_results(crawler, test_url + "/page1.html", paths) - assert content_in_results(crawler, test_url + "/page2.html", paths) - assert content_in_results(crawler, test_url + "/page1_subpage1.html", paths) - assert content_in_results(crawler, test_url + "/page1_subpage2.html", paths) - assert content_in_results(crawler, test_url + "/page2_subpage1.html", paths) - - -@pytest.mark.integration -def test_crawler_depth_2_multiple_urls(test_url, tmp_path): - crawler = Crawler(output_dir=tmp_path, file_path_meta_field_name="file_path") - _urls = [test_url + "/index.html", test_url + "/page1.html"] - documents = crawler.crawl(urls=_urls, crawler_depth=2) - assert len(documents) == 6 - paths = [doc.meta["file_path"] for doc in documents] - assert content_in_results(crawler, test_url + "/index.html", paths) - assert content_in_results(crawler, test_url + "/page1.html", paths) - assert content_in_results(crawler, test_url + "/page2.html", paths) - assert content_in_results(crawler, test_url + "/page1_subpage1.html", paths) - assert content_in_results(crawler, test_url + "/page1_subpage2.html", paths) - assert content_in_results(crawler, test_url + "/page2_subpage1.html", paths) diff --git a/test/nodes/test_diversity_ranker.py b/test/nodes/test_diversity_ranker.py deleted file mode 100644 index b64e4a8b5b..0000000000 --- a/test/nodes/test_diversity_ranker.py +++ /dev/null @@ -1,267 +0,0 @@ -from typing import List - -import pytest - -from haystack import Document -from haystack.nodes.ranker.diversity import DiversityRanker - - -# Tests that predict method returns a list of Document objects -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_returns_list_of_documents(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - query = "test query" - documents = [Document(content="doc1"), Document(content="doc2")] - result = ranker.predict(query=query, documents=documents) - assert isinstance(result, list) - assert len(result) == 2 - assert all(isinstance(doc, Document) for doc in result) - - -# Tests that predict method returns the correct number of documents -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_returns_correct_number_of_documents(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - query = "test query" - documents = [Document(content="doc1"), Document(content="doc2")] - result = ranker.predict(query=query, documents=documents, top_k=1) - assert len(result) == 1 - - -# Tests that predict method returns documents in the correct order -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_returns_documents_in_correct_order(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - query = "city" - documents = [ - Document("France"), - Document("Germany"), - Document("Eiffel Tower"), - Document("Berlin"), - Document("bananas"), - Document("Silicon Valley"), - Document("Brandenburg Gate"), - ] - result = ranker.predict(query=query, documents=documents) - expected_order = "Berlin, bananas, Eiffel Tower, Silicon Valley, France, Brandenburg Gate, Germany" - assert ", ".join([doc.content for doc in result]) == expected_order - - -# Tests that predict_batch method returns a list of lists of Document objects -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_batch_returns_list_of_lists_of_documents(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - queries = ["test query 1", "test query 2"] - documents = [ - [Document(content="doc1"), Document(content="doc2")], - [Document(content="doc3"), Document(content="doc4")], - ] - result: List[List[Document]] = ranker.predict_batch(queries=queries, documents=documents) - assert isinstance(result, list) - assert all(isinstance(docs, list) for docs in result) - assert all(isinstance(doc, Document) for docs in result for doc in docs) - - -# Tests that predict_batch method returns the correct number of documents -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_batch_returns_correct_number_of_documents(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - queries = ["test query 1", "test query 2"] - documents = [ - [Document(content="doc1"), Document(content="doc2")], - [Document(content="doc3"), Document(content="doc4")], - ] - result: List[List[Document]] = ranker.predict_batch(queries=queries, documents=documents, top_k=1) - assert len(result) == 2 - assert len(result[0]) == 1 - assert len(result[1]) == 1 - - -# Tests that predict_batch method returns documents in the correct order -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_batch_returns_documents_in_correct_order(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - queries = ["Berlin", "Paris"] - documents = [ - [Document(content="Germany"), Document(content="Munich"), Document(content="agriculture")], - [Document(content="France"), Document(content="Space exploration"), Document(content="Eiffel Tower")], - ] - result: List[List[Document]] = ranker.predict_batch(queries=queries, documents=documents) - assert len(result) == 2 - - # check the correct most diverse order are in batches - expected_order_0 = "Germany, agriculture, Munich" - expected_order_1 = "France, Space exploration, Eiffel Tower" - assert ", ".join([doc.content for doc in result[0]]) == expected_order_0 - assert ", ".join([doc.content for doc in result[1]]) == expected_order_1 - - -# Tests that predict method returns the correct number of documents for a single document -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_single_document_corner_case(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - query = "test" - documents = [Document(content="doc1")] - result = ranker.predict(query=query, documents=documents) - assert len(result) == 1 - - -# Tests that predict method raises ValueError if query is empty -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_raises_value_error_if_query_is_empty(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - query = "" - documents = [Document(content="doc1"), Document(content="doc2")] - with pytest.raises(ValueError): - ranker.predict(query=query, documents=documents) - - -# Tests that predict method raises ValueError if documents is empty -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_raises_value_error_if_documents_is_empty(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - query = "test query" - documents = [] - with pytest.raises(ValueError): - ranker.predict(query=query, documents=documents) - - -# Tests that predict_batch method raises ValueError if queries is empty -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_batch_raises_value_error_if_queries_is_empty(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - queries = [] - documents = [ - [Document(content="doc1"), Document(content="doc2")], - [Document(content="doc3"), Document(content="doc4")], - ] - with pytest.raises(ValueError): - ranker.predict_batch(queries=queries, documents=documents) - - -# Tests that predict_batch method raises ValueError if documents is empty -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_batch_raises_value_error_if_documents_is_empty(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - queries = ["test query 1", "test query 2"] - documents = [] - with pytest.raises(ValueError): - ranker.predict_batch(queries=queries, documents=documents) - - -@pytest.mark.integration -@pytest.mark.parametrize("similarity", ["dot_product", "cosine"]) -def test_predict_real_world_use_case(similarity: str): - ranker = DiversityRanker(similarity=similarity) # type: ignore - query = "What are the reasons for long-standing animosities between Russia and Poland?" - - doc1 = Document( - "One of the earliest known events in Russian-Polish history dates back to 981, when the Grand Prince of Kiev , " - "Vladimir Svyatoslavich , seized the Cherven Cities from the Duchy of Poland . The relationship between two by " - "that time was mostly close and cordial, as there had been no serious wars between both. In 966, Poland " - "accepted Christianity from Rome while Kievan Rus' —the ancestor of Russia, Ukraine and Belarus—was " - "Christianized by Constantinople. In 1054, the internal Christian divide formally split the Church into " - "the Catholic and Orthodox branches separating the Poles from the Eastern Slavs." - ) - - doc2 = Document( - "Since the fall of the Soviet Union , with Lithuania , Ukraine and Belarus regaining independence, the " - "Polish–Russian border has mostly been replaced by borders with the respective countries, but there still " - "is a 210 km long border between Poland and the Kaliningrad Oblast" - ) - - doc3 = Document( - "As part of Poland's plans to become fully energy independent from Russia within the next years, Piotr " - "Wozniak, president of state-controlled oil and gas company PGNiG , stated in February 2019: 'The strategy of " - "the company is just to forget about Eastern suppliers and especially about Gazprom .'[53] In 2020, the " - "Stockholm Arbitral Tribunal ruled that PGNiG's long-term contract gas price with Gazprom linked to oil prices " - "should be changed to approximate the Western European gas market price, backdated to 1 November 2014 when " - "PGNiG requested a price review under the contract. Gazprom had to refund about $1.5 billion to PGNiG." - ) - - doc4 = Document( - "Both Poland and Russia had accused each other for their historical revisionism . Russia has repeatedly " - "accused Poland for not honoring Soviet Red Army soldiers fallen in World War II for Poland, notably in " - "2017, in which Poland was thought on 'attempting to impose its own version of history' after Moscow was " - "not allowed to join an international effort to renovate a World War II museum at Sobibór , site of a " - "notorious Sobibor extermination camp." - ) - - doc5 = Document( - "President of Russia Vladimir Putin and Prime Minister of Poland Leszek Miller in 2002 Modern Polish–Russian " - "relations begin with the fall of communism – 1989 in Poland ( Solidarity and the Polish Round Table " - "Agreement ) and 1991 in Russia ( dissolution of the Soviet Union ). With a new democratic government after " - "the 1989 elections , Poland regained full sovereignty, [2] and what was the Soviet Union, became 15 newly " - "independent states , including the Russian Federation . Relations between modern Poland and Russia suffer " - "from constant ups and downs." - ) - - doc6 = Document( - "Soviet influence in Poland finally ended with the Round Table Agreement of 1989 guaranteeing free elections " - "in Poland, the Revolutions of 1989 against Soviet-sponsored Communist governments in the Eastern Bloc , and " - "finally the formal dissolution of the Warsaw Pact." - ) - - doc7 = Document( - "Dmitry Medvedev and then Polish Prime Minister Donald Tusk , 6 December 2010 BBC News reported that one of " - "the main effects of the 2010 Polish Air Force Tu-154 crash would be the impact it has on Russian-Polish " - "relations. [38] It was thought if the inquiry into the crash were not transparent, it would increase " - "suspicions toward Russia in Poland." - ) - - doc8 = Document( - "Soviet control over the Polish People's Republic lessened after Stalin's death and Gomułka's Thaw , and " - "ceased completely after the fall of the communist government in Poland in late 1989, although the " - "Soviet-Russian Northern Group of Forces did not leave Polish soil until 1993. The continuing Soviet military " - "presence allowed the Soviet Union to heavily influence Polish politics." - ) - - documents = [doc1, doc2, doc3, doc4, doc5, doc6, doc7, doc8] - result = ranker.predict(query=query, documents=documents) - expected_order = [doc5, doc7, doc3, doc1, doc4, doc2, doc6, doc8] - assert result == expected_order - - -@pytest.mark.integration -def test_diversity_ranker_with_top_k(): - # Tests that predict method returns the correct order of documents - ranker = DiversityRanker(similarity="cosine", top_k=1) - query = "test" - documents = [Document(content="doc1"), Document(content="doc2"), Document(content="doc3")] - result = ranker.predict(query=query, documents=documents) - assert len(result) == 1 - - -@pytest.mark.integration -def test_diversity_ranker_with_top_k_edge(): - # Tests that predict method returns the correct order of documents for edge cases - ranker = DiversityRanker(similarity="cosine", top_k=5) - query = "test" - documents = [Document(content="doc1"), Document(content="doc2"), Document(content="doc3")] - result = ranker.predict(query=query, documents=documents) - assert len(result) == 3 - - # negative top_k should return empty list - ranker = DiversityRanker(similarity="cosine", top_k=-5) - query = "test" - documents = [Document(content="doc1"), Document(content="doc2"), Document(content="doc3")] - result = ranker.predict(query=query, documents=documents) - assert len(result) == 0 - - # we know None is ignored in slice notation, but let's make sure it works - ranker = DiversityRanker(similarity="cosine", top_k=None) - query = "test" - documents = [Document(content="doc1"), Document(content="doc2"), Document(content="doc3")] - result = ranker.predict(query=query, documents=documents) - assert len(result) == 3 diff --git a/test/nodes/test_doc_language_classifier.py b/test/nodes/test_doc_language_classifier.py deleted file mode 100644 index 65a167cb71..0000000000 --- a/test/nodes/test_doc_language_classifier.py +++ /dev/null @@ -1,121 +0,0 @@ -import pytest -import logging - -from haystack.schema import Document -from haystack.nodes.doc_language_classifier import ( - LangdetectDocumentLanguageClassifier, - TransformersDocumentLanguageClassifier, -) - -LANGUAGES_TO_ROUTE = ["en", "es", "it"] -DOCUMENTS = [ - Document(content="My name is Matteo and I live in Rome"), - Document(content="Mi chiamo Matteo e vivo a Roma"), - Document(content="Mi nombre es Matteo y vivo en Roma"), -] - -EXPECTED_LANGUAGES = ["en", "it", "es"] -EXPECTED_OUTPUT_EDGES = ["output_1", "output_3", "output_2"] - - -@pytest.fixture(params=["langdetect", "transformers"]) -def doclangclassifier(request): - if request.param == "langdetect": - return LangdetectDocumentLanguageClassifier(route_by_language=True, languages_to_route=LANGUAGES_TO_ROUTE) - elif request.param == "transformers": - return TransformersDocumentLanguageClassifier( - route_by_language=True, - languages_to_route=LANGUAGES_TO_ROUTE, - model_name_or_path="jb2k/bert-base-multilingual-cased-language-detection", - labels_to_languages_mapping={"LABEL_11": "en", "LABEL_22": "it", "LABEL_38": "es"}, - ) - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect", "transformers"], indirect=True) -def test_doclangclassifier_predict(doclangclassifier): - results = doclangclassifier.predict(documents=DOCUMENTS) - for doc, expected_language in zip(results, EXPECTED_LANGUAGES): - assert doc.to_dict()["meta"]["language"] == expected_language - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["transformers"], indirect=True) -def test_transformers_doclangclassifier_predict_wo_mapping(doclangclassifier): - doclangclassifier.labels_to_languages_mapping = {} - expected_labels = ["LABEL_11", "LABEL_22", "LABEL_38"] - results = doclangclassifier.predict(documents=DOCUMENTS) - for doc, expected_label in zip(results, expected_labels): - assert doc.to_dict()["meta"]["language"] == expected_label - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect", "transformers"], indirect=True) -def test_doclangclassifier_predict_batch(doclangclassifier): - results = doclangclassifier.predict_batch(documents=[DOCUMENTS, DOCUMENTS[:2]]) - expected_languages = [EXPECTED_LANGUAGES, EXPECTED_LANGUAGES[:2]] - for lst_docs, lst_expected_languages in zip(results, expected_languages): - for doc, expected_language in zip(lst_docs, lst_expected_languages): - assert doc.to_dict()["meta"]["language"] == expected_language - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect", "transformers"], indirect=True) -def test_doclangclassifier_run_not_route(doclangclassifier): - doclangclassifier.route_by_language = False - results, edge = doclangclassifier.run(documents=DOCUMENTS) - assert edge == "output_1" - for doc, expected_language in zip(results["documents"], EXPECTED_LANGUAGES): - assert doc.to_dict()["meta"]["language"] == expected_language - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect", "transformers"], indirect=True) -def test_doclangclassifier_run_route(doclangclassifier): - for doc, expected_language, expected_edge in zip(DOCUMENTS, EXPECTED_LANGUAGES, EXPECTED_OUTPUT_EDGES): - result, edge = doclangclassifier.run(documents=[doc]) - document = result["documents"][0] - - assert edge == expected_edge - assert document.to_dict()["meta"]["language"] == expected_language - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect", "transformers"], indirect=True) -def test_doclangclassifier_run_route_fail_on_mixed_languages(doclangclassifier): - with pytest.raises(ValueError, match="Documents of multiple languages"): - doclangclassifier.run(documents=DOCUMENTS) - - -# not testing transformers because current models always predict a language -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect"], indirect=True) -def test_doclangclassifier_run_route_cannot_detect_language(doclangclassifier, caplog): - doc_unidentifiable_lang = Document("01234, 56789, ") - with caplog.at_level(logging.INFO): - results, edge = doclangclassifier.run(documents=[doc_unidentifiable_lang]) - assert "The model cannot detect the language of any of the documents." in caplog.text - assert edge == "output_1" - assert results["documents"][0].to_dict()["meta"]["language"] is None - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect", "transformers"], indirect=True) -def test_doclangclassifier_run_route_fail_on_language_not_in_list(doclangclassifier, caplog): - doc_other_lang = Document("Meu nome é Matteo e moro em Roma") - with pytest.raises(ValueError, match="is not in the list of languages to route"): - doclangclassifier.run(documents=[doc_other_lang]) - - -@pytest.mark.integration -@pytest.mark.parametrize("doclangclassifier", ["langdetect", "transformers"], indirect=True) -def test_doclangclassifier_run_batch(doclangclassifier): - docs = [[doc] for doc in DOCUMENTS] - results, split_edge = doclangclassifier.run_batch(documents=docs) - assert split_edge == "split" - for edge, result in results.items(): - document = result["documents"][0][0] - num_document = DOCUMENTS.index(document) - expected_language = EXPECTED_LANGUAGES[num_document] - assert edge == EXPECTED_OUTPUT_EDGES[num_document] - assert document.to_dict()["meta"]["language"] == expected_language diff --git a/test/nodes/test_document_classifier.py b/test/nodes/test_document_classifier.py deleted file mode 100644 index d0356568a7..0000000000 --- a/test/nodes/test_document_classifier.py +++ /dev/null @@ -1,139 +0,0 @@ -import pytest - -from haystack.schema import Document -from haystack.nodes.document_classifier.base import BaseDocumentClassifier - - -@pytest.mark.integration -def test_document_classifier(document_classifier): - assert isinstance(document_classifier, BaseDocumentClassifier) - - docs = [ - Document( - content="""That's good. I like it.""" * 700, # extra long text to check truncation - meta={"name": "0"}, - id="1", - ), - Document(content="""That's bad. I don't like it.""", meta={"name": "1"}, id="2"), - ] - results = document_classifier.predict(documents=docs) - expected_labels = ["joy", "sadness"] - for i, doc in enumerate(results): - assert doc.to_dict()["meta"]["classification"]["label"] == expected_labels[i] - - -@pytest.mark.integration -def test_document_classifier_details(document_classifier): - docs = [Document(content="""That's good. I like it."""), Document(content="""That's bad. I don't like it.""")] - results = document_classifier.predict(documents=docs) - for doc in results: - assert "details" in doc.meta["classification"] - if document_classifier.top_k is not None: - assert len(doc.meta["classification"]["details"]) == document_classifier.top_k - - -@pytest.mark.integration -def test_document_classifier_batch_single_doc_list(document_classifier): - docs = [ - Document(content="""That's good. I like it.""", meta={"name": "0"}, id="1"), - Document(content="""That's bad. I don't like it.""", meta={"name": "1"}, id="2"), - ] - results = document_classifier.predict_batch(documents=docs) - expected_labels = ["joy", "sadness"] - for i, doc in enumerate(results): - assert doc.to_dict()["meta"]["classification"]["label"] == expected_labels[i] - - -@pytest.mark.integration -def test_document_classifier_batch_multiple_doc_lists(document_classifier): - docs = [ - Document(content="""That's good. I like it.""", meta={"name": "0"}, id="1"), - Document(content="""That's bad. I don't like it.""", meta={"name": "1"}, id="2"), - ] - results = document_classifier.predict_batch(documents=[docs, docs]) - assert len(results) == 2 # 2 Document lists - expected_labels = ["joy", "sadness"] - for i, doc in enumerate(results[0]): - assert doc.to_dict()["meta"]["classification"]["label"] == expected_labels[i] - - -@pytest.mark.integration -def test_zero_shot_document_classifier(zero_shot_document_classifier): - assert isinstance(zero_shot_document_classifier, BaseDocumentClassifier) - - docs = [ - Document( - content="""That's good. I like it.""" * 700, # extra long text to check truncation - meta={"name": "0"}, - id="1", - ), - Document(content="""That's bad. I don't like it.""", meta={"name": "1"}, id="2"), - ] - results = zero_shot_document_classifier.predict(documents=docs) - expected_labels = ["positive", "negative"] - for i, doc in enumerate(results): - assert doc.to_dict()["meta"]["classification"]["label"] == expected_labels[i] - - -@pytest.mark.integration -def test_zero_shot_document_classifier_details(zero_shot_document_classifier): - docs = [Document(content="""That's good. I like it."""), Document(content="""That's bad. I don't like it.""")] - results = zero_shot_document_classifier.predict(documents=docs) - for doc in results: - assert "details" in doc.meta["classification"] - assert set(doc.meta["classification"]["details"].keys()) == set(zero_shot_document_classifier.labels) - - -@pytest.mark.integration -def test_document_classifier_batch_size(batched_document_classifier): - assert isinstance(batched_document_classifier, BaseDocumentClassifier) - - docs = [ - Document( - content="""That's good. I like it.""" * 700, # extra long text to check truncation - meta={"name": "0"}, - id="1", - ), - Document(content="""That's bad. I don't like it.""", meta={"name": "1"}, id="2"), - ] - results = batched_document_classifier.predict(documents=docs) - expected_labels = ["joy", "sadness"] - for i, doc in enumerate(results): - assert doc.to_dict()["meta"]["classification"]["label"] == expected_labels[i] - - -@pytest.mark.integration -def test_document_classifier_as_index_node(indexing_document_classifier): - assert isinstance(indexing_document_classifier, BaseDocumentClassifier) - - docs = [ - { - "content": """That's good. I like it.""" * 700, # extra long text to check truncation - "meta": {"name": "0"}, - "id": "1", - "class_field": "That's bad.", - }, - {"content": """That's bad. I like it.""", "meta": {"name": "1"}, "id": "2", "class_field": "That's good."}, - ] - output, output_name = indexing_document_classifier.run(documents=docs, root_node="File") - expected_labels = ["sadness", "joy"] - for i, doc in enumerate(output["documents"]): - assert doc["meta"]["classification"]["label"] == expected_labels[i] - - -@pytest.mark.integration -def test_document_classifier_as_query_node(document_classifier): - assert isinstance(document_classifier, BaseDocumentClassifier) - - docs = [ - Document( - content="""That's good. I like it.""" * 700, # extra long text to check truncation - meta={"name": "0"}, - id="1", - ), - Document(content="""That's bad. I don't like it.""", meta={"name": "1"}, id="2"), - ] - output, output_name = document_classifier.run(documents=docs, root_node="Query") - expected_labels = ["joy", "sadness"] - for i, doc in enumerate(output["documents"]): - assert doc.to_dict()["meta"]["classification"]["label"] == expected_labels[i] diff --git a/test/nodes/test_document_merger.py b/test/nodes/test_document_merger.py deleted file mode 100644 index c7628c033d..0000000000 --- a/test/nodes/test_document_merger.py +++ /dev/null @@ -1,108 +0,0 @@ -import pytest - -from haystack import Document -from haystack.nodes.other.document_merger import DocumentMerger - - -@pytest.fixture -def doc_dicts(): - return [ - { - "meta": { - "name": "name_1", - "year": "2020", - "month": "01", - "flat_field": 1, - "nested_field": {1: 2, "a": 5, "c": {"3": 3}, "d": "I will be dropped by the meta merge algorithm"}, - }, - "content": "text_1", - }, - { - "meta": { - "name": "name_2", - "year": "2020", - "month": "02", - "flat_field": 1, - "nested_field": {1: 2, "a": 5, "c": {"3": 3}}, - }, - "content": "text_2", - }, - { - "meta": { - "name": "name_3", - "year": "2020", - "month": "03", - "flat_field": 1, - "nested_field": {1: 2, "a": 7, "c": {"3": 3}}, - }, - "content": "text_3", - }, - { - "meta": { - "name": "name_4", - "year": "2021", - "month": "01", - "flat_field": 1, - "nested_field": {1: 2, "a": 5, "c": {"3": 3}}, - }, - "content": "text_4", - }, - { - "meta": { - "name": "name_5", - "year": "2021", - "month": "02", - "flat_field": 1, - "nested_field": {1: 2, "a": 5, "c": {"3": 3}}, - }, - "content": "text_5", - }, - { - "meta": { - "name": "name_6", - "year": "2021", - "month": "03", - "flat_field": 1, - "nested_field": {1: 2, "a": 5, "c": {"3": 3}}, - }, - "content": "text_6", - }, - ] - - -@pytest.fixture -def documents(doc_dicts): - return [Document.from_dict(doc) for doc in doc_dicts] - - -@pytest.mark.unit -def test_document_merger_merge(documents, doc_dicts): - separator = "|" - dm = DocumentMerger(separator=separator) - merged_list = dm.merge(documents) - - assert len(merged_list) == 1 - assert merged_list[0].content == separator.join([doc["content"] for doc in doc_dicts]) - assert merged_list[0].meta == {"flat_field": 1, "nested_field": {1: 2, "c": {"3": 3}}} - - -@pytest.mark.unit -def test_document_merger_run(documents, doc_dicts): - separator = "|" - dm = DocumentMerger(separator=separator) - result = dm.run(documents) - - assert len(result[0]["documents"]) == 1 - assert result[0]["documents"][0].content == separator.join([doc["content"] for doc in doc_dicts]) - assert result[0]["documents"][0].meta == {"flat_field": 1, "nested_field": {1: 2, "c": {"3": 3}}} - - -@pytest.mark.unit -def test_document_merger_run_batch(documents, doc_dicts): - separator = "|" - dm = DocumentMerger(separator=separator) - batch_result = dm.run_batch([documents, documents]) - - assert len(batch_result[0]["documents"]) == 2 - assert batch_result[0]["documents"][0][0].content == separator.join([doc["content"] for doc in doc_dicts]) - assert batch_result[0]["documents"][0][0].meta == {"flat_field": 1, "nested_field": {1: 2, "c": {"3": 3}}} diff --git a/test/nodes/test_extractor.py b/test/nodes/test_extractor.py deleted file mode 100644 index 2a764a9047..0000000000 --- a/test/nodes/test_extractor.py +++ /dev/null @@ -1,235 +0,0 @@ -import pytest - -from haystack.nodes import TextConverter -from haystack.nodes.retriever.sparse import BM25Retriever -from haystack.nodes.reader import FARMReader -from haystack.pipelines import Pipeline -from haystack import Document - -from haystack.nodes.extractor import EntityExtractor, simplify_ner_for_qa - - -@pytest.fixture -def tiny_reader(): - return FARMReader(model_name_or_path="deepset/tinyroberta-squad2", num_processes=0) - - -@pytest.fixture -def ner_node(): - return EntityExtractor(model_name_or_path="elastic/distilbert-base-cased-finetuned-conll03-english") - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_extractor(document_store_with_docs, tiny_reader, ner_node): - es_retriever = BM25Retriever(document_store=document_store_with_docs) - - pipeline = Pipeline() - pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["Query"]) - pipeline.add_node(component=ner_node, name="NER", inputs=["ESRetriever"]) - pipeline.add_node(component=tiny_reader, name="Reader", inputs=["NER"]) - - prediction = pipeline.run( - query="Who lives in Berlin?", params={"ESRetriever": {"top_k": 1}, "Reader": {"top_k": 1}} - ) - entities = [entity["word"] for entity in prediction["answers"][0].meta["entities"]] - assert "Carla" in entities - assert "Berlin" in entities - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_extractor_batch_single_query(document_store_with_docs, tiny_reader, ner_node): - es_retriever = BM25Retriever(document_store=document_store_with_docs) - - pipeline = Pipeline() - pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["Query"]) - pipeline.add_node(component=ner_node, name="NER", inputs=["ESRetriever"]) - pipeline.add_node(component=tiny_reader, name="Reader", inputs=["NER"]) - - prediction = pipeline.run_batch( - queries=["Who lives in Berlin?"], params={"ESRetriever": {"top_k": 1}, "Reader": {"top_k": 1}} - ) - entities = [entity["word"] for entity in prediction["answers"][0][0].meta["entities"]] - assert "Carla" in entities - assert "Berlin" in entities - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_extractor_batch_multiple_queries(document_store_with_docs, tiny_reader, ner_node): - es_retriever = BM25Retriever(document_store=document_store_with_docs) - - pipeline = Pipeline() - pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["Query"]) - pipeline.add_node(component=ner_node, name="NER", inputs=["ESRetriever"]) - pipeline.add_node(component=tiny_reader, name="Reader", inputs=["NER"]) - - prediction = pipeline.run_batch( - queries=["Who lives in Berlin?", "Who lives in New York?"], - params={"ESRetriever": {"top_k": 1}, "Reader": {"top_k": 1}}, - ) - entities_carla = [entity["word"] for entity in prediction["answers"][0][0].meta["entities"]] - entities_paul = [entity["word"] for entity in prediction["answers"][1][0].meta["entities"]] - assert "Carla" in entities_carla - assert "Berlin" in entities_carla - assert "Paul" in entities_paul - assert "New York" in entities_paul - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_extractor_output_simplifier(document_store_with_docs, tiny_reader, ner_node): - es_retriever = BM25Retriever(document_store=document_store_with_docs) - - pipeline = Pipeline() - pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["Query"]) - pipeline.add_node(component=ner_node, name="NER", inputs=["ESRetriever"]) - pipeline.add_node(component=tiny_reader, name="Reader", inputs=["NER"]) - - prediction = pipeline.run( - query="Who lives in Berlin?", params={"ESRetriever": {"top_k": 1}, "Reader": {"top_k": 1}} - ) - simplified = simplify_ner_for_qa(prediction) - assert simplified[0] == {"answer": "Carla and I", "entities": ["Carla"]} - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -def test_extractor_indexing(document_store, samples_path): - doc_path = samples_path / "docs" / "doc_2.txt" - - text_converter = TextConverter() - ner = EntityExtractor( - model_name_or_path="elastic/distilbert-base-cased-finetuned-conll03-english", flatten_entities_in_meta_data=True - ) - - pipeline = Pipeline() - pipeline.add_node(component=text_converter, name="TextConverter", inputs=["File"]) - pipeline.add_node(component=ner, name="NER", inputs=["TextConverter"]) - pipeline.add_node(component=document_store, name="DocumentStore", inputs=["NER"]) - _ = pipeline.run(file_paths=doc_path) - docs = document_store.get_all_documents() - meta = docs[0].meta - assert "ORG" in meta["entity_groups"] - assert "Haystack" in meta["entity_words"] - - -@pytest.mark.integration -def test_extractor_doc_query(ner_node): - pipeline = Pipeline() - pipeline.add_node(component=ner_node, name="NER", inputs=["Query"]) - - prediction = pipeline.run(query=None, documents=[Document(content="Carla lives in Berlin", content_type="text")]) - entities = [x["word"] for x in prediction["documents"][0].meta["entities"]] - assert "Carla" in entities - assert "Berlin" in entities - - -@pytest.mark.integration -def test_extract_method(): - ner = EntityExtractor( - model_name_or_path="Jean-Baptiste/camembert-ner", max_seq_len=12, aggregation_strategy="first" - ) - - text = "Hello my name is Arya. I live in Winterfell and my brother is Jon Snow." - output = ner.extract(text) - for x in output: - x.pop("score") - assert output == [ - {"entity_group": "PER", "word": "Arya.", "start": 16, "end": 22}, - {"entity_group": "LOC", "word": "Winterfell", "start": 32, "end": 43}, - {"entity_group": "PER", "word": "Jon Snow.", "start": 61, "end": 71}, - ] - - text_batch = [text for _ in range(3)] - batch_size = 2 - output = ner.extract_batch(text_batch, batch_size=batch_size) - for item in output: - for x in item: - x.pop("score") - for item in output: - assert item == [ - {"entity_group": "PER", "word": "Arya.", "start": 16, "end": 22}, - {"entity_group": "LOC", "word": "Winterfell", "start": 32, "end": 43}, - {"entity_group": "PER", "word": "Jon Snow.", "start": 61, "end": 71}, - ] - - -@pytest.mark.integration -def test_extract_method_pre_split_text(): - ner = EntityExtractor( - model_name_or_path="elastic/distilbert-base-cased-finetuned-conll03-english", max_seq_len=6, pre_split_text=True - ) - - text = "Hello my name is Arya. I live in Winterfell and my brother is Jon Snow." - output = ner.extract(text) - for x in output: - x.pop("score") - assert output == [ - {"entity_group": "PER", "word": "Arya.", "start": 17, "end": 22}, - {"entity_group": "LOC", "word": "Winterfell", "start": 33, "end": 43}, - {"entity_group": "PER", "word": "Jon Snow.", "start": 62, "end": 71}, - ] - - text_batch = [text for _ in range(3)] - batch_size = 2 - output = ner.extract_batch(text_batch, batch_size=batch_size) - for item in output: - for x in item: - x.pop("score") - for item in output: - assert item == [ - {"entity_group": "PER", "word": "Arya.", "start": 17, "end": 22}, - {"entity_group": "LOC", "word": "Winterfell", "start": 33, "end": 43}, - {"entity_group": "PER", "word": "Jon Snow.", "start": 62, "end": 71}, - ] - - -@pytest.mark.integration -def test_extract_method_unknown_token(): - ner = EntityExtractor( - model_name_or_path="elastic/distilbert-base-cased-finetuned-conll03-english", - max_seq_len=6, - pre_split_text=True, - ignore_labels=[], - ) - - text = "Hi my name is JamesÐ." - output = ner.extract(text) - for x in output: - x.pop("score") - assert output == [{"entity_group": "O", "word": "Hi my name is JamesÐ.", "start": 0, "end": 21}] - - # Different statement in word detection for unknown tokens used when pre_split_text=False - ner = EntityExtractor( - model_name_or_path="elastic/distilbert-base-cased-finetuned-conll03-english", - max_seq_len=6, - pre_split_text=False, - ignore_labels=[], - ) - - text = "Hi my name is JamesÐ." - output = ner.extract(text) - for x in output: - x.pop("score") - assert output == [{"entity_group": "O", "word": "Hi my name is JamesÐ.", "start": 0, "end": 21}] - - -@pytest.mark.integration -def test_extract_method_simple_aggregation(): - ner = EntityExtractor( - model_name_or_path="elastic/distilbert-base-cased-finetuned-conll03-english", - max_seq_len=6, - aggregation_strategy="simple", - ) - - text = "I live in Berlin with my wife Debra." - output = ner.extract(text) - for x in output: - x.pop("score") - assert output == [ - {"entity_group": "LOC", "word": "Berlin", "start": 10, "end": 16}, - {"entity_group": "PER", "word": "De", "start": 30, "end": 32}, - {"entity_group": "LOC", "word": "##bra", "start": 32, "end": 35}, - ] diff --git a/test/nodes/test_file_converter.py b/test/nodes/test_file_converter.py deleted file mode 100644 index 9daee4b587..0000000000 --- a/test/nodes/test_file_converter.py +++ /dev/null @@ -1,631 +0,0 @@ -import csv -import json -import os -import subprocess -import sys -import warnings -from pathlib import Path -from typing import List -from unittest.mock import patch - -import pandas as pd -import pytest - -from haystack import Document -from haystack.nodes import ( - AzureConverter, - CsvTextConverter, - DocxToTextConverter, - PptxConverter, - JsonConverter, - MarkdownConverter, - ParsrConverter, - PDFToTextConverter, - PreProcessor, - TextConverter, - TikaConverter, -) - - -@pytest.mark.tika -@pytest.mark.parametrize("Converter", [PDFToTextConverter, TikaConverter]) -def test_convert(Converter, samples_path): - converter = Converter() - document = converter.run(file_paths=samples_path / "pdf" / "sample_pdf_1.pdf")[0]["documents"][0] - pages = document.content.split("\f") - - assert ( - len(pages) != 1 and pages[0] != "" - ), f'{type(converter).__name__} did return a single empty page indicating a potential issue with your installed poppler version. Try installing via "conda install -c conda-forge poppler" and check test_pdftoppm_command_format()' - - assert len(pages) == 4 # the sample PDF file has four pages. - assert pages[0] != "" # the page 1 of PDF contains text. - assert pages[2] == "" # the page 3 of PDF file is empty. - # assert text is retained from the document. - # As whitespace can differ (\n," ", etc.), we standardize all to simple whitespace - page_standard_whitespace = " ".join(pages[0].split()) - assert "Adobe Systems made the PDF specification available free of charge in 1993." in page_standard_whitespace - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_command_whitespaces(Converter, samples_path): - converter = Converter() - - document = converter.run(file_paths=samples_path / "pdf" / "sample pdf file with spaces on file name.pdf")[0][ - "documents" - ][0] - assert "ɪ" in document.content - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_encoding(Converter, samples_path): - converter = Converter() - - document = converter.run(file_paths=samples_path / "pdf" / "sample_pdf_5.pdf")[0]["documents"][0] - assert "Ж" in document.content - - document = converter.run(file_paths=samples_path / "pdf" / "sample_pdf_2.pdf")[0]["documents"][0] - assert "ɪ" in document.content - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_sort_by_position(Converter, samples_path): - converter = Converter(sort_by_position=True) - - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_3.pdf")[0] - assert str(document.content).startswith("This is the second test sentence.") - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_ligatures(Converter, samples_path): - converter = Converter() - - document = converter.run(file_paths=samples_path / "pdf" / "sample_pdf_2.pdf")[0]["documents"][0] - assert "ff" not in document.content - assert "ɪ" in document.content - - document = converter.run(file_paths=samples_path / "pdf" / "sample_pdf_2.pdf", known_ligatures={})[0]["documents"][ - 0 - ] - assert "ff" in document.content - assert "ɪ" in document.content - - document = converter.run(file_paths=samples_path / "pdf" / "sample_pdf_2.pdf", known_ligatures={"ɪ": "i"})[0][ - "documents" - ][0] - assert "ff" in document.content - assert "ɪ" not in document.content - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_page_range(Converter, samples_path): - converter = Converter() - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_1.pdf", start_page=2)[0] - pages = document.content.split("\f") - - assert ( - len(pages) == 4 - ) # the sample PDF file has four pages, we skipped first (but we wanna correct number of pages) - assert pages[0] == "" # the page 1 was skipped. - assert pages[1] != "" # the page 2 is not empty. - assert pages[2] == "" # the page 3 is empty. - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_page_range_numbers(Converter, samples_path): - converter = Converter() - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_1.pdf", start_page=2)[0] - - preprocessor = PreProcessor( - split_by="word", split_length=5, split_overlap=0, split_respect_sentence_boundary=False, add_page_number=True - ) - documents = preprocessor.process([document]) - - assert documents[1].meta["page"] == 4 - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_parallel(Converter, samples_path): - converter = Converter(multiprocessing=True) - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_6.pdf")[0] - - pages = document.content.split("\f") - - assert pages[0] == "This is the page 1 of the document." - assert pages[-1] == "This is the page 50 of the document." - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_parallel_page_range(Converter, samples_path): - converter = Converter(multiprocessing=True) - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_6.pdf", start_page=2)[0] - - pages = document.content.split("\f") - - assert pages[0] == "" - assert len(pages) == 50 - - -@pytest.mark.unit -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_parallel_sort_by_position(Converter, samples_path): - converter = Converter(multiprocessing=True, sort_by_position=True) - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_6.pdf")[0] - - pages = document.content.split("\f") - - assert pages[0] == "This is the page 1 of the document." - assert pages[-1] == "This is the page 50 of the document." - - -@pytest.mark.integration -@pytest.mark.parametrize("Converter", [PDFToTextConverter]) -def test_pdf_parallel_ocr(Converter, samples_path): - converter = Converter(multiprocessing=True, sort_by_position=True, ocr="full", ocr_language="eng") - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_6.pdf")[0] - - pages = document.content.split("\f") - - assert pages[0] == "This is the page 1 of the document." - assert pages[-1] == "This is the page 50 of the document." - - -@pytest.mark.tika -@pytest.mark.parametrize("Converter", [PDFToTextConverter, TikaConverter]) -def test_table_removal(Converter, samples_path): - converter = Converter(remove_numeric_tables=True) - document = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_1.pdf")[0] - pages = document.content.split("\f") - # assert numeric rows are removed from the table. - assert "324" not in pages[0] - assert "54x growth" not in pages[0] - - -@pytest.mark.tika -@pytest.mark.parametrize("Converter", [PDFToTextConverter, TikaConverter]) -def test_language_validation(Converter, caplog, samples_path): - converter = Converter(valid_languages=["en"]) - converter.convert(file_path=samples_path / "pdf" / "sample_pdf_1.pdf") - assert "sample_pdf_1.pdf is not one of ['en']." not in caplog.text - - converter = Converter(valid_languages=["de"]) - converter.convert(file_path=samples_path / "pdf" / "sample_pdf_1.pdf") - assert "sample_pdf_1.pdf is not one of ['de']." in caplog.text - - -@pytest.mark.unit -def test_docx_converter(samples_path): - converter = DocxToTextConverter() - document = converter.convert(file_path=samples_path / "docx" / "sample_docx.docx")[0] - assert document.content.startswith("Sample Docx File") - - -@pytest.mark.unit -def test_pptx_converter(samples_path): - converter = PptxConverter() - document = converter.convert(file_path=samples_path / "pptx" / "sample_pptx.pptx")[0] - assert document.content.startswith("Sample Pptx File") - - -@pytest.mark.unit -def test_markdown_converter(samples_path): - converter = MarkdownConverter() - document = converter.convert(file_path=samples_path / "markdown" / "sample.md")[0] - assert document.content.startswith("\nWhat to build with Haystack") - assert "# git clone https://github.com/deepset-ai/haystack.git" not in document.content - - -@pytest.mark.unit -def test_markdown_converter_headline_extraction(samples_path): - expected_headlines = [ - ("What to build with Haystack", 1), - ("Core Features", 1), - ("Quick Demo", 1), - ("2nd level headline for testing purposes", 2), - ("3rd level headline for testing purposes", 3), - ] - - converter = MarkdownConverter(extract_headlines=True, remove_code_snippets=False) - document = converter.convert(file_path=samples_path / "markdown" / "sample.md")[0] - - # Check if correct number of headlines are extracted - assert len(document.meta["headlines"]) == 5 - for extracted_headline, (expected_headline, expected_level) in zip(document.meta["headlines"], expected_headlines): - # Check if correct headline and level is extracted - assert extracted_headline["headline"] == expected_headline - assert extracted_headline["level"] == expected_level - - # Check if correct start_idx is extracted - start_idx = extracted_headline["start_idx"] - hl_len = len(extracted_headline["headline"]) - assert extracted_headline["headline"] == document.content[start_idx : start_idx + hl_len] - - -@pytest.mark.unit -def test_markdown_converter_frontmatter_to_meta(samples_path): - converter = MarkdownConverter(add_frontmatter_to_meta=True) - document = converter.convert(file_path=samples_path / "markdown" / "sample.md")[0] - assert document.meta["type"] == "intro" - assert document.meta["date"] == "1.1.2023" - - -@pytest.mark.unit -def test_markdown_converter_remove_code_snippets(samples_path): - converter = MarkdownConverter(remove_code_snippets=False) - document = converter.convert(file_path=samples_path / "markdown" / "sample.md")[0] - assert document.content.startswith("pip install farm-haystack") - - -def test_azure_converter(samples_path): - # Check if Form Recognizer endpoint and credential key in environment variables - if "AZURE_FORMRECOGNIZER_ENDPOINT" in os.environ and "AZURE_FORMRECOGNIZER_KEY" in os.environ: - converter = AzureConverter( - endpoint=os.environ["AZURE_FORMRECOGNIZER_ENDPOINT"], - credential_key=os.environ["AZURE_FORMRECOGNIZER_KEY"], - save_json=True, - ) - - docs = converter.convert(file_path=samples_path / "pdf" / "sample_pdf_1.pdf") - assert len(docs) == 2 - assert docs[0].content_type == "table" - assert docs[0].content.shape[0] == 4 # number of rows - assert docs[0].content.shape[1] == 5 # number of columns, Form Recognizer assumes there are 5 columns - assert list(docs[0].content.columns) == ["", "Column 1", "", "Column 2", "Column 3"] - assert list(docs[0].content.iloc[3]) == ["D", "$54.35", "", "$6345.", ""] - assert ( - docs[0].meta["preceding_context"] == "specification. These proprietary technologies are not " - "standardized and their\nspecification is published only on " - "Adobe's website. Many of them are also not\nsupported by " - "popular third-party implementations of PDF." - ) - assert docs[0].meta["following_context"] == "" - assert docs[0].meta["page"] == 1 - - assert docs[1].content_type == "text" - assert docs[1].content.startswith("A sample PDF file") - - -@pytest.mark.skipif(sys.platform in ["win32", "cygwin"], reason="Parsr not running on Windows CI") -def test_parsr_converter(samples_path): - converter = ParsrConverter() - - docs = converter.convert(file_path=str((samples_path / "pdf" / "sample_pdf_1.pdf").absolute())) - assert len(docs) == 2 - assert docs[0].content_type == "table" - assert docs[0].content.shape[0] == 4 # number of rows - assert docs[0].content.shape[1] == 4 - assert list(docs[0].content.columns) == ["", "Column 1", "Column 2", "Column 3"] - assert list(docs[0].content.iloc[3]) == ["D", "$54.35", "$6345.", ""] - assert ( - docs[0].meta["preceding_context"] == "specification. These proprietary technologies are not " - "standardized and their\nspecification is published only on " - "Adobe's website. Many of them are also not\nsupported by popular " - "third-party implementations of PDF." - ) - assert docs[0].meta["following_context"] == "" - assert docs[0].meta["page"] == 1 - - assert docs[1].content_type == "text" - assert docs[1].content.startswith("A sample PDF file") - assert docs[1].content.endswith("Page 4 of Sample PDF\n… the page 3 is empty.") - - -@pytest.mark.skipif(sys.platform in ["win32", "cygwin"], reason="Parsr not running on Windows CI") -def test_parsr_converter_headline_extraction(samples_path): - expected_headlines = [ - [("Lorem ipsum", 1), ("Cras fringilla ipsum magna, in fringilla dui commodo\na.", 2)], - [ - ("Lorem ipsum", 1), - ("Lorem ipsum dolor sit amet, consectetur adipiscing\nelit. Nunc ac faucibus odio.", 2), - ("Cras fringilla ipsum magna, in fringilla dui commodo\na.", 2), - ("Lorem ipsum dolor sit amet, consectetur adipiscing\nelit.", 2), - ("Maecenas mauris lectus, lobortis et purus mattis, blandit\ndictum tellus.", 2), - ("In eleifend velit vitae libero sollicitudin euismod.", 2), - ], - ] - - converter = ParsrConverter() - - docs = converter.convert(file_path=str((samples_path / "pdf" / "sample_pdf_4.pdf").absolute())) - assert len(docs) == 2 - - for doc, expectation in zip(docs, expected_headlines): - for extracted_headline, (expected_headline, expected_level) in zip(doc.meta["headlines"], expectation): - # Check if correct headline and level is extracted - assert extracted_headline["headline"] == expected_headline - assert extracted_headline["level"] == expected_level - - # Check if correct start_idx is extracted - if doc.content_type == "text": - start_idx = extracted_headline["start_idx"] - hl_len = len(extracted_headline["headline"]) - assert extracted_headline["headline"] == doc.content[start_idx : start_idx + hl_len] - - -@pytest.mark.integration -@pytest.mark.skipif(sys.platform in ["win32", "cygwin"], reason="Parsr not running on Windows CI") -def test_parsr_converter_list_mapping(samples_path): - # This exact line(without line break characters) only exists in the list object we want to make sure it's being mapped correctly - expected_list_line = "Maecenas tincidunt est efficitur ligula euismod, sit amet ornare est vulputate." - - converter = ParsrConverter() - - docs = converter.convert(file_path=str((samples_path / "pdf" / "sample_pdf_4.pdf").absolute())) - assert len(docs) == 2 - assert docs[1].content_type == "text" - assert expected_list_line in docs[1].content - - -@pytest.mark.unit -def test_id_hash_keys_from_pipeline_params(samples_path): - doc_path = samples_path / "docs" / "doc_1.txt" - meta_1 = {"key": "a"} - meta_2 = {"key": "b"} - meta = [meta_1, meta_2] - - converter = TextConverter() - output, _ = converter.run(file_paths=[doc_path, doc_path], meta=meta, id_hash_keys=["content", "meta"]) - documents = output["documents"] - unique_ids = {d.id for d in documents} - - assert len(documents) == 2 - assert len(unique_ids) == 2 - - -@pytest.mark.unit -def write_as_csv(data: List[List[str]], file_path: Path): - with open(file_path, "w") as f: - writer = csv.writer(f) - writer.writerows(data) - - -@pytest.mark.unit -def test_csv_to_document_with_qa_headers(tmp_path): - node = CsvTextConverter() - csv_path = tmp_path / "csv_qa_with_headers.csv" - rows = [ - ["question", "answer"], - ["What is Haystack ?", "Haystack is an NLP Framework to use transformers in your Applications."], - ] - write_as_csv(rows, csv_path) - - output, edge = node.run(file_paths=csv_path) - assert edge == "output_1" - assert "documents" in output - assert len(output["documents"]) == 1 - - doc = output["documents"][0] - assert isinstance(doc, Document) - assert doc.content == "What is Haystack ?" - assert doc.meta["answer"] == "Haystack is an NLP Framework to use transformers in your Applications." - - -@pytest.mark.unit -def test_csv_to_document_with_wrong_qa_headers(tmp_path): - node = CsvTextConverter() - csv_path = tmp_path / "csv_qa_with_wrong_headers.csv" - rows = [ - ["wrong", "headers"], - ["What is Haystack ?", "Haystack is an NLP Framework to use transformers in your Applications."], - ] - write_as_csv(rows, csv_path) - - with pytest.raises(ValueError, match="The CSV must contain two columns named 'question' and 'answer'"): - node.run(file_paths=csv_path) - - -@pytest.mark.unit -def test_csv_to_document_with_one_wrong_qa_headers(tmp_path): - node = CsvTextConverter() - csv_path = tmp_path / "csv_qa_with_wrong_headers.csv" - rows = [ - ["wrong", "answers"], - ["What is Haystack ?", "Haystack is an NLP Framework to use transformers in your Applications."], - ] - write_as_csv(rows, csv_path) - - with pytest.raises(ValueError, match="The CSV must contain two columns named 'question' and 'answer'"): - node.run(file_paths=csv_path) - - -@pytest.mark.unit -def test_csv_to_document_with_another_wrong_qa_headers(tmp_path): - node = CsvTextConverter() - csv_path = tmp_path / "csv_qa_with_wrong_headers.csv" - rows = [ - ["question", "wrong"], - ["What is Haystack ?", "Haystack is an NLP Framework to use transformers in your Applications."], - ] - write_as_csv(rows, csv_path) - - with pytest.raises(ValueError, match="The CSV must contain two columns named 'question' and 'answer'"): - node.run(file_paths=csv_path) - - -@pytest.mark.unit -def test_csv_to_document_with_one_column(tmp_path): - node = CsvTextConverter() - csv_path = tmp_path / "csv_qa_with_wrong_headers.csv" - rows = [["question"], ["What is Haystack ?"]] - write_as_csv(rows, csv_path) - - with pytest.raises(ValueError, match="The CSV must contain two columns named 'question' and 'answer'"): - node.run(file_paths=csv_path) - - -@pytest.mark.unit -def test_csv_to_document_with_three_columns(tmp_path): - node = CsvTextConverter() - csv_path = tmp_path / "csv_qa_with_wrong_headers.csv" - rows = [ - ["question", "answer", "notes"], - ["What is Haystack ?", "Haystack is an NLP Framework to use transformers in your Applications.", "verified"], - ] - write_as_csv(rows, csv_path) - - with pytest.raises(ValueError, match="The CSV must contain two columns named 'question' and 'answer'"): - node.run(file_paths=csv_path) - - -@pytest.mark.unit -def test_csv_to_document_many_files(tmp_path): - csv_paths = [] - for i in range(5): - node = CsvTextConverter() - csv_path = tmp_path / f"{i}_csv_qa_with_headers.csv" - csv_paths.append(csv_path) - rows = [ - ["question", "answer"], - [ - f"{i}. What is Haystack ?", - f"{i}. Haystack is an NLP Framework to use transformers in your Applications.", - ], - ] - write_as_csv(rows, csv_path) - - output, edge = node.run(file_paths=csv_paths) - assert edge == "output_1" - assert "documents" in output - assert len(output["documents"]) == 5 - - for i in range(5): - doc = output["documents"][i] - assert isinstance(doc, Document) - assert doc.content == f"{i}. What is Haystack ?" - assert doc.meta["answer"] == f"{i}. Haystack is an NLP Framework to use transformers in your Applications." - - -@pytest.mark.unit -class TestJsonConverter: - JSON_FILE_NAME = "json_normal.json" - JSONL_FILE_NAME = "json_normal.jsonl" - JSON_SINGLE_LINE_FILE_NAME = "json_all_single.json" - JSONL_LIST_LINE_FILE_NAME = "json_list_line.jsonl" - JSON_INVALID = "json_invalid.json" - - @classmethod - @pytest.fixture(autouse=True) - def setup_class(cls, tmp_path): - # Setup the documents - # Note: We are tying the behavior of `JsonConverter` - # to that of the `to_dict()` method on the `Document` - documents = [ - Document( - content=pd.DataFrame( - [["C", "Yes", "No"], ["Haskell", "No", "No"], ["Python", "Yes", "Yes"]], - columns=["Language", "Imperative", "OO"], - ), - content_type="table", - meta={"context": "Programming Languages", "page": 2}, - ), - Document( - content="Programming languages are used for controlling the behavior of a machine (often a computer).", - content_type="text", - meta={"context": "Programming Languages", "page": 1}, - ), - Document( - content=pd.DataFrame( - [["C", 1, 1], ["Python", 6, 6.5]], columns=["Language", "Statements ratio", "Line ratio"] - ), - content_type="table", - meta={"context": "Expressiveness", "page": 3}, - ), - ] - - doc_dicts_list = [d.to_dict() for d in documents] - - json_path = tmp_path / TestJsonConverter.JSON_FILE_NAME - with open(json_path, "w") as f: - json.dump(doc_dicts_list, f) - - jsonl_path = tmp_path / TestJsonConverter.JSONL_FILE_NAME - with open(jsonl_path, "w") as f: - for doc in doc_dicts_list: - f.write(json.dumps(doc) + "\n") - - # json but everything written in a single line - json_single_path = tmp_path / TestJsonConverter.JSON_SINGLE_LINE_FILE_NAME - with open(json_single_path, "w") as f: - f.write(json.dumps(doc_dicts_list)) - - # Two lines (jsonl) but each line contains a list of dict instead of dict - jsonl_list_line_path = tmp_path / TestJsonConverter.JSONL_LIST_LINE_FILE_NAME - with open(jsonl_list_line_path, "w") as f: - for doc in [doc_dicts_list[:2], doc_dicts_list[2:3]]: - f.write(json.dumps(doc) + "\n") - - json_invalid_path = tmp_path / TestJsonConverter.JSON_INVALID - with open(json_invalid_path, "w") as f: - f.write("{an invalid json string}") - - def _assert_docs_okay(self, docs): - # Two table docs and one text doc - # [table, text, table] - assert len(docs) == 3 - assert all(doc.meta["topic"] == "programming" for doc in docs) - # "context" in metadata should have been overwritten to be "PL" instead of "Programming Languages" - assert all(doc.meta["context"] == "PL" for doc in docs) - assert all(d.content_type == expected for d, expected in zip(docs, ("table", "text", "table"))) - - # Text doc test - assert ( - docs[1].content - == "Programming languages are used for controlling the behavior of a machine (often a computer)." - ) - - # Table doc tests - assert isinstance(docs[0].content, pd.DataFrame) - assert docs[0].content.shape == (3, 3) - - assert isinstance(docs[2].content, pd.DataFrame) - assert docs[2].content.shape == (2, 3) - - def test_json_to_documents(self, tmp_path): - json_path = tmp_path / TestJsonConverter.JSON_FILE_NAME - - converter = JsonConverter() - docs = converter.convert(json_path, meta={"topic": "programming", "context": "PL"}) - - self._assert_docs_okay(docs) - - def test_json_to_documents_single_line(self, tmp_path): - json_path = tmp_path / TestJsonConverter.JSON_SINGLE_LINE_FILE_NAME - - converter = JsonConverter() - docs = converter.convert(json_path, meta={"topic": "programming", "context": "PL"}) - - self._assert_docs_okay(docs) - - def test_jsonl_to_documents(self, tmp_path): - jsonl_path = tmp_path / TestJsonConverter.JSONL_FILE_NAME - - converter = JsonConverter() - docs = converter.convert(jsonl_path, meta={"topic": "programming", "context": "PL"}) - - self._assert_docs_okay(docs) - - def test_jsonl_to_documents_list_line(self, tmp_path): - jsonl_path = tmp_path / TestJsonConverter.JSONL_LIST_LINE_FILE_NAME - - converter = JsonConverter() - docs = converter.convert(jsonl_path, meta={"topic": "programming", "context": "PL"}) - - self._assert_docs_okay(docs) - - def test_json_invalid(self, tmp_path): - json_path = tmp_path / TestJsonConverter.JSON_INVALID - - converter = JsonConverter() - with pytest.raises(json.JSONDecodeError) as excinfo: - converter.convert(json_path) - - # Assert filename is in the error message - assert TestJsonConverter.JSON_INVALID in str(excinfo.value) diff --git a/test/nodes/test_filetype_classifier.py b/test/nodes/test_filetype_classifier.py deleted file mode 100644 index 55fb34455f..0000000000 --- a/test/nodes/test_filetype_classifier.py +++ /dev/null @@ -1,168 +0,0 @@ -import logging -import os -import platform -import shutil -from pathlib import Path - -import pytest - -import haystack -from haystack.nodes.file_classifier.file_type import FileTypeClassifier, DEFAULT_TYPES, DEFAULT_MEDIA_TYPES -import contextlib - - -@pytest.mark.unit -def test_filetype_classifier_single_file(tmp_path): - node = FileTypeClassifier() - test_files = [tmp_path / f"test.{extension}" for extension in DEFAULT_TYPES] - - for edge_index, test_file in enumerate(test_files): - output, edge = node.run(test_file) - assert edge == f"output_{edge_index+1}" - assert output == {"file_paths": [test_file]} - - -@pytest.mark.unit -def test_filetype_classifier_many_files(tmp_path): - node = FileTypeClassifier() - - for edge_index, extension in enumerate(DEFAULT_TYPES): - test_files = [tmp_path / f"test_{idx}.{extension}" for idx in range(10)] - - output, edge = node.run(test_files) - assert edge == f"output_{edge_index+1}" - assert output == {"file_paths": test_files} - - -@pytest.mark.unit -def test_filetype_classifier_many_files_mixed_extensions(tmp_path): - node = FileTypeClassifier() - test_files = [tmp_path / f"test.{extension}" for extension in DEFAULT_TYPES] - - with pytest.raises(ValueError): - node.run(test_files) - - -@pytest.mark.unit -def test_filetype_classifier_unsupported_extension(tmp_path): - node = FileTypeClassifier() - test_file = tmp_path / "test.really_weird_extension" - with pytest.raises(ValueError): - node.run(test_file) - - -@pytest.mark.unit -def test_filetype_classifier_custom_extensions(tmp_path): - node = FileTypeClassifier(supported_types=["my_extension"]) - test_file = tmp_path / "test.my_extension" - output, edge = node.run(test_file) - assert edge == "output_1" - assert output == {"file_paths": [test_file]} - - -@pytest.mark.unit -def test_filetype_classifier_duplicate_custom_extensions(): - with pytest.raises(ValueError): - FileTypeClassifier(supported_types=["my_extension", "my_extension"]) - - -@pytest.mark.unit -@pytest.mark.skipif(platform.system() in ["Windows", "Darwin"], reason="python-magic not available") -def test_filetype_classifier_text_files_without_extension(samples_path): - tested_types = ["docx", "html", "odt", "pdf", "pptx", "txt"] - node = FileTypeClassifier(supported_types=tested_types) - test_files = [samples_path / "extensionless_files" / f"{type_name}_file" for type_name in tested_types] - - for edge_index, test_file in enumerate(test_files): - output, edge = node.run(test_file) - assert edge == f"output_{edge_index+1}" - assert output == {"file_paths": [test_file]} - - -@pytest.mark.unit -@pytest.mark.skipif(platform.system() in ["Windows", "Darwin"], reason="python-magic not available") -def test_filetype_classifier_other_files_without_extension(samples_path): - tested_types = ["gif", "jpg", "mp3", "png", "wav", "zip"] - node = FileTypeClassifier(supported_types=tested_types) - test_files = [samples_path / "extensionless_files" / f"{type_name}_file" for type_name in tested_types] - - for edge_index, test_file in enumerate(test_files): - output, edge = node.run(test_file) - assert edge == f"output_{edge_index+1}" - assert output == {"file_paths": [test_file]} - - -@pytest.mark.unit -def test_filetype_classifier_text_files_without_extension_no_magic(monkeypatch, caplog, samples_path): - with contextlib.suppress(AttributeError): # only monkeypatch if magic is installed - monkeypatch.delattr(haystack.nodes.file_classifier.file_type, "magic") - - node = FileTypeClassifier(supported_types=[""]) - - with caplog.at_level(logging.ERROR): - node.run(samples_path / "extensionless_files" / "pdf_file") - assert "'python-magic' is not installed" in caplog.text - - -@pytest.mark.unit -def test_filetype_classifier_media_extensions_positive(tmp_path): - node = FileTypeClassifier(supported_types=DEFAULT_MEDIA_TYPES) - for idx in range(len(DEFAULT_MEDIA_TYPES)): - test_file = tmp_path / f"test.{DEFAULT_MEDIA_TYPES[idx]}" - output, edge = node.run(test_file) - assert edge == f"output_{idx+1}" - assert output == {"file_paths": [test_file]} - - -@pytest.mark.unit -def test_filetype_classifier_media_extensions_negative(tmp_path): - node = FileTypeClassifier(supported_types=DEFAULT_MEDIA_TYPES) - - test_file = tmp_path / "test.txt" - with pytest.raises(ValueError, match="Files of type 'txt'"): - node.run(test_file) - - -@pytest.mark.unit -@pytest.mark.skipif(platform.system() in ["Windows", "Darwin"], reason="python-magic not available") -def test_filetype_classifier_estimate_media_extensions(tmp_path): - node = FileTypeClassifier(supported_types=DEFAULT_MEDIA_TYPES) - - test_file = "test/samples/audio/answer.wav" - new_file_name = "test_wav_no_extension" - new_file_path = os.path.join(tmp_path, new_file_name) - - shutil.copy(test_file, new_file_path) - - output, edge = node.run(new_file_path) - assert edge == "output_5" - assert output == {"file_paths": [Path(new_file_path)]} - - -@pytest.mark.unit -def test_filetype_classifier_batched_various_media_extensions(tmp_path): - test_files = [] - node = FileTypeClassifier(supported_types=DEFAULT_MEDIA_TYPES) - for idx in range(len(DEFAULT_MEDIA_TYPES)): - test_file = tmp_path / f"test.{DEFAULT_MEDIA_TYPES[idx]}" - test_files.append(test_file) - - # we can't classify a list of files with different media extensions - with pytest.raises(ValueError, match="Multiple non-default file types are not allowed at once."): - node.run_batch(test_files) - - -@pytest.mark.unit -def test_filetype_classifier_batched_same_media_extensions(tmp_path): - test_files = [] - batch_size = 5 - file_index = 0 - node = FileTypeClassifier(supported_types=DEFAULT_MEDIA_TYPES) - for idx in range(batch_size): - test_file = tmp_path / f"test-{idx}.{DEFAULT_MEDIA_TYPES[file_index]}" - test_files.append(test_file) - - # we should be able to pass a list of files with the same extension - output, edge = node.run_batch(test_files) - assert edge == "output_1" - assert output == {"file_paths": test_files} diff --git a/test/nodes/test_generator.py b/test/nodes/test_generator.py deleted file mode 100644 index f69663aeba..0000000000 --- a/test/nodes/test_generator.py +++ /dev/null @@ -1,208 +0,0 @@ -from unittest.mock import patch, create_autospec - -import pytest -from haystack import Pipeline -from haystack.schema import Document, Answer -from haystack.nodes.answer_generator import OpenAIAnswerGenerator -from haystack.nodes import PromptTemplate - -from ..conftest import fail_at_version - -import logging - - -@pytest.mark.unit -@fail_at_version(1, 23) -@patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer") -def test_openaianswergenerator_deprecation(mock_load_tokenizer): - with pytest.warns(DeprecationWarning): - OpenAIAnswerGenerator(api_key="fake_api_key") - - -@pytest.mark.unit -@patch("haystack.nodes.answer_generator.openai.openai_request") -def test_no_openai_organization(mock_request): - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer"): - generator = OpenAIAnswerGenerator(api_key="fake_api_key") - assert generator.openai_organization is None - - generator.predict(query="test query", documents=[Document(content="test document")]) - assert "OpenAI-Organization" not in mock_request.call_args.kwargs["headers"] - - -@pytest.mark.unit -@patch("haystack.nodes.answer_generator.openai.openai_request") -def test_openai_organization(mock_request): - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer"): - generator = OpenAIAnswerGenerator(api_key="fake_api_key", openai_organization="fake_organization") - assert generator.openai_organization == "fake_organization" - - generator.predict(query="test query", documents=[Document(content="test document")]) - assert mock_request.call_args.kwargs["headers"]["OpenAI-Organization"] == "fake_organization" - - -@pytest.mark.unit -@patch("haystack.nodes.answer_generator.openai.openai_request") -def test_openai_answer_generator_default_api_base(mock_request): - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer"): - generator = OpenAIAnswerGenerator(api_key="fake_api_key") - assert generator.api_base == "https://api.openai.com/v1" - generator.predict(query="test query", documents=[Document(content="test document")]) - assert mock_request.call_args.kwargs["url"] == "https://api.openai.com/v1/completions" - - -@pytest.mark.unit -@patch("haystack.nodes.answer_generator.openai.openai_request") -def test_openai_answer_generator_custom_api_base(mock_request): - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer"): - generator = OpenAIAnswerGenerator(api_key="fake_api_key", api_base="https://fake_api_base.com") - assert generator.api_base == "https://fake_api_base.com" - generator.predict(query="test query", documents=[Document(content="test document")]) - assert mock_request.call_args.kwargs["url"] == "https://fake_api_base.com/completions" - - -@pytest.mark.integration -@pytest.mark.parametrize("haystack_openai_config", ["openai", "azure"], indirect=True) -def test_openai_answer_generator(haystack_openai_config, docs): - if not haystack_openai_config: - pytest.skip("No API key found, skipping test") - - openai_generator = OpenAIAnswerGenerator( - api_key=haystack_openai_config["api_key"], - azure_base_url=haystack_openai_config.get("azure_base_url", None), - azure_deployment_name=haystack_openai_config.get("azure_deployment_name", None), - model="text-babbage-001", - top_k=1, - ) - prediction = openai_generator.predict(query="Who lives in Berlin?", documents=docs, top_k=1) - assert len(prediction["answers"]) == 1 - assert "Carla" in prediction["answers"][0].answer - - -@pytest.mark.integration -@pytest.mark.parametrize("haystack_openai_config", ["openai", "azure"], indirect=True) -def test_openai_answer_generator_custom_template(haystack_openai_config, docs): - if not haystack_openai_config: - pytest.skip("No API key found, skipping test") - - lfqa_prompt = PromptTemplate( - """Synthesize a comprehensive answer from your knowledge and the following topk most relevant paragraphs and - the given question.\n===\\Paragraphs: {context}\n===\n{query}""" - ) - node = OpenAIAnswerGenerator( - api_key=haystack_openai_config["api_key"], - azure_base_url=haystack_openai_config.get("azure_base_url", None), - azure_deployment_name=haystack_openai_config.get("azure_deployment_name", None), - model="text-babbage-001", - top_k=1, - prompt_template=lfqa_prompt, - ) - prediction = node.predict(query="Who lives in Berlin?", documents=docs, top_k=1) - assert len(prediction["answers"]) == 1 - - -@pytest.mark.integration -@pytest.mark.parametrize("haystack_openai_config", ["openai", "azure"], indirect=True) -def test_openai_answer_generator_max_token(haystack_openai_config, docs, caplog): - if not haystack_openai_config: - pytest.skip("No API key found, skipping test") - - openai_generator = OpenAIAnswerGenerator( - api_key=haystack_openai_config["api_key"], - azure_base_url=haystack_openai_config.get("azure_base_url", None), - azure_deployment_name=haystack_openai_config.get("azure_deployment_name", None), - model="text-babbage-001", - top_k=1, - ) - openai_generator.MAX_TOKENS_LIMIT = 116 - with caplog.at_level(logging.INFO): - prediction = openai_generator.predict(query="Who lives in Berlin?", documents=docs, top_k=1) - assert "Skipping all of the provided Documents" in caplog.text - assert len(prediction["answers"]) == 1 - # Can't easily check content of answer since it is generative and can change between runs - - -# mock tokenizer that splits the string -class MockTokenizer: - def encode(self, *args, **kwargs): - return str.split(*args, **kwargs) - - def tokenize(self, *args, **kwargs): - return str.split(*args, **kwargs) - - -@pytest.mark.unit -def test_build_prompt_within_max_length(): - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer") as mock_load_tokenizer: - mock_load_tokenizer.return_value = MockTokenizer() - - generator = OpenAIAnswerGenerator(api_key="fake_key", max_tokens=50) - generator.MAX_TOKENS_LIMIT = 92 - query = "query" - documents = [Document("most relevant document"), Document("less relevant document")] - prompt_str, prompt_docs = generator._build_prompt_within_max_length(query=query, documents=documents) - - assert len(prompt_docs) == 1 - assert prompt_docs[0] == documents[0] - - -@pytest.mark.unit -def test_openai_answer_generator_pipeline_max_tokens(): - """ - tests that the max_tokens parameter is passed to the generator component in the pipeline - """ - question = "What is New York City like?" - mocked_response = "Forget NYC, I was generated by the mock method." - nyc_docs = [Document(content="New York is a cool and amazing city to live in the United States of America.")] - pipeline = Pipeline() - - # mock load_openai_tokenizer to avoid accessing the internet to init tiktoken - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer"): - openai_generator = OpenAIAnswerGenerator(api_key="fake_api_key", model="text-babbage-001", top_k=1) - - pipeline.add_node(component=openai_generator, name="generator", inputs=["Query"]) - openai_generator.run = create_autospec(openai_generator.run) - openai_generator.run.return_value = ({"answers": mocked_response}, "output_1") - - result = pipeline.run(query=question, documents=nyc_docs, params={"generator": {"max_tokens": 3}}) - assert result["answers"] == mocked_response - openai_generator.run.assert_called_with(query=question, documents=nyc_docs, max_tokens=3) - - -@pytest.mark.unit -@patch("haystack.nodes.answer_generator.openai.OpenAIAnswerGenerator.predict") -def test_openai_answer_generator_run_with_labels_and_isolated_node_eval(patched_predict, eval_labels): - label = eval_labels[0] - query = label.query - document = label.labels[0].document - - patched_predict.return_value = { - "answers": [Answer(answer=label.labels[0].answer.answer, document_ids=[document.id])] - } - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer"): - openai_generator = OpenAIAnswerGenerator(api_key="fake_api_key", model="text-babbage-001", top_k=1) - result, _ = openai_generator.run(query=query, documents=[document], labels=label, add_isolated_node_eval=True) - - assert "answers_isolated" in result - - -@pytest.mark.unit -@patch("haystack.nodes.answer_generator.base.BaseGenerator.predict_batch") -def test_openai_answer_generator_run_batch_with_labels_and_isolated_node_eval(patched_predict_batch, eval_labels): - queries = [label.query for label in eval_labels] - documents = [[label.labels[0].document] for label in eval_labels] - - patched_predict_batch.return_value = { - "queries": queries, - "answers": [ - [Answer(answer=label.labels[0].answer.answer, document_ids=[label.labels[0].document.id])] - for label in eval_labels - ], - } - with patch("haystack.nodes.answer_generator.openai.load_openai_tokenizer"): - openai_generator = OpenAIAnswerGenerator(api_key="fake_api_key", model="text-babbage-001", top_k=1) - result, _ = openai_generator.run_batch( - queries=queries, documents=documents, labels=eval_labels, add_isolated_node_eval=True - ) - - assert "answers_isolated" in result diff --git a/test/nodes/test_image_to_text.py b/test/nodes/test_image_to_text.py deleted file mode 100644 index 7051245de1..0000000000 --- a/test/nodes/test_image_to_text.py +++ /dev/null @@ -1,93 +0,0 @@ -import pytest - -from haystack import Document -from haystack.nodes.image_to_text.transformers import TransformersImageToText -from haystack.nodes.image_to_text.base import BaseImageToText -from haystack.errors import ImageToTextError - - -@pytest.fixture -def image_file_paths(samples_path): - image_file_names = ["apple.jpg", "car.jpg", "cat.jpg", "galaxy.jpg", "paris.jpg"] - return [str(samples_path / "images" / file_name) for file_name in image_file_names] - - -@pytest.fixture -def image_docs(image_file_paths): - return [Document(content=image_path, content_type="image") for image_path in image_file_paths] - - -EXPECTED_CAPTIONS = [ - "a red apple is sitting on a pile of hay", - "a white car parked in a parking lot", - "a cat laying in the grass", - "a blurry photo of a blurry shot of a black object", - "a city with a large building and a clock tower", -] - - -@pytest.fixture -def image_to_text(): - return TransformersImageToText( - model_name_or_path="nlpconnect/vit-gpt2-image-captioning", - devices=["cpu"], - generation_kwargs={"max_new_tokens": 50}, - ) - - -@pytest.mark.integration -def test_image_to_text_from_files(image_to_text, image_file_paths): - assert isinstance(image_to_text, BaseImageToText) - - results = image_to_text.run(file_paths=image_file_paths) - image_paths = [doc.meta["image_path"] for doc in results[0]["documents"]] - assert image_paths == image_file_paths - generated_captions = [doc.content for doc in results[0]["documents"]] - assert generated_captions == EXPECTED_CAPTIONS - - -@pytest.mark.integration -def test_image_to_text_from_documents(image_to_text, image_file_paths, image_docs): - results = image_to_text.run(documents=image_docs) - image_paths = [doc.meta["image_path"] for doc in results[0]["documents"]] - assert image_paths == image_file_paths - generated_captions = [doc.content for doc in results[0]["documents"]] - assert generated_captions == EXPECTED_CAPTIONS - - -@pytest.mark.integration -def test_image_to_text_from_files_and_documents(image_to_text, image_file_paths, image_docs): - results = image_to_text.run(file_paths=image_file_paths[:3], documents=image_docs[3:]) - image_paths = [doc.meta["image_path"] for doc in results[0]["documents"]] - assert image_paths == image_file_paths - generated_captions = [doc.content for doc in results[0]["documents"]] - assert generated_captions == EXPECTED_CAPTIONS - - -@pytest.mark.integration -def test_image_to_text_invalid_image(image_to_text, samples_path): - markdown_path = str(samples_path / "markdown" / "sample.md") - with pytest.raises(ImageToTextError, match="cannot identify image file"): - image_to_text.run(file_paths=[markdown_path]) - - -@pytest.mark.integration -def test_image_to_text_incorrect_path(image_to_text): - with pytest.raises(ImageToTextError, match="Incorrect path"): - image_to_text.run(file_paths=["wrong_path.jpg"]) - - -@pytest.mark.integration -def test_image_to_text_not_image_document(image_to_text): - textual_document = Document(content="this document is textual", content_type="text") - with pytest.raises(ValueError, match="The ImageToText node only supports image documents."): - image_to_text.run(documents=[textual_document]) - - -@pytest.mark.integration -def test_image_to_text_unsupported_model_after_loading(): - with pytest.raises( - ValueError, - match=r"The model 'deepset/minilm-uncased-squad2' \(class 'BertForQuestionAnswering'\) is not supported for ImageToText", - ): - _ = TransformersImageToText(model_name_or_path="deepset/minilm-uncased-squad2") diff --git a/test/nodes/test_join_answers.py b/test/nodes/test_join_answers.py deleted file mode 100644 index 67567ceabd..0000000000 --- a/test/nodes/test_join_answers.py +++ /dev/null @@ -1,31 +0,0 @@ -import pytest - -from haystack.schema import Answer -from haystack.nodes import JoinAnswers - - -@pytest.mark.unit -@pytest.mark.parametrize("join_mode", ["concatenate", "merge"]) -def test_joinanswers(join_mode): - inputs = [{"answers": [Answer(answer="answer 1", score=0.7)]}, {"answers": [Answer(answer="answer 2", score=0.8)]}] - - join_answers = JoinAnswers(join_mode=join_mode) - result, _ = join_answers.run(inputs) - assert len(result["answers"]) == 2 - assert result["answers"] == sorted(result["answers"], reverse=True) - - result, _ = join_answers.run(inputs, top_k_join=1) - assert len(result["answers"]) == 1 - assert result["answers"][0].answer == "answer 2" - - -@pytest.mark.unit -def test_joinanswers_preserves_root_node(): - # https://github.com/deepset-ai/haystack-private/issues/51 - inputs = [ - {"answers": [Answer(answer="answer 1", score=0.7)], "root_node": "Query"}, - {"answers": [Answer(answer="answer 2", score=0.8)], "root_node": "Query"}, - ] - join_docs = JoinAnswers() - result, _ = join_docs.run(inputs) - assert result["root_node"] == "Query" diff --git a/test/nodes/test_join_documents.py b/test/nodes/test_join_documents.py deleted file mode 100644 index 463aeaa577..0000000000 --- a/test/nodes/test_join_documents.py +++ /dev/null @@ -1,115 +0,0 @@ -import pytest - - -from haystack import Document -from haystack.nodes.other.join_docs import JoinDocuments - - -@pytest.mark.unit -@pytest.mark.parametrize("join_mode", ["concatenate", "merge", "reciprocal_rank_fusion"]) -def test_joindocuments(join_mode): - inputs = [ - {"documents": [Document(content="text document 1", content_type="text", score=0.2)]}, - {"documents": [Document(content="text document 2", content_type="text", score=0.7)]}, - ] - - join_docs = JoinDocuments(join_mode=join_mode) - result, _ = join_docs.run(inputs) - assert len(result["documents"]) == 2 - assert result["documents"] == sorted(result["documents"], reverse=True) - - result, _ = join_docs.run(inputs, top_k_join=1) - assert len(result["documents"]) == 1 - if join_mode == "reciprocal_rank_fusion": - assert result["documents"][0].content == "text document 1" - else: - assert result["documents"][0].content == "text document 2" - - -@pytest.mark.unit -@pytest.mark.parametrize("join_mode", ["concatenate", "merge", "reciprocal_rank_fusion"]) -@pytest.mark.parametrize("sort_by_score", [True, False]) -def test_joindocuments_score_none(join_mode, sort_by_score): - """Testing JoinDocuments() node when some of the documents have `score=None`""" - inputs = [ - {"documents": [Document(content="text document 1", content_type="text", score=0.2)]}, - {"documents": [Document(content="text document 2", content_type="text", score=None)]}, - ] - - join_docs = JoinDocuments(join_mode=join_mode, sort_by_score=sort_by_score) - result, _ = join_docs.run(inputs) - assert len(result["documents"]) == 2 - - result, _ = join_docs.run(inputs, top_k_join=1) - assert len(result["documents"]) == 1 - - -@pytest.mark.unit -def test_joindocuments_preserves_root_node(): - # https://github.com/deepset-ai/haystack-private/issues/51 - inputs = [ - {"documents": [Document(content="text document 1", content_type="text", score=0.2)], "root_node": "File"}, - {"documents": [Document(content="text document 2", content_type="text", score=None)], "root_node": "File"}, - ] - join_docs = JoinDocuments() - result, _ = join_docs.run(inputs) - assert result["root_node"] == "File" - - -@pytest.mark.unit -def test_joindocuments_concatenate_keep_only_highest_ranking_duplicate(): - inputs = [ - { - "documents": [ - Document(content="text document 1", content_type="text", score=0.2), - Document(content="text document 2", content_type="text", score=0.3), - ] - }, - {"documents": [Document(content="text document 2", content_type="text", score=0.7)]}, - ] - expected_outputs = { - "documents": [ - Document(content="text document 2", content_type="text", score=0.7), - Document(content="text document 1", content_type="text", score=0.2), - ] - } - - join_docs = JoinDocuments(join_mode="concatenate") - result, _ = join_docs.run(inputs) - assert len(result["documents"]) == 2 - assert result["documents"] == expected_outputs["documents"] - - -@pytest.mark.unit -def test_joindocuments_concatenate_duplicate_docs_null_score(): - """ - Test that the concatenate method correctly handles duplicate documents, - when one has a null score. - """ - inputs = [ - { - "documents": [ - Document(content="text document 1", content_type="text", score=0.2), - Document(content="text document 2", content_type="text", score=0.3), - Document(content="text document 3", content_type="text", score=None), - ] - }, - { - "documents": [ - Document(content="text document 2", content_type="text", score=0.7), - Document(content="text document 1", content_type="text", score=None), - ] - }, - ] - expected_outputs = { - "documents": [ - Document(content="text document 2", content_type="text", score=0.7), - Document(content="text document 1", content_type="text", score=0.2), - Document(content="text document 3", content_type="text", score=None), - ] - } - - join_docs = JoinDocuments(join_mode="concatenate") - result, _ = join_docs.run(inputs) - assert len(result["documents"]) == 3 - assert result["documents"] == expected_outputs["documents"] diff --git a/test/nodes/test_label_generator.py b/test/nodes/test_label_generator.py deleted file mode 100644 index de2c128071..0000000000 --- a/test/nodes/test_label_generator.py +++ /dev/null @@ -1,135 +0,0 @@ -from typing import List -from pathlib import Path - -import pytest - -from haystack import Document -from haystack.document_stores import BaseDocumentStore -from haystack.nodes import QuestionGenerator, EmbeddingRetriever, PseudoLabelGenerator - - -@pytest.mark.generator -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["embedding_sbert"], indirect=True) -def test_pseudo_label_generator( - document_store: BaseDocumentStore, - retriever: EmbeddingRetriever, - question_generator: QuestionGenerator, - docs_with_true_emb: List[Document], -): - document_store.write_documents(docs_with_true_emb) - psg = PseudoLabelGenerator(question_generator, retriever) - train_examples = [] - output, _ = psg.run(documents=document_store.get_all_documents()) - assert "gpl_labels" in output - for item in output["gpl_labels"]: - assert "question" in item and "pos_doc" in item and "neg_doc" in item and "score" in item - train_examples.append(item) - - assert len(train_examples) > 0 - - -@pytest.mark.generator -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["embedding_sbert"], indirect=True) -def test_pseudo_label_generator_batch( - document_store: BaseDocumentStore, - retriever: EmbeddingRetriever, - question_generator: QuestionGenerator, - docs_with_true_emb: List[Document], -): - document_store.write_documents(docs_with_true_emb) - psg = PseudoLabelGenerator(question_generator, retriever) - train_examples = [] - - output, _ = psg.run_batch(documents=document_store.get_all_documents()) - assert "gpl_labels" in output - for item in output["gpl_labels"]: - assert "question" in item and "pos_doc" in item and "neg_doc" in item and "score" in item - train_examples.append(item) - - assert len(train_examples) > 0 - - -@pytest.mark.generator -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["embedding_sbert"], indirect=True) -def test_pseudo_label_generator_using_question_document_pairs( - document_store: BaseDocumentStore, retriever: EmbeddingRetriever, docs_with_true_emb: List[Document] -): - document_store.write_documents(docs_with_true_emb) - docs = [ - { - "question": "What is the capital of Germany?", - "document": "Berlin is the capital and largest city of Germany by both area and population.", - }, - { - "question": "What is the largest city in Germany by population and area?", - "document": "Berlin is the capital and largest city of Germany by both area and population.", - }, - ] - psg = PseudoLabelGenerator(docs, retriever) - train_examples = [] - output, _ = psg.run(documents=document_store.get_all_documents()) - assert "gpl_labels" in output - for item in output["gpl_labels"]: - assert "question" in item and "pos_doc" in item and "neg_doc" in item and "score" in item - train_examples.append(item) - - assert len(train_examples) > 0 - - -@pytest.mark.generator -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["embedding_sbert"], indirect=True) -def test_pseudo_label_generator_using_question_document_pairs_batch( - document_store: BaseDocumentStore, retriever: EmbeddingRetriever, docs_with_true_emb: List[Document] -): - document_store.write_documents(docs_with_true_emb) - docs = [ - { - "question": "What is the capital of Germany?", - "document": "Berlin is the capital and largest city of Germany by both area and population.", - }, - { - "question": "What is the largest city in Germany by population and area?", - "document": "Berlin is the capital and largest city of Germany by both area and population.", - }, - ] - psg = PseudoLabelGenerator(docs, retriever) - train_examples = [] - - output, _ = psg.run_batch(documents=document_store.get_all_documents()) - assert "gpl_labels" in output - for item in output["gpl_labels"]: - assert "question" in item and "pos_doc" in item and "neg_doc" in item and "score" in item - train_examples.append(item) - - assert len(train_examples) > 0 - - -@pytest.mark.generator -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["embedding_sbert"], indirect=True) -def test_training_and_save(retriever: EmbeddingRetriever, tmp_path: Path): - train_examples = [ - { - "question": "What is the capital of Germany?", - "pos_doc": "Berlin is the capital and largest city of Germany by both area and population.", - "neg_doc": "The capital of Germany is the city state of Berlin.", - "score": -2.2788997, - }, - { - "question": "What is the largest city in Germany by population and area?", - "pos_doc": "Berlin is the capital and largest city of Germany by both area and population.", - "neg_doc": "The capital of Germany is the city state of Berlin.", - "score": 7.0911007, - }, - ] - retriever.train(train_examples) - retriever.save(tmp_path) diff --git a/test/nodes/test_link_content_fetcher.py b/test/nodes/test_link_content_fetcher.py deleted file mode 100644 index 54c0220e68..0000000000 --- a/test/nodes/test_link_content_fetcher.py +++ /dev/null @@ -1,462 +0,0 @@ -from typing import Optional -from unittest.mock import Mock, patch -import logging -import pytest -import requests -from requests import Response - -from haystack import Document -from haystack.nodes import LinkContentFetcher - - -@pytest.fixture -def mocked_requests(): - with patch("haystack.nodes.retriever.link_content.requests") as mock_requests: - mock_response = Mock() - mock_requests.get.return_value = mock_response - mock_response.status_code = 200 - mock_response.text = "Sample content from webpage" - mock_response.headers = {"Content-Type": "text/html"} - yield mock_requests - - -@pytest.fixture -def mocked_article_extractor(): - with patch("boilerpy3.extractors.ArticleExtractor.get_content", return_value="Sample content from webpage"): - yield - - -@pytest.mark.unit -def test_init(): - """ - Checks the initialization of the LinkContentFetcher without a preprocessor. - """ - r = LinkContentFetcher() - - assert r.processor is None - assert isinstance(r.handlers, dict) - assert "text/html" in r.handlers - assert "application/pdf" in r.handlers - - -@pytest.mark.unit -def test_init_with_preprocessor(): - """ - Checks the initialization of the LinkContentFetcher with a preprocessor. - """ - pre_processor_mock = Mock() - r = LinkContentFetcher(processor=pre_processor_mock) - assert r.processor == pre_processor_mock - assert isinstance(r.handlers, dict) - assert "text/html" in r.handlers - assert "application/pdf" in r.handlers - - -@pytest.mark.unit -def test_init_with_content_handlers(): - """ - Checks the initialization of the LinkContentFetcher content handlers. - """ - - def fake_but_valid_video_content_handler(response: Response) -> Optional[str]: - pass - - r = LinkContentFetcher(content_handlers={"video/mp4": fake_but_valid_video_content_handler}) - - assert isinstance(r.handlers, dict) - assert "text/html" in r.handlers - assert "application/pdf" in r.handlers - assert "video/mp4" in r.handlers - - -@pytest.mark.unit -def test_init_with_content_handlers_override(): - """ - Checks the initialization of the LinkContentFetcher content handlers but with pdf handler overridden. - """ - - def new_pdf_content_handler(response: Response) -> Optional[str]: - pass - - r = LinkContentFetcher(content_handlers={"application/pdf": new_pdf_content_handler}) - - assert isinstance(r.handlers, dict) - assert "text/html" in r.handlers - assert "application/pdf" in r.handlers - assert r.handlers["application/pdf"] == new_pdf_content_handler - - -@pytest.mark.unit -def test_init_with_invalid_content_handlers(): - """ - Checks the initialization of the LinkContentFetcher content handlers fails with invalid content handlers. - """ - - # invalid because it does not have the correct signature - def invalid_video_content_handler() -> Optional[str]: - pass - - with pytest.raises(ValueError, match="handler must accept"): - LinkContentFetcher(content_handlers={"video/mp4": invalid_video_content_handler}) - - -@pytest.mark.unit -def test_fetch(mocked_requests, mocked_article_extractor): - """ - Checks if the LinkContentFetcher is able to fetch content. - """ - url = "https://haystack.deepset.ai/" - - pre_processor_mock = Mock() - pre_processor_mock.process.return_value = [Document("Sample content from webpage")] - - r = LinkContentFetcher(processor=pre_processor_mock) - result = r.fetch(url=url, doc_kwargs={"text": "Sample content from webpage"}) - - assert len(result) == 1 - assert isinstance(result[0], Document) - assert result[0].content == "Sample content from webpage" - - -@pytest.mark.unit -def test_fetch_no_url(mocked_requests, mocked_article_extractor): - """ - Ensures an InvalidURL exception is raised when URL is missing. - """ - pre_processor_mock = Mock() - pre_processor_mock.process.return_value = [Document("Sample content from webpage")] - - retriever_no_url = LinkContentFetcher(processor=pre_processor_mock) - with pytest.raises(requests.exceptions.InvalidURL, match="Invalid or missing URL"): - retriever_no_url.fetch(url="") - - -@pytest.mark.unit -def test_fetch_invalid_url(caplog, mocked_requests, mocked_article_extractor): - """ - Ensures an InvalidURL exception is raised when the URL is invalid. - """ - url = "this-is-invalid-url" - - r = LinkContentFetcher() - with pytest.raises(requests.exceptions.InvalidURL): - r.fetch(url=url) - - -@pytest.mark.unit -def test_fetch_no_preprocessor(mocked_requests, mocked_article_extractor): - """ - Checks if the LinkContentFetcher can fetch content without a preprocessor. - """ - url = "https://www.example.com" - r = LinkContentFetcher() - - result_no_preprocessor = r.fetch(url=url) - - assert len(result_no_preprocessor) == 1 - assert isinstance(result_no_preprocessor[0], Document) - assert result_no_preprocessor[0].content == "Sample content from webpage" - - -@pytest.mark.unit -def test_fetch_correct_arguments(mocked_requests, mocked_article_extractor): - """ - Ensures that requests.get is called with correct arguments. - """ - url = "https://www.example.com" - - r = LinkContentFetcher() - r.fetch(url=url) - - # Check the arguments that requests.get was called with - args, kwargs = mocked_requests.get.call_args - assert args[0] == url - assert kwargs["timeout"] == 3 - assert kwargs["headers"] == r._REQUEST_HEADERS - - # another variant - url = "https://deepset.ai" - r.fetch(url=url, timeout=10) - # Check the arguments that requests.get was called with - args, kwargs = mocked_requests.get.call_args - assert args[0] == url - assert kwargs["timeout"] == 10 - assert kwargs["headers"] == r._REQUEST_HEADERS - - -@pytest.mark.unit -def test_fetch_default_empty_content(mocked_requests): - """ - Checks handling of content extraction returning empty content. - """ - url = "https://www.example.com" - timeout = 10 - content_text = "" - r = LinkContentFetcher() - - with patch("boilerpy3.extractors.ArticleExtractor.get_content", return_value=content_text): - result = r.fetch(url=url, timeout=timeout) - - assert "text" not in result - assert isinstance(result, list) and len(result) == 0 - - -@pytest.mark.unit -def test_fetch_exception_during_content_extraction_no_raise_on_failure(caplog, mocked_requests): - """ - Checks the behavior when there's an exception during content extraction, and raise_on_failure is set to False. - """ - caplog.set_level(logging.WARNING) - url = "https://www.example.com" - r = LinkContentFetcher() - - with patch("boilerpy3.extractors.ArticleExtractor.get_content", side_effect=Exception("Could not extract content")): - result = r.fetch(url=url) - - assert "text" not in result - assert "failed to extract content from" in caplog.text - - -@pytest.mark.unit -def test_fetch_exception_during_content_extraction_raise_on_failure(caplog, mocked_requests): - """ - Checks the behavior when there's an exception during content extraction, and raise_on_failure is set to True. - """ - caplog.set_level(logging.WARNING) - url = "https://www.example.com" - r = LinkContentFetcher(raise_on_failure=True) - - with patch( - "boilerpy3.extractors.ArticleExtractor.get_content", side_effect=Exception("Could not extract content") - ), pytest.raises(Exception, match="Could not extract content"): - r.fetch(url=url) - - -@pytest.mark.unit -def test_fetch_exception_during_request_get_no_raise_on_failure(caplog): - """ - Checks the behavior when there's an exception during request.get, and raise_on_failure is set to False. - """ - caplog.set_level(logging.WARNING) - url = "https://www.example.com" - r = LinkContentFetcher() - - with patch("haystack.nodes.retriever.link_content.requests.get", side_effect=requests.RequestException()): - r.fetch(url=url) - assert f"Couldn't retrieve content from {url}" in caplog.text - - -@pytest.mark.unit -def test_fetch_exception_during_request_get_raise_on_failure(caplog): - """ - Checks the behavior when there's an exception during request.get, and raise_on_failure is set to True. - """ - caplog.set_level(logging.WARNING) - url = "https://www.example.com" - r = LinkContentFetcher(raise_on_failure=True) - - with patch( - "haystack.nodes.retriever.link_content.requests.get", side_effect=requests.RequestException() - ), pytest.raises(requests.RequestException): - r.fetch(url=url) - - -@pytest.mark.unit -@pytest.mark.parametrize("error_code", [403, 404, 500]) -def test_handle_various_response_errors(caplog, mocked_requests, error_code: int): - """ - Tests the handling of various HTTP error responses. - """ - caplog.set_level(logging.WARNING) - - url = "https://some-problematic-url.com" - - # we don't throw exceptions, there might be many of them - # we log them on debug level - mock_response = Response() - mock_response.status_code = error_code - mocked_requests.get.return_value = mock_response - - r = LinkContentFetcher() - docs = r.fetch(url=url) - - assert f"Couldn't retrieve content from {url}" in caplog.text - assert len(docs) == 1 - assert isinstance(docs[0], Document) - assert docs[0].content == "" - - -@pytest.mark.unit -@pytest.mark.parametrize("error_code", [403, 404, 500]) -def test_handle_http_error(mocked_requests, error_code: int): - """ - Checks the behavior when there's an HTTPError raised, and raise_on_failure is set to True. - """ - - url = "https://some-problematic-url.com" - - # we don't throw exceptions, there might be many of them - # we log them on debug level - mock_response = Response() - mock_response.status_code = error_code - mocked_requests.get.return_value = mock_response - - r = LinkContentFetcher(raise_on_failure=True) - with pytest.raises(requests.HTTPError): - r.fetch(url=url) - - -@pytest.mark.unit -def test_is_valid_url(): - """ - Checks the _is_valid_url function with a set of valid URLs. - """ - retriever = LinkContentFetcher() - - valid_urls = [ - "http://www.google.com", - "https://www.google.com", - "http://google.com", - "https://google.com", - "http://localhost", - "https://localhost", - "http://127.0.0.1", - "https://127.0.0.1", - "http://[::1]", - "https://[::1]", - "http://example.com/path/to/page?name=value", - "https://example.com/path/to/page?name=value", - "http://example.com:8000", - "https://example.com:8000", - ] - - for url in valid_urls: - assert retriever._is_valid_url(url), f"Expected {url} to be valid" - - -@pytest.mark.unit -def test_is_invalid_url(): - """ - Checks the _is_valid_url function with a set of invalid URLs. - """ - retriever = LinkContentFetcher() - - invalid_urls = [ - "http://", - "https://", - "http:", - "https:", - "www.google.com", - "google.com", - "localhost", - "127.0.0.1", - "[::1]", - "/path/to/page", - "/path/to/page?name=value", - ":8000", - "example.com", - "http:///example.com", - "https:///example.com", - "", - None, - ] - - for url in invalid_urls: - assert not retriever._is_valid_url(url), f"Expected {url} to be invalid" - - -@pytest.mark.unit -def test_switch_user_agent_on_failed_request(): - """ - Test that LinkContentFetcher switches user agents on failed requests - """ - url = "http://fakeurl.com" - retry_attempts = 2 - lc = LinkContentFetcher(user_agents=["ua1", "ua2"], retry_attempts=retry_attempts) - with patch("haystack.nodes.retriever.link_content.requests.get") as mocked_get: - mocked_get.return_value.raise_for_status.side_effect = requests.HTTPError() - lc._get_response(url) - - assert mocked_get.call_count == retry_attempts - assert mocked_get.call_args_list[0][1]["headers"]["User-Agent"] == "ua1" - assert mocked_get.call_args_list[1][1]["headers"]["User-Agent"] == "ua2" - - -@pytest.mark.unit -def test_valid_requests_dont_switch_agent(mocked_requests): - """ - Test that LinkContentFetcher doesn't switch user agents on valid requests - """ - lcf = LinkContentFetcher() - - # Make first valid request - lcf._get_response("http://example.com") - - # Make second valid request - lcf._get_response("http://example.com") - - # Assert that requests.get was called twice with the same default user agents - assert mocked_requests.get.call_count == 2 - assert ( - mocked_requests.get.call_args_list[0][1]["headers"]["User-Agent"] - == mocked_requests.get.call_args_list[1][1]["headers"]["User-Agent"] - ) - - -@pytest.mark.integration -def test_call_with_valid_url_on_live_web(): - """ - Test that LinkContentFetcher can fetch content from a valid URL - """ - - retriever = LinkContentFetcher() - docs = retriever.fetch(url="https://docs.haystack.deepset.ai/", timeout=2) - - assert len(docs) >= 1 - assert isinstance(docs[0], Document) - assert "Haystack" in docs[0].content - - -@pytest.mark.integration -def test_retrieve_with_valid_url_on_live_web(): - """ - Test that LinkContentFetcher can fetch content from a valid URL using the run method - """ - - retriever = LinkContentFetcher() - docs, _ = retriever.run(query="https://docs.haystack.deepset.ai/") - docs = docs["documents"] - - assert len(docs) >= 1 - assert isinstance(docs[0], Document) - assert "Haystack" in docs[0].content - - -@pytest.mark.integration -def test_retrieve_with_invalid_url(): - """ - Test that LinkContentFetcher raises ValueError when trying to fetch content from an invalid URL - """ - - retriever = LinkContentFetcher() - with pytest.raises(ValueError): - retriever.run(query="") - - -@pytest.mark.integration -def test_retrieve_batch(): - """ - Test that LinkContentFetcher can fetch content from a valid URL using the retrieve_batch method - """ - - retriever = LinkContentFetcher() - docs, _ = retriever.run_batch(queries=["https://docs.haystack.deepset.ai/", "https://deepset.ai/"]) - assert docs - - docs = docs["documents"] - # no processor is applied, so each query should return a list of documents with one entry - assert len(docs) == 2 and len(docs[0]) == 1 and len(docs[1]) == 1 - - # each query should return a list of documents - assert isinstance(docs[0], list) and isinstance(docs[0][0], Document) - assert isinstance(docs[1], list) and isinstance(docs[1][0], Document) diff --git a/test/nodes/test_lost_in_the_middle.py b/test/nodes/test_lost_in_the_middle.py deleted file mode 100644 index db89c3926e..0000000000 --- a/test/nodes/test_lost_in_the_middle.py +++ /dev/null @@ -1,154 +0,0 @@ -import pytest - -from haystack import Document -from haystack.nodes.ranker.lost_in_the_middle import LostInTheMiddleRanker - - -@pytest.mark.unit -def test_lost_in_the_middle_order_odd(): - # tests that lost_in_the_middle order works with an odd number of documents - docs = [Document(str(i)) for i in range(1, 10)] - ranker = LostInTheMiddleRanker() - result, _ = ranker.run(query="", documents=docs) - assert result["documents"] - expected_order = "1 3 5 7 9 8 6 4 2".split() - assert all(doc.content == expected_order[idx] for idx, doc in enumerate(result["documents"])) - - -@pytest.mark.unit -def test_batch_lost_in_the_middle_order(): - # tests that lost_in_the_middle order works with a batch of documents - docs = [ - [Document("1"), Document("2"), Document("3"), Document("4")], - [Document("5"), Document("6")], - [Document("7"), Document("8"), Document("9")], - ] - ranker = LostInTheMiddleRanker() - result, _ = ranker.run_batch(queries=[""], documents=docs) - - assert " ".join(doc.content for doc in result["documents"][0]) == "1 3 4 2" - assert " ".join(doc.content for doc in result["documents"][1]) == "5 6" - assert " ".join(doc.content for doc in result["documents"][2]) == "7 9 8" - - -@pytest.mark.unit -def test_lost_in_the_middle_order_even(): - # tests that lost_in_the_middle order works with an even number of documents - docs = [Document(str(i)) for i in range(1, 11)] - ranker = LostInTheMiddleRanker() - result, _ = ranker.run(query="", documents=docs) - expected_order = "1 3 5 7 9 10 8 6 4 2".split() - assert all(doc.content == expected_order[idx] for idx, doc in enumerate(result["documents"])) - - -@pytest.mark.unit -def test_lost_in_the_middle_order_two_docs(): - # tests that lost_in_the_middle order works with two documents - ranker = LostInTheMiddleRanker() - - # two docs - docs = [Document("1"), Document("2")] - result, _ = ranker.run(query="", documents=docs) - assert result["documents"][0].content == "1" - assert result["documents"][1].content == "2" - - -@pytest.mark.unit -def test_lost_in_the_middle_init(): - # tests that LostInTheMiddleRanker initializes with default values - ranker = LostInTheMiddleRanker() - assert ranker.word_count_threshold is None - - ranker = LostInTheMiddleRanker(word_count_threshold=10) - assert ranker.word_count_threshold == 10 - - -@pytest.mark.unit -def test_lost_in_the_middle_init_invalid_word_count_threshold(): - # tests that LostInTheMiddleRanker raises an error when word_count_threshold is <= 0 - with pytest.raises(ValueError, match="Invalid value for word_count_threshold"): - LostInTheMiddleRanker(word_count_threshold=0) - - with pytest.raises(ValueError, match="Invalid value for word_count_threshold"): - LostInTheMiddleRanker(word_count_threshold=-5) - - -@pytest.mark.unit -def test_lost_in_the_middle_with_word_count_threshold(): - # tests that lost_in_the_middle with word_count_threshold works as expected - ranker = LostInTheMiddleRanker(word_count_threshold=6) - docs = [Document("word" + str(i)) for i in range(1, 10)] - result, _ = ranker.run(query="", documents=docs) - expected_order = "word1 word3 word5 word6 word4 word2".split() - assert all(doc.content == expected_order[idx] for idx, doc in enumerate(result["documents"])) - - ranker = LostInTheMiddleRanker(word_count_threshold=9) - result, _ = ranker.run(query="", documents=docs) - expected_order = "word1 word3 word5 word7 word9 word8 word6 word4 word2".split() - assert all(doc.content == expected_order[idx] for idx, doc in enumerate(result["documents"])) - - -@pytest.mark.unit -def test_word_count_threshold_greater_than_total_number_of_words_returns_all_documents(): - ranker = LostInTheMiddleRanker(word_count_threshold=100) - docs = [Document("word" + str(i)) for i in range(1, 10)] - ordered_docs = ranker.predict(query="test", documents=docs) - assert len(ordered_docs) == len(docs) - expected_order = "word1 word3 word5 word7 word9 word8 word6 word4 word2".split() - assert all(doc.content == expected_order[idx] for idx, doc in enumerate(ordered_docs)) - - -@pytest.mark.unit -def test_empty_documents_returns_empty_list(): - ranker = LostInTheMiddleRanker() - assert ranker.predict(query="test", documents=[]) == [] - - -@pytest.mark.unit -def test_list_of_one_document_returns_same_document(): - ranker = LostInTheMiddleRanker() - doc = Document(content="test", content_type="text") - assert ranker.predict(query="test", documents=[doc]) == [doc] - - -@pytest.mark.unit -def test_non_textual_documents(): - # tests that merging a list of non-textual documents raises a ValueError - ranker = LostInTheMiddleRanker() - doc1 = Document(content="This is a textual document.") - doc2 = Document(content_type="image", content="This is a non-textual document.") - with pytest.raises(ValueError, match="Some provided documents are not textual"): - ranker.reorder_documents([doc1, doc2]) - - -@pytest.mark.unit -@pytest.mark.parametrize("top_k", [1, 2, 3, 4, 5, 6, 7, 8, 12, 20]) -def test_lost_in_the_middle_order_with_postive_top_k(top_k: int): - # tests that lost_in_the_middle order works with an odd number of documents and a top_k parameter - docs = [Document(str(i)) for i in range(1, 10)] - ranker = LostInTheMiddleRanker() - result = ranker.predict(query="irrelevant", documents=docs, top_k=top_k) - if top_k < len(docs): - # top_k is less than the number of documents, so only the top_k documents should be returned in LITM order - assert len(result) == top_k - expected_order = ranker.predict(query="irrelevant", documents=[Document(str(i)) for i in range(1, top_k + 1)]) - assert result == expected_order - else: - # top_k is greater than the number of documents, so all documents should be returned in LITM order - assert len(result) == len(docs) - assert result == ranker.predict(query="irrelevant", documents=docs) - - -@pytest.mark.unit -@pytest.mark.parametrize("top_k", [-20, -10, -5, -1]) -def test_lost_in_the_middle_order_with_negative_top_k(top_k: int): - # tests that lost_in_the_middle order works with an odd number of documents and an invalid top_k parameter - docs = [Document(str(i)) for i in range(1, 10)] - ranker = LostInTheMiddleRanker() - result = ranker.predict(query="irrelevant", documents=docs, top_k=top_k) - if top_k < len(docs) * -1: - assert len(result) == 0 # top_k is too negative, so no documents should be returned - else: - # top_k is negative, subtract it from the total number of documents to get the expected number of documents - expected_docs = ranker.predict(query="irrelevant", documents=docs, top_k=len(docs) + top_k) - assert result == expected_docs diff --git a/test/nodes/test_preprocessor.py b/test/nodes/test_preprocessor.py deleted file mode 100644 index 604654d578..0000000000 --- a/test/nodes/test_preprocessor.py +++ /dev/null @@ -1,705 +0,0 @@ -import sys -from pathlib import Path -from typing import Any, Optional, List -from unittest import mock -from unittest.mock import Mock - -import nltk.data -import pytest -import tiktoken -from _pytest.monkeypatch import MonkeyPatch -from _pytest.tmpdir import TempPathFactory -from transformers import AutoTokenizer, PreTrainedTokenizerBase - -from haystack import Document -from haystack.nodes.file_converter.pdf import PDFToTextConverter -from haystack.nodes.preprocessor.preprocessor import PreProcessor - - -TEXT = """ -This is a sample sentence in paragraph_1. This is a sample sentence in paragraph_1. This is a sample sentence in -paragraph_1. This is a sample sentence in paragraph_1. This is a sample sentence in paragraph_1.\f - -This is a sample sentence in paragraph_2. This is a sample sentence in paragraph_2. This is a sample sentence in -paragraph_2. This is a sample sentence in paragraph_2. This is a sample sentence in paragraph_2. - -This is a sample sentence in paragraph_3. This is a sample sentence in paragraph_3. This is a sample sentence in -paragraph_3. This is a sample sentence in paragraph_3. This is to trick the test with using an abbreviation\f like Dr. -in the sentence. -""" - -HEADLINES = [ - {"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}, - {"headline": "paragraph_1", "start_idx": 198, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 223, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 365, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 434, "level": 0}, - {"headline": "trick the test", "start_idx": 603, "level": 1}, -] - -LEGAL_TEXT_PT = """ -A Lei nº 9.514/1997, que instituiu a alienação fiduciária de -bens imóveis, é norma especial e posterior ao Código de Defesa do -Consumidor – CDC. Em tais circunstâncias, o inadimplemento do -devedor fiduciante enseja a aplicação da regra prevista nos arts. 26 e 27 -da lei especial” (REsp 1.871.911/SP, rel. Min. Nancy Andrighi, DJe -25/8/2020). - -A Emenda Constitucional n. 35 alterou substancialmente esse mecanismo, -ao determinar, na nova redação conferida ao art. 53: “§ 3º Recebida a -denúncia contra o Senador ou Deputado, por crime ocorrido após a -diplomação, o Supremo Tribunal Federal dará ciência à Casa respectiva, que, -por iniciativa de partido político nela representado e pelo voto da maioria de -seus membros, poderá, até a decisão final, sustar o andamento da ação”. -Vale ressaltar, contudo, que existem, antes do encaminhamento ao -Presidente da República, os chamados autógrafos. Os autógrafos ocorrem já -com o texto definitivamente aprovado pelo Plenário ou pelas comissões, -quando for o caso. Os autógrafos devem reproduzir com absoluta fidelidade a -redação final aprovada. O projeto aprovado será encaminhado em autógrafos -ao Presidente da República. O tema encontra-se regulamentado pelo art. 200 -do RICD e arts. 328 a 331 do RISF. -""" - - -@pytest.fixture(scope="module") -def module_tmp_dir(tmp_path_factory: TempPathFactory) -> Path: - """Module fixture to avoid that the model data is downloaded for each test.""" - return tmp_path_factory.mktemp("nltk_data") - - -@pytest.fixture(autouse=True) -def patched_nltk_data_path(module_tmp_dir: Path, monkeypatch: MonkeyPatch, tmp_path: Path) -> Path: - """Patch the NLTK data path to use a temporary directory instead of a local, persistent directory.""" - old_find = nltk.data.find - - def patched_find(resource_name: str, paths: Optional[List[str]] = None) -> str: - return old_find(resource_name, paths=[str(tmp_path)]) - - monkeypatch.setattr(nltk.data, nltk.data.find.__name__, patched_find) - - old_download = nltk.download - - def patched_download(*args: Any, **kwargs: Any) -> bool: - return old_download(*args, **kwargs, download_dir=str(tmp_path)) - - monkeypatch.setattr(nltk, nltk.download.__name__, patched_download) - - return tmp_path - - -@pytest.fixture -def mock_huggingface_tokenizer(): - class MockTokenizer(PreTrainedTokenizerBase): - """Simple Mock tokenizer splitting the text into 2-character chunks.""" - - @staticmethod - def tokenize(text, **kwargs): - return [text[i : i + 2] for i in range(0, len(text), 2)] - - @staticmethod - def encode_plus(text, **kwargs): - return Mock(offset_mapping=[(i, min(len(text), i + 2)) for i in range(0, len(text), 2)]) - - mock_tokenizer_instance = MockTokenizer() - - with mock.patch.object(AutoTokenizer, "from_pretrained", return_value=mock_tokenizer_instance): - yield mock_tokenizer_instance - - -@pytest.fixture -def mock_tiktoken_tokenizer(): - class MockTokenizer: - """Simple Mock tokenizer "encoding" the text into a 0 for every 5-character chunk.""" - - @staticmethod - def encode(text, **kwargs): - return [0 for i in range(0, len(text), 5)] - - @staticmethod - def decode_single_token_bytes(token): - return b"mock " - - mock_tokenizer_instance = MockTokenizer() - - with mock.patch.object(tiktoken, "get_encoding", return_value=mock_tokenizer_instance): - yield mock_tokenizer_instance - - -@pytest.mark.unit -@pytest.mark.parametrize("split_length_and_results", [(1, 15), (10, 2)]) -def test_preprocess_sentence_split(split_length_and_results): - split_length, expected_documents_count = split_length_and_results - - document = Document(content=TEXT) - preprocessor = PreProcessor( - split_length=split_length, split_overlap=0, split_by="sentence", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - assert len(documents) == expected_documents_count - - -@pytest.mark.unit -@pytest.mark.parametrize("split_length_and_results", [(1, 15), (10, 2)]) -def test_preprocess_sentence_split_custom_models_wrong_file_format(split_length_and_results, samples_path): - split_length, expected_documents_count = split_length_and_results - - document = Document(content=TEXT) - preprocessor = PreProcessor( - split_length=split_length, - split_overlap=0, - split_by="sentence", - split_respect_sentence_boundary=False, - tokenizer_model_folder=samples_path / "preprocessor" / "nltk_models" / "wrong", - language="en", - ) - documents = preprocessor.process(document) - assert len(documents) == expected_documents_count - - -@pytest.mark.unit -@pytest.mark.parametrize("split_length_and_results", [(1, 15), (10, 2)]) -def test_preprocess_sentence_split_custom_models_non_default_language(split_length_and_results): - split_length, expected_documents_count = split_length_and_results - - document = Document(content=TEXT) - preprocessor = PreProcessor( - split_length=split_length, - split_overlap=0, - split_by="sentence", - split_respect_sentence_boundary=False, - language="ca", - ) - documents = preprocessor.process(document) - assert len(documents) == expected_documents_count - - -@pytest.mark.unit -@pytest.mark.parametrize("split_length_and_results", [(1, 8), (8, 1)]) -def test_preprocess_sentence_split_custom_models(split_length_and_results, samples_path): - split_length, expected_documents_count = split_length_and_results - - document = Document(content=LEGAL_TEXT_PT) - preprocessor = PreProcessor( - split_length=split_length, - split_overlap=0, - split_by="sentence", - split_respect_sentence_boundary=False, - language="pt", - tokenizer_model_folder=samples_path / "preprocessor" / "nltk_models", - ) - documents = preprocessor.process(document) - assert len(documents) == expected_documents_count - - -@pytest.mark.unit -def test_preprocess_word_split(): - document = Document(content=TEXT) - preprocessor = PreProcessor( - split_length=10, split_overlap=0, split_by="word", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - assert len(documents) == 11 - - preprocessor = PreProcessor(split_length=15, split_overlap=0, split_by="word", split_respect_sentence_boundary=True) - documents = preprocessor.process(document) - for i, doc in enumerate(documents): - if i == 0: - assert len(doc.content.split()) == 14 - assert len(doc.content.split()) <= 15 or doc.content.startswith("This is to trick") - assert len(documents) == 8 - - preprocessor = PreProcessor( - split_length=40, split_overlap=10, split_by="word", split_respect_sentence_boundary=True - ) - documents = preprocessor.process(document) - assert len(documents) == 5 - - preprocessor = PreProcessor(split_length=5, split_overlap=0, split_by="word", split_respect_sentence_boundary=True) - documents = preprocessor.process(document) - assert len(documents) == 15 - - -@pytest.mark.unit -def test_preprocess_tiktoken_token_split(mock_tiktoken_tokenizer): - raw_docs = [ - "This is a document. It has two sentences and eleven words.", - "This is a document with a long sentence (longer than my split length), it has seventeen words.", - ] - docs = [Document(content=content) for content in raw_docs] - split_length = 10 - token_split_docs_not_respecting_sentences = PreProcessor( - split_by="token", - split_length=split_length, - split_respect_sentence_boundary=False, - split_overlap=0, - tokenizer="tiktoken", - ).process(docs) - assert len(token_split_docs_not_respecting_sentences) == 4 - enc = tiktoken.get_encoding("cl100k_base") - split_documents_encoded = [ - enc.encode(d.content, allowed_special="all", disallowed_special=()) - for d in token_split_docs_not_respecting_sentences - ] - assert all([len(d) <= split_length for d in split_documents_encoded]) - token_split_docs_respecting_sentences = PreProcessor( - split_by="token", - split_length=split_length, - split_respect_sentence_boundary=True, - split_overlap=0, - tokenizer="tiktoken", - ).process(docs) - assert len(token_split_docs_respecting_sentences) == 3 # should not be more than there are sentences - - -@pytest.mark.unit -def test_preprocess_huggingface_token_split(mock_huggingface_tokenizer): - raw_docs = [ - "This is a document. It has two sentences and eleven words.", - "This is a document with a long sentence (longer than my split length), it has seventeen words.", - ] - docs = [Document(content=content) for content in raw_docs] - split_length = 10 - tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") - token_split_docs_not_respecting_sentences = PreProcessor( - split_by="token", - split_length=split_length, - split_respect_sentence_boundary=False, - split_overlap=0, - tokenizer=tokenizer, - ).process(docs) - assert len(token_split_docs_not_respecting_sentences) == 8 - split_documents_retokenized = [tokenizer.tokenize(d.content) for d in token_split_docs_not_respecting_sentences] - assert all([len(d) <= split_length for d in split_documents_retokenized]) - token_split_docs_respecting_sentences = PreProcessor( - split_by="token", - split_length=split_length, - split_respect_sentence_boundary=True, - split_overlap=0, - tokenizer=tokenizer, - ).process(docs) - assert len(token_split_docs_respecting_sentences) == 3 # should not be more than there are sentences - token_split_docs_not_respecting_sentences_instantiate_by_name = PreProcessor( - split_by="token", - split_length=split_length, - split_respect_sentence_boundary=False, - split_overlap=0, - tokenizer="bert-base-uncased", - ).process(docs) - assert token_split_docs_not_respecting_sentences == token_split_docs_not_respecting_sentences_instantiate_by_name - - -@pytest.mark.unit -@pytest.mark.parametrize("split_length_and_results", [(1, 3), (2, 2)]) -def test_preprocess_passage_split(split_length_and_results): - split_length, expected_documents_count = split_length_and_results - - document = Document(content=TEXT) - preprocessor = PreProcessor( - split_length=split_length, split_overlap=0, split_by="passage", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - assert len(documents) == expected_documents_count - - -@pytest.mark.skipif(sys.platform in ["win32", "cygwin"], reason="FIXME Footer not detected correctly on Windows") -def test_clean_header_footer(samples_path): - converter = PDFToTextConverter() - document = converter.convert( - file_path=Path(samples_path / "pdf" / "sample_pdf_2.pdf") - ) # file contains header/footer - - preprocessor = PreProcessor(clean_header_footer=True, split_by=None) - documents = preprocessor.process(document) - - assert len(documents) == 1 - - assert "This is a header." not in documents[0].content - assert "footer" not in documents[0].content - - -@pytest.mark.unit -def test_remove_substrings(): - document = Document(content="This is a header. Some additional text. wiki. Some emoji ✨ 🪲 Weird whitespace\b\b\b.") - - # check that the file contains the substrings we are about to remove - assert "This is a header." in document.content - assert "wiki" in document.content - assert "🪲" in document.content - assert "whitespace" in document.content - assert "✨" in document.content - - preprocessor = PreProcessor(remove_substrings=["This is a header.", "wiki", "🪲"]) - documents = preprocessor.process(document) - - assert "This is a header." not in documents[0].content - assert "wiki" not in documents[0].content - assert "🪲" not in documents[0].content - assert "whitespace" in documents[0].content - assert "✨" in documents[0].content - - -@pytest.mark.unit -def test_id_hash_keys_from_pipeline_params(): - document_1 = Document(content="This is a document.", meta={"key": "a"}) - document_2 = Document(content="This is a document.", meta={"key": "b"}) - assert document_1.id == document_2.id - - preprocessor = PreProcessor(split_length=2, split_respect_sentence_boundary=False) - output, _ = preprocessor.run(documents=[document_1, document_2], id_hash_keys=["content", "meta"]) - documents = output["documents"] - unique_ids = {d.id for d in documents} - - assert len(documents) == 4 - assert len(unique_ids) == 4 - - -# test_input is a tuple consisting of the parameters for split_length, split_overlap and split_respect_sentence_boundary -# and the expected index in the output list of Documents where the page number changes from 1 to 2 -@pytest.mark.unit -@pytest.mark.parametrize("test_input", [(10, 0, True, 5), (10, 0, False, 4), (10, 5, True, 5), (10, 5, False, 7)]) -def test_page_number_extraction(test_input): - split_length, overlap, resp_sent_boundary, exp_doc_index = test_input - preprocessor = PreProcessor( - add_page_number=True, - split_by="word", - split_length=split_length, - split_overlap=overlap, - split_respect_sentence_boundary=resp_sent_boundary, - ) - document = Document(content=TEXT) - documents = preprocessor.process(document) - for idx, doc in enumerate(documents): - if idx < exp_doc_index: - assert doc.meta["page"] == 1 - else: - assert doc.meta["page"] == 2 - - -@pytest.mark.unit -def test_page_number_extraction_on_empty_pages(): - """ - Often "marketing" documents contain pages without text (visuals only). When extracting page numbers, these pages should be counted as well to avoid - issues when mapping results back to the original document. - """ - preprocessor = PreProcessor(add_page_number=True, split_by="word", split_length=7, split_overlap=0) - text_page_one = "This is a text on page one." - text_page_three = "This is a text on page three." - # this is what we get from PDFToTextConverter in case of an "empty" page - document_with_empty_pages = f"{text_page_one}\f\f{text_page_three}" - document = Document(content=document_with_empty_pages) - - documents = preprocessor.process(document) - - assert documents[0].meta["page"] == 1 - assert documents[1].meta["page"] == 3 - - # verify the placeholder for the empty page has been removed - assert documents[0].content.strip() == text_page_one - assert documents[1].content.strip() == text_page_three - - -@pytest.mark.unit -def test_headline_processing_split_by_word(): - expected_headlines = [ - [{"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}], - [ - {"headline": "sample sentence in paragraph_1", "start_idx": None, "level": 0}, - {"headline": "paragraph_1", "start_idx": 19, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 44, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 186, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 53, "level": 0}, - ], - [ - {"headline": "sample sentence in paragraph_3", "start_idx": None, "level": 0}, - {"headline": "trick the test", "start_idx": 36, "level": 1}, - ], - ] - - document = Document(content=TEXT, meta={"headlines": HEADLINES}) - preprocessor = PreProcessor( - split_length=30, split_overlap=0, split_by="word", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - - for doc, expected in zip(documents, expected_headlines): - assert doc.meta["headlines"] == expected - - -@pytest.mark.unit -def test_headline_processing_split_by_word_overlap(): - expected_headlines = [ - [{"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}], - [ - {"headline": "sample sentence in paragraph_1", "start_idx": None, "level": 0}, - {"headline": "paragraph_1", "start_idx": 71, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 96, "level": 0}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 110, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 179, "level": 0}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 53, "level": 0}, - ], - [ - {"headline": "sample sentence in paragraph_3", "start_idx": None, "level": 0}, - {"headline": "trick the test", "start_idx": 95, "level": 1}, - ], - ] - - document = Document(content=TEXT, meta={"headlines": HEADLINES}) - preprocessor = PreProcessor( - split_length=30, split_overlap=10, split_by="word", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - - for doc, expected in zip(documents, expected_headlines): - assert doc.meta["headlines"] == expected - - -@pytest.mark.unit -def test_headline_processing_split_by_word_respect_sentence_boundary(): - expected_headlines = [ - [{"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}], - [ - {"headline": "sample sentence in paragraph_1", "start_idx": None, "level": 0}, - {"headline": "paragraph_1", "start_idx": 71, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 96, "level": 0}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 110, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 53, "level": 0}, - ], - [ - {"headline": "sample sentence in paragraph_3", "start_idx": None, "level": 0}, - {"headline": "trick the test", "start_idx": 95, "level": 1}, - ], - ] - - document = Document(content=TEXT, meta={"headlines": HEADLINES}) - preprocessor = PreProcessor(split_length=30, split_overlap=5, split_by="word", split_respect_sentence_boundary=True) - documents = preprocessor.process(document) - - for doc, expected in zip(documents, expected_headlines): - assert doc.meta["headlines"] == expected - - -@pytest.mark.unit -def test_headline_processing_split_by_sentence(): - expected_headlines = [ - [ - {"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}, - {"headline": "paragraph_1", "start_idx": 198, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_1", "start_idx": None, "level": 0}, - {"headline": "paragraph_1", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 10, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 152, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 10, "level": 0}, - {"headline": "trick the test", "start_idx": 179, "level": 1}, - ], - ] - - document = Document(content=TEXT, meta={"headlines": HEADLINES}) - preprocessor = PreProcessor( - split_length=5, split_overlap=0, split_by="sentence", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - - for doc, expected in zip(documents, expected_headlines): - assert doc.meta["headlines"] == expected - - -@pytest.mark.unit -def test_headline_processing_split_by_sentence_overlap(): - expected_headlines = [ - [ - {"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}, - {"headline": "paragraph_1", "start_idx": 198, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_1", "start_idx": None, "level": 0}, - {"headline": "paragraph_1", "start_idx": 29, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 54, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 196, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 26, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 95, "level": 0}, - ], - [ - {"headline": "sample sentence in paragraph_3", "start_idx": None, "level": 0}, - {"headline": "trick the test", "start_idx": 95, "level": 1}, - ], - ] - - document = Document(content=TEXT, meta={"headlines": HEADLINES}) - preprocessor = PreProcessor( - split_length=5, split_overlap=1, split_by="sentence", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - - for doc, expected in zip(documents, expected_headlines): - assert doc.meta["headlines"] == expected - - -@pytest.mark.unit -def test_headline_processing_split_by_passage(): - expected_headlines = [ - [ - {"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}, - {"headline": "paragraph_1", "start_idx": 198, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_1", "start_idx": None, "level": 0}, - {"headline": "paragraph_1", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 10, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 152, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_2", "start_idx": None, "level": 0}, - {"headline": "in paragraph_2", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 10, "level": 0}, - {"headline": "trick the test", "start_idx": 179, "level": 1}, - ], - ] - - document = Document(content=TEXT, meta={"headlines": HEADLINES}) - preprocessor = PreProcessor( - split_length=1, split_overlap=0, split_by="passage", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - - for doc, expected in zip(documents, expected_headlines): - assert doc.meta["headlines"] == expected - - -@pytest.mark.unit -def test_headline_processing_split_by_passage_overlap(): - expected_headlines = [ - [ - {"headline": "sample sentence in paragraph_1", "start_idx": 11, "level": 0}, - {"headline": "paragraph_1", "start_idx": 198, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 223, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 365, "level": 1}, - ], - [ - {"headline": "sample sentence in paragraph_1", "start_idx": None, "level": 0}, - {"headline": "paragraph_1", "start_idx": None, "level": 1}, - {"headline": "sample sentence in paragraph_2", "start_idx": 10, "level": 0}, - {"headline": "in paragraph_2", "start_idx": 152, "level": 1}, - {"headline": "sample sentence in paragraph_3", "start_idx": 221, "level": 0}, - {"headline": "trick the test", "start_idx": 390, "level": 1}, - ], - ] - - document = Document(content=TEXT, meta={"headlines": HEADLINES}) - preprocessor = PreProcessor( - split_length=2, split_overlap=1, split_by="passage", split_respect_sentence_boundary=False - ) - documents = preprocessor.process(document) - - for doc, expected in zip(documents, expected_headlines): - assert doc.meta["headlines"] == expected - - -@pytest.mark.unit -def test_file_exists_error_during_download(monkeypatch: MonkeyPatch, module_tmp_dir: Path): - # Pretend the model resources were not found in the first attempt - monkeypatch.setattr(nltk.data, "find", Mock(side_effect=[LookupError, str(module_tmp_dir)])) - - # Pretend download throws a `FileExistsError` exception as a different process already downloaded it - monkeypatch.setattr(nltk, "download", Mock(side_effect=FileExistsError)) - - # This shouldn't raise an exception as the `FileExistsError` is ignored - PreProcessor(split_length=2, split_respect_sentence_boundary=False) - - -@pytest.mark.unit -def test_preprocessor_very_long_document(caplog): - preproc = PreProcessor( - clean_empty_lines=False, clean_header_footer=False, clean_whitespace=False, split_by=None, max_chars_check=10 - ) - documents = [Document(content=str(i) + ("." * i)) for i in range(0, 30, 3)] - results = preproc.process(documents) - assert len(results) == 19 - assert any(d.content.startswith(".") for d in results) - assert any(not d.content.startswith(".") for d in results) - assert "characters long after preprocessing, where the maximum length should be 10." in caplog.text - - -@pytest.mark.unit -def test_split_respect_sentence_boundary_exceeding_split_len_not_repeated(): - preproc = PreProcessor(split_length=13, split_overlap=3, split_by="word", split_respect_sentence_boundary=True) - document = Document( - content=( - "This is a test sentence with many many words that exceeds the split length and should not be repeated. " - "This is another test sentence. (This is a third test sentence.) " - "This is the last test sentence." - ) - ) - documents = preproc.process(document) - assert len(documents) == 3 - assert ( - documents[0].content - == "This is a test sentence with many many words that exceeds the split length and should not be repeated. " - ) - assert "This is a test sentence with many many words" not in documents[1].content - assert "This is a test sentence with many many words" not in documents[2].content - - -@pytest.mark.unit -def test_split_overlap_information(): - preproc = PreProcessor(split_length=13, split_overlap=3, split_by="word", split_respect_sentence_boundary=True) - document = Document( - content=( - "This is a test sentence with many many words that exceeds the split length and should not be repeated. " - "This is another test sentence. (This is a third test sentence.) This is the fourth sentence. " - "This is the last test sentence." - ) - ) - documents = preproc.process(document) - assert len(documents) == 4 - # The first Document should not overlap with any other Document as it exceeds the split length, the other Documents - # should overlap with the previous Document (if applicable) and the next Document (if applicable) - assert len(documents[0].meta["_split_overlap"]) == 0 - assert len(documents[1].meta["_split_overlap"]) == 1 - assert len(documents[2].meta["_split_overlap"]) == 2 - assert len(documents[3].meta["_split_overlap"]) == 1 - - assert documents[1].meta["_split_overlap"][0]["doc_id"] == documents[2].id - assert documents[2].meta["_split_overlap"][0]["doc_id"] == documents[1].id - assert documents[2].meta["_split_overlap"][1]["doc_id"] == documents[3].id - assert documents[3].meta["_split_overlap"][0]["doc_id"] == documents[2].id - - doc1_overlap_doc2 = documents[1].meta["_split_overlap"][0]["range"] - doc2_overlap_doc1 = documents[2].meta["_split_overlap"][0]["range"] - assert ( - documents[1].content[doc1_overlap_doc2[0] : doc1_overlap_doc2[1]] - == documents[2].content[doc2_overlap_doc1[0] : doc2_overlap_doc1[1]] - ) - - doc2_overlap_doc3 = documents[2].meta["_split_overlap"][1]["range"] - doc3_overlap_doc2 = documents[3].meta["_split_overlap"][0]["range"] - assert ( - documents[2].content[doc2_overlap_doc3[0] : doc2_overlap_doc3[1]] - == documents[3].content[doc3_overlap_doc2[0] : doc3_overlap_doc2[1]] - ) diff --git a/test/nodes/test_query_classifier.py b/test/nodes/test_query_classifier.py deleted file mode 100644 index a22eb3c55b..0000000000 --- a/test/nodes/test_query_classifier.py +++ /dev/null @@ -1,103 +0,0 @@ -from unittest.mock import patch -import pytest -from haystack.nodes.query_classifier import TransformersQueryClassifier - - -@pytest.mark.unit -def test_query_classifier_initialized_with_token_instead_of_use_auth_token(): - with patch("haystack.nodes.query_classifier.transformers.pipeline") as mock_transformers_pipeline: - TransformersQueryClassifier(task="zero-shot-classification") - assert "token" in mock_transformers_pipeline.call_args.kwargs - assert "use_auth_token" not in mock_transformers_pipeline.call_args.kwargs - - -@pytest.fixture -def transformers_query_classifier(): - return TransformersQueryClassifier( - model_name_or_path="shahrukhx01/bert-mini-finetune-question-detection", - use_gpu=False, - task="text-classification", - labels=["LABEL_1", "LABEL_0"], - ) - - -@pytest.fixture -def zero_shot_transformers_query_classifier(): - return TransformersQueryClassifier( - model_name_or_path="typeform/distilbert-base-uncased-mnli", - use_gpu=False, - task="zero-shot-classification", - labels=["happy", "unhappy", "neutral"], - ) - - -def test_transformers_query_classifier(transformers_query_classifier): - output = transformers_query_classifier.run(query="morse code") - assert output == ({}, "output_2") - - output = transformers_query_classifier.run(query="How old is John?") - assert output == ({}, "output_1") - - -def test_transformers_query_classifier_batch(transformers_query_classifier): - queries = ["morse code", "How old is John?"] - output = transformers_query_classifier.run_batch(queries=queries) - - assert output[0] == {"output_2": {"queries": ["morse code"]}, "output_1": {"queries": ["How old is John?"]}} - - -def test_zero_shot_transformers_query_classifier(zero_shot_transformers_query_classifier): - output = zero_shot_transformers_query_classifier.run(query="What's the answer?") - assert output == ({}, "output_3") - - output = zero_shot_transformers_query_classifier.run(query="Would you be so kind to tell me the answer?") - assert output == ({}, "output_1") - - output = zero_shot_transformers_query_classifier.run(query="Can you give me the right answer for once??") - assert output == ({}, "output_2") - - -def test_zero_shot_transformers_query_classifier_batch(zero_shot_transformers_query_classifier): - queries = [ - "What's the answer?", - "Would you be so kind to tell me the answer?", - "Can you give me the right answer for once??", - ] - - output = zero_shot_transformers_query_classifier.run_batch(queries=queries) - - assert output[0] == { - "output_3": {"queries": ["What's the answer?"]}, - "output_1": {"queries": ["Would you be so kind to tell me the answer?"]}, - "output_2": {"queries": ["Can you give me the right answer for once??"]}, - } - - -def test_transformers_query_classifier_wrong_labels(): - with pytest.raises(ValueError, match="For text-classification, the provided labels must match the model labels"): - TransformersQueryClassifier( - model_name_or_path="shahrukhx01/bert-mini-finetune-question-detection", - use_gpu=False, - task="text-classification", - labels=["WRONG_LABEL_1", "WRONG_LABEL_2", "WRONG_LABEL_3"], - ) - - -def test_transformers_query_classifier_no_labels(): - with pytest.raises(ValueError, match="The labels must be provided"): - TransformersQueryClassifier( - model_name_or_path="shahrukhx01/bert-mini-finetune-question-detection", - use_gpu=False, - task="text-classification", - labels=None, - ) - - -def test_transformers_query_classifier_unsupported_task(): - with pytest.raises(ValueError, match="Task not supported"): - TransformersQueryClassifier( - model_name_or_path="shahrukhx01/bert-mini-finetune-question-detection", - use_gpu=False, - task="summarization", - labels=["LABEL_1", "LABEL_0"], - ) diff --git a/test/nodes/test_question_generator.py b/test/nodes/test_question_generator.py deleted file mode 100644 index 8270518fba..0000000000 --- a/test/nodes/test_question_generator.py +++ /dev/null @@ -1,150 +0,0 @@ -from typing import List - -import pytest - -from haystack.pipelines import ( - QuestionAnswerGenerationPipeline, - QuestionGenerationPipeline, - RetrieverQuestionGenerationPipeline, -) -from haystack.nodes.question_generator import QuestionGenerator -from haystack.schema import Document - - -text = ( - "The Living End are an Australian punk rockabilly band from Melbourne, formed in 1994. Since 2002, " - "the line-up consists of Chris Cheney (vocals, guitar), Scott Owen (double bass, vocals), and Andy " - "Strachan (drums). The band rose to fame in 1997 after the release of their EP Second Solution / Prisoner " - "of Society, which peaked at No. 4 on the Australian ARIA Singles Chart. They have released eight studio " - "albums, two of which reached the No. 1 spot on the ARIA Albums Chart: The Living End (October 1998) and " - "State of Emergency (February 2006). They have also achieved chart success in the U.S. and the United " - "Kingdom. The Band was nominated 27 times and won five awards at the Australian ARIA Music Awards " - 'ceremonies: "Highest Selling Single" for Second Solution / Prisoner of Society (1998), "Breakthrough ' - 'Artist – Album" and "Best Group" for The Living End (1999), as well as "Best Rock Album" for White ' - "Noise (2008) and The Ending Is Just the Beginning Repeating (2011). In October 2010, their debut album " - 'was listed in the book "100 Best Australian Albums". Australian musicologist Ian McFarlane described ' - 'the group as "one of Australia’s premier rock acts. By blending a range of styles (punk, rockabilly ' - "and flat out rock) with great success, The Living End has managed to produce anthemic choruses and " - 'memorable songs in abundance".' -) -document = Document(content=text) -query = "Living End" -keywords = [ - "Australian", - "punk", - "drummer", - "Living", - "band", - "Band", - "Second", - "album", - "albums", - "dialect", - "music", - "book", - "group", - "produce", - "Music", - "Awards", - "year", - "released", -] -text_2 = ( - "Berlin straddles the banks of the Spree, which flows into the Havel (a tributary of the Elbe) in the " - "western borough of Spandau. Among the city's main topographical features are the many lakes in the western " - "and southeastern boroughs formed by the Spree, Havel and Dahme, the largest of which is Lake Müggelsee. " - "Due to its location in the European Plain, Berlin is influenced by a temperate seasonal climate. About " - "one-third of the city's area is composed of forests, parks, gardens, rivers, canals and lakes. The city " - "lies in the Central German dialect area, the Berlin dialect being a variant of the Lusatian-New Marchian " - "dialects." -) -document_2 = Document(content=text_2) -keywords_2 = [ - "Berlin", - "Elbe", - "Spandau", - "Spree", - "boroughs", - "lakes", - "largest", - "seasonal", - "climate", - "city", - "dialect", - "German", -] - - -def test_qg_pipeline(question_generator): - p = QuestionGenerationPipeline(question_generator) - result = p.run(documents=[document]) - keys = list(result) - assert "generated_questions" in keys - assert len(result["generated_questions"][0]["questions"]) > 0 - - -def test_qg_pipeline_non_default_params(): - question_generator = QuestionGenerator(model_name_or_path="valhalla/t5-small-e2e-qg", num_queries_per_doc=2) - p = QuestionGenerationPipeline(question_generator) - result = p.run(documents=[document, document_2]) - assert isinstance(result, dict) - assert "generated_questions" in result - assert "documents" in result - assert isinstance(result["generated_questions"], list) - assert isinstance(result["documents"], list) - assert len(result["generated_questions"]) == 2 - assert len(result["documents"]) == 2 - assert len(result["generated_questions"][0]["questions"]) == 26 - assert len(result["generated_questions"][1]["questions"]) == 12 - - # first list of questions should be about Australian punk band - verify_questions(result["generated_questions"][0]["questions"], keywords) - # second list of questions should be about Berlin - verify_questions(result["generated_questions"][1]["questions"], keywords_2) - - -@pytest.mark.parametrize("split_length, num_queries_per_doc", [(50, 1), (50, 2), (50, 3), (100, 1), (100, 2), (100, 3)]) -def test_qa_generator_non_default_params(split_length, num_queries_per_doc): - question_generator = QuestionGenerator( - model_name_or_path="valhalla/t5-small-e2e-qg", - split_length=split_length, - num_queries_per_doc=num_queries_per_doc, - ) - questions = question_generator.generate_batch(texts=[document.content, document_2.content]) - assert isinstance(questions, list) - assert len(questions) == 2 - assert isinstance(questions[0], list) - assert isinstance(questions[1], list) - assert len(questions[0]) > 0 - assert len(questions[1]) > 0 - - # first list of questions should be about Australian punk band - verify_questions(questions[0], keywords) - # second list of questions should be about Berlin - verify_questions(questions[1], keywords_2) - - -@pytest.mark.parametrize("retriever,document_store", [("tfidf", "memory")], indirect=True) -def test_rqg_pipeline(question_generator, retriever): - retriever.document_store.write_documents([document]) - p = RetrieverQuestionGenerationPipeline(retriever, question_generator) - result = p.run(query) - keys = list(result) - assert "generated_questions" in keys - assert len(result["generated_questions"][0]["questions"]) > 0 - - -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_qag_pipeline(question_generator, reader): - p = QuestionAnswerGenerationPipeline(question_generator, reader) - results = p.run(documents=[document]) - assert "queries" in results - assert "answers" in results - assert len(results["queries"]) == len(results["answers"]) - assert len(results["answers"]) > 0 - assert results["answers"][0][0].answer is not None - - -def verify_questions(questions: List[str], question_keywords: List[str]): - for q in questions: - assert any(word in q for word in question_keywords) diff --git a/test/nodes/test_ranker.py b/test/nodes/test_ranker.py deleted file mode 100644 index baedd00860..0000000000 --- a/test/nodes/test_ranker.py +++ /dev/null @@ -1,784 +0,0 @@ -import pytest -import math -import warnings -import logging -import copy -from unittest.mock import patch - -import torch -from haystack.schema import Document -from haystack.nodes.ranker.base import BaseRanker -from haystack.nodes.ranker import SentenceTransformersRanker, CohereRanker -from haystack.nodes.ranker.recentness_ranker import RecentnessRanker -from haystack.errors import HaystackError, NodeError - - -@pytest.fixture -def docs(): - docs = [ - Document( - content="""Aaron Aaron ( or ; ""Ahärôn"") is a prophet, high priest, and the brother of Moses in the Abrahamic religions. Knowledge of Aaron, along with his brother Moses, comes exclusively from religious texts, such as the Bible and Quran. The Hebrew Bible relates that, unlike Moses, who grew up in the Egyptian royal court, Aaron and his elder sister Miriam remained with their kinsmen in the eastern border-land of Egypt (Goshen). When Moses first confronted the Egyptian king about the Israelites, Aaron served as his brother's spokesman (""prophet"") to the Pharaoh. Part of the Law (Torah) that Moses received from""", - meta={"name": "0"}, - id="1", - ), - Document( - content="""Democratic Republic of the Congo to the south. Angola's capital, Luanda, lies on the Atlantic coast in the northwest of the country. Angola, although located in a tropical zone, has a climate that is not characterized for this region, due to the confluence of three factors: As a result, Angola's climate is characterized by two seasons: rainfall from October to April and drought, known as ""Cacimbo"", from May to August, drier, as the name implies, and with lower temperatures. On the other hand, while the coastline has high rainfall rates, decreasing from North to South and from to , with""", - id="2", - ), - Document( - content="""Schopenhauer, describing him as an ultimately shallow thinker: ""Schopenhauer has quite a crude mind ... where real depth starts, his comes to an end."" His friend Bertrand Russell had a low opinion on the philosopher, and attacked him in his famous ""History of Western Philosophy"" for hypocritically praising asceticism yet not acting upon it. On the opposite isle of Russell on the foundations of mathematics, the Dutch mathematician L. E. J. Brouwer incorporated the ideas of Kant and Schopenhauer in intuitionism, where mathematics is considered a purely mental activity, instead of an analytic activity wherein objective properties of reality are""", - meta={"name": "1"}, - id="3", - ), - Document( - content="""The Dothraki vocabulary was created by David J. Peterson well in advance of the adaptation. HBO hired the Language Creatio""", - meta={"name": "2"}, - id="4", - ), - Document( - content="""The title of the episode refers to the Great Sept of Baelor, the main religious building in King's Landing, where the episode's pivotal scene takes place. In the world created by George R. R. Martin""", - meta={}, - id="5", - ), - ] - return docs - - -@pytest.fixture -def mock_cohere_post(): - class Response: - def __init__(self, text: str): - self.text = text - - with patch("haystack.nodes.ranker.cohere.CohereRanker._post") as cohere_post: - cohere_post.return_value = Response( - text='{"id":"73701fd4-fe30-4007-9698-e960a51b19b4","results":[{"index":4,"relevance_score":0.9937345},{"index":3,"relevance_score":0.2232077},{"index":0,"relevance_score":0.006538825},{"index":2,"relevance_score":0.002278331},{"index":1,"relevance_score":0.000035633544}],"meta":{"api_version":{"version":"1"}}}' - ) - yield cohere_post - - -@pytest.fixture -def mock_transformer_tokenizer(): - class Features(dict): - def to(self, arg): - return self - - class Tokenizer: - def __call__(self, *args, **kwargs): - return Features( - { - "input_ids": torch.zeros([5, 162]), - "token_type_ids": torch.zeros([5, 162], dtype=torch.long), - "attention_mask": torch.zeros([5, 162], dtype=torch.long), - } - ) - - with patch("transformers.AutoTokenizer.from_pretrained") as mock_tokenizer: - mock_tokenizer.return_value = Tokenizer() - yield mock_tokenizer - - -@pytest.fixture -def mock_transformer_model(): - class Logits: - def __init__(self, logits): - self.logits = logits - - class Model: - def __init__(self): - self.logits = torch.tensor([[-9.7414], [-11.1572], [-11.1708], [-11.1515], [5.2571]]) - self.num_labels = 1 - - def __call__(self, *args, **kwargs): - return Logits(logits=self.logits) - - def eval(self): - return self - - def to(self, arg): - return self - - with patch("transformers.AutoModelForSequenceClassification.from_pretrained") as mock_model: - mock_model.return_value = Model() - yield mock_model - - -@pytest.mark.unit -def test_ranker_preprocess_batch_queries_and_docs_raises(): - query_1 = "query 1" - query_2 = "query 2" - docs = [Document(content="dummy doc 1")] - with patch("haystack.nodes.ranker.sentence_transformers.SentenceTransformersRanker.__init__") as mock_ranker_init: - mock_ranker_init.return_value = None - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - with pytest.raises(HaystackError, match="Number of queries must be 1 if a single list of Documents is provided."): - _, _, _, _ = ranker._preprocess_batch_queries_and_docs(queries=[query_1, query_2], documents=docs) - - -@pytest.mark.unit -def test_ranker_preprocess_batch_queries_and_docs_single_query_single_doc_list(): - query1 = "query 1" - docs1 = [Document(content="dummy doc 1"), Document(content="dummy doc 2")] - with patch("haystack.nodes.ranker.sentence_transformers.SentenceTransformersRanker.__init__") as mock_ranker_init: - mock_ranker_init.return_value = None - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - num_of_docs, all_queries, all_docs, single_list_of_docs = ranker._preprocess_batch_queries_and_docs( - queries=[query1], documents=docs1 - ) - assert single_list_of_docs is True - assert num_of_docs == [2] - assert len(all_queries) == 2 - assert len(all_docs) == 2 - - -@pytest.mark.unit -def test_ranker_preprocess_batch_queries_and_docs_multiple_queries_multiple_doc_lists(): - query_1 = "query 1" - query_2 = "query 2" - docs1 = [Document(content="dummy doc 1"), Document(content="dummy doc 2")] - docs2 = [Document(content="dummy doc 3")] - with patch("haystack.nodes.ranker.sentence_transformers.SentenceTransformersRanker.__init__") as mock_ranker_init: - mock_ranker_init.return_value = None - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - num_of_docs, all_queries, all_docs, single_list_of_docs = ranker._preprocess_batch_queries_and_docs( - queries=[query_1, query_2], documents=[docs1, docs2] - ) - assert single_list_of_docs is False - assert num_of_docs == [2, 1] - assert len(all_queries) == 3 - assert len(all_docs) == 3 - - -@pytest.mark.unit -def test_ranker_get_batches(): - all_queries = ["query 1", "query 1"] - all_docs = [Document(content="dummy doc 1"), Document(content="dummy doc 2")] - batches = SentenceTransformersRanker._get_batches(all_queries=all_queries, all_docs=all_docs, batch_size=None) - assert next(batches) == (all_queries, all_docs) - - batches = SentenceTransformersRanker._get_batches(all_queries=all_queries, all_docs=all_docs, batch_size=1) - assert next(batches) == (all_queries[0:1], all_docs[0:1]) - - -@pytest.mark.unit -def test_add_meta_fields_to_docs(): - docs = [ - Document( - content="dummy doc 1", - meta={ - "str_field": "test1", - "empty_str_field": "", - "numeric_field": 2.0, - "list_field": ["item0.1", "item0.2"], - "empty_list_field": [], - }, - ), - Document( - content="dummy doc 2", - meta={ - "str_field": "test2", - "empty_str_field": "", - "numeric_field": 5.0, - "list_field": ["item1.1", "item1.2"], - "empty_list_field": [], - }, - ), - ] - with patch("haystack.nodes.ranker.sentence_transformers.SentenceTransformersRanker.__init__") as mock_ranker_init: - mock_ranker_init.return_value = None - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - docs_with_meta = ranker._add_meta_fields_to_docs( - documents=docs, - embed_meta_fields=["str_field", "empty_str_field", "numeric_field", "list_field", "empty_list_field"], - ) - assert docs_with_meta[0].content.startswith("test1\n2.0\nitem0.1\nitem0.2\ndummy doc 1") - assert docs_with_meta[1].content.startswith("test2\n5.0\nitem1.1\nitem1.2\ndummy doc 2") - - -@pytest.mark.unit -def test_add_meta_fields_to_docs_none(): - docs = [Document(content="dummy doc 1", meta={"none_field": None})] - with patch("haystack.nodes.ranker.sentence_transformers.SentenceTransformersRanker.__init__") as mock_ranker_init: - mock_ranker_init.return_value = None - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - docs_with_meta = ranker._add_meta_fields_to_docs(documents=docs, embed_meta_fields=["none_field"]) - assert docs_with_meta == docs - - -@pytest.mark.unit -def test_add_meta_fields_to_docs_non_existent(): - docs = [Document(content="dummy doc 1", meta={"test_field": "A string"})] - with patch("haystack.nodes.ranker.sentence_transformers.SentenceTransformersRanker.__init__") as mock_ranker_init: - mock_ranker_init.return_value = None - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - docs_with_meta = ranker._add_meta_fields_to_docs(documents=docs, embed_meta_fields=["wrong_field"]) - assert docs_with_meta == docs - - -@pytest.mark.unit -def test_add_meta_fields_to_docs_empty_list(): - docs = [Document(content="dummy doc 1", meta={"test_field": "A string"})] - with patch("haystack.nodes.ranker.sentence_transformers.SentenceTransformersRanker.__init__") as mock_ranker_init: - mock_ranker_init.return_value = None - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - docs_with_meta = ranker._add_meta_fields_to_docs(documents=docs, embed_meta_fields=[]) - assert docs_with_meta == docs - - -@pytest.mark.unit -def test_ranker(docs, mock_transformer_model, mock_transformer_tokenizer): - with patch("torch.nn.DataParallel"): - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - query = "What is the most important building in King's Landing that has a religious background?" - results = ranker.predict(query=query, documents=docs) - assert results[0] == docs[4] - - -@pytest.mark.unit -def test_ranker_run(docs, mock_transformer_model, mock_transformer_tokenizer): - with patch("torch.nn.DataParallel"): - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - query = "What is the most important building in King's Landing that has a religious background?" - results = ranker.run(query=query, documents=docs) - assert results[0]["documents"][0] == docs[4] - - -@pytest.mark.unit -def test_ranker_batch_single_query_single_doc_list(docs, mock_transformer_model, mock_transformer_tokenizer): - with patch("torch.nn.DataParallel"): - ranker = SentenceTransformersRanker(model_name_or_path="fake_model") - query = "What is the most important building in King's Landing that has a religious background?" - results = ranker.predict_batch(queries=[query], documents=docs) - assert results[0] == docs[4] - - -@pytest.mark.unit -def test_ranker_batch_single_query_multiple_doc_lists(docs, mock_transformer_model, mock_transformer_tokenizer): - with patch("torch.nn.DataParallel"): - ranker = SentenceTransformersRanker(model_name_or_path="fake_model", batch_size=5) - query = "What is the most important building in King's Landing that has a religious background?" - results = ranker.predict_batch(queries=[query], documents=[docs, docs]) - assert isinstance(results, list) - assert isinstance(results[0], list) - for reranked_docs in results: - assert reranked_docs[0] == docs[4] - - -def test_ranker_batch_multiple_queries_multiple_doc_lists(ranker, docs): - query_1 = "What is the most important building in King's Landing that has a religious background?" - query_2 = "How is Angola's climate characterized?" - results = ranker.predict_batch(queries=[query_1, query_2], documents=[docs, docs]) - assert isinstance(results, list) - assert isinstance(results[0], list) - assert results[0][0] == docs[4] - assert results[1][0] == docs[1] - - -@pytest.mark.unit -def test_ranker_with_embed_meta_fields(docs, mock_transformer_model, mock_transformer_tokenizer): - with patch("torch.nn.DataParallel"): - ranker = SentenceTransformersRanker(model_name_or_path="fake_model", embed_meta_fields=["name"]) - query = "What is the most important building in King's Landing that has a religious background?" - results = ranker.predict(query=query, documents=docs) - assert results[0] == docs[4] - - -def test_ranker_two_logits(ranker_two_logits, docs): - assert isinstance(ranker_two_logits, BaseRanker) - assert isinstance(ranker_two_logits, SentenceTransformersRanker) - query = "Welches ist das wichtigste Gebäude in Königsmund, das einen religiösen Hintergrund hat?" - docs = [ - Document( - content="""Aaron Aaron (oder ; "Ahärôn") ist ein Prophet, Hohepriester und der Bruder von Moses in den abrahamitischen Religionen. Aaron ist ebenso wie sein Bruder Moses ausschließlich aus religiösen Texten wie der Bibel und dem Koran bekannt. Die hebräische Bibel berichtet, dass Aaron und seine ältere Schwester Mirjam im Gegensatz zu Mose, der am ägyptischen Königshof aufwuchs, bei ihren Verwandten im östlichen Grenzland Ägyptens (Goschen) blieben. Als Mose den ägyptischen König zum ersten Mal mit den Israeliten konfrontierte, fungierte Aaron als Sprecher ("Prophet") seines Bruders gegenüber dem Pharao. Ein Teil des Gesetzes (Tora), das Mose von""", - meta={"name": "0"}, - id="1", - ), - Document( - content="""Demokratische Republik Kongo im Süden. Die angolanische Hauptstadt Luanda liegt an der Atlantikküste im Nordwesten des Landes. Angola liegt zwar in einer tropischen Zone, hat aber ein Klima, das aufgrund des Zusammenwirkens von drei Faktoren nicht für diese Region typisch ist: So ist das Klima Angolas durch zwei Jahreszeiten gekennzeichnet: Regenfälle von Oktober bis April und die als "Cacimbo" bezeichnete Dürre von Mai bis August, die, wie der Name schon sagt, trockener ist und niedrigere Temperaturen aufweist. Andererseits sind die Niederschlagsmengen an der Küste sehr hoch und nehmen von Norden nach Süden und von Süden nach Süden ab, mit""", - id="2", - ), - Document( - content="""Schopenhauer, indem er ihn als einen letztlich oberflächlichen Denker beschreibt: ""Schopenhauer hat einen ziemlich groben Verstand ... wo wirkliche Tiefe beginnt, hört seine auf."" Sein Freund Bertrand Russell hatte eine schlechte Meinung von dem Philosophen und griff ihn in seiner berühmten "Geschichte der westlichen Philosophie" an, weil er heuchlerisch die Askese lobte, aber nicht danach handelte. Der holländische Mathematiker L. E. J. Brouwer, der auf der gegenüberliegenden Insel von Russell über die Grundlagen der Mathematik sprach, nahm die Ideen von Kant und Schopenhauer in den Intuitionismus auf, in dem die Mathematik als eine rein geistige Tätigkeit betrachtet wird und nicht als eine analytische Tätigkeit, bei der die objektiven Eigenschaften der Realität berücksichtigt werden.""", - meta={"name": "1"}, - id="3", - ), - Document( - content="""Das dothrakische Vokabular wurde von David J. Peterson lange vor der Verfilmung erstellt. HBO beauftragte das Language Creatio""", - meta={"name": "2"}, - id="4", - ), - Document( - content="""Der Titel der Episode bezieht sich auf die Große Septe von Baelor, das wichtigste religiöse Gebäude in Königsmund, in dem die Schlüsselszene der Episode stattfindet. In der von George R. R. Martin geschaffenen Welt""", - meta={}, - id="5", - ), - ] - results = ranker_two_logits.predict(query=query, documents=docs) - assert results[0] == docs[4] - - -def test_ranker_returns_normalized_score(ranker): - query = "What is the most important building in King's Landing that has a religious background?" - - docs = [ - Document( - content="""Aaron Aaron ( or ; ""Ahärôn"") is a prophet, high priest, and the brother of Moses in the Abrahamic religions. Knowledge of Aaron, along with his brother Moses, comes exclusively from religious texts, such as the Bible and Quran. The Hebrew Bible relates that, unlike Moses, who grew up in the Egyptian royal court, Aaron and his elder sister Miriam remained with their kinsmen in the eastern border-land of Egypt (Goshen). When Moses first confronted the Egyptian king about the Israelites, Aaron served as his brother's spokesman (""prophet"") to the Pharaoh. Part of the Law (Torah) that Moses received from""", - meta={"name": "0"}, - id="1", - ) - ] - - results = ranker.predict(query=query, documents=docs) - score = results[0].score - precomputed_score = 5.8796231e-05 - assert math.isclose(precomputed_score, score, rel_tol=0.01) - - -def test_ranker_returns_raw_score_when_no_scaling(): - ranker = SentenceTransformersRanker(model_name_or_path="cross-encoder/ms-marco-MiniLM-L-12-v2", scale_score=False) - query = "What is the most important building in King's Landing that has a religious background?" - - docs = [ - Document( - content="""Aaron Aaron ( or ; ""Ahärôn"") is a prophet, high priest, and the brother of Moses in the Abrahamic religions. Knowledge of Aaron, along with his brother Moses, comes exclusively from religious texts, such as the Bible and Quran. The Hebrew Bible relates that, unlike Moses, who grew up in the Egyptian royal court, Aaron and his elder sister Miriam remained with their kinsmen in the eastern border-land of Egypt (Goshen). When Moses first confronted the Egyptian king about the Israelites, Aaron served as his brother's spokesman (""prophet"") to the Pharaoh. Part of the Law (Torah) that Moses received from""", - meta={"name": "0"}, - id="1", - ) - ] - - results = ranker.predict(query=query, documents=docs) - score = results[0].score - precomputed_score = -9.744687 - assert math.isclose(precomputed_score, score, rel_tol=0.001) - - -def test_ranker_returns_raw_score_for_two_logits(ranker_two_logits): - query = "Welches ist das wichtigste Gebäude in Königsmund, das einen religiösen Hintergrund hat?" - docs = [ - Document( - content="""Aaron Aaron (oder ; "Ahärôn") ist ein Prophet, Hohepriester und der Bruder von Moses in den abrahamitischen Religionen. Aaron ist ebenso wie sein Bruder Moses ausschließlich aus religiösen Texten wie der Bibel und dem Koran bekannt. Die hebräische Bibel berichtet, dass Aaron und seine ältere Schwester Mirjam im Gegensatz zu Mose, der am ägyptischen Königshof aufwuchs, bei ihren Verwandten im östlichen Grenzland Ägyptens (Goschen) blieben. Als Mose den ägyptischen König zum ersten Mal mit den Israeliten konfrontierte, fungierte Aaron als Sprecher ("Prophet") seines Bruders gegenüber dem Pharao. Ein Teil des Gesetzes (Tora), das Mose von""", - meta={"name": "0"}, - id="1", - ) - ] - - results = ranker_two_logits.predict(query=query, documents=docs) - score = results[0].score - precomputed_score = -3.61354 - assert math.isclose(precomputed_score, score, rel_tol=0.001) - - -def test_predict_batch_returns_correct_number_of_docs(ranker): - docs = [Document(content=f"test {number}") for number in range(5)] - assert len(ranker.predict("where is test 3?", docs, top_k=4)) == 4 - assert len(ranker.predict_batch(["where is test 3?"], docs, batch_size=2, top_k=4)) == 4 - - -@pytest.mark.unit -def test_cohere_ranker(docs, mock_cohere_post): - query = "What is the most important building in King's Landing that has a religious background?" - ranker = CohereRanker(api_key="fake_key", model_name_or_path="rerank-english-v2.0") - results = ranker.predict(query=query, documents=docs) - mock_cohere_post.assert_called_once_with( - { - "model": "rerank-english-v2.0", - "query": query, - "documents": [{"text": d.content} for d in docs], - "top_n": None, # By passing None we return all documents and use top_k to truncate later - "return_documents": False, - "max_chunks_per_doc": None, - } - ) - assert results[0] == docs[4] - - -@pytest.mark.unit -def test_cohere_ranker_with_embed_meta_fields(docs, mock_cohere_post): - query = "What is the most important building in King's Landing that has a religious background?" - ranker = CohereRanker(api_key="fake_key", model_name_or_path="rerank-english-v2.0", embed_meta_fields=["name"]) - results = ranker.predict(query=query, documents=docs) - # Prep expected input - documents = [] - for d in docs: - meta = d.meta.get("name") - if meta: - documents.append({"text": d.meta["name"] + "\n" + d.content}) - else: - documents.append({"text": d.content}) - mock_cohere_post.assert_called_once_with( - { - "model": "rerank-english-v2.0", - "query": query, - "documents": documents, - "top_n": None, # By passing None we return all documents and use top_k to truncate later - "return_documents": False, - "max_chunks_per_doc": None, - } - ) - assert results[0] == docs[4] - - -@pytest.mark.unit -def test_cohere_ranker_batch_single_query_single_doc_list(docs, mock_cohere_post): - query = "What is the most important building in King's Landing that has a religious background?" - ranker = CohereRanker(api_key="fake_key", model_name_or_path="rerank-english-v2.0") - results = ranker.predict_batch(queries=[query], documents=docs) - mock_cohere_post.assert_called_once_with( - { - "model": "rerank-english-v2.0", - "query": query, - "documents": [{"text": d.content} for d in docs], - "top_n": None, # By passing None we return all documents and use top_k to truncate later - "return_documents": False, - "max_chunks_per_doc": None, - } - ) - assert results[0] == docs[4] - - -@pytest.mark.unit -def test_cohere_ranker_batch_single_query_single_doc_list_with_embed_meta_fields(docs, mock_cohere_post): - query = "What is the most important building in King's Landing that has a religious background?" - ranker = CohereRanker(api_key="fake_key", model_name_or_path="rerank-english-v2.0", embed_meta_fields=["name"]) - results = ranker.predict_batch(queries=[query], documents=docs) - documents = [] - for d in docs: - meta = d.meta.get("name") - if meta: - documents.append({"text": d.meta["name"] + "\n" + d.content}) - else: - documents.append({"text": d.content}) - mock_cohere_post.assert_called_once_with( - { - "model": "rerank-english-v2.0", - "query": query, - "documents": documents, - "top_n": None, # By passing None we return all documents and use top_k to truncate later - "return_documents": False, - "max_chunks_per_doc": None, - } - ) - assert results[0] == docs[4] - - -@pytest.mark.unit -def test_cohere_ranker_batch_single_query_multiple_doc_lists(docs, mock_cohere_post): - query = "What is the most important building in King's Landing that has a religious background?" - ranker = CohereRanker(api_key="fake_key", model_name_or_path="rerank-english-v2.0") - results = ranker.predict_batch(queries=[query], documents=[docs, docs]) - assert mock_cohere_post.call_count == 2 - mock_cohere_post.assert_called_with( - { - "model": "rerank-english-v2.0", - "query": query, - "documents": [{"text": d.content} for d in docs], - "top_n": None, # By passing None we return all documents and use top_k to truncate later - "return_documents": False, - "max_chunks_per_doc": None, - } - ) - assert isinstance(results, list) - assert isinstance(results[0], list) - for reranked_docs in results: - assert reranked_docs[0] == docs[4] - - -@pytest.mark.unit -def test_cohere_ranker_batch_multiple_queries_multiple_doc_lists(docs, mock_cohere_post): - query = "What is the most important building in King's Landing that has a religious background?" - ranker = CohereRanker(api_key="fake_key", model_name_or_path="rerank-english-v2.0") - results = ranker.predict_batch(queries=[query, query], documents=[docs, docs]) - assert mock_cohere_post.call_count == 2 - mock_cohere_post.assert_called_with( - { - "model": "rerank-english-v2.0", - "query": query, - "documents": [{"text": d.content} for d in docs], - "top_n": None, # By passing None we return all documents and use top_k to truncate later - "return_documents": False, - "max_chunks_per_doc": None, - } - ) - assert isinstance(results, list) - assert isinstance(results[0], list) - assert results[0][0] == docs[4] - assert results[1][0] == docs[4] - - -recency_tests_inputs = [ - # Score ranking mode works as expected - pytest.param( - { - "docs": [ - {"meta": {"date": "2021-02-11"}, "score": 0.3, "id": "1"}, - {"meta": {"date": "2024-02-11"}, "score": 0.4, "id": "2"}, - {"meta": {"date": "2020-02-11"}, "score": 0.6, "id": "3"}, - ], - "weight": 0.5, - "date_meta_field": "date", - "top_k": 2, - "ranking_mode": "score", - "expected_scores": {"1": 0.4833333333333333, "2": 0.7}, - "expected_order": ["2", "1"], - "expected_logs": [], - "expected_warning": "", - }, - id="Score ranking mode works as expected", - ), - # RRF ranking mode works as expected - pytest.param( - { - "docs": [ - {"meta": {"date": "2021-02-11"}, "id": "1"}, - {"meta": {"date": "2018-02-11"}, "id": "2"}, - {"meta": {"date": "2020-02-11"}, "id": "3"}, - ], - "weight": 0.5, - "date_meta_field": "date", - "top_k": 2, - "ranking_mode": "reciprocal_rank_fusion", - "expected_scores": {"1": 0.01639344262295082, "2": 0.016001024065540194}, - "expected_order": ["1", "2"], - "expected_logs": [], - "expected_warning": "", - }, - id="RRF ranking mode works as expected", - ), - # Wrong field to find the date - pytest.param( - { - "docs": [ - {"meta": {"data": "2021-02-11"}, "score": 0.3, "id": "1"}, - {"meta": {"date": "2024-02-11"}, "score": 0.4, "id": "2"}, - {"meta": {"date": "2020-02-11"}, "score": 0.6, "id": "3"}, - ], - "weight": 0.5, - "date_meta_field": "date", - "expected_scores": {"1": 0.3, "2": 0.4, "3": 0.6}, - "expected_order": ["1", "2", "3"], - "expected_exception": NodeError( - """ - Param was set to 'date', but document(s) 1 do not contain this metadata key.\n - Please double-check the names of existing metadata fields of your documents \n - and set to the name of the field that contains dates. - """ - ), - "top_k": 2, - "ranking_mode": "score", - }, - id="Wrong field to find the date", - ), - # Date unparsable - pytest.param( - { - "docs": [ - {"meta": {"date": "abcd"}, "id": "1"}, - {"meta": {"date": "2024-02-11"}, "id": "2"}, - {"meta": {"date": "2020-02-11"}, "id": "3"}, - ], - "weight": 0.5, - "date_meta_field": "date", - "expected_order": ["1", "2", "3"], - "expected_logs": [ - ( - "haystack.nodes.ranker.recentness_ranker", - logging.ERROR, - """ - Could not parse date information for dates: abcd - 2024-02-11 - 2020-02-11\n - Continuing without sorting by date. - """, - ) - ], - "top_k": 2, - "ranking_mode": "reciprocal_rank_fusion", - }, - id="Date unparsable", - ), - # Wrong score, outside of bonds - pytest.param( - { - "docs": [ - {"meta": {"date": "2021-02-11"}, "score": 1.3, "id": "1"}, - {"meta": {"date": "2024-02-11"}, "score": 0.4, "id": "2"}, - {"meta": {"date": "2020-02-11"}, "score": 0.6, "id": "3"}, - ], - "weight": 0.5, - "date_meta_field": "date", - "top_k": 2, - "ranking_mode": "score", - "expected_scores": {"1": 0.5, "2": 0.7, "3": 0.4666666666666667}, - "expected_order": ["2", "3"], - "expected_warning": ["The score 1.3 for document 1 is outside the [0,1] range; defaulting to 0"], - }, - id="Wrong score, outside of bonds", - ), - # Wrong score, not provided - pytest.param( - { - "docs": [ - {"meta": {"date": "2021-02-11"}, "id": "1"}, - {"meta": {"date": "2024-02-11"}, "score": 0.4, "id": "2"}, - {"meta": {"date": "2020-02-11"}, "score": 0.6, "id": "3"}, - ], - "weight": 0.5, - "date_meta_field": "date", - "top_k": 2, - "ranking_mode": "score", - "expected_scores": {"1": 0.5, "2": 0.7, "3": 0.4666666666666667}, - "expected_order": ["2", "3"], - "expected_warning": ["The score was not provided; defaulting to 0"], - }, - id="Wrong score, not provided", - ), - # Wrong ranking mode provided - pytest.param( - { - "docs": [ - {"meta": {"date": "2021-02-11"}, "id": "1"}, - {"meta": {"date": "2024-02-11"}, "score": 0.4, "id": "2"}, - {"meta": {"date": "2020-02-11"}, "score": 0.6, "id": "3"}, - ], - "weight": 0.5, - "date_meta_field": "date", - "top_k": 2, - "ranking_mode": "blablabla", - "expected_scores": {"1": 0.01626123744050767, "2": 0.01626123744050767}, - "expected_order": ["1", "2"], - "expected_exception": NodeError( - """ - Param needs to be 'reciprocal_rank_fusion' or 'score' but was set to 'blablabla'. \n - Please change the when initializing the RecentnessRanker. - """ - ), - }, - id="Wrong ranking mode provided", - ), -] - - -@pytest.mark.unit -@pytest.mark.parametrize("test_input", recency_tests_inputs) -def test_recentness_ranker(caplog, test_input): - # Create a set of docs - docs = [] - for doc in test_input["docs"]: - docs.append(Document(content="abc", **doc)) - - # catch warnings to check they are properly issued - with warnings.catch_warnings(record=True) as warnings_list: - # Initialize the ranker - ranker = RecentnessRanker( - date_meta_field=test_input["date_meta_field"], - ranking_mode=test_input["ranking_mode"], - weight=test_input["weight"], - ) - predict_exception = None - results = [] - try: - results = ranker.predict(query="", documents=docs, top_k=test_input["top_k"]) - except Exception as e: - predict_exception = e - - check_results(results, test_input, warnings_list, caplog, predict_exception) - - -@pytest.mark.unit -@pytest.mark.parametrize("test_input", recency_tests_inputs) -def test_recentness_ranker_batch_list(caplog, test_input): - # Create a set of docs - docs = [] - for doc in test_input["docs"]: - docs.append(Document(content="abc", **doc)) - - # catch warnings to check they are properly issued - with warnings.catch_warnings(record=True) as warnings_list: - # Initialize the ranker - ranker = RecentnessRanker( - date_meta_field=test_input["date_meta_field"], - ranking_mode=test_input["ranking_mode"], - weight=test_input["weight"], - ) - predict_exception = None - results = [] - try: - # Run predict_batch with a list as input - results = ranker.predict_batch(queries="", documents=docs, top_k=test_input["top_k"]) - except Exception as e: - predict_exception = e - - check_results(results, test_input, warnings_list, caplog, predict_exception) - - -@pytest.mark.unit -@pytest.mark.parametrize("test_input", recency_tests_inputs) -def test_recentness_ranker_batch_list_of_lists(caplog, test_input): - # Create a set of docs - docs = [] - for doc in test_input["docs"]: - docs.append(Document(content="abc", **doc)) - - # catch warnings to check they are properly issued - with warnings.catch_warnings(record=True) as warnings_list: - # Initialize the ranker - ranker = RecentnessRanker( - date_meta_field=test_input["date_meta_field"], - ranking_mode=test_input["ranking_mode"], - weight=test_input["weight"], - ) - - predict_exception = None - results = [] - try: - # Run predict_batch with a list of lists as input - results = ranker.predict_batch(queries="", documents=[docs, copy.deepcopy(docs)], top_k=test_input["top_k"]) - except Exception as e: - predict_exception = e - - check_results(results, test_input, warnings_list, caplog, predict_exception, list_of_lists=True) - - -def check_results(results, test_input, warnings_list, caplog, exception, list_of_lists=False): - expected_logs_count = 1 - if list_of_lists: - expected_logs_count = 2 - - if "expected_exception" in test_input and test_input["expected_exception"] is not None: - assert exception.message == test_input["expected_exception"].message - assert type(exception) == type(test_input["expected_exception"]) - return - else: - assert exception is None - - # Check that no warnings were thrown, if we are not expecting any - if "expected_warning" not in test_input or test_input["expected_warning"] == []: - assert len(warnings_list) == 0 - # Check that all expected warnings happened, and only those - else: - assert len(warnings_list) == len(test_input["expected_warning"]) - for i in range(len(warnings_list)): - assert test_input["expected_warning"][int(i)] == str(warnings_list[i].message) - - # If we expect logging, compare them one by one - if "expected_logs" not in test_input or test_input["expected_logs"] == []: - assert len(caplog.record_tuples) == 0 - else: - assert expected_logs_count * len(test_input["expected_logs"]) == len(caplog.record_tuples) - for i in range(len(caplog.record_tuples)): - assert test_input["expected_logs"][int(i / expected_logs_count)] == caplog.record_tuples[i] - - if not list_of_lists: - check_result_content(results, test_input) - else: - for i in results: - check_result_content(i, test_input) - - -# Verify the results, that the order and the score of the documents match -def check_result_content(results, test_input): - assert len(results) == len(test_input["expected_order"]) - for i in range(len(test_input["expected_order"])): - assert test_input["expected_order"][i] == results[i].id - if "expected_scores" in test_input: - assert test_input["expected_scores"][results[i].id] == results[i].score - else: - assert results[i].score is None diff --git a/test/nodes/test_reader.py b/test/nodes/test_reader.py deleted file mode 100644 index c97bf418f5..0000000000 --- a/test/nodes/test_reader.py +++ /dev/null @@ -1,516 +0,0 @@ -import math -import os -from pathlib import Path -from unittest.mock import patch - -import pytest - -from huggingface_hub import snapshot_download -from haystack.modeling.data_handler.inputs import QAInput, Question - -from haystack.schema import Document, Answer, Label, MultiLabel, Span -from haystack.nodes.reader.base import BaseReader -from haystack.nodes import FARMReader, TransformersReader - - -def _joinpath(rootdir, targetdir): - return os.path.join(os.sep, rootdir + os.sep, targetdir) - - -# TODO Fix bug in test_no_answer_output when using -# @pytest.fixture(params=["farm", "transformers"]) -@pytest.fixture(params=["farm"]) -def no_answer_reader(request): - if request.param == "farm": - return FARMReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", - use_gpu=False, - top_k_per_sample=5, - no_ans_boost=0, - return_no_answer=True, - num_processes=0, - ) - if request.param == "transformers": - return TransformersReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", - tokenizer="deepset/bert-medium-squad2-distilled", - use_gpu=-1, - top_k_per_candidate=5, - return_no_answers=True, - ) - - -def test_reader_basic(reader): - assert reader is not None - assert isinstance(reader, BaseReader) - - -def test_output(reader, docs): - prediction = reader.predict(query="Who lives in Berlin?", documents=docs, top_k=5) - assert prediction is not None - assert prediction["query"] == "Who lives in Berlin?" - assert prediction["answers"][0].answer == "Carla" - assert prediction["answers"][0].offsets_in_context[0].start == 11 - assert prediction["answers"][0].offsets_in_context[0].end == 16 - assert prediction["answers"][0].offsets_in_document[0].start == 11 - assert prediction["answers"][0].offsets_in_document[0].end == 16 - assert prediction["answers"][0].type == "extractive" - assert 0 <= prediction["answers"][0].score <= 1 - assert prediction["answers"][0].context == "My name is Carla and I live in Berlin" - assert len(prediction["answers"]) == 5 - - -def test_output_batch_single_query_single_doc_list(reader, docs): - prediction = reader.predict_batch(queries=["Who lives in Berlin?"], documents=docs, top_k=5) - assert prediction is not None - assert prediction["queries"] == ["Who lives in Berlin?"] - # Expected output: List of lists of answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], Answer) - assert len(prediction["answers"]) == 5 # Predictions for 5 docs - - -def test_output_batch_single_query_multiple_doc_lists(reader, docs): - prediction = reader.predict_batch(queries=["Who lives in Berlin?"], documents=[docs, docs], top_k=5) - assert prediction is not None - assert prediction["queries"] == ["Who lives in Berlin?"] - # Expected output: List of lists of answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], Answer) - assert len(prediction["answers"]) == 2 # Predictions for 2 collection of docs - assert len(prediction["answers"][0]) == 5 # top-k of 5 per collection of docs - - -def test_output_batch_multiple_queries_single_doc_list(reader, docs): - prediction = reader.predict_batch( - queries=["Who lives in Berlin?", "Who lives in New York?"], documents=docs, top_k=5 - ) - assert prediction is not None - assert prediction["queries"] == ["Who lives in Berlin?", "Who lives in New York?"] - # Expected output: List of lists of lists of answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], list) - assert isinstance(prediction["answers"][0][0][0], Answer) - assert len(prediction["answers"]) == 2 # Predictions for 2 queries - assert len(prediction["answers"][0]) == 5 # Predictions for 5 documents - - -def test_output_batch_multiple_queries_multiple_doc_lists(reader, docs): - prediction = reader.predict_batch( - queries=["Who lives in Berlin?", "Who lives in New York?"], documents=[docs, docs], top_k=5 - ) - assert prediction is not None - assert prediction["queries"] == ["Who lives in Berlin?", "Who lives in New York?"] - # Expected output: List of lists answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], Answer) - assert len(prediction["answers"]) == 2 # Predictions for 2 collections of documents - assert len(prediction["answers"][0]) == 5 # top-k of 5 for collection of docs - - -def test_output_batch_single_query_single_nested_doc_list(reader, docs): - prediction = reader.predict_batch(queries=["Who lives in Berlin?"], documents=[docs], top_k=5) - assert prediction is not None - assert prediction["queries"] == ["Who lives in Berlin?"] - # Expected output: List of lists answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], Answer) - assert len(prediction["answers"]) == 1 # Predictions for 1 collections of documents - assert len(prediction["answers"][0]) == 5 # top-k of 5 for collection of docs - - -@pytest.mark.integration -def test_no_answer_output(no_answer_reader, docs): - no_answer_prediction = no_answer_reader.predict(query="What is the meaning of life?", documents=docs, top_k=5) - assert no_answer_prediction is not None - assert no_answer_prediction["query"] == "What is the meaning of life?" - assert math.isclose(no_answer_prediction["no_ans_gap"], 0.9094805717468262, rel_tol=0.0001) - assert no_answer_prediction["answers"][0].answer == "" - assert no_answer_prediction["answers"][0].offsets_in_context[0].start == 0 - assert no_answer_prediction["answers"][0].offsets_in_context[0].end == 0 - assert no_answer_prediction["answers"][0].score <= 1 - assert no_answer_prediction["answers"][0].score >= 0 - assert no_answer_prediction["answers"][0].context == None - assert no_answer_prediction["answers"][0].document_ids == None - answers = [x.answer for x in no_answer_prediction["answers"]] - assert answers.count("") == 1 - assert len(no_answer_prediction["answers"]) == 5 - - -@pytest.mark.integration -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_deduplication_for_overlapping_documents(reader): - docs = [ - Document( - content="My name is Carla. I live in Berlin.", - id="doc1", - meta={"_split_id": 0, "_split_overlap": [{"doc_id": "doc2", "range": (18, 35)}]}, - ), - Document( - content="I live in Berlin. My friends call me Carla.", - id="doc2", - meta={"_split_id": 1, "_split_overlap": [{"doc_id": "doc1", "range": (0, 17)}]}, - ), - ] - prediction = reader.predict(query="Where does Carla live?", documents=docs, top_k=5) - - # Check that there are no duplicate answers - assert len({ans.answer for ans in prediction["answers"]}) == len(prediction["answers"]) - - -@pytest.mark.integration -def test_model_download_options(): - # download disabled and model is not cached locally - with pytest.raises(OSError): - FARMReader("mfeb/albert-xxlarge-v2-squad2", local_files_only=True, num_processes=0) - - -@pytest.mark.integration -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -@pytest.mark.parametrize("window_size", [10, 15, 20]) -def test_context_window_size(reader, docs, window_size): - assert isinstance(reader, FARMReader) - - old_window_size = reader.inferencer.model.prediction_heads[0].context_window_size - reader.inferencer.model.prediction_heads[0].context_window_size = window_size - - prediction = reader.predict(query="Who lives in Berlin?", documents=docs, top_k=5) - for answer in prediction["answers"]: - # If the extracted answer is larger than the context window, the context window is expanded. - # If the extracted answer is odd in length, the resulting context window is one less than context_window_size - # due to rounding (See FARM's QACandidate) - # TODO Currently the behaviour of context_window_size in FARMReader and TransformerReader is different - if len(answer.answer) <= window_size: - assert len(answer.context) in [window_size, window_size - 1] - else: - # If the extracted answer is larger than the context window and is odd in length, - # the resulting context window is one more than the answer length - assert len(answer.context) in [len(answer.answer), len(answer.answer) + 1] - - reader.inferencer.model.prediction_heads[0].context_window_size = old_window_size - - # TODO Need to test transformers reader - # TODO Currently the behaviour of context_window_size in FARMReader and TransformerReader is different - - -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -@pytest.mark.parametrize("top_k", [2, 5, 10]) -def test_top_k(reader, docs, top_k): - assert isinstance(reader, FARMReader) - - old_top_k_per_candidate = reader.top_k_per_candidate - reader.top_k_per_candidate = 4 - reader.inferencer.model.prediction_heads[0].n_best = reader.top_k_per_candidate + 1 - try: - old_top_k_per_sample = reader.inferencer.model.prediction_heads[0].n_best_per_sample - reader.inferencer.model.prediction_heads[0].n_best_per_sample = 4 - except: - print("WARNING: Could not set `top_k_per_sample` in FARM. Please update FARM version.") - - prediction = reader.predict(query="Who lives in Berlin?", documents=docs, top_k=top_k) - assert len(prediction["answers"]) == top_k - - reader.top_k_per_candidate = old_top_k_per_candidate - reader.inferencer.model.prediction_heads[0].n_best = reader.top_k_per_candidate + 1 - try: - reader.inferencer.model.prediction_heads[0].n_best_per_sample = old_top_k_per_sample - except: - print("WARNING: Could not set `top_k_per_sample` in FARM. Please update FARM version.") - - -def test_farm_reader_invalid_params(): - # invalid max_seq_len (greater than model maximum seq length) - with pytest.raises(Exception): - FARMReader(model_name_or_path="deepset/tinyroberta-squad2", use_gpu=False, max_seq_len=513) - - # invalid max_seq_len (max_seq_len >= doc_stride) - with pytest.raises(Exception): - FARMReader(model_name_or_path="deepset/tinyroberta-squad2", use_gpu=False, max_seq_len=129, doc_stride=128) - - # invalid doc_stride (doc_stride >= (max_seq_len - max_query_length)) - with pytest.raises(Exception): - FARMReader(model_name_or_path="deepset/tinyroberta-squad2", use_gpu=False, doc_stride=999) - - -def test_farm_reader_update_params(docs): - reader = FARMReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", use_gpu=False, no_ans_boost=0, num_processes=0 - ) - - # original reader - prediction = reader.predict(query="Who lives in Berlin?", documents=docs, top_k=3) - assert len(prediction["answers"]) == 3 - assert prediction["answers"][0].answer == "Carla" - - # update no_ans_boost - reader.update_parameters( - context_window_size=100, no_ans_boost=100, return_no_answer=True, max_seq_len=384, doc_stride=128 - ) - prediction = reader.predict(query="Who lives in Berlin?", documents=docs, top_k=3) - assert len(prediction["answers"]) == 3 - assert prediction["answers"][0].answer == "" - - # update no_ans_boost - reader.update_parameters( - context_window_size=100, no_ans_boost=0, return_no_answer=False, max_seq_len=384, doc_stride=128 - ) - prediction = reader.predict(query="Who lives in Berlin?", documents=docs, top_k=3) - assert len(prediction["answers"]) == 3 - assert None not in [ans.answer for ans in prediction["answers"]] - - # update context_window_size - reader.update_parameters(context_window_size=6, no_ans_boost=-10, max_seq_len=384, doc_stride=128) - prediction = reader.predict(query="Who lives in Berlin?", documents=docs, top_k=3) - assert len(prediction["answers"]) == 3 - assert len(prediction["answers"][0].context) == 6 - - # update doc_stride with invalid value - with pytest.raises(Exception): - reader.update_parameters(context_window_size=100, no_ans_boost=-10, max_seq_len=384, doc_stride=999) - reader.predict(query="Who lives in Berlin?", documents=docs, top_k=3) - - # update max_seq_len with invalid value - with pytest.raises(Exception): - reader.update_parameters(context_window_size=6, no_ans_boost=-10, max_seq_len=99, doc_stride=128) - reader.predict(query="Who lives in Berlin?", documents=docs, top_k=3) - - # update max_seq_len with invalid value (greater than the model maximum sequence length) - with pytest.raises(Exception): - invalid_max_seq_len = reader.inferencer.processor.tokenizer.model_max_length + 1 - reader.update_parameters( - context_window_size=100, no_ans_boost=-10, max_seq_len=invalid_max_seq_len, doc_stride=128 - ) - reader.predict(query="Who lives in Berlin?", documents=docs, top_k=3) - - -# There are 5 different ways to load a FARMReader model. -# 1. HuggingFace Hub (online load) -# 2. HuggingFace downloaded (local load) -# 3. HF Model saved as FARM Model (same works for trained FARM model) (local load) -# 4. FARM Model converted to transformers (same as hf local model) (local load) -# 5. ONNX Model load (covered by test_farm_reader_onnx_conversion_and_inference) -@pytest.mark.integration -def test_farm_reader_load_hf_online(): - # Test Case: 1. HuggingFace Hub (online load) - - hf_model = "hf-internal-testing/tiny-random-RobertaForQuestionAnswering" - _ = FARMReader(model_name_or_path=hf_model, use_gpu=False, no_ans_boost=0, num_processes=0) - - -@pytest.mark.integration -def test_farm_reader_load_hf_local(tmp_path): - # Test Case: 2. HuggingFace downloaded (local load) - - hf_model = "hf-internal-testing/tiny-random-RobertaForQuestionAnswering" - local_model_path = "locally_saved_hf" - - local_model_path = str(Path.joinpath(tmp_path, local_model_path)) - model_path = snapshot_download(repo_id=hf_model, revision="main", cache_dir=local_model_path) - _ = FARMReader(model_name_or_path=model_path, use_gpu=False, no_ans_boost=0, num_processes=0) - - -@pytest.mark.integration -def test_farm_reader_load_farm_local(tmp_path): - # Test Case: 3. HF Model saved as FARM Model (same works for trained FARM model) (local load) - - hf_model = "hf-internal-testing/tiny-random-RobertaForQuestionAnswering" - local_model_path = f"{tmp_path}/locally_saved_farm" - reader = FARMReader(model_name_or_path=hf_model, use_gpu=False, no_ans_boost=0, num_processes=0) - reader.save(Path(local_model_path)) - _ = FARMReader(model_name_or_path=local_model_path, use_gpu=False, no_ans_boost=0, num_processes=0) - - -@pytest.mark.parametrize("use_confidence_scores", [True, False]) -def test_farm_reader_uses_same_sorting_as_QAPredictionHead(use_confidence_scores): - reader = FARMReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", - use_gpu=False, - num_processes=0, - return_no_answer=True, - use_confidence_scores=use_confidence_scores, - ) - - text = """Beer is one of the oldest[1][2][3] and most widely consumed[4] alcoholic drinks in the world, and the third most popular drink overall after water and tea.[5] It is produced by the brewing and fermentation of starches, mainly derived from cereal grains—most commonly from malted barley, though wheat, maize (corn), rice, and oats are also used. During the brewing process, fermentation of the starch sugars in the wort produces ethanol and carbonation in the resulting beer.[6] Most modern beer is brewed with hops, which add bitterness and other flavours and act as a natural preservative and stabilizing agent. Other flavouring agents such as gruit, herbs, or fruits may be included or used instead of hops. In commercial brewing, the natural carbonation effect is often removed during processing and replaced with forced carbonation.[7] -Some of humanity's earliest known writings refer to the production and distribution of beer: the Code of Hammurabi included laws regulating beer and beer parlours,[8] and "The Hymn to Ninkasi", a prayer to the Mesopotamian goddess of beer, served as both a prayer and as a method of remembering the recipe for beer in a culture with few literate people.[9][10] -Beer is distributed in bottles and cans and is also commonly available on draught, particularly in pubs and bars. The brewing industry is a global business, consisting of several dominant multinational companies and many thousands of smaller producers ranging from brewpubs to regional breweries. The strength of modern beer is usually around 4% to 6% alcohol by volume (ABV), although it may vary between 0.5% and 20%, with some breweries creating examples of 40% ABV and above.[11] -Beer forms part of the culture of many nations and is associated with social traditions such as beer festivals, as well as a rich pub culture involving activities like pub crawling, pub quizzes and pub games. -When beer is distilled, the resulting liquor is a form of whisky.[12] -""" - - docs = [Document(text)] - query = "What is the third most popular drink?" - - reader_predictions = reader.predict(query=query, documents=docs, top_k=5) - - farm_input = [QAInput(doc_text=d.content, questions=Question(query)) for d in docs] - inferencer_predictions = reader.inferencer.inference_from_objects(farm_input, return_json=False) - - for answer, qa_cand in zip(reader_predictions["answers"], inferencer_predictions[0].prediction): - assert answer.answer == ("" if qa_cand.answer_type == "no_answer" else qa_cand.answer) - assert answer.offsets_in_document[0].start == qa_cand.offset_answer_start - assert answer.offsets_in_document[0].end == qa_cand.offset_answer_end - if use_confidence_scores: - assert answer.score == qa_cand.confidence - else: - assert answer.score == qa_cand.score - - -@pytest.mark.parametrize( - "model_name", - ["deepset/tinyroberta-squad2", "deepset/bert-medium-squad2-distilled", "deepset/xlm-roberta-base-squad2-distilled"], -) -def test_farm_reader_onnx_conversion_and_inference(model_name, tmpdir, docs): - FARMReader.convert_to_onnx(model_name=model_name, output_path=Path(tmpdir, "onnx")) - assert os.path.exists(Path(tmpdir, "onnx", "model.onnx")) - assert os.path.exists(Path(tmpdir, "onnx", "processor_config.json")) - assert os.path.exists(Path(tmpdir, "onnx", "onnx_model_config.json")) - assert os.path.exists(Path(tmpdir, "onnx", "language_model_config.json")) - - reader = FARMReader(str(Path(tmpdir, "onnx"))) - result = reader.predict(query="Where does Paul live?", documents=[docs[0]]) - assert result["answers"][0].answer == "New York" - - -LABELS = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", content_type="text", content="" # empty document - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="something_else", content_type="text", content="My name is Carla and I live in Munich" - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), -] - - -def test_reader_skips_empty_documents(reader): - predictions, _ = reader.run(query=LABELS[0].labels[0].query, documents=[LABELS[0].labels[0].document]) - assert predictions["answers"] == [] # no answer given for query as document is empty - predictions, _ = reader.run_batch( - queries=[l.labels[0].query for l in LABELS], documents=[[l.labels[0].document] for l in LABELS] - ) - assert predictions["answers"][0] == [] # no answer given for 1st query as document is empty - assert predictions["answers"][1][0].answer == "Carla" # answer given for 2nd query as usual - - -@pytest.mark.parametrize("no_answer_reader", ["farm", "transformers"], indirect=True) -def test_no_answer_reader_skips_empty_documents(no_answer_reader): - predictions, _ = no_answer_reader.run(query=LABELS[0].labels[0].query, documents=[LABELS[0].labels[0].document]) - assert predictions["answers"][0].answer == "" # Return no_answer as document is empty - predictions, _ = no_answer_reader.run_batch( - queries=[l.labels[0].query for l in LABELS], documents=[[l.labels[0].document] for l in LABELS] - ) - assert predictions["answers"][0][0].answer == "" # Return no_answer for 1st query as document is empty - assert predictions["answers"][1][1].answer == "Carla" # answer given for 2nd query as usual - - -@pytest.mark.integration -def test_reader_training_returns_eval(tmp_path, samples_path): - max_seq_len = 16 - max_query_length = 8 - reader = FARMReader( - model_name_or_path="deepset/tinyroberta-squad2", - use_gpu=False, - num_processes=0, - max_seq_len=max_seq_len, - doc_stride=2, - max_query_length=max_query_length, - ) - - save_dir = f"{tmp_path}/test_dpr_training" - reader.train( - data_dir=str(samples_path / "squad"), - train_filename="tiny.json", - dev_filename="tiny.json", - n_epochs=1, - batch_size=1, - grad_acc_steps=1, - evaluate_every=0, - save_dir=save_dir, - max_seq_len=max_seq_len, - max_query_length=max_query_length, - ) - assert reader.inferencer.model.training is False - - -@pytest.mark.integration -def test_reader_training(tmp_path, samples_path): - max_seq_len = 16 - max_query_length = 8 - reader = FARMReader( - model_name_or_path="deepset/tinyroberta-squad2", - use_gpu=False, - num_processes=0, - max_seq_len=max_seq_len, - doc_stride=2, - max_query_length=max_query_length, - ) - - save_dir = f"{tmp_path}/test_dpr_training" - reader.train( - data_dir=str(samples_path / "squad"), - train_filename="tiny.json", - dev_filename="tiny.json", - test_filename="tiny.json", - n_epochs=1, - batch_size=1, - grad_acc_steps=1, - save_dir=save_dir, - evaluate_every=2, - max_seq_len=max_seq_len, - max_query_length=max_query_length, - ) - - -@pytest.mark.integration -def test_reader_long_document(reader): - # Check that long documents with >2^16 characters do not result in negative offsets - docs = [Document(content=("abbreviation " * 2550) + "Christelle lives in Madrid.")] - res = reader.predict(query="Where does Christelle live?", documents=docs) - assert res["answers"][0].offsets_in_document[0].start >= 0 - assert res["answers"][0].offsets_in_document[0].end >= 0 - - -@pytest.mark.unit -@patch("haystack.nodes.reader.farm.QAInferencer") -def test_farmreader_predict_preprocessor_batching(mocked_qa_inferencer, docs): - reader = FARMReader(model_name_or_path="mocked_model", preprocessing_batch_size=2) - reader.predict(query="sample query", documents=docs) - - # We expect 3 calls to the QAInferencer (5 docs / 2 batch_size) - assert reader.inferencer.inference_from_objects.call_count == 3 - - -@pytest.mark.unit -@patch("haystack.nodes.reader.farm.QAInferencer") -def test_farmreader_predict_batch_preprocessor_batching(mocked_qa_inferencer, docs): - reader = FARMReader(model_name_or_path="mocked_model", preprocessing_batch_size=2) - reader.predict_batch(queries=["sample query 1", "sample_query_2"], documents=docs) - - # We expect 5 calls to the QAInferencer (2 queries * 5 docs / 2 batch_size) - assert reader.inferencer.inference_from_objects.call_count == 5 diff --git a/test/nodes/test_retriever.py b/test/nodes/test_retriever.py deleted file mode 100644 index 44cb093870..0000000000 --- a/test/nodes/test_retriever.py +++ /dev/null @@ -1,1237 +0,0 @@ -import logging -import os -from math import isclose -from typing import Dict, List, Optional, Union, Tuple -from unittest.mock import patch, Mock, DEFAULT - -import pytest -import numpy as np -import pandas as pd -import requests -from boilerpy3.extractors import ArticleExtractor -from pandas.testing import assert_frame_equal -from transformers import PreTrainedTokenizerFast - - -try: - from elasticsearch import Elasticsearch -except (ImportError, ModuleNotFoundError) as ie: - from haystack.utils.import_utils import _optional_component_not_installed - - _optional_component_not_installed(__name__, "elasticsearch", ie) - - -from haystack.document_stores.base import BaseDocumentStore, FilterType, KeywordDocumentStore -from haystack.document_stores.memory import InMemoryDocumentStore -from haystack.document_stores import WeaviateDocumentStore -from haystack.nodes.retriever.base import BaseRetriever -from haystack.nodes.retriever.web import WebRetriever -from haystack.nodes.search_engine import WebSearch -from haystack.pipelines import DocumentSearchPipeline -from haystack.schema import Document -from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore -from haystack.nodes.retriever.dense import DensePassageRetriever, EmbeddingRetriever, TableTextRetriever -from haystack.nodes.retriever.sparse import BM25Retriever, FilterRetriever, TfidfRetriever -from haystack.nodes.retriever.multimodal import MultiModalRetriever -from haystack.nodes.retriever._openai_encoder import _OpenAIEmbeddingEncoder - -from ..conftest import MockBaseRetriever, fail_at_version - - -# TODO check if we this works with only "memory" arg -@pytest.mark.parametrize( - "retriever_with_docs,document_store_with_docs", - [ - ("mdr", "elasticsearch"), - ("mdr", "faiss"), - ("mdr", "memory"), - ("dpr", "elasticsearch"), - ("dpr", "faiss"), - ("dpr", "memory"), - ("embedding", "elasticsearch"), - ("embedding", "faiss"), - ("embedding", "memory"), - ("bm25", "elasticsearch"), - ("bm25", "memory"), - ("bm25", "weaviate"), - ("es_filter_only", "elasticsearch"), - ("tfidf", "memory"), - ], - indirect=True, -) -def test_retrieval_without_filters(retriever_with_docs: BaseRetriever, document_store_with_docs: BaseDocumentStore): - if not isinstance(retriever_with_docs, (BM25Retriever, TfidfRetriever)): - document_store_with_docs.update_embeddings(retriever_with_docs) - - # NOTE: FilterRetriever simply returns all documents matching a filter, - # so without filters applied it does nothing - if not isinstance(retriever_with_docs, FilterRetriever): - # the BM25 implementation in Weaviate would NOT pick up the expected records - # because of the lack of stemming: "Who lives in berlin" returns only 1 record while - # "Who live in berlin" returns all 5 records. - # TODO - In Weaviate 1.19.0 there is a fix for the lack of stemming, which means that once 1.19.0 is released - # this `if` can be removed, as the standard search query "Who lives in Berlin?" should work with Weaviate. - # See https://github.com/weaviate/weaviate/issues/2439 - if isinstance(document_store_with_docs, WeaviateDocumentStore): - res = retriever_with_docs.retrieve(query="Who live in berlin") - else: - res = retriever_with_docs.retrieve(query="Who lives in Berlin?") - assert res[0].content == "My name is Carla and I live in Berlin" - assert len(res) == 5 - assert res[0].meta["name"] == "filename1" - - -@pytest.mark.parametrize( - "retriever_with_docs,document_store_with_docs", - [ - ("mdr", "elasticsearch"), - ("mdr", "memory"), - ("dpr", "elasticsearch"), - ("dpr", "memory"), - ("embedding", "elasticsearch"), - ("embedding", "memory"), - ("bm25", "elasticsearch"), - ("bm25", "weaviate"), - ("es_filter_only", "elasticsearch"), - ], - indirect=True, -) -def test_retrieval_with_filters(retriever_with_docs: BaseRetriever, document_store_with_docs: BaseDocumentStore): - if not isinstance(retriever_with_docs, (BM25Retriever, FilterRetriever)): - document_store_with_docs.update_embeddings(retriever_with_docs) - - # single filter - result = retriever_with_docs.retrieve(query="Christelle", filters={"name": ["filename3"]}, top_k=5) - assert len(result) == 1 - assert type(result[0]) == Document - assert result[0].content == "My name is Christelle and I live in Paris" - assert result[0].meta["name"] == "filename3" - - # multiple filters - result = retriever_with_docs.retrieve( - query="Paul", filters={"name": ["filename2"], "meta_field": ["test2", "test3"]}, top_k=5 - ) - assert len(result) == 1 - assert type(result[0]) == Document - assert result[0].meta["name"] == "filename2" - - result = retriever_with_docs.retrieve( - query="Carla", filters={"name": ["filename1"], "meta_field": ["test2", "test3"]}, top_k=5 - ) - assert len(result) == 0 - - -@pytest.mark.unit -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -def test_tfidf_retriever_multiple_indexes(document_store: BaseDocumentStore): - docs_index_0 = [Document(content="test_1"), Document(content="test_2"), Document(content="test_3")] - docs_index_1 = [Document(content="test_4"), Document(content="test_5")] - tfidf_retriever = TfidfRetriever(document_store=document_store) - - document_store.write_documents(docs_index_0, index="index_0") - tfidf_retriever.fit(document_store, index="index_0") - document_store.write_documents(docs_index_1, index="index_1") - tfidf_retriever.fit(document_store, index="index_1") - - assert tfidf_retriever.document_counts["index_0"] == document_store.get_document_count(index="index_0") - assert tfidf_retriever.document_counts["index_1"] == document_store.get_document_count(index="index_1") - - -@pytest.mark.unit -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -def test_retrieval_empty_query(document_store: BaseDocumentStore): - # test with empty query using the run() method - mock_document = Document(id="0", content="test") - retriever = MockBaseRetriever(document_store=document_store, mock_document=mock_document) - result = retriever.run(root_node="Query", query="", filters={}) - assert result[0]["documents"][0] == mock_document - - result = retriever.run_batch(root_node="Query", queries=[""], filters={}) - assert result[0]["documents"][0][0] == mock_document - - -@pytest.mark.parametrize("retriever_with_docs", ["embedding", "dpr", "tfidf"], indirect=True) -def test_batch_retrieval_single_query(retriever_with_docs, document_store_with_docs): - if not isinstance(retriever_with_docs, (BM25Retriever, FilterRetriever, TfidfRetriever)): - document_store_with_docs.update_embeddings(retriever_with_docs) - - res = retriever_with_docs.retrieve_batch(queries=["Who lives in Berlin?"]) - - # Expected return type: List of lists of Documents - assert isinstance(res, list) - assert isinstance(res[0], list) - assert isinstance(res[0][0], Document) - - assert len(res) == 1 - assert len(res[0]) == 5 - assert res[0][0].content == "My name is Carla and I live in Berlin" - assert res[0][0].meta["name"] == "filename1" - - -@pytest.mark.parametrize("retriever_with_docs", ["embedding", "dpr", "tfidf"], indirect=True) -def test_batch_retrieval_multiple_queries(retriever_with_docs, document_store_with_docs): - if not isinstance(retriever_with_docs, (BM25Retriever, FilterRetriever, TfidfRetriever)): - document_store_with_docs.update_embeddings(retriever_with_docs) - - res = retriever_with_docs.retrieve_batch(queries=["Who lives in Berlin?", "Who lives in New York?"]) - - # Expected return type: list of lists of Documents - assert isinstance(res, list) - assert isinstance(res[0], list) - assert isinstance(res[0][0], Document) - - assert res[0][0].content == "My name is Carla and I live in Berlin" - assert len(res[0]) == 5 - assert res[0][0].meta["name"] == "filename1" - - assert res[1][0].content == "My name is Paul and I live in New York" - assert len(res[1]) == 5 - assert res[1][0].meta["name"] == "filename2" - - -@pytest.mark.parametrize("retriever_with_docs", ["bm25"], indirect=True) -def test_batch_retrieval_multiple_queries_with_filters(retriever_with_docs, document_store_with_docs): - if not isinstance(retriever_with_docs, (BM25Retriever, FilterRetriever)): - document_store_with_docs.update_embeddings(retriever_with_docs) - - # Weaviate does not support BM25 with filters yet, only after Weaviate v1.18.0 - # TODO - remove this once Weaviate starts supporting BM25 WITH filters - # You might also need to modify the first query, as Weaviate having problems with - # retrieving the "My name is Carla and I live in Berlin" record just with the - # "Who lives in Berlin?" BM25 query - if isinstance(document_store_with_docs, WeaviateDocumentStore): - return - - res = retriever_with_docs.retrieve_batch( - queries=["Who lives in Berlin?", "Who lives in New York?"], filters=[{"name": "filename1"}, None] - ) - - # Expected return type: list of lists of Documents - assert isinstance(res, list) - assert isinstance(res[0], list) - assert isinstance(res[0][0], Document) - - assert res[0][0].content == "My name is Carla and I live in Berlin" - assert len(res[0]) == 5 - assert res[0][0].meta["name"] == "filename1" - - assert res[1][0].content == "My name is Paul and I live in New York" - assert len(res[1]) == 5 - assert res[1][0].meta["name"] == "filename2" - - -@pytest.mark.unit -def test_embed_meta_fields(docs_with_ids): - with patch( - "haystack.nodes.retriever._embedding_encoder._SentenceTransformersEmbeddingEncoder.__init__" - ) as mock_init: - mock_init.return_value = None - retriever = EmbeddingRetriever( - embedding_model="sentence-transformers/all-mpnet-base-v2", - model_format="sentence_transformers", - embed_meta_fields=["date_field", "numeric_field", "list_field"], - ) - docs_with_embedded_meta = retriever._preprocess_documents(docs=docs_with_ids[:2]) - assert docs_with_embedded_meta[0].content.startswith("2019-10-01\n5.0\nitem0.1\nitem0.2") - assert docs_with_embedded_meta[1].content.startswith("2020-03-01\n5.5\nitem1.1\nitem1.2") - - -@pytest.mark.unit -def test_embed_meta_fields_empty(): - doc = Document(content="My name is Matteo and I live in Rome", meta={"meta_field": "", "list_field": []}) - with patch( - "haystack.nodes.retriever._embedding_encoder._SentenceTransformersEmbeddingEncoder.__init__" - ) as mock_init: - mock_init.return_value = None - retriever = EmbeddingRetriever( - embedding_model="sentence-transformers/all-mpnet-base-v2", - model_format="sentence_transformers", - embed_meta_fields=["meta_field", "list_field"], - ) - docs_with_embedded_meta = retriever._preprocess_documents(docs=[doc]) - assert docs_with_embedded_meta[0].content == "My name is Matteo and I live in Rome" - - -@pytest.mark.unit -def test_embed_meta_fields_list_with_one_item(): - doc = Document(content="My name is Matteo and I live in Rome", meta={"list_field": ["one_item"]}) - with patch( - "haystack.nodes.retriever._embedding_encoder._SentenceTransformersEmbeddingEncoder.__init__" - ) as mock_init: - mock_init.return_value = None - retriever = EmbeddingRetriever( - embedding_model="sentence-transformers/all-mpnet-base-v2", - model_format="sentence_transformers", - embed_meta_fields=["list_field"], - ) - docs_with_embedded_meta = retriever._preprocess_documents(docs=[doc]) - assert docs_with_embedded_meta[0].content == "one_item\nMy name is Matteo and I live in Rome" - - -@pytest.mark.unit -def test_custom_query(): - mock_document_store = Mock(spec=KeywordDocumentStore) - mock_document_store.index = "test" - - custom_query = """ - { - "size": 10, - "query": { - "bool": { - "should": [{ - "multi_match": {"query": ${query}, "type": "most_fields", "fields": ["custom_text_field"]}}], - "filter": ${filters}}}}""" - - retriever = BM25Retriever(document_store=mock_document_store, custom_query=custom_query) - retriever.retrieve(query="test", filters={"year": ["2020", "2021"]}) - assert mock_document_store.query.call_args.kwargs["custom_query"] == custom_query - assert mock_document_store.query.call_args.kwargs["filters"] == {"year": ["2020", "2021"]} - assert mock_document_store.query.call_args.kwargs["query"] == "test" - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["elasticsearch", "faiss", "memory", "weaviate", "pinecone"], indirect=True) -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -def test_dpr_embedding(document_store: BaseDocumentStore, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - docs = document_store.get_all_documents() - docs.sort(key=lambda d: d.id) - - print([doc.id for doc in docs]) - - expected_values = [0.00892, 0.00780, 0.00482, -0.00626, 0.010966] - for doc, expected_value in zip(docs, expected_values): - embedding = doc.embedding - # always normalize vector as faiss returns normalized vectors and other document stores do not - embedding /= np.linalg.norm(embedding) - assert len(embedding) == 768 - assert isclose(embedding[0], expected_value, rel_tol=0.01) - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["elasticsearch", "faiss", "memory", "weaviate", "pinecone"], indirect=True) -@pytest.mark.parametrize("retriever", ["embedding_sbert_instructions"], indirect=True) -def test_embedding_with_instructions(document_store: BaseDocumentStore, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - docs = document_store.get_all_documents() - docs.sort(key=lambda d: d.id) - - print([doc.id for doc in docs]) - - expected_values = [0.00484978, 0.02258789, 0.03414359, -0.01461711, 0.01784192] - for doc, expected_value in zip(docs, expected_values): - embedding = doc.embedding - # always normalize vector as faiss returns normalized vectors and other document stores do not - embedding /= np.linalg.norm(embedding) - assert len(embedding) == 768 - assert isclose(embedding[0], expected_value, rel_tol=0.01) - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["elasticsearch", "faiss", "memory", "weaviate", "pinecone"], indirect=True) -@pytest.mark.parametrize("retriever", ["retribert"], indirect=True) -@pytest.mark.embedding_dim(128) -def test_retribert_embedding(document_store, retriever, docs_with_ids): - if isinstance(document_store, WeaviateDocumentStore): - # Weaviate sets the embedding dimension to 768 as soon as it is initialized. - # We need 128 here and therefore initialize a new WeaviateDocumentStore. - document_store = WeaviateDocumentStore(index="haystack_test", embedding_dim=128, recreate_index=True) - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - docs = document_store.get_all_documents() - docs = sorted(docs, key=lambda d: d.id) - - expected_values = [0.14017, 0.05975, 0.14267, 0.15099, 0.14383] - for doc, expected_value in zip(docs, expected_values): - embedding = doc.embedding - assert len(embedding) == 128 - # always normalize vector as faiss returns normalized vectors and other document stores do not - embedding /= np.linalg.norm(embedding) - assert isclose(embedding[0], expected_value, rel_tol=0.001) - - -@pytest.mark.unit -def test_openai_embedding_retriever_model_format(): - # support text-embedding-ada-002 - assert ( - EmbeddingRetriever._infer_model_format(model_name_or_path="text-embedding-ada-002", use_auth_token=None) - == "openai" - ) - - # support old ada and other text-search--*-001 models - assert EmbeddingRetriever._infer_model_format(model_name_or_path="ada", use_auth_token=None) == "openai" - - # support old babbage and other text-search--*-001 models - assert EmbeddingRetriever._infer_model_format(model_name_or_path="babbage", use_auth_token=None) == "openai" - - # make sure that we can handle potential unreleased models - assert ( - EmbeddingRetriever._infer_model_format(model_name_or_path="text-embedding-babbage-002", use_auth_token=None) - == "openai" - ) - - -@pytest.mark.unit -def test_openai_encoder_setup_encoding_models(): - with patch("haystack.nodes.retriever._openai_encoder._OpenAIEmbeddingEncoder.__init__") as mock_encoder_init: - mock_encoder_init.return_value = None - encoder = _OpenAIEmbeddingEncoder(retriever=None) # type: ignore - - encoder._setup_encoding_models(model_class="ada", model_name="text-embedding-ada-002", max_seq_len=512) - assert encoder.query_encoder_model == "text-embedding-ada-002" - assert encoder.doc_encoder_model == "text-embedding-ada-002" - - # support old ada and other text-search--*-001 models - encoder._setup_encoding_models(model_class="ada", model_name="ada", max_seq_len=512) - assert encoder.query_encoder_model == "text-search-ada-query-001" - assert encoder.doc_encoder_model == "text-search-ada-doc-001" - - # support old babbage and other text-search--*-001 models - encoder._setup_encoding_models(model_class="babbage", model_name="babbage", max_seq_len=512) - assert encoder.query_encoder_model == "text-search-babbage-query-001" - assert encoder.doc_encoder_model == "text-search-babbage-doc-001" - - # make sure that we can handle potential unreleased models - encoder._setup_encoding_models(model_class="babbage", model_name="text-embedding-babbage-002", max_seq_len=512) - assert encoder.query_encoder_model == "text-embedding-babbage-002" - assert encoder.doc_encoder_model == "text-embedding-babbage-002" - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["cohere"], indirect=True) -@pytest.mark.embedding_dim(1024) -@pytest.mark.skipif( - not os.environ.get("COHERE_API_KEY", None), - reason="Please export an env var called COHERE_API_KEY containing " "the Cohere API key to run this test.", -) -def test_basic_cohere_embedding(document_store, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - docs = document_store.get_all_documents() - docs = sorted(docs, key=lambda d: d.id) - - for doc in docs: - assert len(doc.embedding) == 1024 - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["openai"], indirect=True) -@pytest.mark.embedding_dim(1536) -@pytest.mark.skipif( - not os.environ.get("OPENAI_API_KEY", None), - reason=("Please export an env var called OPENAI_API_KEY containing the OpenAI API key to run this test."), -) -def test_basic_openai_embedding(document_store, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - docs = document_store.get_all_documents() - docs = sorted(docs, key=lambda d: d.id) - - for doc in docs: - assert len(doc.embedding) == 1536 - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["azure"], indirect=True) -@pytest.mark.embedding_dim(1536) -@pytest.mark.skipif( - not os.environ.get("AZURE_OPENAI_API_KEY", None) - and not os.environ.get("AZURE_OPENAI_BASE_URL", None) - and not os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME_EMBED", None), - reason=( - "Please export env variables called AZURE_OPENAI_API_KEY containing " - "the Azure OpenAI key, AZURE_OPENAI_BASE_URL containing " - "the Azure OpenAI base URL, and AZURE_OPENAI_DEPLOYMENT_NAME_EMBED containing " - "the Azure OpenAI deployment name to run this test." - ), -) -def test_basic_azure_embedding(document_store, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - docs = document_store.get_all_documents() - docs = sorted(docs, key=lambda d: d.id) - - for doc in docs: - assert len(doc.embedding) == 1536 - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["cohere"], indirect=True) -@pytest.mark.embedding_dim(1024) -@pytest.mark.skipif( - not os.environ.get("COHERE_API_KEY", None), - reason="Please export an env var called COHERE_API_KEY containing the Cohere API key to run this test.", -) -def test_retriever_basic_cohere_search(document_store, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - p_retrieval = DocumentSearchPipeline(retriever) - res = p_retrieval.run(query="Madrid", params={"Retriever": {"top_k": 1}}) - assert len(res["documents"]) == 1 - assert "Madrid" in res["documents"][0].content - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["openai"], indirect=True) -@pytest.mark.embedding_dim(1536) -@pytest.mark.skipif( - not os.environ.get("OPENAI_API_KEY", None), - reason="Please export env called OPENAI_API_KEY containing the OpenAI API key to run this test.", -) -def test_retriever_basic_openai_search(document_store, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - p_retrieval = DocumentSearchPipeline(retriever) - res = p_retrieval.run(query="Madrid", params={"Retriever": {"top_k": 1}}) - assert len(res["documents"]) == 1 - assert "Madrid" in res["documents"][0].content - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["azure"], indirect=True) -@pytest.mark.embedding_dim(1536) -@pytest.mark.skipif( - not os.environ.get("AZURE_OPENAI_API_KEY", None) - and not os.environ.get("AZURE_OPENAI_BASE_URL", None) - and not os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME_EMBED", None), - reason=( - "Please export env variables called AZURE_OPENAI_API_KEY containing " - "the Azure OpenAI key, AZURE_OPENAI_BASE_URL containing " - "the Azure OpenAI base URL, and AZURE_OPENAI_DEPLOYMENT_NAME_EMBED containing " - "the Azure OpenAI deployment name to run this test." - ), -) -def test_retriever_basic_azure_search(document_store, retriever, docs_with_ids): - document_store.return_embedding = True - document_store.write_documents(docs_with_ids) - document_store.update_embeddings(retriever=retriever) - - p_retrieval = DocumentSearchPipeline(retriever) - res = p_retrieval.run(query="Madrid", params={"Retriever": {"top_k": 1}}) - assert len(res["documents"]) == 1 - assert "Madrid" in res["documents"][0].content - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["table_text_retriever"], indirect=True) -@pytest.mark.parametrize("document_store", ["elasticsearch", "memory"], indirect=True) -@pytest.mark.embedding_dim(512) -def test_table_text_retriever_embedding(document_store, retriever, docs): - # BM25 representation is incompatible with table retriever - if isinstance(document_store, InMemoryDocumentStore): - document_store.use_bm25 = False - - document_store.return_embedding = True - document_store.write_documents(docs) - table_data = { - "Mountain": ["Mount Everest", "K2", "Kangchenjunga", "Lhotse", "Makalu"], - "Height": ["8848m", "8,611 m", "8 586m", "8 516 m", "8,485m"], - } - table = pd.DataFrame(table_data) - table_doc = Document(content=table, content_type="table", id="6") - document_store.write_documents([table_doc]) - document_store.update_embeddings(retriever=retriever) - - docs = document_store.get_all_documents() - docs = sorted(docs, key=lambda d: d.id) - - expected_values = [0.061191384, 0.038075786, 0.27447605, 0.09399721, 0.0959682] - for doc, expected_value in zip(docs, expected_values): - assert len(doc.embedding) == 512 - assert isclose(doc.embedding[0], expected_value, rel_tol=0.001) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["table_text_retriever"], indirect=True) -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.embedding_dim(512) -def test_table_text_retriever_embedding_only_text(document_store, retriever): - docs = [ - Document(content="This is a test", content_type="text"), - Document(content="This is another test", content_type="text"), - ] - document_store.write_documents(docs) - document_store.update_embeddings(retriever) - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever", ["table_text_retriever"], indirect=True) -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.embedding_dim(512) -def test_table_text_retriever_embedding_only_table(document_store, retriever): - doc = Document( - content=pd.DataFrame(columns=["id", "text"], data=[["1", "This is a test"], ["2", "This is another test"]]), - content_type="table", - ) - document_store.write_documents([doc]) - document_store.update_embeddings(retriever) - - -@pytest.mark.parametrize("retriever", ["dpr"], indirect=True) -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -def test_dpr_saving_and_loading(tmp_path, retriever, document_store): - retriever.save(f"{tmp_path}/test_dpr_save") - - def sum_params(model): - s = [] - for p in model.parameters(): - n = p.cpu().data.numpy() - s.append(np.sum(n)) - return sum(s) - - original_sum_query = sum_params(retriever.query_encoder) - original_sum_passage = sum_params(retriever.passage_encoder) - del retriever - - loaded_retriever = DensePassageRetriever.load(f"{tmp_path}/test_dpr_save", document_store) - - loaded_sum_query = sum_params(loaded_retriever.query_encoder) - loaded_sum_passage = sum_params(loaded_retriever.passage_encoder) - - assert abs(original_sum_query - loaded_sum_query) < 0.1 - assert abs(original_sum_passage - loaded_sum_passage) < 0.1 - - # comparison of weights (RAM intense!) - # for p1, p2 in zip(retriever.query_encoder.parameters(), loaded_retriever.query_encoder.parameters()): - # assert (p1.data.ne(p2.data).sum() == 0) - # - # for p1, p2 in zip(retriever.passage_encoder.parameters(), loaded_retriever.passage_encoder.parameters()): - # assert (p1.data.ne(p2.data).sum() == 0) - - # attributes - assert loaded_retriever.processor.embed_title == True - assert loaded_retriever.batch_size == 16 - assert loaded_retriever.processor.max_seq_len_passage == 256 - assert loaded_retriever.processor.max_seq_len_query == 64 - - # Tokenizer - assert isinstance(loaded_retriever.passage_tokenizer, PreTrainedTokenizerFast) - assert isinstance(loaded_retriever.query_tokenizer, PreTrainedTokenizerFast) - assert loaded_retriever.passage_tokenizer.do_lower_case == True - assert loaded_retriever.query_tokenizer.do_lower_case == True - assert loaded_retriever.passage_tokenizer.vocab_size == 30522 - assert loaded_retriever.query_tokenizer.vocab_size == 30522 - - -@pytest.mark.parametrize("retriever", ["table_text_retriever"], indirect=True) -@pytest.mark.embedding_dim(512) -def test_table_text_retriever_saving_and_loading(tmp_path, retriever, document_store): - retriever.save(f"{tmp_path}/test_table_text_retriever_save") - - def sum_params(model): - s = [] - for p in model.parameters(): - n = p.cpu().data.numpy() - s.append(np.sum(n)) - return sum(s) - - original_sum_query = sum_params(retriever.query_encoder) - original_sum_passage = sum_params(retriever.passage_encoder) - original_sum_table = sum_params(retriever.table_encoder) - del retriever - - loaded_retriever = TableTextRetriever.load(f"{tmp_path}/test_table_text_retriever_save", document_store) - - loaded_sum_query = sum_params(loaded_retriever.query_encoder) - loaded_sum_passage = sum_params(loaded_retriever.passage_encoder) - loaded_sum_table = sum_params(loaded_retriever.table_encoder) - - assert abs(original_sum_query - loaded_sum_query) < 0.1 - assert abs(original_sum_passage - loaded_sum_passage) < 0.1 - assert abs(original_sum_table - loaded_sum_table) < 0.01 - - # attributes - assert loaded_retriever.processor.embed_meta_fields == ["name", "section_title", "caption"] - assert loaded_retriever.batch_size == 16 - assert loaded_retriever.processor.max_seq_len_passage == 256 - assert loaded_retriever.processor.max_seq_len_table == 256 - assert loaded_retriever.processor.max_seq_len_query == 64 - - # Tokenizer - assert isinstance(loaded_retriever.passage_tokenizer, PreTrainedTokenizerFast) - assert isinstance(loaded_retriever.table_tokenizer, PreTrainedTokenizerFast) - assert isinstance(loaded_retriever.query_tokenizer, PreTrainedTokenizerFast) - assert loaded_retriever.passage_tokenizer.do_lower_case == True - assert loaded_retriever.table_tokenizer.do_lower_case == True - assert loaded_retriever.query_tokenizer.do_lower_case == True - assert loaded_retriever.passage_tokenizer.vocab_size == 30522 - assert loaded_retriever.table_tokenizer.vocab_size == 30522 - assert loaded_retriever.query_tokenizer.vocab_size == 30522 - - -@pytest.mark.embedding_dim(128) -def test_table_text_retriever_training(tmp_path, document_store, samples_path): - retriever = TableTextRetriever( - document_store=document_store, - query_embedding_model="deepset/bert-small-mm_retrieval-question_encoder", - passage_embedding_model="deepset/bert-small-mm_retrieval-passage_encoder", - table_embedding_model="deepset/bert-small-mm_retrieval-table_encoder", - use_gpu=False, - ) - - retriever.train( - data_dir=samples_path / "mmr", - train_filename="sample.json", - n_epochs=1, - n_gpu=0, - save_dir=f"{tmp_path}/test_table_text_retriever_train", - ) - - # Load trained model - retriever = TableTextRetriever.load( - load_dir=f"{tmp_path}/test_table_text_retriever_train", document_store=document_store - ) - - -@pytest.mark.elasticsearch -def test_elasticsearch_highlight(): - client = Elasticsearch() - client.indices.delete(index="haystack_hl_test", ignore=[404]) - - # Mapping the content and title field as "text" perform search on these both fields. - document_store = ElasticsearchDocumentStore( - index="haystack_hl_test", - content_field="title", - custom_mapping={"mappings": {"properties": {"content": {"type": "text"}, "title": {"type": "text"}}}}, - ) - documents = [ - { - "title": "Green tea components", - "meta": { - "content": "The green tea plant contains a range of healthy compounds that make it into the final drink" - }, - "id": "1", - }, - { - "title": "Green tea catechin", - "meta": {"content": "Green tea contains a catechin called epigallocatechin-3-gallate (EGCG)."}, - "id": "2", - }, - { - "title": "Minerals in Green tea", - "meta": {"content": "Green tea also has small amounts of minerals that can benefit your health."}, - "id": "3", - }, - { - "title": "Green tea Benefits", - "meta": {"content": "Green tea does more than just keep you alert, it may also help boost brain function."}, - "id": "4", - }, - ] - document_store.write_documents(documents) - - # Enabled highlighting on "title"&"content" field only using custom query - retriever_1 = BM25Retriever( - document_store=document_store, - custom_query="""{ - "size": 20, - "query": { - "bool": { - "should": [ - { - "multi_match": { - "query": ${query}, - "fields": [ - "content^3", - "title^5" - ] - } - } - ] - } - }, - "highlight": { - "pre_tags": [ - "**" - ], - "post_tags": [ - "**" - ], - "number_of_fragments": 3, - "fragment_size": 5, - "fields": { - "content": {}, - "title": {} - } - } - }""", - ) - results = retriever_1.retrieve(query="is green tea healthy") - - assert len(results[0].meta["highlighted"]) == 2 - assert results[0].meta["highlighted"]["title"] == ["**Green**", "**tea** components"] - assert results[0].meta["highlighted"]["content"] == ["The **green**", "**tea** plant", "range of **healthy**"] - - # Enabled highlighting on "title" field only using custom query - retriever_2 = BM25Retriever( - document_store=document_store, - custom_query="""{ - "size": 20, - "query": { - "bool": { - "should": [ - { - "multi_match": { - "query": ${query}, - "fields": [ - "content^3", - "title^5" - ] - } - } - ] - } - }, - "highlight": { - "pre_tags": [ - "**" - ], - "post_tags": [ - "**" - ], - "number_of_fragments": 3, - "fragment_size": 5, - "fields": { - "title": {} - } - } - }""", - ) - results = retriever_2.retrieve(query="is green tea healthy") - - assert len(results[0].meta["highlighted"]) == 1 - assert results[0].meta["highlighted"]["title"] == ["**Green**", "**tea** components"] - - -def test_elasticsearch_filter_must_not_increase_results(): - index = "filter_must_not_increase_results" - client = Elasticsearch() - client.indices.delete(index=index, ignore=[404]) - documents = [ - { - "content": "The green tea plant contains a range of healthy compounds that make it into the final drink", - "meta": {"content_type": "text"}, - "id": "1", - }, - { - "content": "Green tea contains a catechin called epigallocatechin-3-gallate (EGCG).", - "meta": {"content_type": "text"}, - "id": "2", - }, - { - "content": "Green tea also has small amounts of minerals that can benefit your health.", - "meta": {"content_type": "text"}, - "id": "3", - }, - { - "content": "Green tea does more than just keep you alert, it may also help boost brain function.", - "meta": {"content_type": "text"}, - "id": "4", - }, - ] - doc_store = ElasticsearchDocumentStore(index=index) - doc_store.write_documents(documents) - results_wo_filter = doc_store.query(query="drink") - assert len(results_wo_filter) == 1 - results_w_filter = doc_store.query(query="drink", filters={"content_type": "text"}) - assert len(results_w_filter) == 1 - doc_store.delete_index(index) - - -def test_elasticsearch_all_terms_must_match(): - index = "all_terms_must_match" - client = Elasticsearch() - client.indices.delete(index=index, ignore=[404]) - documents = [ - { - "content": "The green tea plant contains a range of healthy compounds that make it into the final drink", - "meta": {"content_type": "text"}, - "id": "1", - }, - { - "content": "Green tea contains a catechin called epigallocatechin-3-gallate (EGCG).", - "meta": {"content_type": "text"}, - "id": "2", - }, - { - "content": "Green tea also has small amounts of minerals that can benefit your health.", - "meta": {"content_type": "text"}, - "id": "3", - }, - { - "content": "Green tea does more than just keep you alert, it may also help boost brain function.", - "meta": {"content_type": "text"}, - "id": "4", - }, - ] - doc_store = ElasticsearchDocumentStore(index=index) - doc_store.write_documents(documents) - results_wo_all_terms_must_match = doc_store.query(query="drink green tea") - assert len(results_wo_all_terms_must_match) == 4 - results_w_all_terms_must_match = doc_store.query(query="drink green tea", all_terms_must_match=True) - assert len(results_w_all_terms_must_match) == 1 - doc_store.delete_index(index) - - -@pytest.mark.elasticsearch -def test_bm25retriever_all_terms_must_match(): - index = "all_terms_must_match" - client = Elasticsearch() - client.indices.delete(index=index, ignore=[404]) - documents = [ - { - "content": "The green tea plant contains a range of healthy compounds that make it into the final drink", - "meta": {"content_type": "text"}, - "id": "1", - }, - { - "content": "Green tea contains a catechin called epigallocatechin-3-gallate (EGCG).", - "meta": {"content_type": "text"}, - "id": "2", - }, - { - "content": "Green tea also has small amounts of minerals that can benefit your health.", - "meta": {"content_type": "text"}, - "id": "3", - }, - { - "content": "Green tea does more than just keep you alert, it may also help boost brain function.", - "meta": {"content_type": "text"}, - "id": "4", - }, - ] - doc_store = ElasticsearchDocumentStore(index=index) - doc_store.write_documents(documents) - retriever = BM25Retriever(document_store=doc_store) - results_wo_all_terms_must_match = retriever.retrieve(query="drink green tea") - assert len(results_wo_all_terms_must_match) == 4 - retriever = BM25Retriever(document_store=doc_store, all_terms_must_match=True) - results_w_all_terms_must_match = retriever.retrieve(query="drink green tea") - assert len(results_w_all_terms_must_match) == 1 - retriever = BM25Retriever(document_store=doc_store) - results_w_all_terms_must_match = retriever.retrieve(query="drink green tea", all_terms_must_match=True) - assert len(results_w_all_terms_must_match) == 1 - doc_store.delete_index(index) - - -def test_embeddings_encoder_of_embedding_retriever_should_warn_about_model_format(caplog): - document_store = InMemoryDocumentStore() - - with caplog.at_level(logging.WARNING): - EmbeddingRetriever( - document_store=document_store, - embedding_model="sentence-transformers/paraphrase-multilingual-mpnet-base-v2", - model_format="farm", - ) - - assert ( - "You may need to set model_format='sentence_transformers' to ensure correct loading of model." - in caplog.text - ) - - -@pytest.mark.parametrize("retriever", ["es_filter_only"], indirect=True) -@pytest.mark.parametrize("document_store", ["elasticsearch"], indirect=True) -def test_es_filter_only(document_store, retriever): - docs = [ - Document(content="Doc1", meta={"f1": "0"}), - Document(content="Doc2", meta={"f1": "0"}), - Document(content="Doc3", meta={"f1": "0"}), - Document(content="Doc4", meta={"f1": "0"}), - Document(content="Doc5", meta={"f1": "0"}), - Document(content="Doc6", meta={"f1": "0"}), - Document(content="Doc7", meta={"f1": "1"}), - Document(content="Doc8", meta={"f1": "0"}), - Document(content="Doc9", meta={"f1": "0"}), - Document(content="Doc10", meta={"f1": "0"}), - Document(content="Doc11", meta={"f1": "0"}), - Document(content="Doc12", meta={"f1": "0"}), - ] - document_store.write_documents(docs) - retrieved_docs = retriever.retrieve(query="", filters={"f1": ["0"]}) - assert len(retrieved_docs) == 11 - - -# -# MultiModal -# - - -@pytest.fixture -def text_docs() -> List[Document]: - return [ - Document( - content="My name is Paul and I live in New York", - meta={ - "meta_field": "test2", - "name": "filename2", - "date_field": "2019-10-01", - "numeric_field": 5.0, - "odd_field": 0, - }, - ), - Document( - content="My name is Carla and I live in Berlin", - meta={ - "meta_field": "test1", - "name": "filename1", - "date_field": "2020-03-01", - "numeric_field": 5.5, - "odd_field": 1, - }, - ), - Document( - content="My name is Christelle and I live in Paris", - meta={ - "meta_field": "test3", - "name": "filename3", - "date_field": "2018-10-01", - "numeric_field": 4.5, - "odd_field": 1, - }, - ), - Document( - content="My name is Camila and I live in Madrid", - meta={ - "meta_field": "test4", - "name": "filename4", - "date_field": "2021-02-01", - "numeric_field": 3.0, - "odd_field": 0, - }, - ), - Document( - content="My name is Matteo and I live in Rome", - meta={ - "meta_field": "test5", - "name": "filename5", - "date_field": "2019-01-01", - "numeric_field": 0.0, - "odd_field": 1, - }, - ), - ] - - -@pytest.fixture -def table_docs() -> List[Document]: - return [ - Document( - content=pd.DataFrame( - { - "Mountain": ["Mount Everest", "K2", "Kangchenjunga", "Lhotse", "Makalu"], - "Height": ["8848m", "8,611 m", "8 586m", "8 516 m", "8,485m"], - } - ), - content_type="table", - ), - Document( - content=pd.DataFrame( - { - "City": ["Paris", "Lyon", "Marseille", "Lille", "Toulouse", "Bordeaux"], - "Population": ["13,114,718", "2,280,845", "1,873,270 ", "1,510,079", "1,454,158", "1,363,711"], - } - ), - content_type="table", - ), - Document( - content=pd.DataFrame( - { - "City": ["Berlin", "Hamburg", "Munich", "Cologne"], - "Population": ["3,644,826", "1,841,179", "1,471,508", "1,085,664"], - } - ), - content_type="table", - ), - ] - - -@pytest.fixture -def image_docs(samples_path) -> List[Document]: - return [ - Document(content=str(samples_path / "images" / imagefile), content_type="image") - for imagefile in os.listdir(samples_path / "images") - ] - - -@pytest.mark.integration -def test_multimodal_text_retrieval(text_docs: List[Document]): - retriever = MultiModalRetriever( - document_store=InMemoryDocumentStore(return_embedding=True), - query_embedding_model="sentence-transformers/multi-qa-mpnet-base-dot-v1", - document_embedding_models={"text": "sentence-transformers/multi-qa-mpnet-base-dot-v1"}, - ) - retriever.document_store.write_documents(text_docs) - retriever.document_store.update_embeddings(retriever=retriever) - - results = retriever.retrieve(query="Who lives in Paris?") - assert results[0].content == "My name is Christelle and I live in Paris" - - -@pytest.mark.integration -def test_multimodal_text_retrieval_batch(text_docs: List[Document]): - retriever = MultiModalRetriever( - document_store=InMemoryDocumentStore(return_embedding=True), - query_embedding_model="sentence-transformers/multi-qa-mpnet-base-dot-v1", - document_embedding_models={"text": "sentence-transformers/multi-qa-mpnet-base-dot-v1"}, - ) - retriever.document_store.write_documents(text_docs) - retriever.document_store.update_embeddings(retriever=retriever) - - results = retriever.retrieve_batch(queries=["Who lives in Paris?", "Who lives in Berlin?", "Who lives in Madrid?"]) - assert results[0][0].content == "My name is Christelle and I live in Paris" - assert results[1][0].content == "My name is Carla and I live in Berlin" - assert results[2][0].content == "My name is Camila and I live in Madrid" - - -@pytest.mark.integration -def test_multimodal_table_retrieval(table_docs: List[Document]): - retriever = MultiModalRetriever( - document_store=InMemoryDocumentStore(return_embedding=True), - query_embedding_model="deepset/all-mpnet-base-v2-table", - document_embedding_models={"table": "deepset/all-mpnet-base-v2-table"}, - ) - retriever.document_store.write_documents(table_docs) - retriever.document_store.update_embeddings(retriever=retriever) - - results = retriever.retrieve(query="How many people live in Hamburg?") - assert_frame_equal( - results[0].content, - pd.DataFrame( - { - "City": ["Berlin", "Hamburg", "Munich", "Cologne"], - "Population": ["3,644,826", "1,841,179", "1,471,508", "1,085,664"], - } - ), - ) - - -@pytest.mark.skip("Must be reworked as it fails randomly") -@pytest.mark.integration -def test_multimodal_retriever_query(): - retriever = MultiModalRetriever( - document_store=InMemoryDocumentStore(return_embedding=True, embedding_dim=512), - query_embedding_model="sentence-transformers/clip-ViT-B-32", - document_embedding_models={"image": "sentence-transformers/clip-ViT-B-32"}, - ) - - res_emb = retriever.embed_queries(["dummy query 1", "dummy query 1"]) - assert np.array_equal(res_emb[0], res_emb[1]) - - -@pytest.mark.integration -def test_multimodal_image_retrieval(image_docs: List[Document], samples_path): - retriever = MultiModalRetriever( - document_store=InMemoryDocumentStore(return_embedding=True, embedding_dim=512), - query_embedding_model="sentence-transformers/clip-ViT-B-32", - document_embedding_models={"image": "sentence-transformers/clip-ViT-B-32"}, - ) - retriever.document_store.write_documents(image_docs) - retriever.document_store.update_embeddings(retriever=retriever) - - results = retriever.retrieve(query="What's a cat?") - assert str(results[0].content) == str(samples_path / "images" / "cat.jpg") - - -@pytest.mark.skip("Not working yet as intended") -@pytest.mark.integration -def test_multimodal_text_image_retrieval(text_docs: List[Document], image_docs: List[Document], samples_path): - retriever = MultiModalRetriever( - document_store=InMemoryDocumentStore(return_embedding=True, embedding_dim=512), - query_embedding_model="sentence-transformers/clip-ViT-B-32", - document_embedding_models={ - "text": "sentence-transformers/clip-ViT-B-32", - "image": "sentence-transformers/clip-ViT-B-32", - }, - ) - retriever.document_store.write_documents(image_docs) - retriever.document_store.write_documents(text_docs) - retriever.document_store.update_embeddings(retriever=retriever) - - results = retriever.retrieve(query="What's Paris?") - - text_results = [result for result in results if result.content_type == "text"] - image_results = [result for result in results if result.content_type == "image"] - - assert str(image_results[0].content) == str(samples_path / "images" / "paris.jpg") - assert text_results[0].content == "My name is Christelle and I live in Paris" - - -@pytest.mark.unit -@patch("haystack.nodes.retriever._openai_encoder.openai_request") -def test_openai_default_api_base(mock_request): - with patch("haystack.nodes.retriever._openai_encoder.load_openai_tokenizer"): - retriever = EmbeddingRetriever(embedding_model="text-embedding-ada-002", api_key="fake_api_key") - assert retriever.api_base == "https://api.openai.com/v1" - - retriever.embed_queries(queries=["test query"]) - assert mock_request.call_args.kwargs["url"] == "https://api.openai.com/v1/embeddings" - mock_request.reset_mock() - - retriever.embed_documents(documents=[Document(content="test document")]) - assert mock_request.call_args.kwargs["url"] == "https://api.openai.com/v1/embeddings" - - -@pytest.mark.unit -@patch("haystack.nodes.retriever._openai_encoder.openai_request") -def test_openai_custom_api_base(mock_request): - with patch("haystack.nodes.retriever._openai_encoder.load_openai_tokenizer"): - retriever = EmbeddingRetriever( - embedding_model="text-embedding-ada-002", api_key="fake_api_key", api_base="https://fake_api_base.com" - ) - assert retriever.api_base == "https://fake_api_base.com" - - retriever.embed_queries(queries=["test query"]) - assert mock_request.call_args.kwargs["url"] == "https://fake_api_base.com/embeddings" - mock_request.reset_mock() - - retriever.embed_documents(documents=[Document(content="test document")]) - assert mock_request.call_args.kwargs["url"] == "https://fake_api_base.com/embeddings" - - -@pytest.mark.unit -@patch("haystack.nodes.retriever._openai_encoder.openai_request") -def test_openai_no_openai_organization(mock_request): - with patch("haystack.nodes.retriever._openai_encoder.load_openai_tokenizer"): - retriever = EmbeddingRetriever(embedding_model="text-embedding-ada-002", api_key="fake_api_key") - assert retriever.openai_organization is None - - retriever.embed_queries(queries=["test query"]) - assert "OpenAI-Organization" not in mock_request.call_args.kwargs["headers"] - - -@pytest.mark.unit -@patch("haystack.nodes.retriever._openai_encoder.openai_request") -def test_openai_openai_organization(mock_request): - with patch("haystack.nodes.retriever._openai_encoder.load_openai_tokenizer"): - retriever = EmbeddingRetriever( - embedding_model="text-embedding-ada-002", api_key="fake_api_key", openai_organization="fake_organization" - ) - assert retriever.openai_organization == "fake_organization" - - retriever.embed_queries(queries=["test query"]) - assert mock_request.call_args.kwargs["headers"]["OpenAI-Organization"] == "fake_organization" diff --git a/test/nodes/test_route_documents.py b/test/nodes/test_route_documents.py deleted file mode 100644 index 2100aed964..0000000000 --- a/test/nodes/test_route_documents.py +++ /dev/null @@ -1,98 +0,0 @@ -import pytest -import pandas as pd - -from haystack.schema import Document -from haystack.nodes import RouteDocuments - - -@pytest.fixture -def docs_diff_types(): - return [ - Document(content="text document", content_type="text"), - Document( - content=pd.DataFrame(columns=["col 1", "col 2"], data=[["row 1", "row 1"], ["row 2", "row 2"]]), - content_type="table", - ), - Document(content="image/path", content_type="image"), - ] - - -@pytest.fixture -def docs_with_meta(): - return [ - Document(content="text document 1", content_type="text", meta={"meta_field": "test1"}), - Document(content="text document 2", content_type="text", meta={"meta_field": "test2"}), - Document(content="text document 3", content_type="text", meta={"meta_field": "test3"}), - ] - - -@pytest.mark.unit -def test_routedocuments_by_content_type(docs_diff_types): - route_documents = RouteDocuments() - result, _ = route_documents.run(documents=docs_diff_types) - assert route_documents.outgoing_edges == 2 - assert len(result["output_1"]) == 1 - assert len(result["output_2"]) == 1 - assert "output_3" not in result - assert result["output_1"][0].content_type == "text" - assert result["output_2"][0].content_type == "table" - - -@pytest.mark.unit -def test_routedocuments_by_content_type_return_remaining(docs_diff_types): - route_documents = RouteDocuments(return_remaining=True) - result, _ = route_documents.run(documents=docs_diff_types) - assert route_documents.outgoing_edges == 3 - assert len(result["output_1"]) == 1 - assert len(result["output_2"]) == 1 - assert len(result["output_3"]) == 1 - assert result["output_1"][0].content_type == "text" - assert result["output_2"][0].content_type == "table" - assert result["output_3"][0].content_type == "image" - - -@pytest.mark.unit -def test_routedocuments_by_metafield(docs): - route_documents = RouteDocuments(split_by="meta_field", metadata_values=["test1", "test3", "test5"]) - assert route_documents.outgoing_edges == 3 - result, _ = route_documents.run(docs) - assert len(result["output_1"]) == 1 - assert len(result["output_2"]) == 1 - assert len(result["output_3"]) == 1 - assert "output_4" not in result - assert result["output_1"][0].meta["meta_field"] == "test1" - assert result["output_2"][0].meta["meta_field"] == "test3" - assert result["output_3"][0].meta["meta_field"] == "test5" - - -@pytest.mark.unit -def test_routedocuments_by_metafield_return_remaning(docs): - route_documents = RouteDocuments( - split_by="meta_field", metadata_values=["test1", "test3", "test5"], return_remaining=True - ) - assert route_documents.outgoing_edges == 4 - result, _ = route_documents.run(docs) - assert len(result["output_1"]) == 1 - assert len(result["output_2"]) == 1 - assert len(result["output_3"]) == 1 - assert len(result["output_4"]) == 2 - assert result["output_1"][0].meta["meta_field"] == "test1" - assert result["output_2"][0].meta["meta_field"] == "test3" - assert result["output_3"][0].meta["meta_field"] == "test5" - assert result["output_4"][0].meta["meta_field"] == "test2" - - -@pytest.mark.unit -def test_routedocuments_by_metafield_list_of_lists(docs): - route_documents = RouteDocuments( - split_by="meta_field", metadata_values=[["test1", "test3"], "test5"], return_remaining=True - ) - assert route_documents.outgoing_edges == 3 - result, _ = route_documents.run(docs) - assert len(result["output_1"]) == 2 - assert len(result["output_2"]) == 1 - assert len(result["output_3"]) == 2 - assert result["output_1"][0].meta["meta_field"] == "test1" - assert result["output_1"][1].meta["meta_field"] == "test3" - assert result["output_2"][0].meta["meta_field"] == "test5" - assert result["output_3"][0].meta["meta_field"] == "test2" diff --git a/test/nodes/test_sampler.py b/test/nodes/test_sampler.py deleted file mode 100644 index 4ba69037d8..0000000000 --- a/test/nodes/test_sampler.py +++ /dev/null @@ -1,105 +0,0 @@ -import os - -import pytest - -from haystack import Pipeline -from haystack.nodes import TopPSampler, SentenceTransformersRanker -from haystack.nodes.search_engine import WebSearch -from haystack.schema import Document - -docs = [ - Document( - content="""Aaron Aaron ( or ; ""Ahärôn"") is a prophet, high priest, and the brother of Moses in the Abrahamic religions. Knowledge of Aaron, along with his brother Moses, comes exclusively from religious texts, such as the Bible and Quran. The Hebrew Bible relates that, unlike Moses, who grew up in the Egyptian royal court, Aaron and his elder sister Miriam remained with their kinsmen in the eastern border-land of Egypt (Goshen). When Moses first confronted the Egyptian king about the Israelites, Aaron served as his brother's spokesman (""prophet"") to the Pharaoh. Part of the Law (Torah) that Moses received from""", - meta={"name": "0"}, - id="1", - ), - Document( - content="""Democratic Republic of the Congo to the south. Angola's capital, Luanda, lies on the Atlantic coast in the northwest of the country. Angola, although located in a tropical zone, has a climate that is not characterized for this region, due to the confluence of three factors: As a result, Angola's climate is characterized by two seasons: rainfall from October to April and drought, known as ""Cacimbo"", from May to August, drier, as the name implies, and with lower temperatures. On the other hand, while the coastline has high rainfall rates, decreasing from North to South and from to , with""", - id="2", - ), - Document( - content="""Schopenhauer, describing him as an ultimately shallow thinker: ""Schopenhauer has quite a crude mind ... where real depth starts, his comes to an end."" His friend Bertrand Russell had a low opinion on the philosopher, and attacked him in his famous ""History of Western Philosophy"" for hypocritically praising asceticism yet not acting upon it. On the opposite isle of Russell on the foundations of mathematics, the Dutch mathematician L. E. J. Brouwer incorporated the ideas of Kant and Schopenhauer in intuitionism, where mathematics is considered a purely mental activity, instead of an analytic activity wherein objective properties of reality are""", - meta={"name": "1"}, - id="3", - ), - Document( - content="""The Dothraki vocabulary was created by David J. Peterson well in advance of the adaptation. HBO hired the Language Creatio""", - meta={"name": "2"}, - id="4", - ), - Document( - content="""The title of the episode refers to the Great Sept of Baelor, the main religious building in King's Landing, where the episode's pivotal scene takes place. In the world created by George R. R. Martin""", - meta={}, - id="5", - ), -] - - -@pytest.mark.integration -def test_top_p_sampling(top_p_sampler): - query = "What is the most important religious learning from the Bible?" - results = top_p_sampler.predict(query=query, documents=docs, top_p=0.98) - assert len(results) == 2 - assert results[0].id == "1" - assert results[1].id == "5" - - -@pytest.mark.integration -def test_top_p_sampling_top_p_none(top_p_sampler): - query = "What is the most important religious learning from the Bible?" - results = top_p_sampler.predict(query=query, documents=docs, top_p=None) - assert len(results) == 5 - - new_sampler = TopPSampler(top_p=None) - results = new_sampler.predict(query=query, documents=docs) - assert len(results) == 5 - - -@pytest.mark.integration -def test_top_p_sampling_at_least_one_result(top_p_sampler): - query = "What is the most important building in King's Landing that has a religious background?" - results = top_p_sampler.predict(query=query, documents=docs, top_p=0.9) - - # The top_p sampler should always return at least one result if strict is False (default) - # in this case the result with the highest prob score is returned even if top p is too low - assert len(results) == 1 - assert results[0].id == "5" - - # unless strict is set to True - sampler = TopPSampler(strict=True) - results = sampler.predict(query=query, documents=docs, top_p=0.9) - assert len(results) == 0 - - -@pytest.mark.integration -@pytest.mark.skipif( - not os.environ.get("SERPERDEV_API_KEY", None), - reason="Please export an env var called SERPERDEV_API_KEY containing the serper.dev API key to run this test.", -) -def test_sampler_pipeline(top_p_sampler): - ws = WebSearch(api_key=os.environ.get("SERPERDEV_API_KEY", None)) - pipe = Pipeline() - pipe.add_node(component=ws, name="ws", inputs=["Query"]) - pipe.add_node(component=top_p_sampler, name="sampler", inputs=["ws"]) - result = pipe.run(query="Who is the boyfriend of Olivia Wilde?") - assert "documents" in result - assert len(result["documents"]) > 0 - assert isinstance(result["documents"][0], Document) - - -@pytest.mark.integration -@pytest.mark.skipif( - not os.environ.get("SERPERDEV_API_KEY", None), - reason="Please export an env var called SERPERDEV_API_KEY containing the serper.dev API key to run this test.", -) -def test_sampler_with_ranker_pipeline(top_p_sampler): - ws = WebSearch(api_key=os.environ.get("SERPERDEV_API_KEY", None)) - ranker = SentenceTransformersRanker(model_name_or_path="cross-encoder/ms-marco-MiniLM-L-6-v2", top_k=2) - pipe = Pipeline() - pipe.add_node(component=ws, name="ws", inputs=["Query"]) - pipe.add_node(component=top_p_sampler, name="sampler", inputs=["ws"]) - pipe.add_node(component=ranker, name="ranker", inputs=["sampler"]) - result = pipe.run(query="Who is the boyfriend of Olivia Wilde?") - assert "documents" in result - assert len(result["documents"]) == 2 - assert isinstance(result["documents"][0], Document) diff --git a/test/nodes/test_shaper.py b/test/nodes/test_shaper.py deleted file mode 100644 index 4d494de052..0000000000 --- a/test/nodes/test_shaper.py +++ /dev/null @@ -1,1709 +0,0 @@ -from datetime import datetime -import logging - -import pytest - -import haystack -from haystack import Pipeline, Document, Answer -from haystack.document_stores.memory import InMemoryDocumentStore -from haystack.nodes.other.shaper import Shaper -from haystack.nodes.retriever.sparse import BM25Retriever - - -@pytest.fixture -def mock_function(monkeypatch): - monkeypatch.setattr( - haystack.nodes.other.shaper, "REGISTERED_FUNCTIONS", {"test_function": lambda a, b: [a] * len(b)} - ) - - -@pytest.fixture -def mock_function_two_outputs(monkeypatch): - monkeypatch.setattr( - haystack.nodes.other.shaper, "REGISTERED_FUNCTIONS", {"two_output_test_function": lambda a: (a, len(a))} - ) - - -@pytest.mark.unit -def test_basic_invocation_only_inputs(mock_function): - shaper = Shaper(func="test_function", inputs={"a": "query", "b": "documents"}, outputs=["c"]) - results, _ = shaper.run(query="test query", documents=["doesn't", "really", "matter"]) - assert results["invocation_context"]["c"] == ["test query", "test query", "test query"] - - -@pytest.mark.unit -def test_basic_invocation_empty_documents_list(mock_function): - shaper = Shaper(func="test_function", inputs={"a": "query", "b": "documents"}, outputs=["c"]) - results, _ = shaper.run(query="test query", documents=[]) - assert results["invocation_context"]["c"] == [] - - -@pytest.mark.unit -def test_multiple_outputs(mock_function_two_outputs): - shaper = Shaper(func="two_output_test_function", inputs={"a": "query"}, outputs=["c", "d"]) - results, _ = shaper.run(query="test") - assert results["invocation_context"]["c"] == "test" - assert results["invocation_context"]["d"] == 4 - - -@pytest.mark.unit -def test_multiple_outputs_error(mock_function_two_outputs, caplog): - shaper = Shaper(func="two_output_test_function", inputs={"a": "query"}, outputs=["c"]) - with caplog.at_level(logging.WARNING): - results, _ = shaper.run(query="test") - assert "Only 1 output(s) will be stored." in caplog.text - - -@pytest.mark.unit -def test_basic_invocation_only_params(mock_function): - shaper = Shaper(func="test_function", params={"a": "A", "b": list(range(3))}, outputs=["c"]) - results, _ = shaper.run() - assert results["invocation_context"]["c"] == ["A", "A", "A"] - - -@pytest.mark.unit -def test_basic_invocation_inputs_and_params(mock_function): - shaper = Shaper(func="test_function", inputs={"a": "query"}, params={"b": list(range(2))}, outputs=["c"]) - results, _ = shaper.run(query="test query") - assert results["invocation_context"]["c"] == ["test query", "test query"] - - -@pytest.mark.unit -def test_basic_invocation_inputs_and_params_colliding(mock_function): - shaper = Shaper( - func="test_function", inputs={"a": "query"}, params={"a": "default value", "b": list(range(2))}, outputs=["c"] - ) - results, _ = shaper.run(query="test query") - assert results["invocation_context"]["c"] == ["test query", "test query"] - - -@pytest.mark.unit -def test_basic_invocation_inputs_and_params_using_params_as_defaults(mock_function): - shaper = Shaper( - func="test_function", inputs={"a": "query"}, params={"a": "default", "b": list(range(2))}, outputs=["c"] - ) - results, _ = shaper.run() - assert results["invocation_context"]["c"] == ["default", "default"] - - -@pytest.mark.unit -def test_missing_argument(mock_function): - shaper = Shaper(func="test_function", inputs={"b": "documents"}, outputs=["c"]) - with pytest.raises(ValueError, match="Shaper couldn't apply the function to your inputs and parameters."): - shaper.run(query="test query", documents=["doesn't", "really", "matter"]) - - -@pytest.mark.unit -def test_excess_argument(mock_function): - shaper = Shaper( - func="test_function", inputs={"a": "query", "b": "documents", "something_extra": "query"}, outputs=["c"] - ) - with pytest.raises(ValueError, match="Shaper couldn't apply the function to your inputs and parameters."): - shaper.run(query="test query", documents=["doesn't", "really", "matter"]) - - -@pytest.mark.unit -def test_value_not_in_invocation_context(mock_function): - shaper = Shaper(func="test_function", inputs={"a": "query", "b": "something_that_does_not_exist"}, outputs=["c"]) - with pytest.raises(ValueError, match="Shaper couldn't apply the function to your inputs and parameters."): - shaper.run(query="test query", documents=["doesn't", "really", "matter"]) - - -@pytest.mark.unit -def test_value_only_in_invocation_context(mock_function): - shaper = Shaper(func="test_function", inputs={"a": "query", "b": "invocation_context_specific"}, outputs=["c"]) - results, _s = shaper.run( - query="test query", invocation_context={"invocation_context_specific": ["doesn't", "really", "matter"]} - ) - assert results["invocation_context"]["c"] == ["test query", "test query", "test query"] - - -@pytest.mark.unit -def test_yaml(mock_function, tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: test_function - inputs: - a: query - params: - b: [1, 1] - outputs: - - c - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="test query", documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert result["invocation_context"]["c"] == ["test query", "test query"] - assert result["query"] == "test query" - assert result["documents"] == [Document(content="first"), Document(content="second"), Document(content="third")] - - -# -# rename -# - - -@pytest.mark.unit -def test_rename(): - shaper = Shaper(func="rename", inputs={"value": "query"}, outputs=["questions"]) - results, _ = shaper.run(query="test query") - assert results["invocation_context"]["questions"] == "test query" - - -@pytest.mark.unit -def test_rename_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: rename - inputs: - value: query - outputs: - - questions - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(query="test query") - assert result["invocation_context"]["query"] == "test query" - assert result["invocation_context"]["questions"] == "test query" - - -# -# current_datetime -# - - -@pytest.mark.unit -def test_current_datetime(): - shaper = Shaper(func="current_datetime", inputs={}, outputs=["date_time"], params={"format": "%y-%m-%d"}) - results, _ = shaper.run() - assert results["invocation_context"]["date_time"] == datetime.now().strftime("%y-%m-%d") - - -@pytest.mark.unit -def test_current_datetime_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: current_datetime - params: - format: "%y-%m-%d" - outputs: - - date_time - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run() - assert result["invocation_context"]["date_time"] == datetime.now().strftime("%y-%m-%d") - - -# -# value_to_list -# - - -@pytest.mark.unit -def test_value_to_list(): - shaper = Shaper(func="value_to_list", inputs={"value": "query", "target_list": "documents"}, outputs=["questions"]) - results, _ = shaper.run(query="test query", documents=["doesn't", "really", "matter"]) - assert results["invocation_context"]["questions"] == ["test query", "test query", "test query"] - - -@pytest.mark.unit -def test_value_to_list_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: value_to_list - inputs: - value: query - target_list: documents - outputs: - - questions - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="test query", documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert result["invocation_context"]["questions"] == ["test query", "test query", "test query"] - # Assert pipeline output is unaffected - assert result["query"] == "test query" - assert result["documents"] == [Document(content="first"), Document(content="second"), Document(content="third")] - - -# -# join_lists -# - - -@pytest.mark.unit -def test_join_lists(): - shaper = Shaper(func="join_lists", params={"lists": [[1, 2, 3], [4, 5]]}, outputs=["list"]) - results, _ = shaper.run() - assert results["invocation_context"]["list"] == [1, 2, 3, 4, 5] - - -@pytest.mark.unit -def test_join_lists_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: join_lists - inputs: - lists: - - documents - - file_paths - outputs: - - single_list - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=["first", "second", "third"], file_paths=["file1.txt", "file2.txt"]) - assert result["invocation_context"]["single_list"] == ["first", "second", "third", "file1.txt", "file2.txt"] - - -# -# join_strings -# - - -@pytest.mark.unit -def test_join_strings(): - shaper = Shaper( - func="join_strings", params={"strings": ["first", "second"], "delimiter": " | "}, outputs=["single_string"] - ) - results, _ = shaper.run() - assert results["invocation_context"]["single_string"] == "first | second" - - -@pytest.mark.unit -def test_join_strings_default_delimiter(): - shaper = Shaper(func="join_strings", params={"strings": ["first", "second"]}, outputs=["single_string"]) - results, _ = shaper.run() - assert results["invocation_context"]["single_string"] == "first second" - - -@pytest.mark.unit -def test_join_strings_with_str_replace(): - shaper = Shaper( - func="join_strings", - params={"strings": ["first", "second", "third"], "delimiter": " - ", "str_replace": {"r": "R"}}, - outputs=["single_string"], - ) - results, _ = shaper.run() - assert results["invocation_context"]["single_string"] == "fiRst - second - thiRd" - - -@pytest.mark.unit -def test_join_strings_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: join_strings - inputs: - strings: documents - params: - delimiter: ' - ' - outputs: - - single_string - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=["first", "second", "third"]) - assert result["invocation_context"]["single_string"] == "first - second - third" - - -@pytest.mark.unit -def test_join_strings_default_delimiter_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: join_strings - inputs: - strings: documents - outputs: - - single_string - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=["first", "second", "third"]) - assert result["invocation_context"]["single_string"] == "first second third" - - -@pytest.mark.unit -def test_join_strings_with_str_replace_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: join_strings - inputs: - strings: documents - outputs: - - single_string - params: - delimiter: ' - ' - str_replace: - r: R - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=["first", "second", "third"]) - assert result["invocation_context"]["single_string"] == "fiRst - second - thiRd" - - -# -# join_documents -# - - -@pytest.mark.unit -def test_join_documents(): - shaper = Shaper( - func="join_documents", inputs={"documents": "documents"}, params={"delimiter": " | "}, outputs=["documents"] - ) - results, _ = shaper.run( - documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert results["invocation_context"]["documents"] == [Document(content="first | second | third")] - assert results["documents"] == [Document(content="first | second | third")] - - -def test_join_documents_without_publish_outputs(): - shaper = Shaper( - func="join_documents", - inputs={"documents": "documents"}, - params={"delimiter": " | "}, - outputs=["documents"], - publish_outputs=False, - ) - results, _ = shaper.run( - documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert results["invocation_context"]["documents"] == [Document(content="first | second | third")] - assert "documents" not in results - - -def test_join_documents_with_publish_outputs_as_list(): - shaper = Shaper( - func="join_documents", - inputs={"documents": "documents"}, - params={"delimiter": " | "}, - outputs=["documents"], - publish_outputs=["documents"], - ) - results, _ = shaper.run( - documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert results["invocation_context"]["documents"] == [Document(content="first | second | third")] - assert results["documents"] == [Document(content="first | second | third")] - - -@pytest.mark.unit -def test_join_documents_default_delimiter(): - shaper = Shaper(func="join_documents", inputs={"documents": "documents"}, outputs=["documents"]) - results, _ = shaper.run( - documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert results["invocation_context"]["documents"] == [Document(content="first second third")] - - -@pytest.mark.unit -def test_join_documents_with_pattern_and_str_replace(): - shaper = Shaper( - func="join_documents", - inputs={"documents": "documents"}, - outputs=["documents"], - params={"delimiter": " - ", "pattern": "[$idx] $content", "str_replace": {"r": "R"}}, - ) - results, _ = shaper.run( - documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert results["invocation_context"]["documents"] == [Document(content="[1] fiRst - [2] second - [3] thiRd")] - - -@pytest.mark.unit -def test_join_documents_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - - components: - - name: shaper - type: Shaper - params: - func: join_documents - inputs: - documents: documents - params: - delimiter: ' - ' - outputs: - - documents - - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="test query", documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert result["invocation_context"]["documents"] == [Document(content="first - second - third")] - assert result["documents"] == [Document(content="first - second - third")] - - -@pytest.mark.unit -def test_join_documents_default_delimiter_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: join_documents - inputs: - documents: documents - outputs: - - documents - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="test query", documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert result["invocation_context"]["documents"] == [Document(content="first second third")] - - -@pytest.mark.unit -def test_join_documents_with_pattern_and_str_replace_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: join_documents - inputs: - documents: documents - outputs: - - documents - params: - delimiter: ' - ' - pattern: '[$idx] $content' - str_replace: - r: R - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="test query", documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert result["invocation_context"]["documents"] == [Document(content="[1] fiRst - [2] second - [3] thiRd")] - - -# -# strings_to_answers -# - - -@pytest.mark.unit -def test_strings_to_answers_simple(): - shaper = Shaper(func="strings_to_answers", inputs={"strings": "responses"}, outputs=["answers"]) - results, _ = shaper.run(invocation_context={"responses": ["first", "second", "third"]}) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first", type="generative", meta={"prompt": None}), - Answer(answer="second", type="generative", meta={"prompt": None}), - Answer(answer="third", type="generative", meta={"prompt": None}), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_prompt(): - shaper = Shaper(func="strings_to_answers", inputs={"strings": "responses"}, outputs=["answers"]) - results, _ = shaper.run(invocation_context={"responses": ["first", "second", "third"], "prompts": ["test prompt"]}) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first", type="generative", meta={"prompt": "test prompt"}), - Answer(answer="second", type="generative", meta={"prompt": "test prompt"}), - Answer(answer="third", type="generative", meta={"prompt": "test prompt"}), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_documents(): - shaper = Shaper(func="strings_to_answers", inputs={"strings": "responses"}, outputs=["answers"]) - results, _ = shaper.run( - invocation_context={ - "responses": ["first", "second", "third"], - "documents": [Document(id="123", content="test"), Document(id="456", content="test")], - } - ) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - Answer(answer="second", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - Answer(answer="third", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_prompt_per_document(): - shaper = Shaper(func="strings_to_answers", inputs={"strings": "responses"}, outputs=["answers"]) - results, _ = shaper.run( - invocation_context={ - "responses": ["first", "second"], - "documents": [Document(id="123", content="test"), Document(id="456", content="test")], - "prompts": ["prompt1", "prompt2"], - } - ) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first", type="generative", meta={"prompt": "prompt1"}, document_ids=["123"]), - Answer(answer="second", type="generative", meta={"prompt": "prompt2"}, document_ids=["456"]), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_prompt_per_document_multiple_results(): - shaper = Shaper(func="strings_to_answers", inputs={"strings": "responses"}, outputs=["answers"]) - results, _ = shaper.run( - invocation_context={ - "responses": ["first", "second", "third", "fourth"], - "documents": [Document(id="123", content="test"), Document(id="456", content="test")], - "prompts": ["prompt1", "prompt2"], - } - ) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first", type="generative", meta={"prompt": "prompt1"}, document_ids=["123"]), - Answer(answer="second", type="generative", meta={"prompt": "prompt1"}, document_ids=["123"]), - Answer(answer="third", type="generative", meta={"prompt": "prompt2"}, document_ids=["456"]), - Answer(answer="fourth", type="generative", meta={"prompt": "prompt2"}, document_ids=["456"]), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_pattern_group(): - shaper = Shaper( - func="strings_to_answers", - inputs={"strings": "responses"}, - outputs=["answers"], - params={"pattern": r"Answer: (.*)"}, - ) - results, _ = shaper.run(invocation_context={"responses": ["Answer: first", "Answer: second", "Answer: third"]}) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first", type="generative", meta={"prompt": None}), - Answer(answer="second", type="generative", meta={"prompt": None}), - Answer(answer="third", type="generative", meta={"prompt": None}), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_pattern_no_group(): - shaper = Shaper( - func="strings_to_answers", inputs={"strings": "responses"}, outputs=["answers"], params={"pattern": r"[^\n]+$"} - ) - results, _ = shaper.run(invocation_context={"responses": ["Answer\nfirst", "Answer\nsecond", "Answer\n\nthird"]}) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first", type="generative", meta={"prompt": None}), - Answer(answer="second", type="generative", meta={"prompt": None}), - Answer(answer="third", type="generative", meta={"prompt": None}), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_references_index(): - shaper = Shaper( - func="strings_to_answers", - inputs={"strings": "responses", "documents": "documents"}, - outputs=["answers"], - params={"reference_pattern": r"\[(\d+)\]"}, - ) - results, _ = shaper.run( - invocation_context={ - "responses": ["first[1]", "second[2]", "third[1][2]", "fourth"], - "documents": [Document(id="123", content="test"), Document(id="456", content="test")], - } - ) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first[1]", type="generative", meta={"prompt": None}, document_ids=["123"]), - Answer(answer="second[2]", type="generative", meta={"prompt": None}, document_ids=["456"]), - Answer(answer="third[1][2]", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - Answer(answer="fourth", type="generative", meta={"prompt": None}, document_ids=[]), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_references_id(): - shaper = Shaper( - func="strings_to_answers", - inputs={"strings": "responses", "documents": "documents"}, - outputs=["answers"], - params={"reference_pattern": r"\[(\d+)\]", "reference_mode": "id"}, - ) - results, _ = shaper.run( - invocation_context={ - "responses": ["first[123]", "second[456]", "third[123][456]", "fourth"], - "documents": [Document(id="123", content="test"), Document(id="456", content="test")], - } - ) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first[123]", type="generative", meta={"prompt": None}, document_ids=["123"]), - Answer(answer="second[456]", type="generative", meta={"prompt": None}, document_ids=["456"]), - Answer(answer="third[123][456]", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - Answer(answer="fourth", type="generative", meta={"prompt": None}, document_ids=[]), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_references_meta(): - shaper = Shaper( - func="strings_to_answers", - inputs={"strings": "responses", "documents": "documents"}, - outputs=["answers"], - params={"reference_pattern": r"\[([^\]]+)\]", "reference_mode": "meta", "reference_meta_field": "file_id"}, - ) - results, _ = shaper.run( - invocation_context={ - "responses": ["first[123.txt]", "second[456.txt]", "third[123.txt][456.txt]", "fourth"], - "documents": [ - Document(id="123", content="test", meta={"file_id": "123.txt"}), - Document(id="456", content="test", meta={"file_id": "456.txt"}), - ], - } - ) - assert results["invocation_context"]["answers"] == [ - Answer(answer="first[123.txt]", type="generative", meta={"prompt": None}, document_ids=["123"]), - Answer(answer="second[456.txt]", type="generative", meta={"prompt": None}, document_ids=["456"]), - Answer(answer="third[123.txt][456.txt]", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - Answer(answer="fourth", type="generative", meta={"prompt": None}, document_ids=[]), - ] - - -@pytest.mark.unit -def test_strings_to_answers_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: strings_to_answers - params: - strings: ['a', 'b', 'c'] - outputs: - - answers - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run() - assert result["invocation_context"]["answers"] == [ - Answer(answer="a", type="generative", meta={"prompt": None}), - Answer(answer="b", type="generative", meta={"prompt": None}), - Answer(answer="c", type="generative", meta={"prompt": None}), - ] - assert result["answers"] == [ - Answer(answer="a", type="generative", meta={"prompt": None}), - Answer(answer="b", type="generative", meta={"prompt": None}), - Answer(answer="c", type="generative", meta={"prompt": None}), - ] - - -@pytest.mark.unit -def test_strings_to_answers_with_reference_meta_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - r""" - version: ignore - components: - - name: shaper - type: Shaper - params: - func: strings_to_answers - inputs: - documents: documents - params: - reference_meta_field: file_id - reference_mode: meta - reference_pattern: \[([^\]]+)\] - strings: ['first[123.txt]', 'second[456.txt]', 'third[123.txt][456.txt]', 'fourth'] - outputs: - - answers - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - documents=[ - Document(id="123", content="test", meta={"file_id": "123.txt"}), - Document(id="456", content="test", meta={"file_id": "456.txt"}), - ] - ) - assert result["invocation_context"]["answers"] == [ - Answer(answer="first[123.txt]", type="generative", meta={"prompt": None}, document_ids=["123"]), - Answer(answer="second[456.txt]", type="generative", meta={"prompt": None}, document_ids=["456"]), - Answer(answer="third[123.txt][456.txt]", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - Answer(answer="fourth", type="generative", meta={"prompt": None}, document_ids=[]), - ] - assert result["answers"] == [ - Answer(answer="first[123.txt]", type="generative", meta={"prompt": None}, document_ids=["123"]), - Answer(answer="second[456.txt]", type="generative", meta={"prompt": None}, document_ids=["456"]), - Answer(answer="third[123.txt][456.txt]", type="generative", meta={"prompt": None}, document_ids=["123", "456"]), - Answer(answer="fourth", type="generative", meta={"prompt": None}, document_ids=[]), - ] - - -@pytest.mark.integration -def test_strings_to_answers_after_prompt_node_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: prompt_model - type: PromptModel - - - name: prompt_template_raw_qa_per_document - type: PromptTemplate - params: - prompt: 'Given the context please answer the question. Context: {documents}; Question: {query}; Answer:' - - - name: prompt_node_raw_qa - type: PromptNode - params: - model_name_or_path: prompt_model - default_prompt_template: prompt_template_raw_qa_per_document - top_k: 2 - - - name: prompt_node_question_generation - type: PromptNode - params: - model_name_or_path: prompt_model - default_prompt_template: question-generation - output_variable: query - - - name: shaper - type: Shaper - params: - func: strings_to_answers - inputs: - strings: results - outputs: - - answers - - - pipelines: - - name: query - nodes: - - name: prompt_node_question_generation - inputs: - - Query - - name: prompt_node_raw_qa - inputs: - - prompt_node_question_generation - - name: shaper - inputs: - - prompt_node_raw_qa - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="What's Berlin like?", - documents=[ - Document("Berlin is an amazing city.", id="123"), - Document("Berlin is a cool city in Germany.", id="456"), - ], - ) - results = result["answers"] - assert len(results) == 4 - assert any(True for r in results if "Berlin" in r.answer) - for answer in results[:2]: - assert answer.document_ids == ["123"] - assert ( - answer.meta["prompt"] - == f"Given the context please answer the question. Context: Berlin is an amazing city.; Question: {result['query'][0]}; Answer:" - ) - for answer in results[2:]: - assert answer.document_ids == ["456"] - assert ( - answer.meta["prompt"] - == f"Given the context please answer the question. Context: Berlin is a cool city in Germany.; Question: {result['query'][1]}; Answer:" - ) - - -# -# answers_to_strings -# - - -@pytest.mark.unit -def test_answers_to_strings(): - shaper = Shaper(func="answers_to_strings", inputs={"answers": "documents"}, outputs=["strings"]) - results, _ = shaper.run(documents=[Answer(answer="first"), Answer(answer="second"), Answer(answer="third")]) - assert results["invocation_context"]["strings"] == ["first", "second", "third"] - - -@pytest.mark.unit -def test_answers_to_strings_with_pattern_and_str_replace(): - shaper = Shaper( - func="answers_to_strings", - inputs={"answers": "documents"}, - outputs=["strings"], - params={"pattern": "[$idx] $answer", "str_replace": {"r": "R"}}, - ) - results, _ = shaper.run(documents=[Answer(answer="first"), Answer(answer="second"), Answer(answer="third")]) - assert results["invocation_context"]["strings"] == ["[1] fiRst", "[2] second", "[3] thiRd"] - - -@pytest.mark.unit -def test_answers_to_strings_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: answers_to_strings - inputs: - answers: documents - outputs: - - strings - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=[Answer(answer="a"), Answer(answer="b"), Answer(answer="c")]) - assert result["invocation_context"]["strings"] == ["a", "b", "c"] - - -@pytest.mark.unit -def test_answers_to_strings_with_pattern_and_str_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: answers_to_strings - inputs: - answers: documents - outputs: - - strings - params: - pattern: '[$idx] $answer' - str_replace: - r: R - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=[Answer(answer="first"), Answer(answer="second"), Answer(answer="third")]) - assert result["invocation_context"]["strings"] == ["[1] fiRst", "[2] second", "[3] thiRd"] - - -# -# strings_to_documents -# - - -@pytest.mark.unit -def test_strings_to_documents_no_meta_no_hashkeys(): - shaper = Shaper(func="strings_to_documents", inputs={"strings": "responses"}, outputs=["documents"]) - results, _ = shaper.run(invocation_context={"responses": ["first", "second", "third"]}) - assert results["invocation_context"]["documents"] == [ - Document(content="first"), - Document(content="second"), - Document(content="third"), - ] - - -@pytest.mark.unit -def test_strings_to_documents_single_meta_no_hashkeys(): - shaper = Shaper( - func="strings_to_documents", inputs={"strings": "responses"}, params={"meta": {"a": "A"}}, outputs=["documents"] - ) - results, _ = shaper.run(invocation_context={"responses": ["first", "second", "third"]}) - assert results["invocation_context"]["documents"] == [ - Document(content="first", meta={"a": "A"}), - Document(content="second", meta={"a": "A"}), - Document(content="third", meta={"a": "A"}), - ] - - -@pytest.mark.unit -def test_strings_to_documents_wrong_number_of_meta(): - shaper = Shaper( - func="strings_to_documents", - inputs={"strings": "responses"}, - params={"meta": [{"a": "A"}]}, - outputs=["documents"], - ) - - with pytest.raises(ValueError, match="Not enough metadata dictionaries."): - shaper.run(invocation_context={"responses": ["first", "second", "third"]}) - - -@pytest.mark.unit -def test_strings_to_documents_many_meta_no_hashkeys(): - shaper = Shaper( - func="strings_to_documents", - inputs={"strings": "responses"}, - params={"meta": [{"a": i + 1} for i in range(3)]}, - outputs=["documents"], - ) - results, _ = shaper.run(invocation_context={"responses": ["first", "second", "third"]}) - assert results["invocation_context"]["documents"] == [ - Document(content="first", meta={"a": 1}), - Document(content="second", meta={"a": 2}), - Document(content="third", meta={"a": 3}), - ] - - -@pytest.mark.unit -def test_strings_to_documents_single_meta_with_hashkeys(): - shaper = Shaper( - func="strings_to_documents", - inputs={"strings": "responses"}, - params={"meta": {"a": "A"}, "id_hash_keys": ["content", "meta"]}, - outputs=["documents"], - ) - results, _ = shaper.run(invocation_context={"responses": ["first", "second", "third"]}) - assert results["invocation_context"]["documents"] == [ - Document(content="first", meta={"a": "A"}, id_hash_keys=["content", "meta"]), - Document(content="second", meta={"a": "A"}, id_hash_keys=["content", "meta"]), - Document(content="third", meta={"a": "A"}, id_hash_keys=["content", "meta"]), - ] - - -@pytest.mark.unit -def test_strings_to_documents_no_meta_no_hashkeys_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: strings_to_documents - params: - strings: ['a', 'b', 'c'] - outputs: - - documents - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run() - assert result["invocation_context"]["documents"] == [ - Document(content="a"), - Document(content="b"), - Document(content="c"), - ] - - -@pytest.mark.unit -def test_strings_to_documents_meta_and_hashkeys_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: strings_to_documents - params: - strings: ['first', 'second', 'third'] - id_hash_keys: ['content', 'meta'] - meta: - - a: 1 - - a: 2 - - a: 3 - outputs: - - documents - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run() - assert result["invocation_context"]["documents"] == [ - Document(content="first", meta={"a": 1}, id_hash_keys=["content", "meta"]), - Document(content="second", meta={"a": 2}, id_hash_keys=["content", "meta"]), - Document(content="third", meta={"a": 3}, id_hash_keys=["content", "meta"]), - ] - - -# -# documents_to_strings -# - - -@pytest.mark.unit -def test_documents_to_strings(): - shaper = Shaper(func="documents_to_strings", inputs={"documents": "documents"}, outputs=["strings"]) - results, _ = shaper.run( - documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert results["invocation_context"]["strings"] == ["first", "second", "third"] - - -@pytest.mark.unit -def test_documents_to_strings_with_pattern_and_str_replace(): - shaper = Shaper( - func="documents_to_strings", - inputs={"documents": "documents"}, - outputs=["strings"], - params={"pattern": "[$idx] $content", "str_replace": {"r": "R"}}, - ) - results, _ = shaper.run( - documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - assert results["invocation_context"]["strings"] == ["[1] fiRst", "[2] second", "[3] thiRd"] - - -@pytest.mark.unit -def test_documents_to_strings_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: documents_to_strings - inputs: - documents: documents - outputs: - - strings - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=[Document(content="a"), Document(content="b"), Document(content="c")]) - assert result["invocation_context"]["strings"] == ["a", "b", "c"] - - -@pytest.mark.unit -def test_documents_to_strings_with_pattern_and_str_replace_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: shaper - type: Shaper - params: - func: documents_to_strings - inputs: - documents: documents - outputs: - - strings - params: - pattern: '[$idx] $content' - str_replace: - r: R - pipelines: - - name: query - nodes: - - name: shaper - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(documents=[Document(content="first"), Document(content="second"), Document(content="third")]) - assert result["invocation_context"]["strings"] == ["[1] fiRst", "[2] second", "[3] thiRd"] - - -# -# Chaining and real-world usage -# - - -@pytest.mark.unit -def test_chain_shapers(): - shaper_1 = Shaper( - func="join_documents", inputs={"documents": "documents"}, params={"delimiter": " - "}, outputs=["documents"] - ) - shaper_2 = Shaper( - func="value_to_list", inputs={"value": "query", "target_list": "documents"}, outputs=["questions"] - ) - - pipe = Pipeline() - pipe.add_node(shaper_1, name="shaper_1", inputs=["Query"]) - pipe.add_node(shaper_2, name="shaper_2", inputs=["shaper_1"]) - - results = pipe.run( - query="test query", documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - - assert results["invocation_context"]["documents"] == [Document(content="first - second - third")] - assert results["invocation_context"]["questions"] == ["test query"] - - -@pytest.mark.unit -def test_chain_shapers_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - - name: shaper_1 - type: Shaper - params: - func: join_documents - inputs: - documents: documents - params: - delimiter: ' - ' - outputs: - - documents - - - name: shaper_2 - type: Shaper - params: - func: value_to_list - inputs: - value: query - target_list: documents - outputs: - - questions - - pipelines: - - name: query - nodes: - - name: shaper_1 - inputs: - - Query - - name: shaper_2 - inputs: - - shaper_1 - """ - ) - pipe = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - results = pipe.run( - query="test query", documents=[Document(content="first"), Document(content="second"), Document(content="third")] - ) - - assert results["invocation_context"]["documents"] == [Document(content="first - second - third")] - assert results["invocation_context"]["questions"] == ["test query"] - - -@pytest.mark.unit -def test_chain_shapers_yaml_2(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - - name: shaper_1 - type: Shaper - params: - func: strings_to_documents - params: - strings: - - first - - second - - third - outputs: - - string_documents - - - name: shaper_2 - type: Shaper - params: - func: value_to_list - inputs: - target_list: string_documents - params: - value: hello - outputs: - - greetings - - - name: shaper_3 - type: Shaper - params: - func: join_strings - inputs: - strings: greetings - params: - delimiter: '. ' - outputs: - - many_greetings - - - name: expander - type: Shaper - params: - func: value_to_list - inputs: - value: many_greetings - params: - target_list: [1] - outputs: - - many_greetings - - - name: shaper_4 - type: Shaper - params: - func: strings_to_documents - inputs: - strings: many_greetings - outputs: - - documents_with_greetings - - pipelines: - - name: query - nodes: - - name: shaper_1 - inputs: - - Query - - name: shaper_2 - inputs: - - shaper_1 - - name: shaper_3 - inputs: - - shaper_2 - - name: expander - inputs: - - shaper_3 - - name: shaper_4 - inputs: - - expander - """ - ) - pipe = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - results = pipe.run() - assert results["invocation_context"]["documents_with_greetings"] == [Document(content="hello. hello. hello")] - - -@pytest.mark.integration -def test_with_prompt_node(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: prompt_model - type: PromptModel - - - name: prompt_node - type: PromptNode - params: - output_variable: answers - model_name_or_path: prompt_model - default_prompt_template: question-answering-per-document - - pipelines: - - name: query - nodes: - - name: prompt_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="What's Berlin like?", - documents=[Document("Berlin is an amazing city."), Document("Berlin is a cool city in Germany.")], - ) - assert len(result["answers"]) == 2 - raw_answers = [answer.answer for answer in result["answers"]] - assert any(word for word in ["berlin", "germany", "cool", "city", "amazing"] if word in raw_answers) - - -@pytest.mark.integration -def test_with_multiple_prompt_nodes(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: prompt_model - type: PromptModel - - - name: renamer - type: Shaper - params: - func: rename - inputs: - value: new-questions - outputs: - - query - - - name: prompt_node - type: PromptNode - params: - model_name_or_path: prompt_model - default_prompt_template: question-answering-per-document - - - name: prompt_node_second - type: PromptNode - params: - model_name_or_path: prompt_model - default_prompt_template: question-generation - output_variable: new-questions - - - name: prompt_node_third - type: PromptNode - params: - model_name_or_path: google/flan-t5-small - default_prompt_template: question-answering-per-document - - pipelines: - - name: query - nodes: - - name: prompt_node - inputs: - - Query - - name: prompt_node_second - inputs: - - prompt_node - - name: renamer - inputs: - - prompt_node_second - - name: prompt_node_third - inputs: - - renamer - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run( - query="What's Berlin like?", - documents=[Document("Berlin is an amazing city."), Document("Berlin is a cool city in Germany.")], - ) - results = result["answers"] - assert len(results) == 2 - assert any(True for r in results if "Berlin" in r.answer) - - -@pytest.mark.unit -def test_join_query_and_documents_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - - components: - - name: expander - type: Shaper - params: - func: value_to_list - inputs: - value: query - params: - target_list: [1] - outputs: - - query - - - name: joiner - type: Shaper - params: - func: join_lists - inputs: - lists: - - documents - - query - outputs: - - query - - pipelines: - - name: query - nodes: - - name: expander - inputs: - - Query - - name: joiner - inputs: - - expander - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(query="What is going on here?", documents=["first", "second", "third"]) - assert result["query"] == ["first", "second", "third", "What is going on here?"] - - -@pytest.mark.unit -def test_join_query_and_documents_into_single_string_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: expander - type: Shaper - params: - func: value_to_list - inputs: - value: query - params: - target_list: [1] - outputs: - - query - - - name: joiner - type: Shaper - params: - func: join_lists - inputs: - lists: - - documents - - query - outputs: - - query - - - name: concatenator - type: Shaper - params: - func: join_strings - inputs: - strings: query - outputs: - - query - - pipelines: - - name: query - nodes: - - name: expander - inputs: - - Query - - name: joiner - inputs: - - expander - - name: concatenator - inputs: - - joiner - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(query="What is going on here?", documents=["first", "second", "third"]) - assert result["query"] == "first second third What is going on here?" - - -@pytest.mark.unit -def test_join_query_and_documents_convert_into_documents_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: expander - type: Shaper - params: - func: value_to_list - inputs: - value: query - params: - target_list: [1] - outputs: - - query - - - name: joiner - type: Shaper - params: - func: join_lists - inputs: - lists: - - documents - - query - outputs: - - query_and_docs - - - name: converter - type: Shaper - params: - func: strings_to_documents - inputs: - strings: query_and_docs - outputs: - - query_and_docs - - pipelines: - - name: query - nodes: - - name: expander - inputs: - - Query - - name: joiner - inputs: - - expander - - name: converter - inputs: - - joiner - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(query="What is going on here?", documents=["first", "second", "third"]) - assert result["invocation_context"]["query_and_docs"] - assert len(result["invocation_context"]["query_and_docs"]) == 4 - assert isinstance(result["invocation_context"]["query_and_docs"][0], Document) - - -@pytest.mark.unit -def test_shaper_publishes_unknown_arg_does_not_break_pipeline(): - documents = [Document(content="test query")] - shaper = Shaper(func="rename", inputs={"value": "query"}, outputs=["unknown_by_retriever"], publish_outputs=True) - document_store = InMemoryDocumentStore(use_bm25=True) - document_store.write_documents(documents) - retriever = BM25Retriever(document_store=document_store) - pipeline = Pipeline() - pipeline.add_node(component=shaper, name="shaper", inputs=["Query"]) - pipeline.add_node(component=retriever, name="retriever", inputs=["shaper"]) - - result = pipeline.run(query="test query") - assert result["invocation_context"]["unknown_by_retriever"] == "test query" - assert result["unknown_by_retriever"] == "test query" - assert len(result["documents"]) == 1 diff --git a/test/nodes/test_summarizer.py b/test/nodes/test_summarizer.py deleted file mode 100644 index b44a469614..0000000000 --- a/test/nodes/test_summarizer.py +++ /dev/null @@ -1,85 +0,0 @@ -import pytest - -import haystack -from haystack.utils.torch_utils import ListDataset -from haystack.schema import Document -from haystack.nodes import TransformersSummarizer - - -DOCS = [Document(content=doc) for doc in ["First test doc", "Second test doc"]] -EXPECTED_SUMMARIES = ["First summary", "Second summary"] -SUMMARIZED_DOCS = [ - Document(content=doc.content, meta={"summary": summary}) for doc, summary in zip(DOCS, EXPECTED_SUMMARIES) -] - - -class MockHFPipeline: - def __init__(self, *a, **k): - pass - - def __call__(self, docs, *a, **k): - summaries = [{"summary_text": summary} for summary in EXPECTED_SUMMARIES] - if isinstance(docs, ListDataset): - return [summaries for _ in docs] - return summaries - - def tokenizer(self, *a, **k): - return {"input_ids": []} - - -@pytest.fixture -def mock_models(monkeypatch): - monkeypatch.setattr(haystack.nodes.summarizer.transformers, "pipeline", MockHFPipeline) - - -@pytest.fixture -def summarizer(mock_models) -> TransformersSummarizer: - return TransformersSummarizer(model_name_or_path="irrelevant/anyway", use_gpu=False) - - -@pytest.mark.unit -def test_summarization_no_docs(summarizer): - with pytest.raises(ValueError, match="at least one document"): - summarizer.predict(documents=[]) - with pytest.raises(ValueError, match="at least one document"): - summarizer.predict_batch(documents=[]) - - -@pytest.mark.unit -def test_summarization_no_docs_min_max(summarizer): - summarizer.min_length = 10 - summarizer.max_length = 1 - with pytest.raises(ValueError, match="min_length cannot be greater than max_length"): - summarizer.predict(documents=DOCS) - - -@pytest.mark.unit -def test_summarization_one_doc(summarizer): - summarized_docs = summarizer.predict(documents=[DOCS[0]]) - assert len(summarized_docs) == 1 - assert EXPECTED_SUMMARIES[0] == summarized_docs[0].meta["summary"] - - -@pytest.mark.unit -def test_summarization_more_docs(summarizer): - summarized_docs = summarizer.predict(documents=DOCS) - assert len(summarized_docs) == len(DOCS) - for expected_summary, summary in zip(EXPECTED_SUMMARIES, summarized_docs): - assert expected_summary == summary.meta["summary"] - - -@pytest.mark.unit -def test_summarization_batch_single_doc_list(summarizer): - summarized_docs = summarizer.predict_batch(documents=DOCS) - assert len(summarized_docs) == len(DOCS) - for expected_summary, summary in zip(EXPECTED_SUMMARIES, summarized_docs): - assert expected_summary == summary.meta["summary"] - - -@pytest.mark.unit -def test_summarization_batch_multiple_doc_lists(summarizer): - summarized_docs = summarizer.predict_batch(documents=[DOCS, DOCS]) - assert len(summarized_docs) == 2 # Number of document lists - assert len(summarized_docs[0]) == len(DOCS) - for expected_summary, summary in zip(EXPECTED_SUMMARIES, summarized_docs[0]): - assert expected_summary == summary.meta["summary"] diff --git a/test/nodes/test_table_reader.py b/test/nodes/test_table_reader.py deleted file mode 100644 index e7673cc04c..0000000000 --- a/test/nodes/test_table_reader.py +++ /dev/null @@ -1,263 +0,0 @@ -import logging - -import pandas as pd -import pytest - -from haystack.schema import Document, Answer, Span, TableCell -from haystack.pipelines.base import Pipeline - -from haystack.nodes.reader.table import _calculate_answer_offsets - - -@pytest.fixture -def table_doc1(): - data = { - "actors": ["brad pitt", "leonardo di caprio", "george clooney"], - "age": [58, 47, 60], - "number of movies": [87, 53, 69], - "date of birth": ["18 december 1963", "11 november 1974", "6 may 1961"], - } - return Document(content=pd.DataFrame(data), content_type="table", id="doc1") - - -@pytest.fixture -def table_doc2(): - data = { - "actors": ["chris pratt", "gal gadot", "oprah winfrey"], - "age": [45, 36, 65], - "number of movies": [49, 34, 5], - "date of birth": ["12 january 1975", "5 april 1980", "15 september 1960"], - } - return Document(content=pd.DataFrame(data), content_type="table", id="doc2") - - -@pytest.fixture -def table_doc3(): - data = { - "Mountain": ["Mount Everest", "K2", "Kangchenjunga", "Lhotse", "Makalu"], - "Height": ["8848m", "8,611 m", "8 586m", "8 516 m", "8,485m"], - } - return Document(content=pd.DataFrame(data), content_type="table", id="doc3") - - -@pytest.mark.unit -def test_calculate_answer_offsets_table_cell(table_doc1): - offsets_span = _calculate_answer_offsets(answer_coordinates=[(0, 1), (1, 3)]) - assert offsets_span == [TableCell(row=0, col=1), TableCell(row=1, col=3)] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_table_reader(table_reader_and_param, table_doc1, table_doc2): - table_reader, param = table_reader_and_param - - query = "When was Di Caprio born?" - prediction = table_reader.predict(query=query, documents=[table_doc1, table_doc2]) - - assert prediction["query"] == "When was Di Caprio born?" - - # Check number of answers - reference0 = {"tapas_small": {"num_answers": 2}, "rci": {"num_answers": 10}, "tapas_scored": {"num_answers": 6}} - assert len(prediction["answers"]) == reference0[param]["num_answers"] - - # Check the first answer in the list - reference1 = {"tapas_small": {"score": 1.0}, "rci": {"score": -6.5301}, "tapas_scored": {"score": 0.50568}} - assert prediction["answers"][0].score == pytest.approx(reference1[param]["score"], rel=1e-3) - assert prediction["answers"][0].answer == "11 november 1974" - assert prediction["answers"][0].offsets_in_context[0].row == 1 - assert prediction["answers"][0].offsets_in_context[0].col == 3 - assert prediction["answers"][0].document_ids == ["doc1"] - - # Check the second answer in the list - reference2 = { - "tapas_small": {"answer": "5 april 1980", "row": 1, "col": 3, "score": 0.86314, "doc_id": ["doc2"]}, - "rci": {"answer": "47", "row": 1, "col": 1, "score": -6.836, "doc_id": ["doc1"]}, - "tapas_scored": {"answer": "brad pitt", "row": 0, "col": 0, "score": 0.49078, "doc_id": ["doc1"]}, - } - assert prediction["answers"][1].score == pytest.approx(reference2[param]["score"], rel=1e-3) - assert prediction["answers"][1].answer == reference2[param]["answer"] - assert prediction["answers"][1].offsets_in_context[0].row == reference2[param]["row"] - assert prediction["answers"][1].offsets_in_context[0].col == reference2[param]["col"] - assert prediction["answers"][1].document_ids == reference2[param]["doc_id"] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_table_reader_batch_single_query_single_doc_list(table_reader_and_param, table_doc1, table_doc2): - table_reader, param = table_reader_and_param - query = "When was Di Caprio born?" - prediction = table_reader.predict_batch(queries=[query], documents=[table_doc1, table_doc2]) - # Expected output: List of lists of answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], Answer) - assert prediction["queries"] == ["When was Di Caprio born?", "When was Di Caprio born?"] - - # Check number of answers for each document - num_ans_reference = { - "tapas_small": {"num_answers": [1, 1]}, - "rci": {"num_answers": [10, 10]}, - "tapas_scored": {"num_answers": [3, 3]}, - } - assert len(prediction["answers"]) == 2 - for i, ans_list in enumerate(prediction["answers"]): - assert len(ans_list) == num_ans_reference[param]["num_answers"][i] - - # Check first answer from the 1ST document - score_reference = {"tapas_small": {"score": 1.0}, "rci": {"score": -6.5301}, "tapas_scored": {"score": 0.50568}} - assert prediction["answers"][0][0].score == pytest.approx(score_reference[param]["score"], rel=1e-3) - assert prediction["answers"][0][0].answer == "11 november 1974" - assert prediction["answers"][0][0].offsets_in_context[0].row == 1 - assert prediction["answers"][0][0].offsets_in_context[0].col == 3 - assert prediction["answers"][0][0].document_ids == ["doc1"] - - # Check first answer from the 2ND Document - ans_reference = { - "tapas_small": {"answer": "5 april 1980", "row": 1, "col": 3, "score": 0.86314, "doc_id": ["doc2"]}, - "rci": {"answer": "15 september 1960", "row": 2, "col": 3, "score": -7.9429, "doc_id": ["doc2"]}, - "tapas_scored": {"answer": "5", "row": 2, "col": 2, "score": 0.11485, "doc_id": ["doc2"]}, - } - assert prediction["answers"][1][0].score == pytest.approx(ans_reference[param]["score"], rel=1e-3) - assert prediction["answers"][1][0].answer == ans_reference[param]["answer"] - assert prediction["answers"][1][0].offsets_in_context[0].row == ans_reference[param]["row"] - assert prediction["answers"][1][0].offsets_in_context[0].col == ans_reference[param]["col"] - assert prediction["answers"][1][0].document_ids == ans_reference[param]["doc_id"] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_table_reader_batch_single_query_multiple_doc_lists(table_reader_and_param, table_doc1, table_doc2, table_doc3): - table_reader, param = table_reader_and_param - query = "When was Di Caprio born?" - prediction = table_reader.predict_batch(queries=[query], documents=[[table_doc1, table_doc2], [table_doc3]]) - # Expected output: List of lists of answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], Answer) - assert prediction["queries"] == ["When was Di Caprio born?", "When was Di Caprio born?"] - - # Check number of answers for each document - num_ans_reference = { - "tapas_small": {"num_answers": [2, 1]}, - "rci": {"num_answers": [10, 10]}, - "tapas_scored": {"num_answers": [6, 3]}, - } - assert len(prediction["answers"]) == 2 - for i, ans_list in enumerate(prediction["answers"]): - assert len(ans_list) == num_ans_reference[param]["num_answers"][i] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_table_reader_batch_multiple_queries_single_doc_list(table_reader_and_param, table_doc1, table_doc2): - table_reader, param = table_reader_and_param - query = "When was Di Caprio born?" - query2 = "When was Brad Pitt born?" - prediction = table_reader.predict_batch(queries=[query, query2], documents=[table_doc1, table_doc2]) - # Expected output: List of lists of lists of answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], list) - assert isinstance(prediction["answers"][0][0][0], Answer) - assert prediction["queries"] == [ - "When was Di Caprio born?", - "When was Di Caprio born?", - "When was Brad Pitt born?", - "When was Brad Pitt born?", - ] - - # Check number of answers for each document - num_ans_reference = { - "tapas_small": {"num_answers": [[1, 1], [1, 1]]}, - "rci": {"num_answers": [[10, 10], [10, 10]]}, - "tapas_scored": {"num_answers": [[3, 3], [3, 3]]}, - } - assert len(prediction["answers"]) == 2 # Predictions for 2 queries - for i, ans_list1 in enumerate(prediction["answers"]): - for j, ans_list2 in enumerate(ans_list1): - assert len(ans_list2) == num_ans_reference[param]["num_answers"][i][j] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_table_reader_batch_multiple_queries_multiple_doc_lists( - table_reader_and_param, table_doc1, table_doc2, table_doc3 -): - table_reader, param = table_reader_and_param - query = "When was Di Caprio born?" - query2 = "Which is the tallest mountain?" - prediction = table_reader.predict_batch(queries=[query, query2], documents=[[table_doc1, table_doc2], [table_doc3]]) - # Expected output: List of lists answers - assert isinstance(prediction["answers"], list) - assert isinstance(prediction["answers"][0], list) - assert isinstance(prediction["answers"][0][0], Answer) - assert prediction["queries"] == ["When was Di Caprio born?", "Which is the tallest mountain?"] - - # Check number of answers for each document - num_ans_reference = { - "tapas_small": {"num_answers": [2, 1]}, - "rci": {"num_answers": [10, 10]}, - "tapas_scored": {"num_answers": [6, 3]}, - } - assert len(prediction["answers"]) == 2 # Predictions for 2 collections of documents - for i, ans_list in enumerate(prediction["answers"]): - assert len(ans_list) == num_ans_reference[param]["num_answers"][i] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_table_reader_in_pipeline(table_reader_and_param, table_doc1): - table_reader, param = table_reader_and_param - pipeline = Pipeline() - pipeline.add_node(table_reader, "TableReader", ["Query"]) - query = "When was Di Caprio born?" - - prediction = pipeline.run(query=query, documents=[table_doc1]) - assert prediction["answers"][0].answer == "11 november 1974" - assert prediction["answers"][0].offsets_in_context[0].row == 1 - assert prediction["answers"][0].offsets_in_context[0].col == 3 - assert prediction["answers"][0].document_ids == ["doc1"] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_base"], indirect=True) -def test_table_reader_aggregation(table_reader_and_param, table_doc3): - table_reader, param = table_reader_and_param - - query = "How tall are all mountains on average?" - prediction = table_reader.predict(query=query, documents=[table_doc3]) - assert prediction["answers"][0].score == pytest.approx(1.0) - assert prediction["answers"][0].answer == "8609.2 m" - assert prediction["answers"][0].meta["aggregation_operator"] == "AVERAGE" - assert prediction["answers"][0].meta["answer_cells"] == ["8848m", "8,611 m", "8 586m", "8 516 m", "8,485m"] - - query = "How tall are all mountains together?" - prediction = table_reader.predict(query=query, documents=[table_doc3]) - assert prediction["answers"][0].score == pytest.approx(1.0) - assert prediction["answers"][0].answer == "43046.0 m" - assert prediction["answers"][0].meta["aggregation_operator"] == "SUM" - assert prediction["answers"][0].meta["answer_cells"] == ["8848m", "8,611 m", "8 586m", "8 516 m", "8,485m"] - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_table_without_rows(caplog, table_reader_and_param): - table_reader, param = table_reader_and_param - # empty DataFrame - table = pd.DataFrame() - document = Document(content=table, content_type="table", id="no_rows") - with caplog.at_level(logging.WARNING): - predictions = table_reader.predict(query="test", documents=[document]) - assert "Skipping document with id 'no_rows'" in caplog.text - assert len(predictions["answers"]) == 0 - - -@pytest.mark.integration -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small", "rci", "tapas_scored"], indirect=True) -def test_text_document(caplog, table_reader_and_param): - table_reader, param = table_reader_and_param - document = Document(content="text", id="text_doc") - with caplog.at_level(logging.WARNING): - predictions = table_reader.predict(query="test", documents=[document]) - assert "Skipping document with id 'text_doc'" in caplog.text - assert len(predictions["answers"]) == 0 diff --git a/test/nodes/test_translator.py b/test/nodes/test_translator.py deleted file mode 100644 index 83a21dfb2e..0000000000 --- a/test/nodes/test_translator.py +++ /dev/null @@ -1,115 +0,0 @@ -import pytest - -import haystack -from haystack.schema import Document -from haystack.nodes import TransformersTranslator - - -ORIGINAL_TEXT = "TEST QUERY" -TRANSLATION = "MOCK TRANSLATION" - - -class MockTokenizer: - @classmethod - def from_pretrained(cls, *a, **k): - return cls() - - def __call__(self, *a, **k): - return self - - def to(self, *a, **k): - return {} - - def batch_decode(self, *a, **k): - return [TRANSLATION] - - -class MockModel: - @classmethod - def from_pretrained(cls, *a, **k): - return cls() - - def generate(self, *a, **k): - return None - - def to(self, *a, **k): - return None - - -@pytest.fixture -def mock_models(monkeypatch): - monkeypatch.setattr(haystack.nodes.translator.transformers, "AutoModelForSeq2SeqLM", MockModel) - monkeypatch.setattr(haystack.nodes.translator.transformers, "AutoTokenizer", MockTokenizer) - - -@pytest.fixture -def en_to_de_translator(mock_models) -> TransformersTranslator: - return TransformersTranslator(model_name_or_path="irrelevant/anyway") - - -@pytest.fixture -def de_to_en_translator(mock_models) -> TransformersTranslator: - return TransformersTranslator(model_name_or_path="irrelevant/anyway") - - -@pytest.mark.unit -def test_translator_with_query(en_to_de_translator): - assert en_to_de_translator.translate(query=ORIGINAL_TEXT) == TRANSLATION - - -@pytest.mark.unit -def test_translator_with_list(en_to_de_translator): - assert en_to_de_translator.translate(documents=[ORIGINAL_TEXT])[0] == TRANSLATION - - -@pytest.mark.unit -def test_translator_with_document(en_to_de_translator): - assert en_to_de_translator.translate(documents=[Document(content=ORIGINAL_TEXT)])[0].content == TRANSLATION - - -@pytest.mark.unit -def test_translator_with_document_preserves_original(en_to_de_translator): - original_document = Document(content=ORIGINAL_TEXT) - en_to_de_translator.translate(documents=[original_document]) - assert original_document.content == ORIGINAL_TEXT - - -@pytest.mark.unit -def test_translator_with_dictionary(en_to_de_translator): - assert en_to_de_translator.translate(documents=[{"content": ORIGINAL_TEXT}])[0]["content"] == TRANSLATION - - -@pytest.mark.unit -def test_translator_with_dictionary_preserves_original(en_to_de_translator): - original_document = {"content": ORIGINAL_TEXT} - en_to_de_translator.translate(documents=[original_document]) - assert original_document["content"] == ORIGINAL_TEXT - - -@pytest.mark.unit -def test_translator_with_dictionary_with_dict_key(en_to_de_translator): - assert en_to_de_translator.translate(documents=[{"key": ORIGINAL_TEXT}], dict_key="key")[0]["key"] == TRANSLATION - - -@pytest.mark.unit -def test_translator_with_empty_original(en_to_de_translator): - with pytest.raises(AttributeError): - en_to_de_translator.translate() - - -@pytest.mark.unit -def test_translator_with_query_and_documents(en_to_de_translator): - with pytest.raises(AttributeError): - en_to_de_translator.translate(query=ORIGINAL_TEXT, documents=[ORIGINAL_TEXT]) - - -@pytest.mark.unit -def test_translator_with_dict_without_text_key(en_to_de_translator): - with pytest.raises(AttributeError): - en_to_de_translator.translate(documents=[{"text1": ORIGINAL_TEXT}]) - - -@pytest.mark.unit -def test_translator_with_dict_with_non_string_value(en_to_de_translator): - with pytest.raises(AttributeError): - en_to_de_translator.translate(documents=[{"text": 123}]) diff --git a/test/nodes/test_web_retriever.py b/test/nodes/test_web_retriever.py deleted file mode 100644 index 16cbe3cbf7..0000000000 --- a/test/nodes/test_web_retriever.py +++ /dev/null @@ -1,267 +0,0 @@ -import os -from unittest.mock import patch, Mock -from test.conftest import MockDocumentStore -import pytest - -from haystack import Document, Pipeline -from haystack.nodes import WebRetriever, PromptNode -from haystack.nodes.retriever.link_content import html_content_handler -from haystack.nodes.retriever.web import SearchResult -from test.nodes.conftest import example_serperdev_response - - -@pytest.fixture -def mocked_requests(): - with patch("haystack.nodes.retriever.link_content.requests") as mock_requests: - mock_response = Mock() - mock_requests.get.return_value = mock_response - mock_response.status_code = 200 - mock_response.text = "Sample content from webpage" - yield mock_requests - - -@pytest.fixture -def mocked_article_extractor(): - with patch("boilerpy3.extractors.ArticleExtractor.get_content", return_value="Sample content from webpage"): - yield - - -@pytest.fixture -def mocked_link_content_fetcher_handler_type(): - with patch( - "haystack.nodes.retriever.link_content.LinkContentFetcher._get_content_type_handler", - return_value=html_content_handler, - ): - yield - - -@pytest.mark.unit -def test_init_default_parameters(): - retriever = WebRetriever(api_key="test_key") - - assert retriever.top_k == 5 - assert retriever.mode == "snippets" - assert retriever.preprocessor is None - assert retriever.cache_document_store is None - assert retriever.cache_index is None - - -@pytest.mark.unit -@pytest.mark.parametrize("mode", ["snippets", "raw_documents", "preprocessed_documents"]) -@pytest.mark.parametrize("top_k", [1, 5, 7]) -def test_retrieve_from_web_all_params(mock_web_search, mode, top_k): - """ - Test that the retriever returns the correct number of documents in all modes - """ - search_result_len = len(example_serperdev_response["organic"]) - wr = WebRetriever(api_key="fake_key", top_k=top_k, mode=mode) - - docs = [Document("test" + str(i)) for i in range(search_result_len)] - with patch("haystack.nodes.retriever.web.WebRetriever._scrape_links", return_value=docs): - retrieved_docs = wr.retrieve(query="who is the boyfriend of olivia wilde?") - - assert isinstance(retrieved_docs, list) - assert all(isinstance(doc, Document) for doc in retrieved_docs) - assert len(retrieved_docs) == top_k - - -@pytest.mark.unit -def test_retrieve_from_web_invalid_query(mock_web_search): - """ - Test that the retriever raises an error if the query is invalid - """ - wr = WebRetriever(api_key="fake_key") - with pytest.raises(ValueError, match="WebSearch run requires"): - wr.retrieve("") - - with pytest.raises(ValueError, match="WebSearch run requires"): - wr.retrieve(None) - - -@pytest.mark.unit -def test_prepare_links_empty_list(): - """ - Test that the retriever's _prepare_links method returns an empty list if the input is an empty list - """ - wr = WebRetriever(api_key="fake_key") - result = wr._prepare_links([]) - assert result == [] - - result = wr._prepare_links(None) - assert result == [] - - -@pytest.mark.unit -def test_scrape_links_empty_list(): - """ - Test that the retriever's _scrape_links method returns an empty list if the input is an empty list - """ - wr = WebRetriever(api_key="fake_key") - result = wr._scrape_links([]) - assert result == [] - - -@pytest.mark.unit -def test_scrape_links_with_search_results( - mocked_requests, mocked_article_extractor, mocked_link_content_fetcher_handler_type -): - """ - Test that the retriever's _scrape_links method returns a list of Documents if the input is a list of SearchResults - """ - wr = WebRetriever(api_key="fake_key") - - sr1 = SearchResult("https://pagesix.com", "Some text", 0.43, "1") - sr2 = SearchResult("https://www.yahoo.com/", "Some text", 0.43, "2") - fake_search_results = [sr1, sr2] - - result = wr._scrape_links(fake_search_results) - - assert isinstance(result, list) - assert all(isinstance(r, Document) for r in result) - assert len(result) == 2 - - -@pytest.mark.unit -def test_scrape_links_with_search_results_with_preprocessor( - mocked_requests, mocked_article_extractor, mocked_link_content_fetcher_handler_type -): - """ - Test that the retriever's _scrape_links method returns a list of Documents if the input is a list of SearchResults - and a preprocessor is provided - """ - wr = WebRetriever(api_key="fake_key", mode="preprocessed_documents") - - sr1 = SearchResult("https://pagesix.com", "Some text", 0.43, "1") - sr2 = SearchResult("https://www.yahoo.com/", "Some text", 0.43, "2") - fake_search_results = [sr1, sr2] - - result = wr._scrape_links(fake_search_results) - - assert isinstance(result, list) - assert all(isinstance(r, Document) for r in result) - # the documents from above SearchResult are so small that they will not be split into multiple documents - # by the preprocessor - assert len(result) == 2 - - -@pytest.mark.unit -def test_retrieve_checks_cache(mock_web_search): - """ - Test that the retriever's retrieve method checks the cache - """ - wr = WebRetriever(api_key="fake_key", mode="preprocessed_documents") - - with patch.object(wr, "_check_cache", return_value=([], [])) as mock_check_cache: - wr.retrieve("query") - - # assert cache is checked - mock_check_cache.assert_called() - - -@pytest.mark.unit -def test_retrieve_no_cache_checks_in_snippet_mode(mock_web_search): - """ - Test that the retriever's retrieve method does not check the cache if the mode is snippets - """ - wr = WebRetriever(api_key="fake_key", mode="snippets") - - with patch.object(wr, "_check_cache", return_value=([], [])) as mock_check_cache: - wr.retrieve("query") - - # assert cache is NOT checked - mock_check_cache.assert_not_called() - - -@pytest.mark.unit -def test_retrieve_batch(mock_web_search): - """ - Test that the retriever's retrieve_batch method returns a list of lists of Documents - """ - queries = ["query1", "query2"] - wr = WebRetriever(api_key="fake_key", mode="preprocessed_documents") - web_docs = [Document("doc1"), Document("doc2"), Document("doc3")] - with patch("haystack.nodes.retriever.web.WebRetriever._scrape_links", return_value=web_docs): - result = wr.retrieve_batch(queries) - - assert len(result) == len(queries) - - # check that the result is a list of lists of Documents - assert all(isinstance(docs, list) for docs in result) - assert all(isinstance(doc, Document) for docs in result for doc in docs) - - # check that the result is a list of lists of Documents, so that the number of Documents - # is equal to the number of queries * number of documents retrieved per query - assert len([doc for docs in result for doc in docs]) == len(web_docs) * len(queries) - - -@pytest.mark.unit -def test_retrieve_uses_cache(mock_web_search): - """ - Test that the retriever's retrieve method uses the cache if it is available - """ - wr = WebRetriever(api_key="fake_key", mode="raw_documents", cache_document_store=MockDocumentStore()) - - cached_links = [ - SearchResult("https://pagesix.com", "Some text", 0.43, "1"), - SearchResult("https://www.yahoo.com/", "Some text", 0.43, "2"), - ] - cached_docs = [Document("doc1"), Document("doc2")] - with patch.object(wr, "_check_cache", return_value=(cached_links, cached_docs)) as mock_check_cache, patch.object( - wr, "_save_to_cache" - ) as mock_save_cache, patch.object(wr, "_scrape_links", return_value=[]): - result = wr.retrieve("query") - - # checking cache is always called - mock_check_cache.assert_called() - - # cache save is called but with empty list of documents - mock_save_cache.assert_called() - assert mock_save_cache.call_args[0][0] == [] - assert result == cached_docs - - -@pytest.mark.unit -def test_retrieve_saves_to_cache(mock_web_search): - """ - Test that the retriever's retrieve method saves to the cache if it is available - """ - wr = WebRetriever(api_key="fake_key", cache_document_store=MockDocumentStore(), mode="preprocessed_documents") - web_docs = [Document("doc1"), Document("doc2"), Document("doc3")] - - with patch.object(wr, "_save_to_cache") as mock_save_cache, patch.object( - wr, "_scrape_links", return_value=web_docs - ): - wr.retrieve("query") - - mock_save_cache.assert_called() - - -@pytest.mark.integration -@pytest.mark.skipif( - not os.environ.get("SERPERDEV_API_KEY", None), - reason="Please export an env var called SERPERDEV_API_KEY containing the serper.dev API key to run this test.", -) -@pytest.mark.skipif( - not os.environ.get("OPENAI_API_KEY", None), - reason="Please export an env var called OPENAI_API_KEY containing the OpenAI API key to run this test.", -) -@pytest.mark.parametrize("top_k", [2, 4]) -def test_top_k_parameter_in_pipeline(top_k): - """ - Test that the top_k parameter works in the pipeline - """ - prompt_node = PromptNode( - "gpt-3.5-turbo", - api_key=os.environ.get("OPENAI_API_KEY"), - max_length=256, - default_prompt_template="question-answering-with-document-scores", - ) - - retriever = WebRetriever(api_key=os.environ.get("SERPERDEV_API_KEY")) - - pipe = Pipeline() - - pipe.add_node(component=retriever, name="WebRetriever", inputs=["Query"]) - pipe.add_node(component=prompt_node, name="QAwithScoresPrompt", inputs=["WebRetriever"]) - result = pipe.run(query="What year was Obama president", params={"WebRetriever": {"top_k": top_k}}) - assert len(result["results"]) == top_k diff --git a/test/nodes/test_web_search.py b/test/nodes/test_web_search.py deleted file mode 100644 index 0dc7cd04f0..0000000000 --- a/test/nodes/test_web_search.py +++ /dev/null @@ -1,145 +0,0 @@ -import os -from unittest.mock import MagicMock, patch - -import pytest - -from haystack.nodes.search_engine import WebSearch -from haystack.schema import Document - -try: - import googleapiclient - - googleapi_installed = True -except ImportError: - googleapi_installed = False - - -@pytest.mark.skipif( - not os.environ.get("SERPERDEV_API_KEY", None), - reason="Please export an env var called SERPERDEV_API_KEY containing the serper.dev API key to run this test.", -) -@pytest.mark.integration -def test_web_search(): - ws = WebSearch(api_key=os.environ.get("SERPERDEV_API_KEY", None)) - result, _ = ws.run(query="Who is the boyfriend of Olivia Wilde?") - assert "documents" in result - assert len(result["documents"]) > 0 - assert isinstance(result["documents"][0], Document) - - -@pytest.mark.skipif( - not os.environ.get("SERPERDEV_API_KEY", None), - reason="Please export an env var called SERPERDEV_API_KEY containing the serper.dev API key to run this test.", -) -@pytest.mark.integration -def test_web_search_with_site_keyword(): - ws = WebSearch(api_key=os.environ.get("SERPERDEV_API_KEY", None)) - result, _ = ws.run(query='site:lifewire.com OR site:nasa.gov "electric vehicles"') - assert "documents" in result - assert len(result["documents"]) > 0 - assert isinstance(result["documents"][0], Document) - assert all( - "nasa" in doc.meta["link"] or "lifewire" in doc.meta["link"] for doc in result["documents"] - ), "Some documents are not from the specified sites lifewire.com or nasa.gov." - - -@pytest.mark.skipif( - not os.environ.get("SEARCHAPI_API_KEY", None), - reason="Please export an env var called SEARCHAPI_API_KEY containing the searchapi.io API key to run this test.", -) -@pytest.mark.integration -def test_web_search_with_searchapi(): - ws = WebSearch(api_key=os.environ.get("SEARCHAPI_API_KEY", None), search_engine_provider="SearchApi") - result, _ = ws.run(query="What is the hometown of the reigning men's U.S. Open champion?") - assert "documents" in result - assert len(result["documents"]) > 0 - assert isinstance(result["documents"][0], Document) - - -@pytest.mark.skipif( - not os.environ.get("SEARCHAPI_API_KEY", None), - reason="Please export an env var called SEARCHAPI_API_KEY containing the searchapi.io API key to run this test.", -) -@pytest.mark.integration -def test_web_search_with_searchapi_with_site_keyword(): - ws = WebSearch(api_key=os.environ.get("SEARCHAPI_API_KEY", None), search_engine_provider="SearchApi") - result, _ = ws.run(query='site:openai.com OR site:langchain.com "Agent types"') - assert "documents" in result - assert len(result["documents"]) > 0 - assert isinstance(result["documents"][0], Document) - assert all( - "langchain" in doc.meta["link"] or "openai" in doc.meta["link"] for doc in result["documents"] - ), "Some documents are not from the specified sites openai.com or langchain.com." - - -@pytest.mark.unit -def test_web_search_with_google_api_provider(): - if not googleapi_installed: - pytest.skip("google-api-python-client is not installed, skipping test.") - - GOOGLE_API_KEY = "dummy_api_key" - SEARCH_ENGINE_ID = "dummy_search_engine_id" - query = "The founder of Python" - - with patch("haystack.nodes.search_engine.WebSearch.run") as mock_run: - mock_run.return_value = ([{"content": "Guido van Rossum"}], None) - ws = WebSearch( - api_key=GOOGLE_API_KEY, - search_engine_provider="GoogleAPI", - search_engine_kwargs={"engine_id": SEARCH_ENGINE_ID}, - ) - result, _ = ws.run(query=query) - - mock_run.assert_called_once_with(query=query) - - assert "guido" in result[0]["content"].lower() - - -@pytest.mark.unit -def test_web_search_with_google_api_client(): - if not googleapi_installed: - pytest.skip("google-api-python-client is not installed, skipping test.") - - GOOGLE_API_KEY = "dummy_api_key" - SEARCH_ENGINE_ID = "dummy_search_engine_id" - query = "The founder of Python" - - with patch("googleapiclient.discovery.build") as mock_build: - mock_service = MagicMock() - mock_cse = MagicMock() - mock_list = MagicMock() - - mock_build.return_value = mock_service - mock_service.cse.return_value = mock_cse - mock_cse.list.return_value = mock_list - mock_list.execute.return_value = { - "items": [ - { - "title": "Guido van Rossum", - "snippet": "The founder of Python programming language.", - "link": "https://example.com/guido", - } - ] - } - - ws = WebSearch( - api_key=GOOGLE_API_KEY, - search_engine_provider="GoogleAPI", - search_engine_kwargs={"engine_id": SEARCH_ENGINE_ID}, - ) - _, _ = ws.run(query=query) - - mock_build.assert_called_once_with("customsearch", "v1", developerKey=GOOGLE_API_KEY) - mock_service.cse.assert_called_once() - mock_cse.list.assert_called_once_with(q=query, cx=SEARCH_ENGINE_ID, num=10) - mock_list.execute.assert_called_once() - - -@pytest.mark.unit -@pytest.mark.parametrize("top_k", [1, 3, 6]) -def test_web_search_top_k(mock_web_search, top_k): - ws = WebSearch(api_key="some_invalid_key") - result, _ = ws.run(query="Who is the boyfriend of Olivia Wilde?", top_k=top_k) - assert "documents" in result - assert len(result["documents"]) == top_k - assert all(isinstance(doc, Document) for doc in result["documents"]) diff --git a/test/nodes/test_whisper.py b/test/nodes/test_whisper.py deleted file mode 100644 index 48d7a09e66..0000000000 --- a/test/nodes/test_whisper.py +++ /dev/null @@ -1,59 +0,0 @@ -import os - -import pytest - -from haystack import Pipeline -from haystack.nodes.audio import WhisperTranscriber -from haystack.utils.import_utils import is_whisper_available - - -@pytest.mark.skipif(os.environ.get("OPENAI_API_KEY", "") == "", reason="OpenAI API key not found") -@pytest.mark.integration -def test_whisper_api_transcribe(samples_path): - w = WhisperTranscriber(api_key=os.environ.get("OPENAI_API_KEY")) - audio_object_transcript, audio_path_transcript = transcribe_test_helper(w, samples_path=samples_path) - assert "segments" not in audio_object_transcript and "segments" not in audio_path_transcript - - -@pytest.mark.skip("Fails on CI cause it fills up memory") -@pytest.mark.integration -@pytest.mark.skipif(not is_whisper_available(), reason="Whisper is not installed") -def test_whisper_local_transcribe(samples_path): - w = WhisperTranscriber() - audio_object_transcript, audio_path_transcript = transcribe_test_helper(w, samples_path=samples_path, language="en") - assert "segments" not in audio_object_transcript and "segments" not in audio_path_transcript - - -@pytest.mark.skip("Fails on CI cause it fills up memory") -@pytest.mark.integration -@pytest.mark.skipif(not is_whisper_available(), reason="Whisper is not installed") -def test_whisper_local_transcribe_with_params(samples_path): - w = WhisperTranscriber() - audio_object, audio_path = transcribe_test_helper(w, samples_path=samples_path, language="en", return_segments=True) - assert len(audio_object["segments"]) == 1 and len(audio_path["segments"]) == 1 - - -def transcribe_test_helper(whisper, samples_path, **kwargs): - # this file is 1 second long and contains the word "answer" - file_path = str(samples_path / "audio" / "answer.wav") - - # using audio object - with open(file_path, mode="rb") as audio_file: - audio_object_transcript = whisper.transcribe(audio_file=audio_file, **kwargs) - assert "answer" in audio_object_transcript["text"].lower() - - # using path to audio file - audio_path_transcript = whisper.transcribe(audio_file=file_path, **kwargs) - assert "answer" in audio_path_transcript["text"].lower() - return audio_object_transcript, audio_path_transcript - - -@pytest.mark.skipif(os.environ.get("OPENAI_API_KEY", "") == "", reason="OpenAI API key not found") -@pytest.mark.integration -def test_whisper_pipeline(samples_path): - w = WhisperTranscriber(api_key=os.environ.get("OPENAI_API_KEY")) - pipeline = Pipeline() - pipeline.add_node(component=w, name="whisper", inputs=["File"]) - res = pipeline.run(file_paths=[str(samples_path / "audio" / "answer.wav")]) - assert res["documents"] and len(res["documents"]) == 1 - assert "answer" in res["documents"][0].content.lower() diff --git a/test/others/__init__.py b/test/others/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/others/test_eval_data_from_json.py b/test/others/test_eval_data_from_json.py deleted file mode 100644 index 4e2959f43c..0000000000 --- a/test/others/test_eval_data_from_json.py +++ /dev/null @@ -1,65 +0,0 @@ -import json -import os -import pytest -from haystack.document_stores import eval_data_from_json - - -@pytest.fixture -def temp_squad_file(tmp_path): - temp_filename = tmp_path / "temp_squad_file.json" - with open(temp_filename, "w", encoding="utf-8") as temp_file: - json.dump( - { - "metadata": { - "dataset_version": "1.0", - "description": "This dataset contains questions and answers related to...", - "other_metadata_field": "value", - }, - "data": [ - { - "title": "Article Title", - "paragraphs": [ - { - "context": "This is the context of the article.", - "qas": [ - { - "question": "What is the SQuAD dataset?", - "id": 0, - "answers": [{"text": "This is the context", "answer_start": 0}], - "annotator": "annotator0", - "date": "2023-11-07", - }, - { - "question": "Another question?", - "id": 1, - "answers": [{"text": "This is the context of the article", "answer_start": 0}], - "annotator": "annotator1", - "date": "2023-12-09", - }, - ], - } - ], - "author": "Your Name", - "creation_date": "2023-11-14", - } - ], - }, - temp_file, - indent=2, - ) - return temp_filename - - -def test_eval_data_from_json(temp_squad_file): - # Call the function with the temporary file - docs, labels = eval_data_from_json(temp_squad_file) - - assert len(docs) == 1 - assert len(labels) == 2 - - assert docs[0].content == "This is the context of the article." - assert labels[0].query == "What is the SQuAD dataset?" - assert labels[0].meta == {"annotator": "annotator0", "date": "2023-11-07"} - - assert labels[1].query == "Another question?" - assert labels[1].meta == {"annotator": "annotator1", "date": "2023-12-09"} diff --git a/test/others/test_schema.py b/test/others/test_schema.py deleted file mode 100644 index 867aea1cd1..0000000000 --- a/test/others/test_schema.py +++ /dev/null @@ -1,1126 +0,0 @@ -import json - -from haystack.schema import Document, EvaluationResult, Label, Answer, Span, MultiLabel, TableCell, _dict_factory -import pytest -import numpy as np -import pandas as pd - - -@pytest.fixture -def text_label(): - return Label( - query="some", - answer=Answer( - answer="an answer", - type="extractive", - score=0.1, - document_ids=["doc_1"], - offsets_in_document=[Span(start=1, end=3)], - ), - document=Document(content="some text", content_type="text", id="doc_1"), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - created_at="2023-05-02 11:43:56", - id="text_label_1", - ) - - -@pytest.fixture -def text_label_dict(): - return { - "id": "text_label_1", - "query": "some", - "document": { - "id": "doc_1", - "content": "some text", - "content_type": "text", - "meta": {}, - "id_hash_keys": ["content"], - "score": None, - "embedding": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "answer": { - "answer": "an answer", - "type": "extractive", - "score": 0.1, - "context": None, - "offsets_in_document": [{"start": 1, "end": 3}], - "offsets_in_context": None, - "document_ids": ["doc_1"], - "meta": {}, - }, - "pipeline_id": None, - "created_at": "2023-05-02 11:43:56", - "updated_at": None, - "meta": {}, - "filters": None, - } - - -@pytest.fixture -def text_label_json(samples_path): - with open(samples_path / "schema" / "text_label.json") as f1: - data = json.load(f1) - return data - - -@pytest.fixture -def table_label(): - return Label( - query="some", - answer=Answer( - answer="text_2", - type="extractive", - score=0.1, - document_ids=["123"], - context=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - offsets_in_document=[TableCell(row=1, col=0)], - ), - document=Document( - content=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - content_type="table", - id="fe5cb68f8226776914781f6bd40ad718", - ), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - created_at="2023-05-02 11:43:56", - updated_at=None, - id="fbd79f71-d690-4b21-bd0a-1094292b9809", - ) - - -@pytest.fixture -def table_label_dict(): - return { - "id": "fbd79f71-d690-4b21-bd0a-1094292b9809", - "query": "some", - "document": { - "id": "fe5cb68f8226776914781f6bd40ad718", - "content": [["col1", "col2"], ["text_1", 1], ["text_2", 2]], - "content_type": "table", - "meta": {}, - "id_hash_keys": ["content"], - "score": None, - "embedding": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "answer": { - "answer": "text_2", - "type": "extractive", - "score": 0.1, - "context": [["col1", "col2"], ["text_1", 1], ["text_2", 2]], - "offsets_in_document": [{"row": 1, "col": 0}], - "offsets_in_context": None, - "document_ids": ["123"], - "meta": {}, - }, - "pipeline_id": None, - "created_at": "2023-05-02 11:43:56", - "updated_at": None, - "meta": {}, - "filters": None, - } - - -@pytest.fixture -def table_label_json(samples_path): - with open(samples_path / "schema" / "table_label.json") as f1: - data = json.load(f1) - return data - - -@pytest.fixture -def text_answer(): - return Answer( - answer="an answer", - type="extractive", - score=0.1, - context="abc", - offsets_in_document=[Span(start=1, end=10)], - offsets_in_context=[Span(start=3, end=5)], - document_ids=["123"], - ) - - -@pytest.fixture -def text_answer_dict(): - return { - "answer": "an answer", - "type": "extractive", - "score": 0.1, - "context": "abc", - "offsets_in_document": [{"start": 1, "end": 10}], - "offsets_in_context": [{"start": 3, "end": 5}], - "document_ids": ["123"], - "meta": {}, - } - - -@pytest.fixture -def text_answer_json(samples_path): - with open(samples_path / "schema" / "text_answer.json") as f1: - data = json.load(f1) - return data - - -@pytest.fixture -def table_answer(): - return Answer( - answer="text_2", - type="extractive", - score=0.1, - context=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - offsets_in_document=[TableCell(row=1, col=0)], - offsets_in_context=[TableCell(row=1, col=0)], - document_ids=["123"], - ) - - -@pytest.fixture -def table_answer_dict(): - return { - "answer": "text_2", - "type": "extractive", - "score": 0.1, - "context": [["col1", "col2"], ["text_1", 1], ["text_2", 2]], - "offsets_in_document": [{"row": 1, "col": 0}], - "offsets_in_context": [{"row": 1, "col": 0}], - "document_ids": ["123"], - "meta": {}, - } - - -@pytest.fixture -def table_answer_json(samples_path): - with open(samples_path / "schema" / "table_answer.json") as f1: - data = json.load(f1) - return data - - -@pytest.fixture -def text_doc(): - return Document(content="some text", content_type="text", id="doc1") - - -@pytest.fixture -def text_doc_dict(): - return { - "content": "some text", - "content_type": "text", - "score": None, - "meta": {}, - "id_hash_keys": ["content"], - "embedding": None, - "id": "doc1", - } - - -@pytest.fixture -def text_doc_json(samples_path): - with open(samples_path / "schema" / "text_doc.json") as f1: - json_str = f1.read() - return json_str - - -@pytest.fixture -def text_doc_with_embedding(): - return Document(content="some text", content_type="text", id="doc2", embedding=np.array([1.1, 2.2, 3.3, 4.4])) - - -@pytest.fixture -def text_doc_with_embedding_json(samples_path): - with open(samples_path / "schema" / "text_doc_emb.json") as f1: - json_str = f1.read() - return json_str - - -@pytest.fixture -def table_doc(): - data = { - "actors": ["brad pitt", "leonardo di caprio", "george clooney"], - "age": [58, 47, 60], - "number of movies": [87, 53, 69], - "date of birth": ["18 december 1963", "11 november 1974", "6 may 1961"], - } - return Document(content=pd.DataFrame(data), content_type="table", id="doc1") - - -@pytest.fixture -def table_doc_dict(): - return { - "content": [ - ["actors", "age", "number of movies", "date of birth"], - ["brad pitt", 58, 87, "18 december 1963"], - ["leonardo di caprio", 47, 53, "11 november 1974"], - ["george clooney", 60, 69, "6 may 1961"], - ], - "content_type": "table", - "score": None, - "meta": {}, - "id_hash_keys": ["content"], - "embedding": None, - "id": "doc1", - } - - -@pytest.fixture -def table_doc_json(samples_path): - with open(samples_path / "schema" / "table_doc.json") as f1: - json_str = f1.read() - return json_str - - -@pytest.fixture -def table_doc_with_embedding(): - data = { - "actors": ["brad pitt", "leonardo di caprio", "george clooney"], - "age": [58, 47, 60], - "number of movies": [87, 53, 69], - "date of birth": ["18 december 1963", "11 november 1974", "6 may 1961"], - } - return Document( - content=pd.DataFrame(data), content_type="table", id="doc2", embedding=np.array([1.1, 2.2, 3.3, 4.4]) - ) - - -@pytest.fixture -def table_doc_with_embedding_json(samples_path): - with open(samples_path / "schema" / "table_doc_emb.json") as f1: - json_str = f1.read() - return json_str - - -@pytest.mark.unit -def test_no_answer_label(): - label_no_answer = Label( - query="question", - answer=Answer(answer=""), - is_correct_answer=True, - is_correct_document=True, - document=Document(content="some", id="777"), - origin="gold-label", - ) - label_with_answer = Label( - query="question", - answer=Answer(answer="some"), - is_correct_answer=True, - is_correct_document=True, - document=Document(content="some", id="777"), - origin="gold-label", - ) - assert label_no_answer.no_answer - assert not label_with_answer.no_answer - - -@pytest.mark.unit -def test_text_labels_with_identical_fields_are_equal(text_label): - text_label_copy = Label( - query="some", - answer=Answer( - answer="an answer", - type="extractive", - score=0.1, - document_ids=["doc_1"], - offsets_in_document=[Span(start=1, end=3)], - ), - document=Document(content="some text", content_type="text", id="doc_1"), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - created_at="2023-05-02 11:43:56", - id="text_label_1", - ) - assert text_label == text_label_copy - - -@pytest.mark.unit -def test_text_labels_with_different_fields_are_not_equal(text_label): - text_label_different = Label( - query="some", - answer=Answer( - answer="different answer", - type="extractive", - score=0.1, - document_ids=["doc_1"], - offsets_in_document=[Span(start=5, end=15)], - ), - document=Document(content="some text", content_type="text", id="doc_1"), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - created_at="2023-05-02 11:43:56", - id="text_label_1", - ) - assert text_label != text_label_different - - -@pytest.mark.unit -def test_label_from_json(text_label, text_label_json): - text_label_from_json = Label.from_json(text_label_json) - assert text_label_from_json == text_label - - -@pytest.mark.unit -def test_label_to_json(text_label, text_label_json): - text_label_to_json = json.loads(text_label.to_json()) - assert text_label_to_json == text_label_json - - -@pytest.mark.unit -def test_text_label_from_dict(text_label, text_label_dict): - text_label_from_dict = Label.from_dict(text_label_dict) - assert text_label_from_dict == text_label - - -@pytest.mark.unit -def test_text_label_to_dict(text_label, text_label_dict): - text_label_to_dict = text_label.to_dict() - assert text_label_to_dict == text_label_dict - - -@pytest.mark.unit -def test_table_labels_with_identical_fields_are_equal(table_label): - table_label_copy = Label( - query="some", - answer=Answer( - answer="text_2", - type="extractive", - score=0.1, - document_ids=["123"], - context=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - offsets_in_document=[TableCell(row=1, col=0)], - ), - document=Document( - content=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - content_type="table", - ), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - ) - assert table_label == table_label_copy - - -@pytest.mark.unit -def test_table_labels_with_different_fields_are_not_equal(table_label): - table_label_different = Label( - query="some", - answer=Answer( - answer="text_1", - type="extractive", - score=0.1, - document_ids=["123"], - context=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - offsets_in_document=[TableCell(row=0, col=0)], - ), - document=Document( - content=pd.DataFrame.from_records([{"col1": "text_1", "col2": 1}, {"col1": "text_2", "col2": 2}]), - content_type="table", - ), - is_correct_answer=True, - is_correct_document=True, - origin="user-feedback", - ) - assert table_label != table_label_different - - -@pytest.mark.unit -def test_table_label_from_json(table_label, table_label_json): - table_label_from_json = Label.from_json(table_label_json) - assert table_label_from_json == table_label - - -@pytest.mark.unit -def test_table_label_to_json(table_label, table_label_json): - table_label_to_json = json.loads(table_label.to_json()) - assert table_label_to_json == table_label_json - - -@pytest.mark.unit -def test_table_label_from_dict(table_label, table_label_dict): - table_label_from_dict = Label.from_dict(table_label_dict) - assert table_label_from_dict == table_label - - -@pytest.mark.unit -def test_table_label_to_dict(table_label, table_label_dict): - table_label_to_dict = table_label.to_dict() - assert table_label_to_dict == table_label_dict - - -@pytest.mark.unit -def test_answer_to_json(text_answer, text_answer_json): - text_answer_to_json = json.loads(text_answer.to_json()) - assert text_answer_to_json == text_answer_json - - -@pytest.mark.unit -def test_answer_from_json(text_answer, text_answer_json): - text_answer_from_json = Answer.from_json(text_answer_json) - assert text_answer_from_json == text_answer - - -@pytest.mark.unit -def test_answer_to_dict(text_answer, text_answer_dict): - assert text_answer.to_dict() == text_answer_dict - - -@pytest.mark.unit -def test_answer_from_dict(text_answer, text_answer_dict): - assert text_answer == Answer.from_dict(text_answer_dict) - - -@pytest.mark.unit -def test_table_answer_to_json(table_answer, table_answer_json): - table_answer_to_json = json.loads(table_answer.to_json()) - assert table_answer_to_json == table_answer_json - - -@pytest.mark.unit -def test_table_answer_from_json(table_answer, table_answer_json): - table_answer_from_json = Answer.from_json(table_answer_json) - assert table_answer_from_json == table_answer - - -@pytest.mark.unit -def test_table_answer_to_dict(table_answer, table_answer_dict): - assert table_answer.to_dict() == table_answer_dict - - -@pytest.mark.unit -def test_table_answer_from_dict(table_answer, table_answer_dict): - assert table_answer == Answer.from_dict(table_answer_dict) - - -@pytest.mark.unit -def test_document_from_dict(text_doc, text_doc_dict): - assert text_doc == Document.from_dict(text_doc_dict) - - -@pytest.mark.unit -def test_document_to_dict(text_doc, text_doc_dict): - assert text_doc.to_dict() == text_doc_dict - - -@pytest.mark.unit -def test_table_document_from_dict(table_doc, table_doc_dict): - assert table_doc == Document.from_dict(table_doc_dict) - - -@pytest.mark.unit -def test_table_document_to_dict(table_doc, table_doc_dict): - assert table_doc.to_dict() == table_doc_dict - - -@pytest.mark.unit -def test_document_from_json_with_embedding(text_doc_with_embedding, text_doc_with_embedding_json): - text_doc_emb_from_json = Document.from_json(text_doc_with_embedding_json) - assert text_doc_with_embedding == text_doc_emb_from_json - - -@pytest.mark.unit -def test_document_from_json_without_embedding(text_doc, text_doc_json): - text_doc_no_emb_from_json = Document.from_json(text_doc_json) - assert text_doc == text_doc_no_emb_from_json - - -@pytest.mark.unit -def test_document_to_json_with_embedding(text_doc_with_embedding, text_doc_with_embedding_json): - text_doc_emb_to_json = json.loads(text_doc_with_embedding.to_json()) - assert json.loads(text_doc_with_embedding_json) == text_doc_emb_to_json - - -@pytest.mark.unit -def test_document_to_json_without_embedding(text_doc, text_doc_json): - text_doc_no_emb_to_json = json.loads(text_doc.to_json()) - assert json.loads(text_doc_json) == text_doc_no_emb_to_json - - -@pytest.mark.unit -def test_table_doc_from_json_with_embedding(table_doc_with_embedding, table_doc_with_embedding_json): - table_doc_emb_from_json = Document.from_json(table_doc_with_embedding_json) - assert table_doc_with_embedding == table_doc_emb_from_json - - -@pytest.mark.unit -def test_table_doc_from_json_without_embedding(table_doc, table_doc_json): - table_doc_no_emb_from_json = Document.from_json(table_doc_json) - assert table_doc == table_doc_no_emb_from_json - - -@pytest.mark.unit -def test_table_doc_to_json_with_embedding(table_doc_with_embedding, table_doc_with_embedding_json): - # With embedding - table_doc_emb_to_json = json.loads(table_doc_with_embedding.to_json()) - assert json.loads(table_doc_with_embedding_json) == table_doc_emb_to_json - - -@pytest.mark.unit -def test_table_doc_to_json_without_embedding(table_doc, table_doc_json): - # No embedding - table_doc_no_emb_to_json = json.loads(table_doc.to_json()) - assert json.loads(table_doc_json) == table_doc_no_emb_to_json - - -@pytest.mark.unit -def test_answer_postinit(): - a = Answer(answer="test", offsets_in_document=[{"start": 10, "end": 20}]) - assert a.meta == {} - assert isinstance(a.offsets_in_document[0], Span) - - -@pytest.mark.unit -def test_table_answer_postinit(): - table_answer = Answer(answer="test", offsets_in_document=[{"row": 1, "col": 2}]) - assert table_answer.meta == {} - assert isinstance(table_answer.offsets_in_document[0], TableCell) - - -@pytest.mark.unit -def test_generate_doc_id_using_text(): - text1 = "text1" - text2 = "text2" - doc1_text1 = Document(content=text1, meta={"name": "doc1"}) - doc2_text1 = Document(content=text1, meta={"name": "doc2"}) - doc3_text2 = Document(content=text2, meta={"name": "doc3"}) - - assert doc1_text1.id == doc2_text1.id - assert doc1_text1.id != doc3_text2.id - - -@pytest.mark.unit -def test_generate_doc_id_using_custom_list(): - text1 = "text1" - text2 = "text2" - - doc1_meta1_id_by_content = Document(content=text1, meta={"name": "doc1"}, id_hash_keys=["content"]) - doc1_meta2_id_by_content = Document(content=text1, meta={"name": "doc2"}, id_hash_keys=["content"]) - assert doc1_meta1_id_by_content.id == doc1_meta2_id_by_content.id - - doc1_meta1_id_by_content_and_meta = Document(content=text1, meta={"name": "doc1"}, id_hash_keys=["content", "meta"]) - doc1_meta2_id_by_content_and_meta = Document(content=text1, meta={"name": "doc2"}, id_hash_keys=["content", "meta"]) - assert doc1_meta1_id_by_content_and_meta.id != doc1_meta2_id_by_content_and_meta.id - - doc1_text1 = Document(content=text1, meta={"name": "doc1"}, id_hash_keys=["content"]) - doc3_text2 = Document(content=text2, meta={"name": "doc3"}, id_hash_keys=["content"]) - assert doc1_text1.id != doc3_text2.id - - with pytest.raises(ValueError): - _ = Document(content=text1, meta={"name": "doc1"}, id_hash_keys=["content", "non_existing_field"]) - - -@pytest.mark.unit -def test_generate_doc_id_custom_list_meta(): - text1 = "text1" - text2 = "text2" - - doc1_text1 = Document( - content=text1, meta={"name": "doc1", "url": "https://deepset.ai"}, id_hash_keys=["content", "meta.url"] - ) - doc2_text1 = Document( - content=text1, meta={"name": "doc2", "url": "https://deepset.ai"}, id_hash_keys=["content", "meta.url"] - ) - assert doc1_text1.id == doc2_text1.id - - doc1_text1 = Document(content=text1, meta={"name": "doc1", "url": "https://deepset.ai"}, id_hash_keys=["meta.url"]) - doc2_text2 = Document(content=text2, meta={"name": "doc2", "url": "https://deepset.ai"}, id_hash_keys=["meta.url"]) - assert doc1_text1.id == doc2_text2.id - - doc1_text1 = Document(content=text1, meta={"name": "doc1", "url": "https://deepset.ai"}, id_hash_keys=["meta.url"]) - doc2_text2 = Document( - content=text2, meta={"name": "doc2", "url": "https://deepset.ai"}, id_hash_keys=["meta.url", "meta.name"] - ) - assert doc1_text1.id != doc2_text2.id - - -@pytest.mark.unit -def test_aggregate_labels_with_labels(): - label1_with_filter1 = Label( - query="question", - answer=Answer(answer="1"), - is_correct_answer=True, - is_correct_document=True, - document=Document(content="some", id="777"), - origin="gold-label", - filters={"name": ["filename1"]}, - ) - label2_with_filter1 = Label( - query="question", - answer=Answer(answer="2"), - is_correct_answer=True, - is_correct_document=True, - document=Document(content="some", id="777"), - origin="gold-label", - filters={"name": ["filename1"]}, - ) - label3_with_filter2 = Label( - query="question", - answer=Answer(answer="2"), - is_correct_answer=True, - is_correct_document=True, - document=Document(content="some", id="777"), - origin="gold-label", - filters={"name": ["filename2"]}, - ) - label = MultiLabel(labels=[label1_with_filter1, label2_with_filter1]) - assert label.filters == {"name": ["filename1"]} - with pytest.raises(ValueError): - _ = MultiLabel(labels=[label1_with_filter1, label3_with_filter2]) - - -@pytest.mark.unit -def test_multilabel_preserve_order(): - labels = [ - Label( - id="0", - query="question", - answer=Answer(answer="answer1", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="1", - query="question", - answer=Answer(answer="answer2", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="2", - query="question", - answer=Answer(answer="answer3", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some other", id="333"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="3", - query="question", - answer=Answer(answer="", offsets_in_document=[Span(start=0, end=0)]), - document=Document(content="some", id="777"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="4", - query="question", - answer=Answer(answer="answer5", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ), - ] - - multilabel = MultiLabel(labels=labels) - - for i in range(0, 5): - assert multilabel.labels[i].id == str(i) - - -@pytest.mark.unit -def test_multilabel_preserve_order_w_duplicates(): - labels = [ - Label( - id="0", - query="question", - answer=Answer( - answer="answer1", - offsets_in_document=[Span(start=12, end=18)], - offsets_in_context=[Span(start=1, end=7)], - ), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="1", - query="question", - answer=Answer( - answer="answer2", - offsets_in_document=[Span(start=10, end=16)], - offsets_in_context=[Span(start=0, end=6)], - ), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="2", - query="question", - answer=Answer( - answer="answer3", - offsets_in_document=[Span(start=14, end=20)], - offsets_in_context=[Span(start=2, end=8)], - ), - document=Document(content="some other", id="333"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="0", - query="question", - answer=Answer( - answer="answer1", - offsets_in_document=[Span(start=12, end=18)], - offsets_in_context=[Span(start=1, end=7)], - ), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( - id="2", - query="question", - answer=Answer( - answer="answer3", - offsets_in_document=[Span(start=14, end=20)], - offsets_in_context=[Span(start=2, end=8)], - ), - document=Document(content="some other", id="333"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - ] - - multilabel = MultiLabel(labels=labels) - - assert multilabel.query == "question" - assert multilabel.answers == ["answer1", "answer2", "answer3"] - assert multilabel.document_ids == ["123", "123", "333"] - assert multilabel.contexts == ["some", "some", "some other"] - assert multilabel.offsets_in_documents == [ - {"start": 12, "end": 18}, - {"start": 10, "end": 16}, - {"start": 14, "end": 20}, - ] - assert multilabel.offsets_in_contexts == [{"start": 1, "end": 7}, {"start": 0, "end": 6}, {"start": 2, "end": 8}] - - for i in range(0, 3): - assert multilabel.labels[i].id == str(i) - - -@pytest.mark.unit -def test_multilabel_id(): - query1 = "question 1" - query2 = "question 2" - document1 = Document(content="something", id="1") - answer1 = Answer(answer="answer 1") - filter1 = {"name": ["name 1"]} - filter2 = {"name": ["name 1"], "author": ["author 1"]} - label1 = Label( - query=query1, - document=document1, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - answer=answer1, - filters=filter1, - ) - label2 = Label( - query=query2, - document=document1, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - answer=answer1, - filters=filter2, - ) - label3 = Label( - query=query1, - document=document1, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - answer=answer1, - filters=filter2, - ) - - assert MultiLabel(labels=[label1]).id == "33a3e58e13b16e9d6ec682ffe59ccc89" - assert MultiLabel(labels=[label2]).id == "1b3ad38b629db7b0e869373b01bc32b1" - assert MultiLabel(labels=[label3]).id == "531445fa3bdf98b8598a3bea032bd605" - - -@pytest.mark.unit -def test_multilabel_with_doc_containing_dataframes(): - table = pd.DataFrame({"col1": [1, 2], "col2": [3, 4]}) - table_doc = Document(content=table, content_type="table", id="table1") - label = Label( - query="A question", - document=table_doc, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - answer=Answer( - answer="1", - context=table, - offsets_in_document=[TableCell(0, 0)], - offsets_in_context=[TableCell(0, 0)], - document_ids=[table_doc.id], - ), - ) - multilabel = MultiLabel(labels=[label]) - assert multilabel.query == "A question" - assert multilabel.contexts == [" col1 col2\n0 1 3\n1 2 4"] - assert multilabel.answers == ["1"] - assert multilabel.document_ids == ["table1"] - assert multilabel.offsets_in_documents == [{"row": 0, "col": 0}] - assert multilabel.offsets_in_contexts == [{"row": 0, "col": 0}] - - -@pytest.mark.unit -def test_multilabel_serialization(): - label_dict = { - "id": "011079cf-c93f-49e6-83bb-42cd850dce12", - "query": "When was the final season first shown on TV?", - "document": { - "content": "\n\n\n\n\nThe eighth and final season of the fantasy drama television series ''Game of Thrones'', produced by HBO, premiered on April 14, 2019, and concluded on May 19, 2019. Unlike the first six seasons, which consisted of ten episodes each, and the seventh season, which consisted of seven episodes, the eighth season consists of only six episodes.\n\nThe final season depicts the culmination of the series' two primary conflicts: the G", - "content_type": "text", - "id": "9c82c97c9dc8ba6895893a53aafa610f", - "meta": {}, - "score": None, - "embedding": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "answer": { - "answer": "April 14", - "type": "extractive", - "score": None, - "context": "\n\n\n\n\nThe eighth and final season of the fantasy drama television series ''Game of Thrones'', produced by HBO, premiered on April 14, 2019, and concluded on May 19, 2019. Unlike the first six seasons, which consisted of ten episodes each, and the seventh season, which consisted of seven episodes, the eighth season consists of only six episodes.\n\nThe final season depicts the culmination of the series' two primary conflicts: the G", - "offsets_in_document": [{"start": 124, "end": 132}], - "offsets_in_context": None, - "document_ids": None, - "meta": {}, - }, - "no_answer": False, - "pipeline_id": None, - "created_at": "2022-07-22T13:29:33.699781+00:00", - "updated_at": "2022-07-22T13:29:33.784895+00:00", - "meta": {"answer_id": "374394", "document_id": "604995", "question_id": "345530"}, - "filters": None, - } - - label = Label.from_dict(label_dict) - original_multilabel = MultiLabel([label]) - - deserialized_multilabel = MultiLabel.from_dict(original_multilabel.to_dict()) - assert deserialized_multilabel == original_multilabel - assert deserialized_multilabel.labels[0] == label - - json_deserialized_multilabel = MultiLabel.from_json(original_multilabel.to_json()) - assert json_deserialized_multilabel == original_multilabel - assert json_deserialized_multilabel.labels[0] == label - - -@pytest.mark.unit -def test_table_multilabel_serialization(): - tabel_label_dict = { - "id": "011079cf-c93f-49e6-83bb-42cd850dce12", - "query": "What is the first number?", - "document": { - "content": [["col1", "col2"], [1, 3], [2, 4]], - "content_type": "table", - "id": "table1", - "meta": {}, - "score": None, - "embedding": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "answer": { - "answer": "1", - "type": "extractive", - "score": None, - "context": [["col1", "col2"], [1, 3], [2, 4]], - "offsets_in_document": [{"row": 0, "col": 0}], - "offsets_in_context": [{"row": 0, "col": 0}], - "document_ids": ["table1"], - "meta": {}, - }, - "no_answer": False, - "pipeline_id": None, - "created_at": "2022-07-22T13:29:33.699781+00:00", - "updated_at": "2022-07-22T13:29:33.784895+00:00", - "meta": {"answer_id": "374394", "document_id": "604995", "question_id": "345530"}, - "filters": None, - } - - label = Label.from_dict(tabel_label_dict) - original_multilabel = MultiLabel([label]) - - deserialized_multilabel = MultiLabel.from_dict(original_multilabel.to_dict()) - assert deserialized_multilabel == original_multilabel - assert deserialized_multilabel.labels[0] == label - - json_deserialized_multilabel = MultiLabel.from_json(original_multilabel.to_json()) - assert json_deserialized_multilabel == original_multilabel - assert json_deserialized_multilabel.labels[0] == label - - -@pytest.mark.unit -def test_span_in(): - assert 10 in Span(5, 15) - assert 20 not in Span(1, 15) - - -@pytest.mark.unit -def test_span_in_edges(): - assert 5 in Span(5, 15) - assert 15 not in Span(5, 15) - - -@pytest.mark.unit -def test_span_in_other_values(): - assert 10.0 in Span(5, 15) - assert "10" in Span(5, 15) - with pytest.raises(ValueError): - assert "hello" in Span(5, 15) - - -@pytest.mark.unit -def test_assert_span_vs_span(): - assert Span(10, 11) in Span(5, 15) - assert Span(5, 10) in Span(5, 15) - assert not Span(10, 15) in Span(5, 15) - assert not Span(5, 15) in Span(5, 15) - assert Span(5, 14) in Span(5, 15) - - assert not Span(0, 1) in Span(5, 15) - assert not Span(0, 10) in Span(5, 15) - assert not Span(10, 20) in Span(5, 15) - - -@pytest.mark.unit -def test_id_hash_keys_not_ignored(): - # Test that two documents with the same content but different metadata get assigned different ids if and only if - # id_hash_keys is set to 'meta' - doc1 = Document(content="hello world", meta={"doc_id": "1"}, id_hash_keys=["meta"]) - doc2 = Document(content="hello world", meta={"doc_id": "2"}, id_hash_keys=["meta"]) - assert doc1.id != doc2.id - doc3 = Document(content="hello world", meta={"doc_id": "3"}) - doc4 = Document(content="hello world", meta={"doc_id": "4"}) - assert doc3.id == doc4.id - - -@pytest.mark.unit -def test_legacy_answer_document_id(): - legacy_label = { - "id": "123", - "query": "Who made the PDF specification?", - "document": { - "content": "Some content", - "content_type": "text", - "score": None, - "id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "embedding": [0.1, 0.2, 0.3], - }, - "answer": { - "answer": "Adobe Systems", - "type": "extractive", - "context": "Some content", - "offsets_in_context": [{"start": 60, "end": 73}], - "offsets_in_document": [{"start": 60, "end": 73}], - # legacy document_id answer - "document_id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "score": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "pipeline_id": "some-123", - } - - answer = Answer.from_dict(legacy_label["answer"]) - assert answer.document_ids == ["fc18c987a8312e72a47fb1524f230bb0"] - - label = Label.from_dict(legacy_label) - assert label.answer.document_ids == ["fc18c987a8312e72a47fb1524f230bb0"] - - -@pytest.mark.unit -def test_legacy_answer_document_id_is_none(): - legacy_label = { - "id": "123", - "query": "Who made the PDF specification?", - "document": { - "content": "Some content", - "content_type": "text", - "score": None, - "id": "fc18c987a8312e72a47fb1524f230bb0", - "meta": {}, - "embedding": [0.1, 0.2, 0.3], - }, - "answer": { - "answer": "Adobe Systems", - "type": "extractive", - "context": "Some content", - "offsets_in_context": [{"start": 60, "end": 73}], - "offsets_in_document": [{"start": 60, "end": 73}], - # legacy document_id answer - "document_id": None, - "meta": {}, - "score": None, - }, - "is_correct_answer": True, - "is_correct_document": True, - "origin": "user-feedback", - "pipeline_id": "some-123", - } - - answer = Answer.from_dict(legacy_label["answer"]) - assert answer.document_ids is None - - label = Label.from_dict(legacy_label) - assert label.answer.document_ids is None - - -@pytest.mark.unit -def test_dict_factory(): - data = [ - ("key1", "some_value"), - ("key2", ["val1", "val2"]), - ("key3", pd.DataFrame({"col1": [1, 2], "col2": [3, 4]})), - ] - result = _dict_factory(data) - assert result["key1"] == "some_value" - assert result["key2"] == ["val1", "val2"] - assert result["key3"] == [["col1", "col2"], [1, 3], [2, 4]] - - -@pytest.mark.unit -def test_evaluation_result_append(): - df1 = pd.DataFrame({"col1": [1, 2], "index": [3, 4]}) - df2 = pd.DataFrame({"col1": [5, 6], "index": [7, 8]}) - df_expected = pd.DataFrame({"col1": [1, 2, 5, 6], "index": [3, 4, 7, 8]}) - - eval_result = EvaluationResult() - eval_result.append("test", df1) - pd.testing.assert_frame_equal(eval_result["test"], df1) - assert isinstance(eval_result["test"].index, pd.RangeIndex) - - eval_result.append("test", df2) - pd.testing.assert_frame_equal(eval_result["test"], df_expected) - assert isinstance(eval_result["test"].index, pd.RangeIndex) diff --git a/test/others/test_squad_data.py b/test/others/test_squad_data.py deleted file mode 100644 index 216c9ff83d..0000000000 --- a/test/others/test_squad_data.py +++ /dev/null @@ -1,140 +0,0 @@ -import pandas as pd -import pytest - -from haystack.utils.squad_data import SquadData -from haystack.utils.augment_squad import augment_squad -from haystack.schema import Document, Label, Answer - - -def test_squad_augmentation(samples_path): - input_ = samples_path / "squad" / "tiny.json" - output = samples_path / "squad" / "tiny_augmented.json" - glove_path = samples_path / "glove" / "tiny.txt" # dummy glove file, will not even be use when augmenting tiny.json - multiplication_factor = 5 - augment_squad( - model="distilbert-base-uncased", - tokenizer="distilbert-base-uncased", - squad_path=input_, - output_path=output, - glove_path=glove_path, - multiplication_factor=multiplication_factor, - ) - original_squad = SquadData.from_file(input_) - augmented_squad = SquadData.from_file(output) - assert original_squad.count(unit="paragraph") == augmented_squad.count(unit="paragraph") * multiplication_factor - - -@pytest.mark.unit -def test_squad_data_converts_df_to_data(): - df = pd.DataFrame( - [["title", "context", "question", "id", "answer", 1, False]], - columns=["title", "context", "question", "id", "answer_text", "answer_start", "is_impossible"], - ) - expected_result = [ - { - "title": "title", - "paragraphs": [ - { - "context": "context", - "qas": [ - { - "question": "question", - "id": "id", - "answers": [{"text": "answer", "answer_start": 1}], - "is_impossible": False, - } - ], - } - ], - } - ] - - result = SquadData.df_to_data(df) - - assert result == expected_result - - -@pytest.mark.unit -def test_squad_data_converts_data_to_df(): - data = [ - { - "title": "title", - "paragraphs": [ - { - "context": "context", - "document_id": "document_id", - "qas": [ - { - "question": "question", - "id": "id", - "answers": [{"text": "answer", "answer_start": 1}], - "is_impossible": False, - } - ], - } - ], - } - ] - expected_result = pd.DataFrame( - [["title", "context", "question", "id", "answer", 1, False, "document_id"]], - columns=["title", "context", "question", "id", "answer_text", "answer_start", "is_impossible", "document_id"], - ) - result = SquadData.to_df(data) - assert result.equals(expected_result) - - -def test_to_label_object(): - squad_data_list = [ - { - "title": "title", - "paragraphs": [ - { - "context": "context", - "qas": [ - { - "question": "question", - "id": "id", - "answers": [{"text": "answer", "answer_start": 1}], - "is_impossible": False, - }, - { - "question": "another question", - "id": "another_id", - "answers": [{"text": "this is the response", "answer_start": 1}], - "is_impossible": False, - }, - ], - }, - { - "context": "the second paragraph context", - "qas": [ - { - "question": "the third question", - "id": "id_3", - "answers": [{"text": "this is another response", "answer_start": 1}], - "is_impossible": False, - }, - { - "question": "the forth question", - "id": "id_4", - "answers": [{"text": "this is the response", "answer_start": 1}], - "is_impossible": False, - }, - ], - }, - ], - } - ] - squad_data = SquadData(squad_data=squad_data_list) - answer_type = "generative" - labels = squad_data.to_label_objs(answer_type=answer_type) - for label, expected_question in zip(labels, squad_data.df.iterrows()): - expected_question = expected_question[1] - assert isinstance(label, Label) - assert isinstance(label.document, Document) - assert isinstance(label.answer, Answer) - assert label.query == expected_question["question"] - assert label.document.content == expected_question.context - assert label.document.id == expected_question.document_id - assert label.id == expected_question.id - assert label.answer.answer == expected_question.answer_text diff --git a/test/others/test_utils.py b/test/others/test_utils.py deleted file mode 100644 index 9e0c86a99a..0000000000 --- a/test/others/test_utils.py +++ /dev/null @@ -1,1712 +0,0 @@ -import importlib -import logging -from typing import List -from unittest import mock - -import numpy as np -import pytest -import pandas as pd -import responses -from responses import matchers - -import _pytest - -from haystack.schema import Answer, Document, Span, Label -from haystack.utils import print_answers -from haystack.utils.deepsetcloud import DeepsetCloud, DeepsetCloudExperiments -from haystack.utils.import_utils import get_filename_extension_from_url -from haystack.utils.labels import aggregate_labels -from haystack.utils.preprocessing import convert_files_to_docs, tika_convert_files_to_docs -from haystack.utils.cleaning import clean_wiki_text -from haystack.utils.context_matching import calculate_context_similarity, match_context, match_contexts - -from .. import conftest -from ..conftest import DC_API_ENDPOINT, DC_API_KEY, MOCK_DC, deepset_cloud_fixture, fail_at_version - - -@pytest.fixture -def sample_context(): - return """Der Merkantilismus förderte Handel und Verkehr mit teils marktkonformen, teils dirigistischen Maßnahmen. -An der Schwelle zum 19. Jahrhundert entstand ein neuer Typus des Nationalstaats, der die Säkularisation durchsetzte, -moderne Bildungssysteme etablierte und die Industrialisierung vorantrieb.\n -Beim Begriff der Aufklärung geht es auch um die Prozesse zwischen diesen frühneuzeitlichen Eckpunkten. -Man versucht die fortschrittlichen Faktoren zu definieren, die in das 19. Jahrhundert führten. -Widerstände gegen diesen Fortschritt werden anti-aufklärerischen Kräften oder unreflektierten Traditionen zugeordnet. -Die Epochendefinition rückt vor allem publizistisch tätige Gruppen in den gesellschaftlichen Fokus, -die zunächst selten einen bürgerlichen Hintergrund aufwiesen, sondern weitaus häufiger der Geistlichkeit oder Aristokratie angehörten: -Wissenschaftler, Journalisten, Autoren, sogar Regenten, die Traditionen der Kritik unterzogen, indem sie sich auf die Vernunftperspektive beriefen.""" - - -@pytest.fixture -def sample_context_2(): - return """Beer is one of the oldest[1][2][3] and most widely consumed[4] alcoholic drinks in the world, and the third most popular drink overall after water and tea.[5] It is produced by the brewing and fermentation of starches, mainly derived from cereal grains—most commonly from malted barley, though wheat, maize (corn), rice, and oats are also used. During the brewing process, fermentation of the starch sugars in the wort produces ethanol and carbonation in the resulting beer.[6] Most modern beer is brewed with hops, which add bitterness and other flavours and act as a natural preservative and stabilizing agent. Other flavouring agents such as gruit, herbs, or fruits may be included or used instead of hops. In commercial brewing, the natural carbonation effect is often removed during processing and replaced with forced carbonation.[7] -Some of humanity's earliest known writings refer to the production and distribution of beer: the Code of Hammurabi included laws regulating beer and beer parlours,[8] and "The Hymn to Ninkasi", a prayer to the Mesopotamian goddess of beer, served as both a prayer and as a method of remembering the recipe for beer in a culture with few literate people.[9][10] -Beer is distributed in bottles and cans and is also commonly available on draught, particularly in pubs and bars. The brewing industry is a global business, consisting of several dominant multinational companies and many thousands of smaller producers ranging from brewpubs to regional breweries. The strength of modern beer is usually around 4% to 6% alcohol by volume (ABV), although it may vary between 0.5% and 20%, with some breweries creating examples of 40% ABV and above.[11] -Beer forms part of the culture of many nations and is associated with social traditions such as beer festivals, as well as a rich pub culture involving activities like pub crawling, pub quizzes and pub games. -When beer is distilled, the resulting liquor is a form of whisky.[12] -""" - - -# Util function for testing -def noop(): - return True - - -@pytest.mark.unit -def test_deprecation_previous_major_and_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"), pytest.warns( - match="This feature is marked for removal in v1.1" - ): - fail_at_version(1, 1)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(1, 1)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(1, 1)(noop)() - - -@pytest.mark.unit -def test_deprecation_previous_major_same_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"), pytest.warns( - match="This feature is marked for removal in v1.2" - ): - fail_at_version(1, 2)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(1, 2)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(1, 2)(noop)() - - -@pytest.mark.unit -def test_deprecation_previous_major_later_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"), pytest.warns( - match="This feature is marked for removal in v1.3" - ): - fail_at_version(1, 3)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(1, 3)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(1, 3)(noop)() - - -@pytest.mark.unit -def test_deprecation_same_major_previous_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"), pytest.warns( - match="This feature is marked for removal in v2.1" - ): - fail_at_version(2, 1)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(2, 1)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(2, 1)(noop)() - - -@pytest.mark.unit -def test_deprecation_same_major_same_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"), pytest.warns( - match="This feature is marked for removal in v2.2" - ): - fail_at_version(2, 2)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(2, 2)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"), pytest.raises(_pytest.outcomes.Failed): - fail_at_version(2, 2)(noop)() - - -@pytest.mark.unit -def test_deprecation_same_major_later_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"): - assert fail_at_version(2, 3)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"): - assert fail_at_version(2, 3)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"): - assert fail_at_version(2, 3)(noop)() - - -@pytest.mark.unit -def test_deprecation_later_major_previous_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"): - assert fail_at_version(3, 1)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"): - assert fail_at_version(3, 1)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"): - assert fail_at_version(3, 1)(noop)() - - -@pytest.mark.unit -def test_deprecation_later_major_same_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"): - assert fail_at_version(3, 2)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"): - assert fail_at_version(3, 2)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"): - assert fail_at_version(3, 2)(noop)() - - -@pytest.mark.unit -def test_deprecation_later_major_later_minor(): - with mock.patch.object(conftest, "haystack_version", "2.2.2-rc0"): - assert fail_at_version(3, 3)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2rc1"): - assert fail_at_version(3, 3)(noop)() - - with mock.patch.object(conftest, "haystack_version", "2.2.2"): - assert fail_at_version(3, 3)(noop)() - - -@pytest.mark.unit -def test_convert_txt_files_to_docs(samples_path): - pdf_samples_path = samples_path / "docs" - documents = convert_files_to_docs( - dir_path=(pdf_samples_path).absolute(), clean_func=clean_wiki_text, split_paragraphs=True - ) - assert documents and len(documents) > 0 - - -@pytest.mark.unit -def test_convert_docx_files_to_docs(samples_path): - pdf_samples_path = samples_path / "docx" - documents = convert_files_to_docs( - dir_path=(pdf_samples_path).absolute(), clean_func=clean_wiki_text, split_paragraphs=True - ) - assert documents and len(documents) > 0 - - -def test_convert_pdf_files_to_docs(samples_path): - pdf_samples_path = samples_path / "pdf" - documents = convert_files_to_docs( - dir_path=(pdf_samples_path).absolute(), clean_func=clean_wiki_text, split_paragraphs=True - ) - assert documents and len(documents) > 0 - - -@pytest.mark.unit -def test_convert_list_of_file_paths_to_docs(sample_txt_file_paths_list): - documents = convert_files_to_docs( - file_paths=sample_txt_file_paths_list, clean_func=clean_wiki_text, split_paragraphs=True - ) - assert documents and len(documents) > 0 - - -@pytest.mark.unit -def test_convert_dirpath_and_file_paths_list_to_docs(samples_path, sample_txt_file_paths_list): - docx_samples_path = samples_path / "docx" - documents = convert_files_to_docs( - dir_path=docx_samples_path, - file_paths=sample_txt_file_paths_list, - clean_func=clean_wiki_text, - split_paragraphs=True, - ) - assert documents and len(documents) > 0 - - -@pytest.mark.unit -def test_convert_with_no_dirpath_or_file_paths(): - with pytest.raises(ValueError): - convert_files_to_docs() - - -@pytest.mark.unit -def test_get_filename_extension_from_url_without_params_zip(): - url = "http://www.mysite.com/resources/myfile.zip" - file_name, extension = get_filename_extension_from_url(url) - assert extension == "zip" - assert file_name == "myfile" - - -@pytest.mark.unit -def test_get_filename_extension_from_url_with_params_zip(): - url = "https:/.s3..amazonaws.com/filename.zip?response-content-disposition=inline&X-Amz-Security-Token=&X-Amz-Algorithm=&X-Amz-Date=&X-Amz-SignedHeaders=host&X-Amz-Expires=&X-Amz-Credential=&X-Amz-Signature=" - file_name, extension = get_filename_extension_from_url(url) - assert extension == "zip" - assert file_name == "filename" - - -@pytest.mark.unit -def test_get_filename_extension_from_url_with_params_xz(): - url = "https:/.s3..amazonaws.com/filename.tar.xz?response-content-disposition=inline&X-Amz-Security-Token=&X-Amz-Algorithm=&X-Amz-Date=&X-Amz-SignedHeaders=host&X-Amz-Expires=&X-Amz-Credential=&X-Amz-Signature=" - file_name, extension = get_filename_extension_from_url(url) - assert extension == "xz" - assert file_name == "filename.tar" - - -@pytest.mark.tika -def test_tika_convert_files_to_docs(samples_path): - documents = tika_convert_files_to_docs(dir_path=samples_path, clean_func=clean_wiki_text, split_paragraphs=True) - assert documents and len(documents) > 0 - - -@pytest.mark.tika -def test_tika_convert_list_of_file_paths_to_docs(sample_txt_file_paths_list): - documents = tika_convert_files_to_docs( - file_paths=sample_txt_file_paths_list, clean_func=clean_wiki_text, split_paragraphs=True - ) - assert documents and len(documents) > 0 - - -@pytest.mark.unit -def test_calculate_context_similarity_on_parts_of_whole_document(sample_context): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - for i in range(len(whole_document) - context_size): - partial_context = whole_document[i : i + context_size] - score = calculate_context_similarity(partial_context, whole_document, min_length=min_length) - assert score == 100.0 - - -@pytest.mark.unit -def test_calculate_context_similarity_on_parts_of_whole_document_different_case(sample_context): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - for i in range(len(whole_document) - context_size): - partial_context = whole_document[i : i + context_size].lower() - score = calculate_context_similarity(partial_context, whole_document, min_length=min_length) - assert score == 100.0 - - -@pytest.mark.unit -def test_calculate_context_similarity_on_parts_of_whole_document_different_whitesapce(sample_context): - whole_document = sample_context - words = whole_document.split() - min_length = 100 - context_word_size = 20 - for i in range(len(words) - context_word_size): - partial_context = "\n\t\t\t".join(words[i : i + context_word_size]) - score = calculate_context_similarity(partial_context, whole_document, min_length=min_length) - assert score == 100.0 - - -@pytest.mark.unit -def test_calculate_context_similarity_min_length(sample_context): - whole_document = sample_context - min_length = 100 - context_size = min_length - 1 - for i in range(len(whole_document) - context_size): - partial_context = whole_document[i : i + context_size] - score = calculate_context_similarity(partial_context, whole_document, min_length=min_length) - assert score == 0.0 - - -@pytest.mark.unit -def test_calculate_context_similarity_on_partially_overlapping_contexts(sample_context): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - stride = context_size // 2 - for i in range(len(whole_document) - context_size - stride): - partial_context_1 = whole_document[i : i + context_size] - partial_context_2 = whole_document[i + stride : i + stride + context_size] - score = calculate_context_similarity(partial_context_1, partial_context_2, min_length=min_length) - assert score >= 65.0 - - -@pytest.mark.unit -def test_calculate_context_similarity_on_non_matching_contexts(sample_context): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - scores = [] - for i in range(len(whole_document) - context_size): - partial_context = whole_document[i : i + context_size // 2] + _get_random_chars(context_size // 2) - score = calculate_context_similarity(partial_context, whole_document, min_length=min_length) - scores.append(score) - for i in range(len(whole_document) - context_size): - partial_context = ( - _get_random_chars(context_size // 2) + whole_document[i + context_size // 2 : i + context_size] - ) - score = calculate_context_similarity(partial_context, whole_document, min_length=min_length) - scores.append(score) - accuracy = np.where(np.array(scores) < 65, 1, 0).mean() - assert accuracy > 0.99 - - -@pytest.mark.unit -def test_calculate_context_similarity_on_parts_of_whole_document_with_noise(sample_context): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - for i in range(len(whole_document) - context_size): - partial_context = _insert_noise(whole_document[i : i + context_size], 0.1) - score = calculate_context_similarity(partial_context, whole_document, min_length=min_length) - assert score >= 85.0 - - -@pytest.mark.unit -def test_calculate_context_similarity_on_partially_overlapping_contexts_with_noise(sample_context): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - stride = context_size // 2 - scores = [] - for i in range(len(whole_document) - context_size - stride): - partial_context_1 = whole_document[i : i + context_size] - partial_context_2 = _insert_noise(whole_document[i + stride : i + stride + context_size], 0.1) - score = calculate_context_similarity(partial_context_1, partial_context_2, min_length=min_length) - scores.append(score) - accuracy = np.where(np.array(scores) >= 65, 1, 0).mean() - assert accuracy > 0.99 - - -@pytest.mark.unit -def test_match_context_multi_process(sample_context, sample_context_2): - whole_document = sample_context[:300] - min_length = 100 - margin = 5 - context_size = min_length + margin - # Test a few different partial_contexts - partial_contexts = [whole_document[i : i + context_size] for i in [0, 50, len(whole_document) - context_size]] - for partial_context in partial_contexts: - candidates = (c for c in [("0", sample_context), ("1", sample_context_2)]) - results = match_context(partial_context, candidates, min_length=min_length, num_processes=2) - assert len(results) == 1 - id, score = results[0] - assert id == "0" - assert score == 100.0 - - -@pytest.mark.unit -def test_match_context_single_process(sample_context, sample_context_2): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - # Test a few different partial_contexts - partial_contexts = [whole_document[i : i + context_size] for i in [0, 300, len(whole_document) - context_size]] - for partial_context in partial_contexts: - candidates = (c for c in [("0", sample_context), ("1", sample_context_2)]) - results = match_context(partial_context, candidates, min_length=min_length, num_processes=1) - assert len(results) == 1 - id, score = results[0] - assert id == "0" - assert score == 100.0 - - -@pytest.mark.unit -def test_match_contexts_multi_process(sample_context, sample_context_2): - whole_document = sample_context - min_length = 100 - margin = 5 - context_size = min_length + margin - candidates = (c for c in [("0", sample_context), ("1", sample_context_2)]) - partial_contexts = [whole_document[i : i + context_size] for i in [0, 300, len(whole_document) - context_size]] - result_list = match_contexts(partial_contexts, candidates, min_length=min_length, num_processes=2) - assert len(result_list) == len(partial_contexts) - for results in result_list: - assert len(results) == 1 - id, score = results[0] - assert id == "0" - assert score == 100.0 - - -def _get_random_chars(size: int): - chars = np.random.choice( - list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZß?/.,;:-#äöüÄÖÜ+*~1234567890$€%&!§ "), size=size - ) - return "".join(list(chars)) - - -def _insert_noise(input: str, ratio): - size = int(ratio * len(input)) - insert_idxs = sorted(np.random.choice(range(len(input)), size=size, replace=False), reverse=True) - insert_chars = np.random.choice( - list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZß?/.,;:-#äöüÄÖÜ+*~1234567890$€%&!§"), size=size - ) - for idx, char in zip(insert_idxs, insert_chars): - input = input[:idx] + char + input[idx:] - return input - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_upload_file_to_deepset_cloud(caplog, samples_path): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/files", - json={"file_id": "abc"}, - status=200, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/files", - json={"file_id": "def"}, - status=200, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/files", - json={"file_id": "def"}, - status=200, - ) - - client = DeepsetCloud.get_file_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - file_paths = [ - samples_path / "docx/sample_docx.docx", - samples_path / "pdf/sample_pdf_1.pdf", - samples_path / "docs/doc_1.txt", - ] - metas = [{"file_id": "sample_docx.docx"}, {"file_id": "sample_pdf_1.pdf"}, {"file_id": "doc_1.txt"}] - with caplog.at_level(logging.INFO): - client.upload_files(file_paths=file_paths, metas=metas) - assert f"Successfully uploaded {len(file_paths)} files." in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_upload_file_to_deepset_cloud_file_fails(caplog, samples_path): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/files", - json={"file_id": "abc"}, - status=200, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/files", - json={"error": "my-error"}, - status=500, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/files", - json={"file_id": "def"}, - status=200, - ) - - client = DeepsetCloud.get_file_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - file_paths = [ - samples_path / "docx/sample_docx.docx", - samples_path / "pdf/sample_pdf_1.pdf", - samples_path / "docs/doc_1.txt", - ] - metas = [{"file_id": "sample_docx.docx"}, {"file_id": "sample_pdf_1.pdf"}, {"file_id": "doc_1.txt"}] - with caplog.at_level(logging.INFO): - client.upload_files(file_paths=file_paths, metas=metas) - assert "Successfully uploaded 2 files." in caplog.text - assert "Error uploading file" in caplog.text - assert "my-error" in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_delete_file_to_deepset_cloud(): - if MOCK_DC: - responses.add(method=responses.DELETE, url=f"{DC_API_ENDPOINT}/workspaces/default/files/abc", status=200) - - client = DeepsetCloud.get_file_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - client.delete_file(file_id="abc") - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_delete_all_file_to_deepset_cloud(): - if MOCK_DC: - responses.add(method=responses.DELETE, url=f"{DC_API_ENDPOINT}/workspaces/default/files", status=200) - - client = DeepsetCloud.get_file_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - client.delete_all_files() - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_list_files_on_deepset_cloud(): - if MOCK_DC: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/files", - json={ - "data": [ - { - "characters": -1, - "created_at": "2022-05-19T15:40:07.538162+00:00", - "file_id": "b6cdd48b-3db5-488b-a44d-4240c12a96d5", - "languages": [], - "meta": {}, - "name": "sample_pdf_1.pdf", - "params": {"id_hash_keys": ["content", "meta"]}, - "size": 44524, - "url": "/api/v1/workspaces/e282219f-19b2-41ff-927e-bda4e6e67418/files/b6cdd48b-3db5-488b-a44d-4240c12a96d5", - }, - { - "characters": -1, - "created_at": "2022-05-23T12:39:53.393716+00:00", - "file_id": "51e9c2af-5676-453d-9b71-db9a560ae266", - "languages": [], - "meta": {"file_id": "sample_pdf_2.pdf"}, - "name": "sample_pdf_2.pdf", - "params": {"id_hash_keys": ["content", "meta"]}, - "size": 26093, - "url": "/api/v1/workspaces/e282219f-19b2-41ff-927e-bda4e6e67418/files/51e9c2af-5676-453d-9b71-db9a560ae266", - }, - ], - "has_more": False, - "total": 2, - }, - status=200, - ) - - client = DeepsetCloud.get_file_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - files = list(client.list_files()) - assert len(files) == 2 - assert files[0]["name"] == "sample_pdf_1.pdf" - assert files[1]["name"] == "sample_pdf_2.pdf" - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_create_eval_run(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={"data": {"eval_run_name": "my-eval-run-1"}}, - status=200, - match=[ - matchers.json_params_matcher( - { - "name": "my-eval-run-1", - "pipeline_name": "my-pipeline-1", - "evaluation_set_name": "my-eval-set-1", - "eval_mode": 0, - "comment": "this is my first run", - "debug": False, - "tags": ["my-experiment-1"], - } - ) - ], - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={ - "data": [ - { - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "metrics": { - "integrated_exact_match": None, - "integrated_f1": None, - "integrated_sas": None, - "isolated_exact_match": None, - "isolated_f1": None, - "isolated_sas": None, - "mean_average_precision": None, - "mean_reciprocal_rank": None, - "normal_discounted_cummulative_gain": None, - "precision": None, - "recall_multi_hit": None, - "recall_single_hit": None, - }, - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": 1, - } - ], - "has_more": False, - "total": 1, - }, - status=200, - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", - json={ - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "metrics": { - "integrated_exact_match": None, - "integrated_f1": None, - "integrated_sas": None, - "isolated_exact_match": None, - "isolated_f1": None, - "isolated_sas": None, - "mean_average_precision": None, - "mean_reciprocal_rank": None, - "normal_discounted_cummulative_gain": None, - "precision": None, - "recall_multi_hit": None, - "recall_single_hit": None, - }, - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": 1, - }, - status=200, - ) - - client = DeepsetCloud.get_eval_run_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - client.create_eval_run( - eval_run_name="my-eval-run-1", - pipeline_config_name="my-pipeline-1", - evaluation_set="my-eval-set-1", - eval_mode="integrated", - comment="this is my first run", - tags=["my-experiment-1"], - ) - - runs = client.get_eval_runs() - assert len(runs) == 1 - assert runs[0]["name"] == "my-eval-run-1" - assert runs[0]["tags"] == ["my-experiment-1"] - assert runs[0]["comment"] == "this is my first run" - assert runs[0]["parameters"]["pipeline_name"] == "my-pipeline-1" - assert runs[0]["parameters"]["evaluation_set_name"] == "my-eval-set-1" - - run = client.get_eval_run("my-eval-run-1") - assert run["name"] == "my-eval-run-1" - assert run["tags"] == ["my-experiment-1"] - assert run["comment"] == "this is my first run" - assert run["parameters"]["pipeline_name"] == "my-pipeline-1" - assert run["parameters"]["evaluation_set_name"] == "my-eval-set-1" - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_update_eval_run(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={"data": {"eval_run_name": "my-eval-run-1"}}, - status=200, - match=[ - matchers.json_params_matcher( - { - "name": "my-eval-run-1", - "pipeline_name": "my-pipeline-1", - "evaluation_set_name": "my-eval-set-1", - "eval_mode": 0, - "comment": "this is my first run", - "debug": False, - "tags": ["my-experiment-1"], - } - ) - ], - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", - json={ - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "metrics": { - "integrated_exact_match": None, - "integrated_f1": None, - "integrated_sas": None, - "isolated_exact_match": None, - "isolated_f1": None, - "isolated_sas": None, - "mean_average_precision": None, - "mean_reciprocal_rank": None, - "normal_discounted_cummulative_gain": None, - "precision": None, - "recall_multi_hit": None, - "recall_single_hit": None, - }, - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": "CREATED", - }, - status=200, - ) - - responses.add( - method=responses.PATCH, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", - json={"data": {"eval_run_name": "my-eval-run-1"}}, - status=200, - match=[ - matchers.json_params_matcher( - {"pipeline_name": "my-pipeline-2", "comment": "this is my first run with second pipeline"} - ) - ], - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", - json={ - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run with second pipeline", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "metrics": { - "integrated_exact_match": None, - "integrated_f1": None, - "integrated_sas": None, - "isolated_exact_match": None, - "isolated_f1": None, - "isolated_sas": None, - "mean_average_precision": None, - "mean_reciprocal_rank": None, - "normal_discounted_cummulative_gain": None, - "precision": None, - "recall_multi_hit": None, - "recall_single_hit": None, - }, - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-2", - }, - "status": "CREATED", - }, - status=200, - ) - - client = DeepsetCloud.get_eval_run_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - client.create_eval_run( - eval_run_name="my-eval-run-1", - pipeline_config_name="my-pipeline-1", - evaluation_set="my-eval-set-1", - eval_mode="integrated", - comment="this is my first run", - tags=["my-experiment-1"], - ) - - run = client.get_eval_run("my-eval-run-1") - assert run["name"] == "my-eval-run-1" - assert run["tags"] == ["my-experiment-1"] - assert run["comment"] == "this is my first run" - assert run["parameters"]["pipeline_name"] == "my-pipeline-1" - assert run["parameters"]["evaluation_set_name"] == "my-eval-set-1" - - client.update_eval_run( - eval_run_name="my-eval-run-1", - pipeline_config_name="my-pipeline-2", - comment="this is my first run with second pipeline", - ) - - run = client.get_eval_run("my-eval-run-1") - assert run["name"] == "my-eval-run-1" - assert run["tags"] == ["my-experiment-1"] - assert run["comment"] == "this is my first run with second pipeline" - assert run["parameters"]["pipeline_name"] == "my-pipeline-2" - assert run["parameters"]["evaluation_set_name"] == "my-eval-set-1" - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_start_eval_run(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={"data": {"eval_run_name": "my-eval-run-1"}}, - status=200, - match=[ - matchers.json_params_matcher( - { - "name": "my-eval-run-1", - "pipeline_name": "my-pipeline-1", - "evaluation_set_name": "my-eval-set-1", - "eval_mode": 0, - "comment": "this is my first run", - "debug": False, - "tags": ["my-experiment-1"], - } - ) - ], - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", - json={ - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "metrics": { - "integrated_exact_match": None, - "integrated_f1": None, - "integrated_sas": None, - "isolated_exact_match": None, - "isolated_f1": None, - "isolated_sas": None, - "mean_average_precision": None, - "mean_reciprocal_rank": None, - "normal_discounted_cummulative_gain": None, - "precision": None, - "recall_multi_hit": None, - "recall_single_hit": None, - }, - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": "CREATED", - }, - status=200, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1/start", - json={}, - status=200, - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", - json={ - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "metrics": { - "integrated_exact_match": None, - "integrated_f1": None, - "integrated_sas": None, - "isolated_exact_match": None, - "isolated_f1": None, - "isolated_sas": None, - "mean_average_precision": None, - "mean_reciprocal_rank": None, - "normal_discounted_cummulative_gain": None, - "precision": None, - "recall_multi_hit": None, - "recall_single_hit": None, - }, - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": "STARTED", - }, - status=200, - ) - - client = DeepsetCloud.get_eval_run_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - client.create_eval_run( - eval_run_name="my-eval-run-1", - pipeline_config_name="my-pipeline-1", - evaluation_set="my-eval-set-1", - eval_mode="integrated", - comment="this is my first run", - tags=["my-experiment-1"], - ) - - run = client.get_eval_run("my-eval-run-1") - assert run["name"] == "my-eval-run-1" - assert run["tags"] == ["my-experiment-1"] - assert run["comment"] == "this is my first run" - assert run["parameters"]["pipeline_name"] == "my-pipeline-1" - assert run["parameters"]["evaluation_set_name"] == "my-eval-set-1" - assert run["status"] == "CREATED" - - client.start_eval_run(eval_run_name="my-eval-run-1") - - run = client.get_eval_run("my-eval-run-1") - assert run["name"] == "my-eval-run-1" - assert run["tags"] == ["my-experiment-1"] - assert run["comment"] == "this is my first run" - assert run["parameters"]["pipeline_name"] == "my-pipeline-1" - assert run["parameters"]["evaluation_set_name"] == "my-eval-set-1" - assert run["status"] == "STARTED" - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_fetch_predictions_for_node(): - mock_prediction = {} - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={"data": {"eval_run_name": "my-eval-run-1"}}, - status=200, - match=[ - matchers.json_params_matcher( - { - "name": "my-eval-run-1", - "pipeline_name": "my-pipeline-1", - "evaluation_set_name": "my-eval-set-1", - "eval_mode": 0, - "comment": "this is my first run", - "debug": False, - "tags": ["my-experiment-1"], - } - ) - ], - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={ - "data": [ - { - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "eval_results": [ - { - "node_name": "AnswerNode", - "node_type": "answer_node", - "isolated_exact_match": 1.0, - "isolated_f1": 1.0, - "integrated_exact_match": 0, - "integrated_f1": 0, - } - ], - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": 1, - } - ], - "has_more": False, - "total": 1, - }, - status=200, - ) - - mock_prediction = { - "prediction_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "created_at": "2022-08-03T13:42:58.968Z", - "updated_at": "2022-08-03T13:42:58.968Z", - "eval_node_result_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "eval_mode": "Evaluation mode", - "query": "What?", - "context": "This", - "rank": 0, - "document_id": "0", - "filters": [{}], - "labels": [ - { - "label_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "query": "What?", - "answer": "This", - "answer_start": 0, - "answer_end": 3, - "meta": {}, - "context": "This", - "external_file_name": "this_file.txt", - "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa7", - "state": "MATCHED", - "candidates": None, - "answer_exact_match": True, - "f1": 1.0, - "document_id_match": True, - "answer_match": "Answer match", - "context_similarity": "Context similarity", - } - ], - "prediction_type": "answer", - "answer": "This", - "exact_match": True, - "f1": 1.0, - "exact_match_context_scope": True, - "f1_document_id_scope": 0, - "exact_match_document_id_and_context_scope": True, - "f1_context_scope": 0, - "f1_document_id_and_context_scope": 0, - "answer_start": "Answer start", - "answer_end": "Answer end", - } - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1/nodes/AnswerNode/predictions?page_number=1", - json={"data": [mock_prediction], "has_more": False, "total": 1}, - status=200, - ) - - client = DeepsetCloud.get_eval_run_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - client.create_eval_run( - eval_run_name="my-eval-run-1", - pipeline_config_name="my-pipeline-1", - evaluation_set="my-eval-set-1", - eval_mode="integrated", - comment="this is my first run", - tags=["my-experiment-1"], - ) - - predictions = client.get_eval_run_predictions(eval_run_name="my-eval-run-1", node_name="AnswerNode") - - assert len(predictions) == 1 - assert predictions[0] == mock_prediction - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_delete_eval_run(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={"data": {"eval_run_name": "my-eval-run-1"}}, - status=200, - match=[ - matchers.json_params_matcher( - { - "name": "my-eval-run-1", - "pipeline_name": "my-pipeline-1", - "evaluation_set_name": "my-eval-set-1", - "eval_mode": 0, - "comment": "this is my first run", - "debug": False, - "tags": ["my-experiment-1"], - } - ) - ], - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={ - "data": [ - { - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "metrics": { - "integrated_exact_match": None, - "integrated_f1": None, - "integrated_sas": None, - "isolated_exact_match": None, - "isolated_f1": None, - "isolated_sas": None, - "mean_average_precision": None, - "mean_reciprocal_rank": None, - "normal_discounted_cummulative_gain": None, - "precision": None, - "recall_multi_hit": None, - "recall_single_hit": None, - }, - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": 1, - } - ], - "has_more": False, - "total": 1, - }, - status=200, - ) - - responses.add( - method=responses.DELETE, url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", status=204 - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={"data": [], "has_more": False, "total": 0}, - status=200, - ) - - client = DeepsetCloud.get_eval_run_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - client.create_eval_run( - eval_run_name="my-eval-run-1", - pipeline_config_name="my-pipeline-1", - evaluation_set="my-eval-set-1", - eval_mode="integrated", - comment="this is my first run", - tags=["my-experiment-1"], - ) - - runs = client.get_eval_runs() - assert len(runs) == 1 - - client.delete_eval_run("my-eval-run-1") - - runs = client.get_eval_runs() - assert len(runs) == 0 - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_upload_eval_set(caplog, samples_path): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/evaluation_sets/import", - json={"evaluation_set_id": "c2d06025-2c00-43b5-8f73-b81b12e63afc"}, - status=200, - ) - - client = DeepsetCloud.get_evaluation_set_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - with caplog.at_level(logging.INFO): - client.upload_evaluation_set(file_path=samples_path / "dc/matching_test_1.csv") - assert "Successfully uploaded evaluation set file" in caplog.text - assert "You can access it now under evaluation set 'matching_test_1.csv'." in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_upload_existing_eval_set(caplog, samples_path): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/evaluation_sets/import", - json={"errors": ["Evaluation set with the same name already exists."]}, - status=409, - ) - - client = DeepsetCloud.get_evaluation_set_client(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - with caplog.at_level(logging.INFO): - client.upload_evaluation_set(file_path=samples_path / "dc/matching_test_1.csv") - assert "Successfully uploaded evaluation set file" not in caplog.text - assert "You can access it now under evaluation set 'matching_test_1.csv'." not in caplog.text - assert "Evaluation set with the same name already exists." in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_get_eval_run_results(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs", - json={"data": {"eval_run_name": "my-eval-run-1"}}, - status=200, - match=[ - matchers.json_params_matcher( - { - "name": "my-eval-run-1", - "pipeline_name": "my-pipeline-1", - "evaluation_set_name": "my-eval-set-1", - "eval_mode": 0, - "comment": "this is my first run", - "debug": False, - "tags": ["my-experiment-1"], - } - ) - ], - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1", - json={ - "created_at": "2022-05-24T12:13:16.445857+00:00", - "eval_mode": 0, - "eval_run_id": "17875c63-7c07-42d8-bb01-4fcd95ce113c", - "name": "my-eval-run-1", - "comment": "this is my first run", - "tags": ["my-experiment-1"], - "eval_run_labels": [], - "logs": {}, - "eval_results": [ - { - "node_name": "AnswerNode", - "node_type": "answer_node", - "isolated_exact_match": 1.0, - "isolated_f1": 1.0, - "integrated_exact_match": 0, - "integrated_f1": 0, - } - ], - "parameters": { - "debug": False, - "eval_mode": 0, - "evaluation_set_name": "my-eval-set-1", - "pipeline_name": "my-pipeline-1", - }, - "status": 1, - }, - status=200, - ) - - mock_prediction = { - "prediction_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "created_at": "2022-08-03T13:42:58.968Z", - "updated_at": "2022-08-03T13:42:58.968Z", - "eval_node_result_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "eval_mode": "Evaluation mode", - "query": "What?", - "context": "This", - "rank": 0, - "document_id": "0", - "filters": [{}], - "labels": [ - { - "label_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "query": "What?", - "answer": "This", - "answer_start": 0, - "answer_end": 3, - "meta": {}, - "context": "This", - "external_file_name": "this_file.txt", - "file_id": "3fa85f64-5717-4562-b3fc-2c963f66afa7", - "state": "MATCHED", - "candidates": None, - "answer_exact_match": True, - "f1": 1.0, - "document_id_match": True, - "answer_match": True, - "context_similarity": 1.0, - } - ], - "prediction_type": "answer", - "answer": "This", - "exact_match": True, - "f1": 1.0, - "exact_match_context_scope": True, - "f1_document_id_scope": 0.0, - "exact_match_document_id_and_context_scope": True, - "f1_context_scope": 0.0, - "f1_document_id_and_context_scope": 0.0, - "answer_start": 1, - "answer_end": 10, - } - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/eval_runs/my-eval-run-1/nodes/AnswerNode/predictions?page_number=1", - json={"data": [mock_prediction], "has_more": False, "total": 1}, - status=200, - ) - - experiments_client = DeepsetCloudExperiments() - eval_run_results = experiments_client.get_run_result( - eval_run_name="my-eval-run-1", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - assert "AnswerNode" in eval_run_results - - node_results = eval_run_results["AnswerNode"] - assert isinstance(node_results, pd.DataFrame) - - first_result = node_results.iloc[0] - assert first_result["exact_match"] == True - assert first_result["answer"] == "This" - - -def test_secure_model_loading(monkeypatch, caplog): - caplog.set_level(logging.INFO) - monkeypatch.setenv("TORCH_FORCE_WEIGHTS_ONLY_LOAD", "0") - - # now testing if just importing haystack is enough to enable secure loading of pytorch models - import haystack - - importlib.reload(haystack) - assert "already set to" in caplog.text - - -class TestAggregateLabels: - @pytest.fixture - def standard_labels(self) -> List[Label]: - return [ - Label( - id="standard", - query="question", - answer=Answer(answer="answer1", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - # same label should be ignored - Label( - id="standard", - query="question", - answer=Answer(answer="answer1", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - # different answer in same doc - Label( - id="diff-answer-same-doc", - query="question", - answer=Answer(answer="answer2", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - # answer in different doc - Label( - id="diff-answer-diff-doc", - query="question", - answer=Answer(answer="answer3", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some other", id="333"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - # no_answer - Label( - id="no-answer", - query="question", - answer=Answer(answer="", offsets_in_document=[Span(start=0, end=0)]), - document=Document(content="some", id="777"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - # no_answer in doc with other answer - Label( - id="no-answer-of-doc-with-other-answer", - query="question", - answer=Answer(answer="", offsets_in_document=[Span(start=0, end=0)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - # negative label - Label( - id="negative", - query="question", - answer=Answer(answer="answer5", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ), - ] - - @pytest.fixture - def filter_meta_labels(self) -> List[Label]: - return [ - Label( - id="standard", - query="question", - answer=Answer(answer="answer1", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - filters={"from_filter": 123}, - meta={"from_meta": ["123"]}, - ), - # different answer in same doc - Label( - id="diff-answer-same-doc", - query="question", - answer=Answer(answer="answer2", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - filters={"from_filter": 123}, - meta={"from_meta": ["123"]}, - ), - # answer in different doc - Label( - id="diff-answer-diff-doc", - query="question", - answer=Answer(answer="answer3", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some other", id="333"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - filters={"from_filter": 333}, - meta={"from_meta": ["333"]}, - ), - # 'no answer' - Label( - id="no-answer", - query="question", - answer=Answer(answer="", offsets_in_document=[Span(start=0, end=0)]), - document=Document(content="some", id="777"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - filters={"from_filter": 777}, - meta={"from_meta": ["777"]}, - ), - # different id, meta, same filters - Label( - id="5-888", - query="question", - answer=Answer(answer="answer5", offsets_in_document=[Span(start=12, end=18)]), - document=Document(content="some", id="123"), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - filters={"from_filter": 123}, - meta={"from_meta": ["888"]}, - ), - ] - - @pytest.mark.unit - def test_label_aggregation(self, standard_labels: List[Label]): - multi_labels = aggregate_labels(standard_labels) - assert len(multi_labels) == 1 - assert len(multi_labels[0].labels) == 6 - assert len(multi_labels[0].answers) == 4 - assert len(multi_labels[0].document_ids) == 4 - assert multi_labels[0].no_answer is False - - @pytest.mark.unit - def test_label_aggregation_drop_negatives(self, standard_labels: List[Label]): - multi_labels = aggregate_labels(standard_labels, drop_negative_labels=True) - assert len(multi_labels) == 1 - assert len(multi_labels[0].labels) == 5 - assert len(multi_labels[0].answers) == 3 - assert "5-negative" not in [l.id for l in multi_labels[0].labels] - assert len(multi_labels[0].document_ids) == 3 - assert multi_labels[0].no_answer is False - - @pytest.mark.unit - def test_label_aggregation_drop_no_answers(self, standard_labels: List[Label]): - multi_labels = aggregate_labels(standard_labels, drop_no_answers=True) - assert len(multi_labels) == 1 - assert len(multi_labels[0].labels) == 4 - assert len(multi_labels[0].answers) == 4 - assert len(multi_labels[0].document_ids) == 4 - assert multi_labels[0].no_answer is False - - @pytest.mark.unit - def test_label_aggregation_drop_negatives_and_no_answers(self, standard_labels: List[Label]): - multi_labels = aggregate_labels(standard_labels, drop_negative_labels=True, drop_no_answers=True) - assert len(multi_labels) == 1 - assert len(multi_labels[0].labels) == 3 - assert len(multi_labels[0].answers) == 3 - assert len(multi_labels[0].document_ids) == 3 - assert multi_labels[0].no_answer is False - - @pytest.mark.unit - def test_label_aggregation_closed_domain(self, standard_labels: List[Label]): - multi_labels = aggregate_labels(standard_labels, add_closed_domain_filter=True) - assert len(multi_labels) == 3 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [4, 1, 1] - assert len(multi_labels[0].answers) == len(multi_labels[0].document_ids) - assert multi_labels[0].no_answer is False - assert multi_labels[1].no_answer is False - assert multi_labels[2].no_answer is True - for ml in multi_labels: - assert "_id" in ml.filters - - @pytest.mark.unit - def test_label_aggregation_closed_domain_drop_negatives(self, standard_labels: List[Label]): - multi_labels = aggregate_labels(standard_labels, add_closed_domain_filter=True, drop_negative_labels=True) - assert len(multi_labels) == 3 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [3, 1, 1] - assert len(multi_labels[0].answers) == len(multi_labels[0].document_ids) - assert multi_labels[0].no_answer is False - assert multi_labels[1].no_answer is False - assert multi_labels[2].no_answer is True - for ml in multi_labels: - assert "_id" in ml.filters - - @pytest.mark.unit - def test_aggregate_labels_filter_aggregations_with_no_sequence_values(self, filter_meta_labels: List[Label]): - multi_labels = aggregate_labels(filter_meta_labels) - assert len(multi_labels) == 3 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [3, 1, 1] - assert len(multi_labels[0].answers) == len(multi_labels[0].document_ids) - for multi_label in multi_labels: - for l in multi_label.labels: - assert "from_filter" in l.filters - assert multi_label.filters == l.filters - - @pytest.mark.unit - def test_aggregate_labels_filter_aggregations_with_string_values(self, filter_meta_labels: List[Label]): - for label in filter_meta_labels: - label.filters["from_filter"] = str(label.filters["from_filter"]) - - multi_labels = aggregate_labels(filter_meta_labels) - assert len(multi_labels) == 3 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [3, 1, 1] - assert len(multi_labels[0].answers) == len(multi_labels[0].document_ids) - for multi_label in multi_labels: - for l in multi_label.labels: - assert "from_filter" in l.filters - assert multi_label.filters == l.filters - - @pytest.mark.unit - def test_aggregate_labels_filter_aggregations_with_list_values(self, filter_meta_labels: List[Label]): - for label in filter_meta_labels: - label.filters["from_filter"] = [label.filters["from_filter"], "some_other_value"] - - multi_labels = aggregate_labels(filter_meta_labels) - assert len(multi_labels) == 3 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [3, 1, 1] - assert len(multi_labels[0].answers) == len(multi_labels[0].document_ids) - for multi_label in multi_labels: - for l in multi_label.labels: - assert "from_filter" in l.filters - assert multi_label.filters == l.filters - - @pytest.mark.unit - def test_aggregate_labels_filter_aggregations_with_no_sequence_values_closed_domain( - self, filter_meta_labels: List[Label] - ): - multi_labels = aggregate_labels(filter_meta_labels, add_closed_domain_filter=True) - assert len(multi_labels) == 3 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [3, 1, 1] - assert len(multi_labels[0].answers) == len(multi_labels[0].document_ids) - for multi_label in multi_labels: - for l in multi_label.labels: - assert "from_filter" in l.filters - assert "_id" in l.filters - assert multi_label.filters == l.filters - - @pytest.mark.unit - def test_aggregate_labels_meta_aggregations(self, filter_meta_labels: List[Label]): - multi_labels = aggregate_labels(filter_meta_labels, add_meta_filters="from_meta") - assert len(multi_labels) == 4 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [2, 1, 1, 1] - for multi_label in multi_labels: - for l in multi_label.labels: - assert "from_filter" in l.filters - assert l.filters["from_meta"] == l.meta["from_meta"] - assert multi_label.filters == l.filters - - @pytest.mark.unit - def test_aggregate_labels_meta_aggregations_closed_domain(self, filter_meta_labels: List[Label]): - multi_labels = aggregate_labels(filter_meta_labels, add_closed_domain_filter=True, add_meta_filters="from_meta") - assert len(multi_labels) == 4 - label_counts = [len(ml.labels) for ml in multi_labels] - assert label_counts == [2, 1, 1, 1] - for multi_label in multi_labels: - for l in multi_label.labels: - assert "from_filter" in l.filters - assert l.filters["from_meta"] == l.meta["from_meta"] - assert "_id" in l.filters - assert multi_label.filters == l.filters - - -@pytest.mark.unit -def test_print_answers_run(): - with mock.patch("pprint.PrettyPrinter.pprint") as pprint: - query_string = "Who is the father of Arya Stark?" - run_result = { - "query": query_string, - "answers": [Answer(answer="Eddard", context="Eddard"), Answer(answer="Ned", context="Eddard")], - } - - print_answers(run_result, details="minimum") - - expected_pprint_string = f"Query: {query_string}" - pprint.assert_any_call(expected_pprint_string) - - expected_pprint_answers = [ - {"answer": answer.answer, "context": answer.context} # filtered fields for minimum - for answer in run_result["answers"] - ] - pprint.assert_any_call(expected_pprint_answers) - - -@pytest.mark.unit -def test_print_answers_run_batch(): - with mock.patch("pprint.PrettyPrinter.pprint") as pprint: - queries = ["Who is the father of Arya Stark?", "Who is the sister of Arya Stark?"] - answers = [ - [Answer(answer="Eddard", context="Eddard"), Answer(answer="Ned", context="Eddard")], - [Answer(answer="Sansa", context="Sansa")], - ] - run_batch_result = {"queries": queries, "answers": answers} - - print_answers(run_batch_result, details="minimum") - - for query in queries: - expected_pprint_string = f"Query: {query}" - pprint.assert_any_call(expected_pprint_string) - for answer_list in answers: - expected_pprint_answers = [ - {"answer": answer.answer, "context": answer.context} # filtered fields for minimum - for answer in answer_list - ] - pprint.assert_any_call(expected_pprint_answers) diff --git a/test/pipelines/__init__.py b/test/pipelines/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/pipelines/conftest.py b/test/pipelines/conftest.py deleted file mode 100644 index d47d57e2ad..0000000000 --- a/test/pipelines/conftest.py +++ /dev/null @@ -1,14 +0,0 @@ -import pytest - -from haystack.nodes import FARMReader - - -@pytest.fixture -def reader_without_normalized_scores(): - return FARMReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", - use_gpu=False, - top_k_per_sample=5, - num_processes=0, - use_confidence_scores=False, - ) diff --git a/test/pipelines/test_eval.py b/test/pipelines/test_eval.py deleted file mode 100644 index 19b952c14d..0000000000 --- a/test/pipelines/test_eval.py +++ /dev/null @@ -1,2185 +0,0 @@ -from csv import DictWriter -import logging -from pathlib import Path -import pytest -import sys -import pandas as pd -from copy import deepcopy - -import responses -from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore -from haystack.nodes.answer_generator.openai import OpenAIAnswerGenerator -from haystack.nodes.preprocessor import PreProcessor -from haystack.nodes.prompt.prompt_node import PromptNode -from haystack.nodes.query_classifier.transformers import TransformersQueryClassifier -from haystack.nodes.retriever.dense import DensePassageRetriever -from haystack.nodes.retriever.sparse import BM25Retriever -from haystack.nodes.summarizer.transformers import TransformersSummarizer -from haystack.pipelines.base import Pipeline -from haystack.pipelines import ExtractiveQAPipeline, GenerativeQAPipeline, SearchSummarizationPipeline -from haystack.pipelines.standard_pipelines import ( - DocumentSearchPipeline, - FAQPipeline, - RetrieverQuestionGenerationPipeline, - TranslationWrapperPipeline, -) -from haystack.nodes.translator.transformers import TransformersTranslator -from haystack.schema import Answer, Document, EvaluationResult, Label, MultiLabel, Span, TableCell - - -@pytest.mark.skipif(sys.platform in ["win32", "cygwin"], reason="Causes OOM on windows github runner") -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever_with_docs", ["embedding"], indirect=True) -def test_summarizer_calculate_metrics( - document_store_with_docs: ElasticsearchDocumentStore, retriever_with_docs, eval_labels -): - document_store_with_docs.update_embeddings(retriever=retriever_with_docs) - summarizer = TransformersSummarizer(model_name_or_path="sshleifer/distill-pegasus-xsum-16-4", use_gpu=False) - pipeline = SearchSummarizationPipeline( - retriever=retriever_with_docs, summarizer=summarizer, return_in_answer_format=True - ) - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, params={"Retriever": {"top_k": 5}}, context_matching_min_length=10 - ) - - metrics = eval_result.calculate_metrics(document_scope="context") - - assert "Retriever" in eval_result - assert "Summarizer" in eval_result - assert len(eval_result) == 2 - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - assert metrics["Summarizer"]["mrr"] == 1.0 - assert metrics["Summarizer"]["map"] == 1.0 - assert metrics["Summarizer"]["recall_multi_hit"] == 1.0 - assert metrics["Summarizer"]["recall_single_hit"] == 1.0 - assert metrics["Summarizer"]["precision"] == 1.0 - assert metrics["Summarizer"]["ndcg"] == 1.0 - - -@pytest.mark.parametrize("document_store", ["elasticsearch", "faiss", "memory"], indirect=True) -@pytest.mark.parametrize("batch_size", [None, 20]) -def test_add_eval_data(document_store, batch_size, samples_path): - # add eval data (SQUAD format) - document_store.add_eval_data( - filename=samples_path / "squad" / "small.json", - doc_index=document_store.index, - label_index=document_store.label_index, - batch_size=batch_size, - ) - - assert document_store.get_document_count() == 87 - assert document_store.get_label_count() == 1214 - - # test documents - docs = document_store.get_all_documents(filters={"name": ["Normans"]}) - assert docs[0].meta["name"] == "Normans" - assert len(docs[0].meta.keys()) == 1 - - # test labels - labels = document_store.get_all_labels() - label = None - for l in labels: - if l.query == "In what country is Normandy located?": - label = l - break - assert label.answer.answer == "France" - assert label.no_answer == False - assert label.is_correct_answer == True - assert label.is_correct_document == True - assert label.query == "In what country is Normandy located?" - assert label.origin == "gold-label" - assert label.answer.offsets_in_document[0].start == 159 - assert ( - label.answer.context[label.answer.offsets_in_context[0].start : label.answer.offsets_in_context[0].end] - == "France" - ) - assert label.answer.document_ids == [label.document.id] - - # check combination - doc = document_store.get_document_by_id(label.document.id) - start = label.answer.offsets_in_document[0].start - end = label.answer.offsets_in_document[0].end - assert end == start + len(label.answer.answer) - assert doc.content[start:end] == "France" - - -@pytest.mark.parametrize("document_store", ["elasticsearch", "faiss", "memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -@pytest.mark.parametrize("use_confidence_scores", [True, False]) -def test_eval_reader(reader, document_store, use_confidence_scores, samples_path): - # add eval data (SQUAD format) - document_store.add_eval_data( - filename=samples_path / "squad" / "tiny.json", - doc_index=document_store.index, - label_index=document_store.label_index, - ) - assert document_store.get_document_count() == 2 - - reader.use_confidence_scores = use_confidence_scores - - # eval reader - reader_eval_results = reader.eval( - document_store=document_store, - label_index=document_store.label_index, - doc_index=document_store.index, - device="cpu", - ) - - if use_confidence_scores: - assert reader_eval_results["f1"] == 50 - assert reader_eval_results["EM"] == 50 - assert reader_eval_results["top_n_accuracy"] == 100.0 - else: - assert reader_eval_results["f1"] == 50 - assert reader_eval_results["EM"] == 50 - assert reader_eval_results["top_n_accuracy"] == 100.0 - - -# using ElasticsearchDocumentStore, since InMemoryDocumentStore doesn't return meaningful BM25 scores when there are very few documents -@pytest.mark.elasticsearch -@pytest.mark.parametrize("document_store", ["elasticsearch"], indirect=True) -@pytest.mark.parametrize("open_domain", [True, False]) -@pytest.mark.parametrize("retriever", ["bm25"], indirect=True) -def test_eval_elastic_retriever(document_store, open_domain, retriever, samples_path): - # add eval data (SQUAD format) - document_store.add_eval_data( - filename=samples_path / "squad" / "tiny.json", - doc_index=document_store.index, - label_index=document_store.label_index, - ) - assert document_store.get_document_count() == 2 - - # eval retriever - results = retriever.eval( - top_k=1, label_index=document_store.label_index, doc_index=document_store.index, open_domain=open_domain - ) - assert results["recall"] == 1.0 - assert results["mrr"] == 1.0 - if not open_domain: - assert results["map"] == 1.0 - - -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -@pytest.mark.parametrize("retriever", ["bm25"], indirect=True) -def test_eval_pipeline(document_store, reader, retriever, samples_path): - # add eval data (SQUAD format) - document_store.add_eval_data( - filename=samples_path / "squad" / "tiny.json", - doc_index=document_store.index, - label_index=document_store.label_index, - ) - assert document_store.get_document_count() == 2 - - p = Pipeline() - p.add_node(component=retriever, name="Retriever", inputs=["Query"]) - p.add_node(component=reader, name="Reader", inputs=["Retriever"]) - - labels = document_store.get_all_labels_aggregated(drop_negative_labels=True, drop_no_answers=False) - - metrics_vanilla = p.eval(labels=labels, params={"Retriever": {"top_k": 5}}).calculate_metrics() - metrics_sas_sentence_transformers = p.eval( - labels=labels, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - ).calculate_metrics() - metrics_sas_cross_encoder = p.eval( - labels=labels, params={"Retriever": {"top_k": 5}}, sas_model_name_or_path="cross-encoder/stsb-TinyBERT-L-4" - ).calculate_metrics() - - assert metrics_vanilla["Retriever"]["recall_single_hit"] == 1.0 - assert metrics_sas_sentence_transformers["Reader"]["f1"] == pytest.approx(0.75) - assert metrics_sas_sentence_transformers["Reader"]["exact_match"] == 0.5 - assert metrics_sas_sentence_transformers["Reader"]["sas"] == pytest.approx(0.87586, 1e-4) - assert metrics_sas_sentence_transformers["Reader"]["exact_match"] == metrics_vanilla["Reader"]["exact_match"] - assert metrics_sas_cross_encoder["Reader"]["sas"] == pytest.approx(0.71063, 1e-4) - - -@pytest.mark.parametrize("document_store", ["elasticsearch", "faiss", "memory"], indirect=True) -def test_eval_data_split_word(document_store, samples_path): - # splitting by word - preprocessor = PreProcessor( - clean_empty_lines=False, - clean_whitespace=False, - clean_header_footer=False, - split_by="word", - split_length=4, - split_overlap=0, - split_respect_sentence_boundary=False, - ) - - document_store.add_eval_data( - filename=samples_path / "squad" / "tiny.json", - doc_index=document_store.index, - label_index=document_store.label_index, - preprocessor=preprocessor, - ) - labels = document_store.get_all_labels_aggregated() - docs = document_store.get_all_documents() - assert len(docs) == 5 - assert len(set(labels[0].document_ids)) == 2 - - -@pytest.mark.parametrize("document_store", ["elasticsearch", "faiss", "memory"], indirect=True) -def test_eval_data_split_passage(document_store, samples_path): - # splitting by passage - preprocessor = PreProcessor( - clean_empty_lines=False, - clean_whitespace=False, - clean_header_footer=False, - split_by="passage", - split_length=1, - split_overlap=0, - split_respect_sentence_boundary=False, - ) - - document_store.add_eval_data( - filename=samples_path / "squad" / "tiny_passages.json", - doc_index=document_store.index, - label_index=document_store.label_index, - preprocessor=preprocessor, - ) - docs = document_store.get_all_documents() - assert len(docs) == 2 - assert len(docs[1].content) == 56 - - -NO_ANSWER_EVAL_LABELS = [ - MultiLabel( - labels=[ - Label( - query="Why does probability work?", - document=Document(""), - answer=None, - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ) -] - -DOC_SEARCH_EVAL_LABELS = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=None, - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=None, - document=Document( - id="something_else", content_type="text", content="My name is Carla and I live in Munich" - ), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ) - ] - ), -] - -DOC_SEARCH_ID_EVAL_LABELS = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=None, - document=Document(id="a0747b83aea0b60c4b114b15476dd32d", content_type="text", content=""), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=None, - document=Document(id="something_else", content_type="text", content=""), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ) - ] - ), -] - -FILE_SEARCH_EVAL_LABELS = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=None, - document=Document(content_type="text", content="", meta={"name": "filename1"}), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=None, - document=Document(content_type="text", content="", meta={"name": "filename2"}), - is_correct_answer=False, - is_correct_document=True, - origin="gold-label", - ) - ] - ), -] - -EVAL_TABLE_LABELS = [ - MultiLabel( - labels=[ - Label( - query="How old is Brad Pitt?", - answer=Answer(answer="56", offsets_in_context=[TableCell(1, 2)]), - document=Document( - id="a044cf3fb8aade03a12399c7a2fe9a6b", - content_type="table", - content=pd.DataFrame( - columns=["Actors", "Age", "Number of movies"], - data=[ - ["Brad Pitt", "56", "87"], - ["Leonardo Di Caprio", "45", "53"], - ["George Clooney", "59", "69"], - ], - ), - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - Label( # Label with different doc but same answer and query - query="How old is Brad Pitt?", - answer=Answer(answer="56", offsets_in_context=[TableCell(4, 5)]), - document=Document( - id="a044cf3fb8aade03a12399c7a2fe9a6b", - content_type="table", - content=pd.DataFrame( - columns=["Actors", "Age", "Number of movies"], - data=[["Beyonce", "45", "53"], ["Brad Pitt", "56", "87"], ["Jane Doe", "59", "69"]], - ), - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ), - ] - ), - MultiLabel( - labels=[ - Label( - query="To which state does Spikeroog belong?", - answer=Answer(answer="Lower Saxony", offsets_in_context=[TableCell(7, 8)]), - document=Document( - id="b044cf3fb8aade03a12399c7a2fe9a6c", - content_type="table", - content=pd.DataFrame( - columns=["0", "1"], - data=[ - ["Area", "18.25 km2 (7.05 sq mi)"], - ["Population", "794"], - ["Country", "Germany"], - ["State", "Lower Saxony"], - ["District", "Wittmund"], - ], - ), - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), -] - - -@pytest.mark.skip(reason="Should be an end-to-end test since it uses model inferencing") -@pytest.mark.integration -@pytest.mark.parametrize("document_store", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever", ["table_text_retriever"], indirect=True) -@pytest.mark.parametrize("table_reader_and_param", ["tapas_small"], indirect=True) -@pytest.mark.embedding_dim(512) -def test_table_qa_eval(table_reader_and_param, document_store, retriever): - docs = [] - for multi_label in EVAL_TABLE_LABELS: - for label in multi_label.labels: - docs.append(label.document) - - assert len(docs) == 3 - - document_store.write_documents(docs) - document_store.update_embeddings(retriever=retriever) - - table_reader, _ = table_reader_and_param - p = Pipeline() - p.add_node(component=retriever, name="TableRetriever", inputs=["Query"]) - p.add_node(component=table_reader, name="TableReader", inputs=["TableRetriever"]) - - eval_result = p.eval(labels=EVAL_TABLE_LABELS, params={"TableRetriever": {"top_k": 2}}) - table_reader_results = eval_result.node_results["TableReader"] - - assert set(table_reader_results["query"].tolist()) == { - "How old is Brad Pitt?", - "To which state does Spikeroog belong?", - } - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_answer") - assert metrics["TableRetriever"]["recall_single_hit"] == 1.0 - assert metrics["TableRetriever"]["recall_multi_hit"] == 1.0 - assert metrics["TableRetriever"]["precision"] == 0.5 - assert metrics["TableRetriever"]["mrr"] == 1.0 - assert metrics["TableRetriever"]["map"] == 1.0 - assert metrics["TableRetriever"]["ndcg"] == 1.0 - assert metrics["TableReader"]["exact_match"] == 1.0 - assert metrics["TableReader"]["f1"] == 1.0 - - # assert metrics are floats - for node_metrics in metrics.values(): - for value in node_metrics.values(): - assert isinstance(value, float) - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval(reader, retriever_with_docs, tmp_path, eval_labels): - labels = eval_labels[:1] - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result = pipeline.eval(labels=labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - reader_result = eval_result["Reader"] - retriever_result = eval_result["Retriever"] - - expected_reader_result_columns = [ - "answer", # answer-specific - "exact_match", # answer-specific - "f1", # answer-specific - # "sas", # answer-specific optional - "exact_match_context_scope", # answer-specific - "f1_context_scope", # answer-specific - # "sas_context_scope", # answer-specific optional - "exact_match_document_id_scope", # answer-specific - "f1_document_id_scope", # answer-specific - # "sas_document_id_scope", # answer-specific optional - "exact_match_document_id_and_context_scope", # answer-specific - "f1_document_id_and_context_scope", # answer-specific - # "sas_document_id_and_context_scope", # answer-specific optional - "offsets_in_document", # answer-specific - "gold_offsets_in_documents", # answer-specific - "offsets_in_context", # answer-specific - "gold_offsets_in_contexts", # answer-specific - "gold_answers_exact_match", # answer-specific - "gold_answers_f1", # answer-specific - # "gold_answers_sas", # answer-specific optional - "document_ids", # answer-specific - ] - - expected_retriever_result_columns = [ - "gold_id_match", # doc-specific - "context_match", # doc-specific - "answer_match", # doc-specific - "gold_id_or_answer_match", # doc-specific - "gold_id_and_answer_match", # doc-specific - "gold_id_or_context_match", # doc-specific - "gold_id_and_context_match", # doc-specific - "gold_id_and_context_and_answer_match", # doc-specific - "context_and_answer_match", # doc-specific - "gold_answers_match", # doc-specific, - "document_id", # doc-specific - ] - - expected_generic_result_columns = [ - "multilabel_id", # generic - "query", # generic - "filters", # generic - "context", # generic - "gold_contexts", # generic - "gold_documents_id_match", # generic - "gold_contexts_similarity", # generic - "type", # generic - "node", # generic - "eval_mode", # generic - "rank", # generic - "gold_document_ids", # generic - "gold_answers", # generic - # "custom_document_id", # generic optional - # "gold_custom_document_ids", # generic optional - ] - - # all expected columns are part of the evaluation result dataframe - assert sorted(expected_reader_result_columns + expected_generic_result_columns + ["index"]) == sorted( - reader_result.columns - ) - assert sorted(expected_retriever_result_columns + expected_generic_result_columns + ["index"]) == sorted( - retriever_result.columns - ) - - assert ( - reader_result[reader_result["rank"] == 1]["answer"].iloc[0] - in reader_result[reader_result["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_result[retriever_result["rank"] == 1]["document_id"].iloc[0] - in retriever_result[retriever_result["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - # assert metrics are floats - for node_metrics in metrics.values(): - for value in node_metrics.values(): - assert isinstance(value, float) - - eval_result.save(tmp_path) - saved_eval_result = EvaluationResult.load(tmp_path) - - for key, df in eval_result.node_results.items(): - pd.testing.assert_frame_equal(df, saved_eval_result[key]) - - metrics = saved_eval_result.calculate_metrics(document_scope="document_id") - - assert ( - reader_result[reader_result["rank"] == 1]["answer"].iloc[0] - in reader_result[reader_result["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_result[retriever_result["rank"] == 1]["document_id"].iloc[0] - in retriever_result[retriever_result["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - # assert metrics are floats - for node_metrics in metrics.values(): - for value in node_metrics.values(): - assert isinstance(value, float) - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@responses.activate -def test_generative_qa_eval(retriever_with_docs, tmp_path, eval_labels): - labels = eval_labels[:1] - responses.add( - responses.POST, - "https://api.openai.com/v1/completions", - json={"choices": [{"text": "test", "finish_reason": "stop"}, {"text": "test2", "finish_reason": "stop"}]}, - status=200, - ) - responses.add_passthru("https://openaipublic.blob.core.windows.net") - generator = OpenAIAnswerGenerator(api_key="dummy", top_k=2) - pipeline = GenerativeQAPipeline(generator=generator, retriever=retriever_with_docs) - eval_result = pipeline.eval(labels=labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - generator_result = eval_result["Generator"] - retriever_result = eval_result["Retriever"] - - expected_generator_result_columns = [ - "answer", # answer-specific - "exact_match", # answer-specific - "f1", # answer-specific - # "sas", # answer-specific optional - "exact_match_context_scope", # answer-specific - "f1_context_scope", # answer-specific - # "sas_context_scope", # answer-specific optional - "exact_match_document_id_scope", # answer-specific - "f1_document_id_scope", # answer-specific - # "sas_document_id_scope", # answer-specific optional - "exact_match_document_id_and_context_scope", # answer-specific - "f1_document_id_and_context_scope", # answer-specific - # "sas_document_id_and_context_scope", # answer-specific optional - "offsets_in_document", # answer-specific - "gold_offsets_in_documents", # answer-specific - "offsets_in_context", # answer-specific - "gold_offsets_in_contexts", # answer-specific - "gold_answers_exact_match", # answer-specific - "gold_answers_f1", # answer-specific - # "gold_answers_sas", # answer-specific optional - "document_ids", # answer-specific - "prompt", # answer-specific - ] - - expected_retriever_result_columns = [ - "gold_id_match", # doc-specific - "context_match", # doc-specific - "answer_match", # doc-specific - "gold_id_or_answer_match", # doc-specific - "gold_id_and_answer_match", # doc-specific - "gold_id_or_context_match", # doc-specific - "gold_id_and_context_match", # doc-specific - "gold_id_and_context_and_answer_match", # doc-specific - "context_and_answer_match", # doc-specific - "gold_answers_match", # doc-specific, - "document_id", # doc-specific - ] - - expected_generic_result_columns = [ - "multilabel_id", # generic - "query", # generic - "filters", # generic - "context", # generic - "gold_contexts", # generic - "gold_documents_id_match", # generic - "gold_contexts_similarity", # generic - "type", # generic - "node", # generic - "eval_mode", # generic - "rank", # generic - "gold_document_ids", # generic - "gold_answers", # generic - # "custom_document_id", # generic optional - # "gold_custom_document_ids", # generic optional - ] - - # all expected columns are part of the evaluation result dataframe - assert sorted(expected_generator_result_columns + expected_generic_result_columns + ["index"]) == sorted( - generator_result.columns - ) - assert sorted(expected_retriever_result_columns + expected_generic_result_columns + ["index"]) == sorted( - retriever_result.columns - ) - - assert generator_result["prompt"].iloc[0] is not None - - # assert metrics are floats - for node_metrics in metrics.values(): - for value in node_metrics.values(): - assert isinstance(value, float) - - eval_result.save(tmp_path) - saved_eval_result = EvaluationResult.load(tmp_path) - - for key, df in eval_result.node_results.items(): - pd.testing.assert_frame_equal(df, saved_eval_result[key]) - - loaded_metrics = saved_eval_result.calculate_metrics(document_scope="document_id") - assert metrics == loaded_metrics - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_generative_qa_w_promptnode_eval(retriever_with_docs, tmp_path, eval_labels): - labels = eval_labels[:1] - pipeline = Pipeline() - pipeline.add_node(retriever_with_docs, name="Retriever", inputs=["Query"]) - pipeline.add_node( - PromptNode(default_prompt_template="question-answering", model_name_or_path="google/flan-t5-small", top_k=2), - name="PromptNode", - inputs=["Retriever"], - ) - - eval_result = pipeline.eval(labels=labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - generator_result = eval_result["PromptNode"] - retriever_result = eval_result["Retriever"] - - expected_generator_result_columns = [ - "answer", # answer-specific - "exact_match", # answer-specific - "f1", # answer-specific - # "sas", # answer-specific optional - "exact_match_context_scope", # answer-specific - "f1_context_scope", # answer-specific - # "sas_context_scope", # answer-specific optional - "exact_match_document_id_scope", # answer-specific - "f1_document_id_scope", # answer-specific - # "sas_document_id_scope", # answer-specific optional - "exact_match_document_id_and_context_scope", # answer-specific - "f1_document_id_and_context_scope", # answer-specific - # "sas_document_id_and_context_scope", # answer-specific optional - "offsets_in_document", # answer-specific - "gold_offsets_in_documents", # answer-specific - "offsets_in_context", # answer-specific - "gold_offsets_in_contexts", # answer-specific - "gold_answers_exact_match", # answer-specific - "gold_answers_f1", # answer-specific - # "gold_answers_sas", # answer-specific optional - "document_ids", # answer-specific - "prompt", # answer-specific - ] - - expected_retriever_result_columns = [ - "gold_id_match", # doc-specific - "context_match", # doc-specific - "answer_match", # doc-specific - "gold_id_or_answer_match", # doc-specific - "gold_id_and_answer_match", # doc-specific - "gold_id_or_context_match", # doc-specific - "gold_id_and_context_match", # doc-specific - "gold_id_and_context_and_answer_match", # doc-specific - "context_and_answer_match", # doc-specific - "gold_answers_match", # doc-specific, - "document_id", # doc-specific - ] - - expected_generic_result_columns = [ - "multilabel_id", # generic - "query", # generic - "filters", # generic - "context", # generic - "gold_contexts", # generic - "gold_documents_id_match", # generic - "gold_contexts_similarity", # generic - "type", # generic - "node", # generic - "eval_mode", # generic - "rank", # generic - "gold_document_ids", # generic - "gold_answers", # generic - # "custom_document_id", # generic optional - # "gold_custom_document_ids", # generic optional - ] - - # all expected columns are part of the evaluation result dataframe - assert sorted(expected_generator_result_columns + expected_generic_result_columns + ["index"]) == sorted( - generator_result.columns - ) - assert sorted(expected_retriever_result_columns + expected_generic_result_columns + ["index"]) == sorted( - retriever_result.columns - ) - - assert generator_result["prompt"].iloc[0] is not None - - # assert metrics are floats - for node_metrics in metrics.values(): - for value in node_metrics.values(): - assert isinstance(value, float) - - eval_result.save(tmp_path) - saved_eval_result = EvaluationResult.load(tmp_path) - - for key, df in eval_result.node_results.items(): - pd.testing.assert_frame_equal(df, saved_eval_result[key]) - - loaded_metrics = saved_eval_result.calculate_metrics(document_scope="document_id") - assert metrics == loaded_metrics - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_multiple_queries(reader, retriever_with_docs, tmp_path, eval_labels): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval(labels=eval_labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - reader_result = eval_result["Reader"] - retriever_result = eval_result["Retriever"] - - reader_berlin = reader_result[reader_result["query"] == "Who lives in Berlin?"] - reader_munich = reader_result[reader_result["query"] == "Who lives in Munich?"] - - retriever_berlin = retriever_result[retriever_result["query"] == "Who lives in Berlin?"] - retriever_munich = retriever_result[retriever_result["query"] == "Who lives in Munich?"] - - assert ( - reader_berlin[reader_berlin["rank"] == 1]["answer"].iloc[0] - in reader_berlin[reader_berlin["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_berlin[retriever_berlin["rank"] == 1]["document_id"].iloc[0] - in retriever_berlin[retriever_berlin["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert ( - reader_munich[reader_munich["rank"] == 1]["answer"].iloc[0] - not in reader_munich[reader_munich["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_munich[retriever_munich["rank"] == 1]["document_id"].iloc[0] - not in retriever_munich[retriever_munich["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - eval_result.save(tmp_path) - saved_eval_result = EvaluationResult.load(tmp_path) - - for key, df in eval_result.node_results.items(): - pd.testing.assert_frame_equal(df, saved_eval_result[key]) - - metrics = saved_eval_result.calculate_metrics(document_scope="document_id") - - assert ( - reader_berlin[reader_berlin["rank"] == 1]["answer"].iloc[0] - in reader_berlin[reader_berlin["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_berlin[retriever_berlin["rank"] == 1]["document_id"].iloc[0] - in retriever_berlin[retriever_berlin["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert ( - reader_munich[reader_munich["rank"] == 1]["answer"].iloc[0] - not in reader_munich[reader_munich["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_munich[retriever_munich["rank"] == 1]["document_id"].iloc[0] - not in retriever_munich[retriever_munich["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["bm25"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_labels_with_filters(reader, retriever_with_docs, tmp_path): - labels = [ - # MultiLabel with filter that selects only the document about Carla - MultiLabel( - labels=[ - Label( - query="What's her name?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - filters={"name": ["filename1"]}, - ) - ] - ), - # MultiLabel with filter that selects only the document about Christelle - MultiLabel( - labels=[ - Label( - query="What's her name?", - answer=Answer(answer="Christelle", offsets_in_context=[Span(11, 20)]), - document=Document( - id="4fa3938bef1d83e4d927669666d0b705", - content_type="text", - content="My name is Christelle and I live in Paris", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - filters={"name": ["filename3"]}, - ) - ] - ), - ] - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result = pipeline.eval(labels=labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - reader_result = eval_result["Reader"] - retriever_result = eval_result["Retriever"] - - # The same query but with two different filters and thus two different answers is answered correctly in both cases. - assert ( - reader_result[reader_result["rank"] == 1]["answer"].iloc[0] - in reader_result[reader_result["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_result[retriever_result["rank"] == 1]["document_id"].iloc[0] - in retriever_result[retriever_result["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_sas(reader, retriever_with_docs, eval_labels): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert "sas" in metrics["Reader"] - assert metrics["Reader"]["sas"] == pytest.approx(1.0) - - # assert metrics are floats - for node_metrics in metrics.values(): - for value in node_metrics.values(): - assert isinstance(value, float) - - -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_reader_eval_in_pipeline(reader, eval_labels): - pipeline = Pipeline() - pipeline.add_node(component=reader, name="Reader", inputs=["Query"]) - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, - documents=[[label.document for label in multilabel.labels] for multilabel in eval_labels], - params={}, - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_extractive_qa_eval_document_scope(retriever_with_docs, eval_labels): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, - params={"Retriever": {"top_k": 5}}, - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_and_context") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="answer") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_answer") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_document_search_eval_document_scope(retriever_with_docs): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=DOC_SEARCH_EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_and_context") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="answer") - - assert metrics["Retriever"]["mrr"] == 0.0 - assert metrics["Retriever"]["map"] == 0.0 - assert metrics["Retriever"]["recall_multi_hit"] == 0.0 - assert metrics["Retriever"]["recall_single_hit"] == 0.0 - assert metrics["Retriever"]["precision"] == 0.0 - assert metrics["Retriever"]["ndcg"] == 0.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_answer") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_document_search_id_only_eval_document_scope(retriever_with_docs): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=DOC_SEARCH_ID_EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="context") - - assert metrics["Retriever"]["mrr"] == 0.0 - assert metrics["Retriever"]["map"] == 0.0 - assert metrics["Retriever"]["recall_multi_hit"] == 0.0 - assert metrics["Retriever"]["recall_single_hit"] == 0.0 - assert metrics["Retriever"]["precision"] == 0.0 - assert metrics["Retriever"]["ndcg"] == 0.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_and_context") - - assert metrics["Retriever"]["mrr"] == 0.0 - assert metrics["Retriever"]["map"] == 0.0 - assert metrics["Retriever"]["recall_multi_hit"] == 0.0 - assert metrics["Retriever"]["recall_single_hit"] == 0.0 - assert metrics["Retriever"]["precision"] == 0.0 - assert metrics["Retriever"]["ndcg"] == 0.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_context") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="answer") - - assert metrics["Retriever"]["mrr"] == 0.0 - assert metrics["Retriever"]["map"] == 0.0 - assert metrics["Retriever"]["recall_multi_hit"] == 0.0 - assert metrics["Retriever"]["recall_single_hit"] == 0.0 - assert metrics["Retriever"]["precision"] == 0.0 - assert metrics["Retriever"]["ndcg"] == 0.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_answer") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_file_search_eval_document_scope(retriever_with_docs): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=FILE_SEARCH_EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - custom_document_id_field="name", - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Retriever"]["mrr"] == 0.6 - assert metrics["Retriever"]["map"] == 0.6 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == pytest.approx(0.6934, 0.0001) - - metrics = eval_result.calculate_metrics(document_scope="context") - - assert metrics["Retriever"]["mrr"] == 0.0 - assert metrics["Retriever"]["map"] == 0.0 - assert metrics["Retriever"]["recall_multi_hit"] == 0.0 - assert metrics["Retriever"]["recall_single_hit"] == 0.0 - assert metrics["Retriever"]["precision"] == 0.0 - assert metrics["Retriever"]["ndcg"] == 0.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_and_context") - - assert metrics["Retriever"]["mrr"] == 0.0 - assert metrics["Retriever"]["map"] == 0.0 - assert metrics["Retriever"]["recall_multi_hit"] == 0.0 - assert metrics["Retriever"]["recall_single_hit"] == 0.0 - assert metrics["Retriever"]["precision"] == 0.0 - assert metrics["Retriever"]["ndcg"] == 0.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_context") - - assert metrics["Retriever"]["mrr"] == 0.6 - assert metrics["Retriever"]["map"] == 0.6 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == pytest.approx(0.6934, 0.0001) - - metrics = eval_result.calculate_metrics(document_scope="answer") - - assert metrics["Retriever"]["mrr"] == 0.0 - assert metrics["Retriever"]["map"] == 0.0 - assert metrics["Retriever"]["recall_multi_hit"] == 0.0 - assert metrics["Retriever"]["recall_single_hit"] == 0.0 - assert metrics["Retriever"]["precision"] == 0.0 - assert metrics["Retriever"]["ndcg"] == 0.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_answer") - - assert metrics["Retriever"]["mrr"] == 0.6 - assert metrics["Retriever"]["map"] == 0.6 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == pytest.approx(0.6934, 0.0001) - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize( - "document_scope", - ["document_id", "context", "document_id_and_context", "document_id_or_context", "answer", "document_id_or_answer"], -) -def test_extractive_qa_eval_document_scope_no_answer(retriever_with_docs, document_scope): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=NO_ANSWER_EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - metrics = eval_result.calculate_metrics(document_scope=document_scope) - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_answer_scope(reader, retriever_with_docs, eval_labels): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - metrics = eval_result.calculate_metrics(answer_scope="any") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Reader"]["sas"] == pytest.approx(1.0) - - metrics = eval_result.calculate_metrics(answer_scope="context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Reader"]["sas"] == pytest.approx(1.0) - - metrics = eval_result.calculate_metrics(answer_scope="document_id") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert metrics["Reader"]["exact_match"] == 0.5 - assert metrics["Reader"]["f1"] == 0.5 - assert metrics["Reader"]["sas"] == pytest.approx(0.5) - - metrics = eval_result.calculate_metrics(answer_scope="document_id_and_context") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert metrics["Reader"]["exact_match"] == 0.5 - assert metrics["Reader"]["f1"] == 0.5 - assert metrics["Reader"]["sas"] == pytest.approx(0.5) - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_answer_document_scope_combinations(reader, retriever_with_docs, caplog, eval_labels): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - # valid values for non default answer_scopes - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id_or_answer", answer_scope="context") - eval_result.calculate_metrics(document_scope="answer", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" not in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="context", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id_and_context", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id_or_context", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_simulated_top_k_reader(reader, retriever_with_docs, eval_labels): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - ) - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_reader=1, document_scope="document_id") - - assert metrics_top_1["Reader"]["exact_match"] == 0.5 - assert metrics_top_1["Reader"]["f1"] == 0.5 - assert metrics_top_1["Reader"]["sas"] == pytest.approx(0.6003, abs=1e-4) - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 0.1 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_2 = eval_result.calculate_metrics(simulated_top_k_reader=2, document_scope="document_id") - - assert metrics_top_2["Reader"]["exact_match"] == 0.5 - assert metrics_top_2["Reader"]["f1"] == 0.5 - assert metrics_top_2["Reader"]["sas"] == pytest.approx(0.6003, abs=1e-4) - assert metrics_top_2["Retriever"]["mrr"] == 0.5 - assert metrics_top_2["Retriever"]["map"] == 0.5 - assert metrics_top_2["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_2["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_2["Retriever"]["precision"] == 0.1 - assert metrics_top_2["Retriever"]["ndcg"] == 0.5 - - metrics_top_5 = eval_result.calculate_metrics(simulated_top_k_reader=5, document_scope="document_id") - - assert metrics_top_5["Reader"]["exact_match"] == 1.0 - assert metrics_top_5["Reader"]["f1"] == 1.0 - assert metrics_top_5["Reader"]["sas"] == pytest.approx(1.0, abs=1e-4) - assert metrics_top_5["Retriever"]["mrr"] == 0.5 - assert metrics_top_5["Retriever"]["map"] == 0.5 - assert metrics_top_5["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_5["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_5["Retriever"]["precision"] == 0.1 - assert metrics_top_5["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_simulated_top_k_retriever(reader, retriever_with_docs, eval_labels): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval(labels=eval_labels, params={"Retriever": {"top_k": 5}}) - - metrics_top_10 = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics_top_10["Reader"]["exact_match"] == 1.0 - assert metrics_top_10["Reader"]["f1"] == 1.0 - assert metrics_top_10["Retriever"]["mrr"] == 0.5 - assert metrics_top_10["Retriever"]["map"] == 0.5 - assert metrics_top_10["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_10["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_10["Retriever"]["precision"] == 0.1 - assert metrics_top_10["Retriever"]["ndcg"] == 0.5 - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_retriever=1, document_scope="document_id") - - assert metrics_top_1["Reader"]["exact_match"] == 1.0 - assert metrics_top_1["Reader"]["f1"] == 1.0 - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 0.5 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_2 = eval_result.calculate_metrics(simulated_top_k_retriever=2, document_scope="document_id") - - assert metrics_top_2["Reader"]["exact_match"] == 1.0 - assert metrics_top_2["Reader"]["f1"] == 1.0 - assert metrics_top_2["Retriever"]["mrr"] == 0.5 - assert metrics_top_2["Retriever"]["map"] == 0.5 - assert metrics_top_2["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_2["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_2["Retriever"]["precision"] == 0.25 - assert metrics_top_2["Retriever"]["ndcg"] == 0.5 - - metrics_top_3 = eval_result.calculate_metrics(simulated_top_k_retriever=3, document_scope="document_id") - - assert metrics_top_3["Reader"]["exact_match"] == 1.0 - assert metrics_top_3["Reader"]["f1"] == 1.0 - assert metrics_top_3["Retriever"]["mrr"] == 0.5 - assert metrics_top_3["Retriever"]["map"] == 0.5 - assert metrics_top_3["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_3["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_3["Retriever"]["precision"] == 1.0 / 6 - assert metrics_top_3["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_simulated_top_k_reader_and_retriever(reader, retriever_with_docs, eval_labels): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval(labels=eval_labels, params={"Retriever": {"top_k": 10}}) - - metrics_top_10 = eval_result.calculate_metrics(simulated_top_k_reader=1, document_scope="document_id") - - assert metrics_top_10["Reader"]["exact_match"] == 0.5 - assert metrics_top_10["Reader"]["f1"] == 0.5 - assert metrics_top_10["Retriever"]["mrr"] == 0.5 - assert metrics_top_10["Retriever"]["map"] == 0.5 - assert metrics_top_10["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_10["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_10["Retriever"]["precision"] == 0.1 - assert metrics_top_10["Retriever"]["ndcg"] == 0.5 - - metrics_top_1 = eval_result.calculate_metrics( - simulated_top_k_reader=1, simulated_top_k_retriever=1, document_scope="document_id" - ) - - assert metrics_top_1["Reader"]["exact_match"] == 1.0 - assert metrics_top_1["Reader"]["f1"] == 1.0 - - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 0.5 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_2 = eval_result.calculate_metrics( - simulated_top_k_reader=1, simulated_top_k_retriever=2, document_scope="document_id" - ) - - assert metrics_top_2["Reader"]["exact_match"] == 0.5 - assert metrics_top_2["Reader"]["f1"] == 0.5 - assert metrics_top_2["Retriever"]["mrr"] == 0.5 - assert metrics_top_2["Retriever"]["map"] == 0.5 - assert metrics_top_2["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_2["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_2["Retriever"]["precision"] == 0.25 - assert metrics_top_2["Retriever"]["ndcg"] == 0.5 - - metrics_top_3 = eval_result.calculate_metrics( - simulated_top_k_reader=1, simulated_top_k_retriever=3, document_scope="document_id" - ) - - assert metrics_top_3["Reader"]["exact_match"] == 0.5 - assert metrics_top_3["Reader"]["f1"] == 0.5 - assert metrics_top_3["Retriever"]["mrr"] == 0.5 - assert metrics_top_3["Retriever"]["map"] == 0.5 - assert metrics_top_3["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_3["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_3["Retriever"]["precision"] == 1.0 / 6 - assert metrics_top_3["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_isolated(reader, retriever_with_docs, eval_labels): - labels = deepcopy(eval_labels) - # Copy one of the labels and change only the answer have a label with a different answer but same Document - label_copy = deepcopy(labels[0].labels[0]) - label_copy.answer = Answer(answer="I", offsets_in_context=[Span(21, 22)]) - labels[0].labels.append(label_copy) - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval( - labels=labels, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - add_isolated_node_eval=True, - ) - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_reader=1, document_scope="document_id") - - assert metrics_top_1["Reader"]["exact_match"] == 0.5 - assert metrics_top_1["Reader"]["f1"] == 0.5 - assert metrics_top_1["Reader"]["sas"] == pytest.approx(0.6003, abs=1e-4) - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 1.0 / 10 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_reader=1, eval_mode="isolated") - - assert metrics_top_1["Reader"]["exact_match"] == 1.0 - assert metrics_top_1["Reader"]["f1"] == 1.0 - assert metrics_top_1["Reader"]["sas"] == pytest.approx(1.0, abs=1e-4) - - # Check if same Document in MultiLabel got deduplicated - assert labels[0].labels[0].id == labels[0].labels[1].id - reader_eval_df = eval_result.node_results["Reader"] - isolated_reader_eval_df = reader_eval_df[reader_eval_df["eval_mode"] == "isolated"] - assert len(isolated_reader_eval_df) == len(labels) * reader.top_k_per_candidate - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_wrong_examples(reader, retriever_with_docs): - labels = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=Answer(answer="Pete", offsets_in_context=[Span(11, 16)]), - document=Document( - id="something_else", content_type="text", content="My name is Pete and I live in Munich" - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - ] - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval(labels=labels, params={"Retriever": {"top_k": 5}}) - - wrongs_retriever = eval_result.wrong_examples(node="Retriever", n=1) - wrongs_reader = eval_result.wrong_examples(node="Reader", n=1) - - assert len(wrongs_retriever) == 1 - assert len(wrongs_reader) == 1 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_print_eval_report(reader, retriever_with_docs): - labels = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=Answer(answer="Pete", offsets_in_context=[Span(11, 16)]), - document=Document( - id="something_else", content_type="text", content="My name is Pete and I live in Munich" - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - ] - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval(labels=labels, params={"Retriever": {"top_k": 5}}) - pipeline.print_eval_report(eval_result) - - # in addition with labels as input to reader node rather than output of retriever node - eval_result: EvaluationResult = pipeline.eval( - labels=labels, params={"Retriever": {"top_k": 5}}, add_isolated_node_eval=True - ) - pipeline.print_eval_report(eval_result) - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_document_search_calculate_metrics(retriever_with_docs, eval_labels): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval(labels=eval_labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert len(eval_result) == 1 - retriever_result = eval_result["Retriever"] - retriever_berlin = retriever_result[retriever_result["query"] == "Who lives in Berlin?"] - retriever_munich = retriever_result[retriever_result["query"] == "Who lives in Munich?"] - - assert ( - retriever_berlin[retriever_berlin["rank"] == 1]["document_id"].iloc[0] - in retriever_berlin[retriever_berlin["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert ( - retriever_munich[retriever_munich["rank"] == 1]["document_id"].iloc[0] - not in retriever_munich[retriever_munich["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_document_search_isolated(retriever_with_docs, eval_labels): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - # eval run must not fail even though no node supports add_isolated_node_eval - eval_result: EvaluationResult = pipeline.eval( - labels=eval_labels, params={"Retriever": {"top_k": 5}}, add_isolated_node_eval=True - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert len(eval_result) == 1 - retriever_result = eval_result["Retriever"] - retriever_berlin = retriever_result[retriever_result["query"] == "Who lives in Berlin?"] - retriever_munich = retriever_result[retriever_result["query"] == "Who lives in Munich?"] - - assert ( - retriever_berlin[retriever_berlin["rank"] == 1]["document_id"].iloc[0] - in retriever_berlin[retriever_berlin["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert ( - retriever_munich[retriever_munich["rank"] == 1]["document_id"].iloc[0] - not in retriever_munich[retriever_munich["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - isolated_metrics = eval_result.calculate_metrics(document_scope="document_id", eval_mode="isolated") - # empty metrics for nodes that do not support add_isolated_node_eval - assert isolated_metrics["Retriever"] == {} - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_faq_calculate_metrics(retriever_with_docs, eval_labels): - pipeline = FAQPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval(labels=eval_labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert "Docs2Answers" in eval_result - assert len(eval_result) == 2 - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert metrics["Docs2Answers"]["exact_match"] == 0.0 - assert metrics["Docs2Answers"]["f1"] == 0.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_translation(reader, retriever_with_docs, eval_labels): - # FIXME it makes no sense to have DE->EN input and DE->EN output, right? - # Yet switching direction breaks the test. TO BE FIXED. - input_translator = TransformersTranslator(model_name_or_path="Helsinki-NLP/opus-mt-de-en") - output_translator = TransformersTranslator(model_name_or_path="Helsinki-NLP/opus-mt-de-en") - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - pipeline = TranslationWrapperPipeline( - input_translator=input_translator, output_translator=output_translator, pipeline=pipeline - ) - eval_result: EvaluationResult = pipeline.eval(labels=eval_labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert "Reader" in eval_result - assert "OutputTranslator" in eval_result - assert len(eval_result) == 3 - - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - assert metrics["OutputTranslator"]["exact_match"] == 1.0 - assert metrics["OutputTranslator"]["f1"] == 1.0 - assert metrics["OutputTranslator"]["mrr"] == 0.5 - assert metrics["OutputTranslator"]["map"] == 0.5 - assert metrics["OutputTranslator"]["recall_multi_hit"] == 0.5 - assert metrics["OutputTranslator"]["recall_single_hit"] == 0.5 - assert metrics["OutputTranslator"]["precision"] == 0.1 - assert metrics["OutputTranslator"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_question_generation_eval(retriever_with_docs, question_generator, eval_labels): - pipeline = RetrieverQuestionGenerationPipeline(retriever=retriever_with_docs, question_generator=question_generator) - - eval_result: EvaluationResult = pipeline.eval(labels=eval_labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert "QuestionGenerator" in eval_result - assert len(eval_result) == 2 - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - assert metrics["QuestionGenerator"]["mrr"] == 0.5 - assert metrics["QuestionGenerator"]["map"] == 0.5 - assert metrics["QuestionGenerator"]["recall_multi_hit"] == 0.5 - assert metrics["QuestionGenerator"]["recall_single_hit"] == 0.5 - assert metrics["QuestionGenerator"]["precision"] == 0.1 - assert metrics["QuestionGenerator"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_qa_multi_retriever_pipeline_eval(document_store_with_docs, reader, eval_labels): - es_retriever = BM25Retriever(document_store=document_store_with_docs) - dpr_retriever = DensePassageRetriever(document_store_with_docs) - document_store_with_docs.update_embeddings(retriever=dpr_retriever) - - # QA Pipeline with two retrievers, we always want QA output - pipeline = Pipeline() - pipeline.add_node(component=TransformersQueryClassifier(), name="QueryClassifier", inputs=["Query"]) - pipeline.add_node(component=dpr_retriever, name="DPRRetriever", inputs=["QueryClassifier.output_1"]) - pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["QueryClassifier.output_2"]) - pipeline.add_node(component=reader, name="QAReader", inputs=["ESRetriever", "DPRRetriever"]) - - # EVAL_QUERIES: 2 go dpr way - # in Berlin goes es way - labels = eval_labels + [ - MultiLabel( - labels=[ - Label( - query="in Berlin", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ) - ] - - eval_result: EvaluationResult = pipeline.eval( - labels=labels, params={"ESRetriever": {"top_k": 5}, "DPRRetriever": {"top_k": 5}} - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "ESRetriever" in eval_result - assert "DPRRetriever" in eval_result - assert "QAReader" in eval_result - assert len(eval_result) == 3 - - assert metrics["DPRRetriever"]["mrr"] == 0.5 - assert metrics["DPRRetriever"]["map"] == 0.5 - assert metrics["DPRRetriever"]["recall_multi_hit"] == 0.5 - assert metrics["DPRRetriever"]["recall_single_hit"] == 0.5 - assert metrics["DPRRetriever"]["precision"] == 0.1 - assert metrics["DPRRetriever"]["ndcg"] == 0.5 - - assert metrics["ESRetriever"]["mrr"] == 1.0 - assert metrics["ESRetriever"]["map"] == 1.0 - assert metrics["ESRetriever"]["recall_multi_hit"] == 1.0 - assert metrics["ESRetriever"]["recall_single_hit"] == 1.0 - assert metrics["ESRetriever"]["precision"] == 0.2 - assert metrics["ESRetriever"]["ndcg"] == 1.0 - - assert metrics["QAReader"]["exact_match"] == 1.0 - assert metrics["QAReader"]["f1"] == 1.0 - - -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -def test_multi_retriever_pipeline_eval(document_store_with_docs, eval_labels): - es_retriever = BM25Retriever(document_store=document_store_with_docs) - dpr_retriever = DensePassageRetriever(document_store_with_docs) - document_store_with_docs.update_embeddings(retriever=dpr_retriever) - - # QA Pipeline with two retrievers, no QA output - pipeline = Pipeline() - pipeline.add_node(component=TransformersQueryClassifier(), name="QueryClassifier", inputs=["Query"]) - pipeline.add_node(component=dpr_retriever, name="DPRRetriever", inputs=["QueryClassifier.output_1"]) - pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["QueryClassifier.output_2"]) - - # EVAL_QUERIES: 2 go dpr way - # in Berlin goes es way - labels = eval_labels + [ - MultiLabel( - labels=[ - Label( - query="in Berlin", - answer=None, - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ) - ] - - eval_result: EvaluationResult = pipeline.eval( - labels=labels, params={"ESRetriever": {"top_k": 5}, "DPRRetriever": {"top_k": 5}} - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "ESRetriever" in eval_result - assert "DPRRetriever" in eval_result - assert len(eval_result) == 2 - - assert metrics["DPRRetriever"]["mrr"] == 0.5 - assert metrics["DPRRetriever"]["map"] == 0.5 - assert metrics["DPRRetriever"]["recall_multi_hit"] == 0.5 - assert metrics["DPRRetriever"]["recall_single_hit"] == 0.5 - assert metrics["DPRRetriever"]["precision"] == 0.1 - assert metrics["DPRRetriever"]["ndcg"] == 0.5 - - assert metrics["ESRetriever"]["mrr"] == 1.0 - assert metrics["ESRetriever"]["map"] == 1.0 - assert metrics["ESRetriever"]["recall_multi_hit"] == 1.0 - assert metrics["ESRetriever"]["recall_single_hit"] == 1.0 - assert metrics["ESRetriever"]["precision"] == 0.2 - assert metrics["ESRetriever"]["ndcg"] == 1.0 - - -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_multi_retriever_pipeline_with_asymmetric_qa_eval(document_store_with_docs, reader, eval_labels): - es_retriever = BM25Retriever(document_store=document_store_with_docs) - dpr_retriever = DensePassageRetriever(document_store_with_docs) - document_store_with_docs.update_embeddings(retriever=dpr_retriever) - - # QA Pipeline with two retrievers, we only get QA output from dpr - pipeline = Pipeline() - pipeline.add_node(component=TransformersQueryClassifier(), name="QueryClassifier", inputs=["Query"]) - pipeline.add_node(component=dpr_retriever, name="DPRRetriever", inputs=["QueryClassifier.output_1"]) - pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["QueryClassifier.output_2"]) - pipeline.add_node(component=reader, name="QAReader", inputs=["DPRRetriever"]) - - # EVAL_QUERIES: 2 go dpr way - # in Berlin goes es way - labels = eval_labels + [ - MultiLabel( - labels=[ - Label( - query="in Berlin", - answer=None, - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ) - ] - - eval_result: EvaluationResult = pipeline.eval( - labels=labels, params={"ESRetriever": {"top_k": 5}, "DPRRetriever": {"top_k": 5}} - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "ESRetriever" in eval_result - assert "DPRRetriever" in eval_result - assert "QAReader" in eval_result - assert len(eval_result) == 3 - - assert metrics["DPRRetriever"]["mrr"] == 0.5 - assert metrics["DPRRetriever"]["map"] == 0.5 - assert metrics["DPRRetriever"]["recall_multi_hit"] == 0.5 - assert metrics["DPRRetriever"]["recall_single_hit"] == 0.5 - assert metrics["DPRRetriever"]["precision"] == 0.1 - assert metrics["DPRRetriever"]["ndcg"] == 0.5 - - assert metrics["ESRetriever"]["mrr"] == 1.0 - assert metrics["ESRetriever"]["map"] == 1.0 - assert metrics["ESRetriever"]["recall_multi_hit"] == 1.0 - assert metrics["ESRetriever"]["recall_single_hit"] == 1.0 - assert metrics["ESRetriever"]["precision"] == 0.2 - assert metrics["ESRetriever"]["ndcg"] == 1.0 - - assert metrics["QAReader"]["exact_match"] == 1.0 - assert metrics["QAReader"]["f1"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm", "transformers"], indirect=True) -def test_empty_documents_dont_fail_pipeline(reader, retriever_with_docs, eval_labels): - multilabels = eval_labels[:2] - multilabels[0].labels[0].document.content = "" - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result_integrated: EvaluationResult = pipeline.eval(labels=multilabels, add_isolated_node_eval=False) - assert eval_result_integrated["Reader"]["answer"].iloc[0] == "Carla" - eval_result_iso: EvaluationResult = pipeline.eval(labels=multilabels, add_isolated_node_eval=True) - assert eval_result_iso["Reader"].loc[eval_result_iso["Reader"]["eval_mode"] == "isolated"]["answer"].iloc[0] == "" - - eval_batch_result_integrated: EvaluationResult = pipeline.eval_batch( - labels=multilabels, add_isolated_node_eval=False - ) - assert eval_batch_result_integrated["Reader"]["answer"].iloc[0] == "Carla" - eval_batch_result_iso: EvaluationResult = pipeline.eval_batch(labels=multilabels, add_isolated_node_eval=True) - assert ( - eval_batch_result_iso["Reader"] - .loc[eval_batch_result_iso["Reader"]["eval_mode"] == "isolated"]["answer"] - .iloc[0] - == "" - ) - - -@pytest.mark.unit -def test_load_legacy_evaluation_result(tmp_path): - legacy_csv = Path(tmp_path) / "legacy.csv" - with open(legacy_csv, "w") as legacy_csv: - columns = ["answer", "document_id", "custom_document_id", "gold_document_contents", "content"] - writer = DictWriter(legacy_csv, fieldnames=columns) - writer.writeheader() - writer.writerow( - { - "answer": "answer", - "document_id": Document("test").id, - "custom_document_id": "custom_id", - "gold_document_contents": ["gold", "document", "contents"], - "content": "content", - } - ) - - eval_result = EvaluationResult.load(tmp_path) - assert "legacy" in eval_result - assert len(eval_result["legacy"]) == 1 - assert eval_result["legacy"]["answer"].iloc[0] == "answer" - assert eval_result["legacy"]["document_ids"].iloc[0] == [Document("test").id] - assert eval_result["legacy"]["custom_document_ids"].iloc[0] == ["custom_id"] - assert eval_result["legacy"]["gold_contexts"].iloc[0] == ["gold", "document", "contents"] - assert eval_result["legacy"]["context"].iloc[0] == "content" - - assert "document_id" not in eval_result["legacy"] - assert "custom_document_id" not in eval_result["legacy"] - assert "gold_document_contents" not in eval_result["legacy"] - assert "content" not in eval_result["legacy"] - - -@pytest.mark.unit -def test_load_evaluation_result(tmp_path): - eval_result_csv = Path(tmp_path) / "Reader.csv" - with open(eval_result_csv, "w") as eval_result_csv: - columns = [ - "multilabel_id", - "query", - "filters", - "gold_answers", - "answer", - "context", - "exact_match", - "f1", - "exact_match_context_scope", - "f1_context_scope", - "exact_match_document_id_scope", - "f1_document_id_scope", - "exact_match_document_id_and_context_scope", - "f1_document_id_and_context_scope", - "gold_contexts", - "rank", - "document_ids", - "gold_document_ids", - "offsets_in_document", - "gold_offsets_in_documents", - "offsets_in_context", - "gold_offsets_in_contexts", - "gold_answers_exact_match", - "gold_answers_f1", - "gold_documents_id_match", - "gold_contexts_similarity", - "type", - "node", - "eval_mode", - "index", - ] - writer = DictWriter(eval_result_csv, fieldnames=columns) - writer.writeheader() - writer.writerow( - { - "multilabel_id": "ddc1562602f2d6d895b91e53f83e4c16", - "query": "who is written in the book of life", - "filters": "b'null'", - "gold_answers": "['every person who is destined for Heaven or the World to Come', 'all people considered righteous before God']", - "answer": None, - "context": None, - "exact_match": 0.0, - "f1": 0.0, - "exact_match_context_scope": 0.0, - "f1_context_scope": 0.0, - "exact_match_document_id_scope": 0.0, - "f1_document_id_scope": 0.0, - "exact_match_document_id_and_context_scope": 0.0, - "f1_document_id_and_context_scope": 0.0, - "gold_contexts": "['Book of Life - wikipedia Book of Life Jump to: navigation, search...']", - "rank": 1.0, - "document_ids": None, - "gold_document_ids": "['de2fd2f109e11213af1ea189fd1488a3-0', 'de2fd2f109e11213af1ea189fd1488a3-0']", - "offsets_in_document": "[{'start': 0, 'end': 0}]", - "gold_offsets_in_documents": "[{'start': 374, 'end': 434}, {'start': 1107, 'end': 1149}]", - "offsets_in_context": "[{'start': 0, 'end': 0}]", - "gold_offsets_in_contexts": "[{'start': 374, 'end': 434}, {'start': 1107, 'end': 1149}]", - "gold_answers_exact_match": "[0, 0]", - "gold_answers_f1": "[0, 0]", - "gold_documents_id_match": "[0.0, 0.0]", - "gold_contexts_similarity": "[0.0, 0.0]", - "type": "answer", - "node": "Reader", - "eval_mode": "integrated", - } - ) - - eval_result = EvaluationResult.load(tmp_path) - known_result = { - "multilabel_id": {0: "ddc1562602f2d6d895b91e53f83e4c16"}, - "query": {0: "who is written in the book of life"}, - "filters": {0: b"null"}, - "gold_answers": { - 0: [ - "every person who is destined for Heaven or the World to Come", - "all people considered righteous before God", - ] - }, - "answer": {0: None}, - "context": {0: None}, - "exact_match": {0: 0.0}, - "f1": {0: 0.0}, - "exact_match_context_scope": {0: 0.0}, - "f1_context_scope": {0: 0.0}, - "exact_match_document_id_scope": {0: 0.0}, - "f1_document_id_scope": {0: 0.0}, - "exact_match_document_id_and_context_scope": {0: 0.0}, - "f1_document_id_and_context_scope": {0: 0.0}, - "gold_contexts": {0: ["Book of Life - wikipedia Book of Life Jump to: navigation, search..."]}, - "rank": {0: 1.0}, - "document_ids": {0: None}, - "gold_document_ids": {0: ["de2fd2f109e11213af1ea189fd1488a3-0", "de2fd2f109e11213af1ea189fd1488a3-0"]}, - "offsets_in_document": {0: [{"start": 0, "end": 0}]}, - "gold_offsets_in_documents": {0: [{"start": 374, "end": 434}, {"start": 1107, "end": 1149}]}, - "offsets_in_context": {0: [{"start": 0, "end": 0}]}, - "gold_offsets_in_contexts": {0: [{"start": 374, "end": 434}, {"start": 1107, "end": 1149}]}, - "gold_answers_exact_match": {0: [0, 0]}, - "gold_answers_f1": {0: [0, 0]}, - "gold_documents_id_match": {0: [0.0, 0.0]}, - "gold_contexts_similarity": {0: [0.0, 0.0]}, - "type": {0: "answer"}, - "node": {0: "Reader"}, - "eval_mode": {0: "integrated"}, - "index": {0: None}, - } - assert "Reader" in eval_result - assert len(eval_result) == 1 - assert eval_result["Reader"].to_dict() == known_result diff --git a/test/pipelines/test_eval_batch.py b/test/pipelines/test_eval_batch.py deleted file mode 100644 index e765ba292b..0000000000 --- a/test/pipelines/test_eval_batch.py +++ /dev/null @@ -1,1035 +0,0 @@ -import logging -from unittest.mock import patch - -import pytest -import sys -from copy import deepcopy -from haystack.document_stores.memory import InMemoryDocumentStore -from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore -from haystack.nodes.preprocessor import PreProcessor -from haystack.nodes.query_classifier.transformers import TransformersQueryClassifier -from haystack.nodes.retriever.dense import DensePassageRetriever -from haystack.nodes.retriever.sparse import BM25Retriever -from haystack.nodes.summarizer.transformers import TransformersSummarizer -from haystack.pipelines.base import Pipeline -from haystack.pipelines import ExtractiveQAPipeline, GenerativeQAPipeline, SearchSummarizationPipeline -from haystack.pipelines.standard_pipelines import ( - DocumentSearchPipeline, - FAQPipeline, - RetrieverQuestionGenerationPipeline, - TranslationWrapperPipeline, -) -from haystack.nodes.translator.transformers import TransformersTranslator -from haystack.schema import Answer, Document, EvaluationResult, Label, MultiLabel, Span - - -@pytest.mark.unit -@patch("haystack.pipelines.base.Pipeline.run_batch") -def test_eval_batch_add_isolated_node_eval_passed_to_run_batch(mock_run_batch): - pipeline = Pipeline() - pipeline.eval_batch(labels=EVAL_LABELS, add_isolated_node_eval=True) - _, kwargs = mock_run_batch.call_args - assert "add_isolated_node_eval" in kwargs["params"] - assert kwargs["params"]["add_isolated_node_eval"] is True - - -@pytest.mark.skipif(sys.platform in ["win32", "cygwin"], reason="Causes OOM on windows github runner") -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("retriever_with_docs", ["embedding"], indirect=True) -def test_summarizer_calculate_metrics(document_store_with_docs: ElasticsearchDocumentStore, retriever_with_docs): - document_store_with_docs.update_embeddings(retriever=retriever_with_docs) - summarizer = TransformersSummarizer(model_name_or_path="sshleifer/distill-pegasus-xsum-16-4", use_gpu=False) - pipeline = SearchSummarizationPipeline( - retriever=retriever_with_docs, summarizer=summarizer, return_in_answer_format=True - ) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=EVAL_LABELS, params={"Retriever": {"top_k": 5}}, context_matching_min_length=10 - ) - - metrics = eval_result.calculate_metrics(document_scope="context") - - assert "Retriever" in eval_result - assert "Summarizer" in eval_result - assert len(eval_result) == 2 - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - assert metrics["Summarizer"]["mrr"] == 1.0 - assert metrics["Summarizer"]["map"] == 1.0 - assert metrics["Summarizer"]["recall_multi_hit"] == 1.0 - assert metrics["Summarizer"]["recall_single_hit"] == 1.0 - assert metrics["Summarizer"]["precision"] == 1.0 - assert metrics["Summarizer"]["ndcg"] == 1.0 - - -EVAL_LABELS = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="something_else", content_type="text", content="My name is Carla and I live in Munich" - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), -] - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm", "transformers"], indirect=True) -def test_extractive_qa_eval(reader, retriever_with_docs, tmp_path): - labels = EVAL_LABELS[:1] - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result = pipeline.eval_batch(labels=labels, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - reader_result = eval_result["Reader"] - retriever_result = eval_result["Retriever"] - - assert ( - reader_result[reader_result["rank"] == 1]["answer"].iloc[0] - in reader_result[reader_result["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_result[retriever_result["rank"] == 1]["document_id"].iloc[0] - in retriever_result[retriever_result["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - eval_result.save(tmp_path) - saved_eval_result = EvaluationResult.load(tmp_path) - metrics = saved_eval_result.calculate_metrics(document_scope="document_id") - - assert ( - reader_result[reader_result["rank"] == 1]["answer"].iloc[0] - in reader_result[reader_result["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_result[retriever_result["rank"] == 1]["document_id"].iloc[0] - in retriever_result[retriever_result["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_multiple_queries(reader, retriever_with_docs, tmp_path): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch(labels=EVAL_LABELS, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - reader_result = eval_result["Reader"] - retriever_result = eval_result["Retriever"] - - reader_berlin = reader_result[reader_result["query"] == "Who lives in Berlin?"] - reader_munich = reader_result[reader_result["query"] == "Who lives in Munich?"] - - retriever_berlin = retriever_result[retriever_result["query"] == "Who lives in Berlin?"] - retriever_munich = retriever_result[retriever_result["query"] == "Who lives in Munich?"] - - assert ( - reader_berlin[reader_berlin["rank"] == 1]["answer"].iloc[0] - in reader_berlin[reader_berlin["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_berlin[retriever_berlin["rank"] == 1]["document_id"].iloc[0] - in retriever_berlin[retriever_berlin["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert ( - reader_munich[reader_munich["rank"] == 1]["answer"].iloc[0] - not in reader_munich[reader_munich["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_munich[retriever_munich["rank"] == 1]["document_id"].iloc[0] - not in retriever_munich[retriever_munich["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - eval_result.save(tmp_path) - saved_eval_result = EvaluationResult.load(tmp_path) - metrics = saved_eval_result.calculate_metrics(document_scope="document_id") - - assert ( - reader_berlin[reader_berlin["rank"] == 1]["answer"].iloc[0] - in reader_berlin[reader_berlin["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_berlin[retriever_berlin["rank"] == 1]["document_id"].iloc[0] - in retriever_berlin[retriever_berlin["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert ( - reader_munich[reader_munich["rank"] == 1]["answer"].iloc[0] - not in reader_munich[reader_munich["rank"] == 1]["gold_answers"].iloc[0] - ) - assert ( - retriever_munich[retriever_munich["rank"] == 1]["document_id"].iloc[0] - not in retriever_munich[retriever_munich["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_sas(reader, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert "sas" in metrics["Reader"] - assert metrics["Reader"]["sas"] == pytest.approx(1.0) - - -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_reader_eval_in_pipeline(reader): - pipeline = Pipeline() - pipeline.add_node(component=reader, name="Reader", inputs=["Query"]) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=EVAL_LABELS, - documents=[[label.document for label in multilabel.labels] for multilabel in EVAL_LABELS], - params={}, - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_extractive_qa_eval_document_scope(retriever_with_docs): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_and_context") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 1.0 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="answer") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - - metrics = eval_result.calculate_metrics(document_scope="document_id_or_answer") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_answer_scope(reader, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - metrics = eval_result.calculate_metrics(answer_scope="any") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Reader"]["sas"] == pytest.approx(1.0) - - metrics = eval_result.calculate_metrics(answer_scope="context") - - assert metrics["Retriever"]["mrr"] == 1.0 - assert metrics["Retriever"]["map"] == 1.0 - assert metrics["Retriever"]["recall_multi_hit"] == 1.0 - assert metrics["Retriever"]["recall_single_hit"] == 1.0 - assert metrics["Retriever"]["precision"] == 0.2 - assert metrics["Retriever"]["ndcg"] == 1.0 - assert metrics["Reader"]["exact_match"] == 1.0 - assert metrics["Reader"]["f1"] == 1.0 - assert metrics["Reader"]["sas"] == pytest.approx(1.0) - - metrics = eval_result.calculate_metrics(answer_scope="document_id") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert metrics["Reader"]["exact_match"] == 0.5 - assert metrics["Reader"]["f1"] == 0.5 - assert metrics["Reader"]["sas"] == pytest.approx(0.5) - - metrics = eval_result.calculate_metrics(answer_scope="document_id_and_context") - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert metrics["Reader"]["exact_match"] == 0.5 - assert metrics["Reader"]["f1"] == 0.5 - assert metrics["Reader"]["sas"] == pytest.approx(0.5) - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_answer_document_scope_combinations(reader, retriever_with_docs, caplog): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - context_matching_min_length=20, # artificially set down min_length to see if context matching is working properly - ) - - # valid values for non default answer_scopes - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id_or_answer", answer_scope="context") - eval_result.calculate_metrics(document_scope="answer", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" not in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="context", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id_and_context", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - with caplog.at_level(logging.WARNING): - eval_result.calculate_metrics(document_scope="document_id_or_context", answer_scope="context") - assert "You specified a non-answer document_scope together with a non-default answer_scope" in caplog.text - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_simulated_top_k_reader(reader, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=EVAL_LABELS, - params={"Retriever": {"top_k": 5}}, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - ) - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_reader=1, document_scope="document_id") - - assert metrics_top_1["Reader"]["exact_match"] == 0.5 - assert metrics_top_1["Reader"]["f1"] == 0.5 - assert metrics_top_1["Reader"]["sas"] == pytest.approx(0.6003, abs=1e-4) - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 0.1 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_2 = eval_result.calculate_metrics(simulated_top_k_reader=2, document_scope="document_id") - - assert metrics_top_2["Reader"]["exact_match"] == 0.5 - assert metrics_top_2["Reader"]["f1"] == 0.5 - assert metrics_top_2["Reader"]["sas"] == pytest.approx(0.6003, abs=1e-4) - assert metrics_top_2["Retriever"]["mrr"] == 0.5 - assert metrics_top_2["Retriever"]["map"] == 0.5 - assert metrics_top_2["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_2["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_2["Retriever"]["precision"] == 0.1 - assert metrics_top_2["Retriever"]["ndcg"] == 0.5 - - metrics_top_5 = eval_result.calculate_metrics(simulated_top_k_reader=5, document_scope="document_id") - - assert metrics_top_5["Reader"]["exact_match"] == 1.0 - assert metrics_top_5["Reader"]["f1"] == 1.0 - assert metrics_top_5["Reader"]["sas"] == pytest.approx(1.0, abs=1e-4) - assert metrics_top_5["Retriever"]["mrr"] == 0.5 - assert metrics_top_5["Retriever"]["map"] == 0.5 - assert metrics_top_5["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_5["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_5["Retriever"]["precision"] == 0.1 - assert metrics_top_5["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_simulated_top_k_retriever(reader, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch(labels=EVAL_LABELS, params={"Retriever": {"top_k": 5}}) - - metrics_top_10 = eval_result.calculate_metrics(document_scope="document_id") - - assert metrics_top_10["Reader"]["exact_match"] == 1.0 - assert metrics_top_10["Reader"]["f1"] == 1.0 - assert metrics_top_10["Retriever"]["mrr"] == 0.5 - assert metrics_top_10["Retriever"]["map"] == 0.5 - assert metrics_top_10["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_10["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_10["Retriever"]["precision"] == 0.1 - assert metrics_top_10["Retriever"]["ndcg"] == 0.5 - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_retriever=1, document_scope="document_id") - - assert metrics_top_1["Reader"]["exact_match"] == 1.0 - assert metrics_top_1["Reader"]["f1"] == 1.0 - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 0.5 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_2 = eval_result.calculate_metrics(simulated_top_k_retriever=2, document_scope="document_id") - - assert metrics_top_2["Reader"]["exact_match"] == 1.0 - assert metrics_top_2["Reader"]["f1"] == 1.0 - assert metrics_top_2["Retriever"]["mrr"] == 0.5 - assert metrics_top_2["Retriever"]["map"] == 0.5 - assert metrics_top_2["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_2["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_2["Retriever"]["precision"] == 0.25 - assert metrics_top_2["Retriever"]["ndcg"] == 0.5 - - metrics_top_3 = eval_result.calculate_metrics(simulated_top_k_retriever=3, document_scope="document_id") - - assert metrics_top_3["Reader"]["exact_match"] == 1.0 - assert metrics_top_3["Reader"]["f1"] == 1.0 - assert metrics_top_3["Retriever"]["mrr"] == 0.5 - assert metrics_top_3["Retriever"]["map"] == 0.5 - assert metrics_top_3["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_3["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_3["Retriever"]["precision"] == 1.0 / 6 - assert metrics_top_3["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_simulated_top_k_reader_and_retriever(reader, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch(labels=EVAL_LABELS, params={"Retriever": {"top_k": 10}}) - - metrics_top_10 = eval_result.calculate_metrics(simulated_top_k_reader=1, document_scope="document_id") - - assert metrics_top_10["Reader"]["exact_match"] == 0.5 - assert metrics_top_10["Reader"]["f1"] == 0.5 - assert metrics_top_10["Retriever"]["mrr"] == 0.5 - assert metrics_top_10["Retriever"]["map"] == 0.5 - assert metrics_top_10["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_10["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_10["Retriever"]["precision"] == 0.1 - assert metrics_top_10["Retriever"]["ndcg"] == 0.5 - - metrics_top_1 = eval_result.calculate_metrics( - simulated_top_k_reader=1, simulated_top_k_retriever=1, document_scope="document_id" - ) - - assert metrics_top_1["Reader"]["exact_match"] == 1.0 - assert metrics_top_1["Reader"]["f1"] == 1.0 - - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 0.5 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_2 = eval_result.calculate_metrics( - simulated_top_k_reader=1, simulated_top_k_retriever=2, document_scope="document_id" - ) - - assert metrics_top_2["Reader"]["exact_match"] == 0.5 - assert metrics_top_2["Reader"]["f1"] == 0.5 - assert metrics_top_2["Retriever"]["mrr"] == 0.5 - assert metrics_top_2["Retriever"]["map"] == 0.5 - assert metrics_top_2["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_2["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_2["Retriever"]["precision"] == 0.25 - assert metrics_top_2["Retriever"]["ndcg"] == 0.5 - - metrics_top_3 = eval_result.calculate_metrics( - simulated_top_k_reader=1, simulated_top_k_retriever=3, document_scope="document_id" - ) - - assert metrics_top_3["Reader"]["exact_match"] == 0.5 - assert metrics_top_3["Reader"]["f1"] == 0.5 - assert metrics_top_3["Retriever"]["mrr"] == 0.5 - assert metrics_top_3["Retriever"]["map"] == 0.5 - assert metrics_top_3["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_3["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_3["Retriever"]["precision"] == 1.0 / 6 - assert metrics_top_3["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_isolated(reader, retriever_with_docs): - labels = deepcopy(EVAL_LABELS) - # Copy one of the labels and change only the answer have a label with a different answer but same Document - label_copy = deepcopy(labels[0].labels[0]) - label_copy.answer = Answer(answer="I", offsets_in_context=[Span(21, 22)]) - labels[0].labels.append(label_copy) - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch( - labels=labels, - sas_model_name_or_path="sentence-transformers/paraphrase-MiniLM-L3-v2", - add_isolated_node_eval=True, - ) - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_reader=1, document_scope="document_id") - - assert metrics_top_1["Reader"]["exact_match"] == 0.5 - assert metrics_top_1["Reader"]["f1"] == 0.5 - assert metrics_top_1["Reader"]["sas"] == pytest.approx(0.6003, abs=1e-4) - assert metrics_top_1["Retriever"]["mrr"] == 0.5 - assert metrics_top_1["Retriever"]["map"] == 0.5 - assert metrics_top_1["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics_top_1["Retriever"]["recall_single_hit"] == 0.5 - assert metrics_top_1["Retriever"]["precision"] == 1.0 / 10 - assert metrics_top_1["Retriever"]["ndcg"] == 0.5 - - metrics_top_1 = eval_result.calculate_metrics(simulated_top_k_reader=1, eval_mode="isolated") - - assert metrics_top_1["Reader"]["exact_match"] == 1.0 - assert metrics_top_1["Reader"]["f1"] == 1.0 - assert metrics_top_1["Reader"]["sas"] == pytest.approx(1.0, abs=1e-4) - - # Check if same Document in MultiLabel got deduplicated - assert labels[0].labels[0].id == labels[0].labels[1].id - reader_eval_df = eval_result.node_results["Reader"] - isolated_reader_eval_df = reader_eval_df[reader_eval_df["eval_mode"] == "isolated"] - assert len(isolated_reader_eval_df) == len(labels) * reader.top_k_per_candidate - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_eval_wrong_examples(reader, retriever_with_docs): - labels = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=Answer(answer="Pete", offsets_in_context=[Span(11, 16)]), - document=Document( - id="something_else", content_type="text", content="My name is Pete and I live in Munich" - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - ] - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch(labels=labels, params={"Retriever": {"top_k": 5}}) - - wrongs_retriever = eval_result.wrong_examples(node="Retriever", n=1) - wrongs_reader = eval_result.wrong_examples(node="Reader", n=1) - - assert len(wrongs_retriever) == 1 - assert len(wrongs_reader) == 1 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -@pytest.mark.parametrize("reader", ["farm"], indirect=True) -def test_extractive_qa_print_eval_report(reader, retriever_with_docs): - labels = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=Answer(answer="Pete", offsets_in_context=[Span(11, 16)]), - document=Document( - id="something_else", content_type="text", content="My name is Pete and I live in Munich" - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - ] - - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch(labels=labels, params={"Retriever": {"top_k": 5}}) - pipeline.print_eval_report(eval_result) - - # in addition with labels as input to reader node rather than output of retriever node - eval_result: EvaluationResult = pipeline.eval_batch( - labels=labels, params={"Retriever": {"top_k": 5}}, add_isolated_node_eval=True - ) - pipeline.print_eval_report(eval_result) - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_document_search_calculate_metrics(retriever_with_docs): - pipeline = DocumentSearchPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch(labels=EVAL_LABELS, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert len(eval_result) == 1 - retriever_result = eval_result["Retriever"] - retriever_berlin = retriever_result[retriever_result["query"] == "Who lives in Berlin?"] - retriever_munich = retriever_result[retriever_result["query"] == "Who lives in Munich?"] - - assert ( - retriever_berlin[retriever_berlin["rank"] == 1]["document_id"].iloc[0] - in retriever_berlin[retriever_berlin["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert ( - retriever_munich[retriever_munich["rank"] == 1]["document_id"].iloc[0] - not in retriever_munich[retriever_munich["rank"] == 1]["gold_document_ids"].iloc[0] - ) - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_faq_calculate_metrics(retriever_with_docs): - pipeline = FAQPipeline(retriever=retriever_with_docs) - eval_result: EvaluationResult = pipeline.eval_batch(labels=EVAL_LABELS, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert "Docs2Answers" in eval_result - assert len(eval_result) == 2 - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - assert metrics["Docs2Answers"]["exact_match"] == 0.0 - assert metrics["Docs2Answers"]["f1"] == 0.0 - - -# Commented out because of the following issue https://github.com/deepset-ai/haystack/issues/2964 -# @pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -# @pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -# @pytest.mark.parametrize("reader", ["farm"], indirect=True) -# def test_extractive_qa_eval_translation(reader, retriever_with_docs): -# -# # FIXME it makes no sense to have DE->EN input and DE->EN output, right? -# # Yet switching direction breaks the test. TO BE FIXED. -# input_translator = TransformersTranslator(model_name_or_path="Helsinki-NLP/opus-mt-de-en") -# output_translator = TransformersTranslator(model_name_or_path="Helsinki-NLP/opus-mt-de-en") -# -# pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) -# pipeline = TranslationWrapperPipeline( -# input_translator=input_translator, output_translator=output_translator, pipeline=pipeline -# ) -# eval_result: EvaluationResult = pipeline.eval_batch(labels=EVAL_LABELS, params={"Retriever": {"top_k": 5}}) -# -# metrics = eval_result.calculate_metrics(document_scope="document_id") -# -# assert "Retriever" in eval_result -# assert "Reader" in eval_result -# assert "OutputTranslator" in eval_result -# assert len(eval_result) == 3 -# -# assert metrics["Reader"]["exact_match"] == 1.0 -# assert metrics["Reader"]["f1"] == 1.0 -# assert metrics["Retriever"]["mrr"] == 0.5 -# assert metrics["Retriever"]["map"] == 0.5 -# assert metrics["Retriever"]["recall_multi_hit"] == 0.5 -# assert metrics["Retriever"]["recall_single_hit"] == 0.5 -# assert metrics["Retriever"]["precision"] == 0.1 -# assert metrics["Retriever"]["ndcg"] == 0.5 -# -# assert metrics["OutputTranslator"]["exact_match"] == 1.0 -# assert metrics["OutputTranslator"]["f1"] == 1.0 -# assert metrics["OutputTranslator"]["mrr"] == 0.5 -# assert metrics["OutputTranslator"]["map"] == 0.5 -# assert metrics["OutputTranslator"]["recall_multi_hit"] == 0.5 -# assert metrics["OutputTranslator"]["recall_single_hit"] == 0.5 -# assert metrics["OutputTranslator"]["precision"] == 0.1 -# assert metrics["OutputTranslator"]["ndcg"] == 0.5 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_question_generation_eval(retriever_with_docs, question_generator): - pipeline = RetrieverQuestionGenerationPipeline(retriever=retriever_with_docs, question_generator=question_generator) - - eval_result: EvaluationResult = pipeline.eval_batch(labels=EVAL_LABELS, params={"Retriever": {"top_k": 5}}) - - metrics = eval_result.calculate_metrics(document_scope="document_id") - - assert "Retriever" in eval_result - assert "QuestionGenerator" in eval_result - assert len(eval_result) == 2 - - assert metrics["Retriever"]["mrr"] == 0.5 - assert metrics["Retriever"]["map"] == 0.5 - assert metrics["Retriever"]["recall_multi_hit"] == 0.5 - assert metrics["Retriever"]["recall_single_hit"] == 0.5 - assert metrics["Retriever"]["precision"] == 0.1 - assert metrics["Retriever"]["ndcg"] == 0.5 - - assert metrics["QuestionGenerator"]["mrr"] == 0.5 - assert metrics["QuestionGenerator"]["map"] == 0.5 - assert metrics["QuestionGenerator"]["recall_multi_hit"] == 0.5 - assert metrics["QuestionGenerator"]["recall_single_hit"] == 0.5 - assert metrics["QuestionGenerator"]["precision"] == 0.1 - assert metrics["QuestionGenerator"]["ndcg"] == 0.5 - - -# Commented out because of the following issue https://github.com/deepset-ai/haystack/issues/2962 -# @pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -# @pytest.mark.parametrize("reader", ["farm"], indirect=True) -# def test_qa_multi_retriever_pipeline_eval(document_store_with_docs, reader): -# es_retriever = BM25Retriever(document_store=document_store_with_docs) -# dpr_retriever = DensePassageRetriever(document_store_with_docs) -# document_store_with_docs.update_embeddings(retriever=dpr_retriever) -# -# # QA Pipeline with two retrievers, we always want QA output -# pipeline = Pipeline() -# pipeline.add_node(component=TransformersQueryClassifier(), name="QueryClassifier", inputs=["Query"]) -# pipeline.add_node(component=dpr_retriever, name="DPRRetriever", inputs=["QueryClassifier.output_1"]) -# pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["QueryClassifier.output_2"]) -# pipeline.add_node(component=reader, name="QAReader", inputs=["ESRetriever", "DPRRetriever"]) -# -# # EVAL_QUERIES: 2 go dpr way -# # in Berlin goes es way -# labels = EVAL_LABELS + [ -# MultiLabel( -# labels=[ -# Label( -# query="in Berlin", -# answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), -# document=Document( -# id="a0747b83aea0b60c4b114b15476dd32d", -# content_type="text", -# content="My name is Carla and I live in Berlin", -# ), -# is_correct_answer=True, -# is_correct_document=True, -# origin="gold-label", -# ) -# ] -# ) -# ] -# -# eval_result: EvaluationResult = pipeline.eval_batch( -# labels=labels, params={"ESRetriever": {"top_k": 5}, "DPRRetriever": {"top_k": 5}} -# ) -# -# metrics = eval_result.calculate_metrics(document_scope="document_id") -# -# assert "ESRetriever" in eval_result -# assert "DPRRetriever" in eval_result -# assert "QAReader" in eval_result -# assert len(eval_result) == 3 -# -# assert metrics["DPRRetriever"]["mrr"] == 0.5 -# assert metrics["DPRRetriever"]["map"] == 0.5 -# assert metrics["DPRRetriever"]["recall_multi_hit"] == 0.5 -# assert metrics["DPRRetriever"]["recall_single_hit"] == 0.5 -# assert metrics["DPRRetriever"]["precision"] == 0.1 -# assert metrics["DPRRetriever"]["ndcg"] == 0.5 -# -# assert metrics["ESRetriever"]["mrr"] == 1.0 -# assert metrics["ESRetriever"]["map"] == 1.0 -# assert metrics["ESRetriever"]["recall_multi_hit"] == 1.0 -# assert metrics["ESRetriever"]["recall_single_hit"] == 1.0 -# assert metrics["ESRetriever"]["precision"] == 0.2 -# assert metrics["ESRetriever"]["ndcg"] == 1.0 -# -# assert metrics["QAReader"]["exact_match"] == 1.0 -# assert metrics["QAReader"]["f1"] == 1.0 - - -# Commented out because of the following issue https://github.com/deepset-ai/haystack/issues/2962 -# @pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -# def test_multi_retriever_pipeline_eval(document_store_with_docs): -# es_retriever = BM25Retriever(document_store=document_store_with_docs) -# dpr_retriever = DensePassageRetriever(document_store_with_docs) -# document_store_with_docs.update_embeddings(retriever=dpr_retriever) -# -# # QA Pipeline with two retrievers, no QA output -# pipeline = Pipeline() -# pipeline.add_node(component=TransformersQueryClassifier(), name="QueryClassifier", inputs=["Query"]) -# pipeline.add_node(component=dpr_retriever, name="DPRRetriever", inputs=["QueryClassifier.output_1"]) -# pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["QueryClassifier.output_2"]) -# -# # EVAL_QUERIES: 2 go dpr way -# # in Berlin goes es way -# labels = EVAL_LABELS + [ -# MultiLabel( -# labels=[ -# Label( -# query="in Berlin", -# answer=None, -# document=Document( -# id="a0747b83aea0b60c4b114b15476dd32d", -# content_type="text", -# content="My name is Carla and I live in Berlin", -# ), -# is_correct_answer=True, -# is_correct_document=True, -# origin="gold-label", -# ) -# ] -# ) -# ] -# -# eval_result: EvaluationResult = pipeline.eval_batch( -# labels=labels, params={"ESRetriever": {"top_k": 5}, "DPRRetriever": {"top_k": 5}} -# ) -# -# metrics = eval_result.calculate_metrics(document_scope="document_id") -# -# assert "ESRetriever" in eval_result -# assert "DPRRetriever" in eval_result -# assert len(eval_result) == 2 -# -# assert metrics["DPRRetriever"]["mrr"] == 0.5 -# assert metrics["DPRRetriever"]["map"] == 0.5 -# assert metrics["DPRRetriever"]["recall_multi_hit"] == 0.5 -# assert metrics["DPRRetriever"]["recall_single_hit"] == 0.5 -# assert metrics["DPRRetriever"]["precision"] == 0.1 -# assert metrics["DPRRetriever"]["ndcg"] == 0.5 -# -# assert metrics["ESRetriever"]["mrr"] == 1.0 -# assert metrics["ESRetriever"]["map"] == 1.0 -# assert metrics["ESRetriever"]["recall_multi_hit"] == 1.0 -# assert metrics["ESRetriever"]["recall_single_hit"] == 1.0 -# assert metrics["ESRetriever"]["precision"] == 0.2 -# assert metrics["ESRetriever"]["ndcg"] == 1.0 - - -# Commented out because of the following issue https://github.com/deepset-ai/haystack/issues/2962 -# @pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -# @pytest.mark.parametrize("reader", ["farm"], indirect=True) -# def test_multi_retriever_pipeline_with_asymmetric_qa_eval(document_store_with_docs, reader): -# es_retriever = BM25Retriever(document_store=document_store_with_docs) -# dpr_retriever = DensePassageRetriever(document_store_with_docs) -# document_store_with_docs.update_embeddings(retriever=dpr_retriever) -# -# # QA Pipeline with two retrievers, we only get QA output from dpr -# pipeline = Pipeline() -# pipeline.add_node(component=TransformersQueryClassifier(), name="QueryClassifier", inputs=["Query"]) -# pipeline.add_node(component=dpr_retriever, name="DPRRetriever", inputs=["QueryClassifier.output_1"]) -# pipeline.add_node(component=es_retriever, name="ESRetriever", inputs=["QueryClassifier.output_2"]) -# pipeline.add_node(component=reader, name="QAReader", inputs=["DPRRetriever"]) -# -# # EVAL_QUERIES: 2 go dpr way -# # in Berlin goes es way -# labels = EVAL_LABELS + [ -# MultiLabel( -# labels=[ -# Label( -# query="in Berlin", -# answer=None, -# document=Document( -# id="a0747b83aea0b60c4b114b15476dd32d", -# content_type="text", -# content="My name is Carla and I live in Berlin", -# ), -# is_correct_answer=True, -# is_correct_document=True, -# origin="gold-label", -# ) -# ] -# ) -# ] -# -# eval_result: EvaluationResult = pipeline.eval_batch( -# labels=labels, params={"ESRetriever": {"top_k": 5}, "DPRRetriever": {"top_k": 5}} -# ) -# -# metrics = eval_result.calculate_metrics(document_scope="document_id") -# -# assert "ESRetriever" in eval_result -# assert "DPRRetriever" in eval_result -# assert "QAReader" in eval_result -# assert len(eval_result) == 3 -# -# assert metrics["DPRRetriever"]["mrr"] == 0.5 -# assert metrics["DPRRetriever"]["map"] == 0.5 -# assert metrics["DPRRetriever"]["recall_multi_hit"] == 0.5 -# assert metrics["DPRRetriever"]["recall_single_hit"] == 0.5 -# assert metrics["DPRRetriever"]["precision"] == 0.1 -# assert metrics["DPRRetriever"]["ndcg"] == 0.5 -# -# assert metrics["ESRetriever"]["mrr"] == 1.0 -# assert metrics["ESRetriever"]["map"] == 1.0 -# assert metrics["ESRetriever"]["recall_multi_hit"] == 1.0 -# assert metrics["ESRetriever"]["recall_single_hit"] == 1.0 -# assert metrics["ESRetriever"]["precision"] == 0.2 -# assert metrics["ESRetriever"]["ndcg"] == 1.0 -# -# assert metrics["QAReader"]["exact_match"] == 1.0 -# assert metrics["QAReader"]["f1"] == 1.0 diff --git a/test/pipelines/test_pipeline.py b/test/pipelines/test_pipeline.py deleted file mode 100644 index 69fa27f0b9..0000000000 --- a/test/pipelines/test_pipeline.py +++ /dev/null @@ -1,2131 +0,0 @@ -import ssl -import json -import platform -import sys -from typing import Tuple -from copy import deepcopy -from unittest import mock - -import pytest -from requests import PreparedRequest -import responses -import logging -import yaml - -from haystack import __version__ -from haystack.document_stores.deepsetcloud import DeepsetCloudDocumentStore -from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore -from haystack.document_stores.memory import InMemoryDocumentStore -from haystack.nodes.other.join_docs import JoinDocuments -from haystack.nodes.base import BaseComponent -from haystack.nodes.retriever.sparse import BM25Retriever -from haystack.nodes.retriever.sparse import FilterRetriever -from haystack.pipelines import ( - Pipeline, - RootNode, - GenerativeQAPipeline, - FAQPipeline, - ExtractiveQAPipeline, - SearchSummarizationPipeline, - TranslationWrapperPipeline, - RetrieverQuestionGenerationPipeline, - QuestionAnswerGenerationPipeline, - DocumentSearchPipeline, - QuestionGenerationPipeline, - MostSimilarDocumentsPipeline, -) -from haystack.pipelines.config import get_component_definitions -from haystack.pipelines.utils import generate_code -from haystack.errors import PipelineConfigError -from haystack.nodes import PreProcessor, TextConverter -from haystack.utils.deepsetcloud import DeepsetCloudError -from haystack import Answer - -from ..conftest import ( - MOCK_DC, - DC_API_ENDPOINT, - DC_API_KEY, - DC_TEST_INDEX, - MockDocumentStore, - MockSeq2SegGenerator, - MockRetriever, - MockNode, - deepset_cloud_fixture, - MockReader, - MockSummarizer, - MockTranslator, - MockQuestionGenerator, -) - -logger = logging.getLogger(__name__) - - -@pytest.fixture -def reduce_windows_recursion_limit(): - """ - Prevents Windows CI from crashing with Stackoverflow in situations we want to provoke a RecursionError - """ - is_windows = platform.system() == "Windows" - default_recursion_limit = sys.getrecursionlimit() - if is_windows: - reduced_recursion_limit = default_recursion_limit // 2 - logger.warning("Reducing recursion limit to %s", reduced_recursion_limit) - sys.setrecursionlimit(reduced_recursion_limit) - yield - if is_windows: - logger.warning("Resetting recursion limit to %s", default_recursion_limit) - sys.setrecursionlimit(default_recursion_limit) - - -class ParentComponent(BaseComponent): - outgoing_edges = 1 - - def __init__(self, dependent: BaseComponent) -> None: - super().__init__() - - def run(*args, **kwargs): - logger.info("ParentComponent run() was called") - - def run_batch(*args, **kwargs): - pass - - -class ParentComponent2(BaseComponent): - outgoing_edges = 1 - - def __init__(self, dependent: BaseComponent) -> None: - super().__init__() - - def run(*args, **kwargs): - logger.info("ParentComponent2 run() was called") - - def run_batch(*args, **kwargs): - pass - - -class ChildComponent(BaseComponent): - outgoing_edges = 0 - - def __init__(self, some_key: str = None) -> None: - super().__init__() - - def run(*args, **kwargs): - logger.info("ChildComponent run() was called") - - def run_batch(*args, **kwargs): - pass - - -class DummyRetriever(MockRetriever): - def __init__(self, document_store): - self.document_store = document_store - - def run(self): - test = "test" - return {"test": test}, "output_1" - - -class JoinNode(RootNode): - def run(self, output=None, inputs=None): - if inputs: - output = "" - for input_dict in inputs: - output += input_dict["output"] - return {"output": output}, "output_1" - - -# -# Integration tests -# - - -@pytest.mark.integration -@pytest.mark.elasticsearch -def test_to_code_creates_same_pipelines(samples_path): - index_pipeline = Pipeline.load_from_yaml( - samples_path / "pipeline" / "test.haystack-pipeline.yml", pipeline_name="indexing_pipeline" - ) - query_pipeline = Pipeline.load_from_yaml( - samples_path / "pipeline" / "test.haystack-pipeline.yml", pipeline_name="query_pipeline" - ) - query_pipeline_code = query_pipeline.to_code(pipeline_variable_name="query_pipeline_from_code") - index_pipeline_code = index_pipeline.to_code(pipeline_variable_name="index_pipeline_from_code") - - exec(query_pipeline_code) - exec(index_pipeline_code) - assert locals()["query_pipeline_from_code"] is not None - assert locals()["index_pipeline_from_code"] is not None - assert query_pipeline.get_config() == locals()["query_pipeline_from_code"].get_config() - assert index_pipeline.get_config() == locals()["index_pipeline_from_code"].get_config() - - -# -# Unit tests -# - - -@pytest.mark.unit -def test_get_config_creates_dependent_component(): - child = ChildComponent() - parent = ParentComponent(dependent=child) - pipeline = Pipeline() - pipeline.add_node(component=parent, name="parent", inputs=["Query"]) - - expected_pipelines = [{"name": "query", "nodes": [{"name": "parent", "inputs": ["Query"]}]}] - expected_components = [ - {"name": "parent", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - {"name": "ChildComponent", "type": "ChildComponent", "params": {}}, - ] - - config = pipeline.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_creates_only_one_dependent_component_referenced_by_multiple_parents(): - child = ChildComponent() - parent = ParentComponent(dependent=child) - parent2 = ParentComponent2(dependent=child) - p_ensemble = Pipeline() - p_ensemble.add_node(component=parent, name="Parent1", inputs=["Query"]) - p_ensemble.add_node(component=parent2, name="Parent2", inputs=["Query"]) - p_ensemble.add_node(component=JoinDocuments(join_mode="merge"), name="JoinResults", inputs=["Parent1", "Parent2"]) - - expected_components = [ - {"name": "Parent1", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - {"name": "ChildComponent", "type": "ChildComponent", "params": {}}, - {"name": "Parent2", "type": "ParentComponent2", "params": {"dependent": "ChildComponent"}}, - {"name": "JoinResults", "type": "JoinDocuments", "params": {"join_mode": "merge"}}, - ] - - expected_pipelines = [ - { - "name": "query", - "nodes": [ - {"name": "Parent1", "inputs": ["Query"]}, - {"name": "Parent2", "inputs": ["Query"]}, - {"name": "JoinResults", "inputs": ["Parent1", "Parent2"]}, - ], - } - ] - - config = p_ensemble.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_creates_two_different_dependent_components_of_same_type(): - child_a = ChildComponent(some_key="A") - child_b = ChildComponent(some_key="B") - parent = ParentComponent(dependent=child_a) - parent2 = ParentComponent(dependent=child_b) - p_ensemble = Pipeline() - p_ensemble.add_node(component=parent, name="ParentA", inputs=["Query"]) - p_ensemble.add_node(component=parent2, name="ParentB", inputs=["Query"]) - p_ensemble.add_node(component=JoinDocuments(join_mode="merge"), name="JoinResults", inputs=["ParentA", "ParentB"]) - - expected_components = [ - {"name": "ParentA", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - {"name": "ChildComponent", "type": "ChildComponent", "params": {"some_key": "A"}}, - {"name": "ParentB", "type": "ParentComponent", "params": {"dependent": "ChildComponent_2"}}, - {"name": "ChildComponent_2", "type": "ChildComponent", "params": {"some_key": "B"}}, - {"name": "JoinResults", "type": "JoinDocuments", "params": {"join_mode": "merge"}}, - ] - - expected_pipelines = [ - { - "name": "query", - "nodes": [ - {"name": "ParentA", "inputs": ["Query"]}, - {"name": "ParentB", "inputs": ["Query"]}, - {"name": "JoinResults", "inputs": ["ParentA", "ParentB"]}, - ], - } - ] - - config = p_ensemble.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_reuses_same_dependent_components(): - child = ChildComponent() - parent = ParentComponent(dependent=child) - pipeline = Pipeline() - pipeline.add_node(component=parent, name="parent", inputs=["Query"]) - pipeline.add_node(component=child, name="child", inputs=["parent"]) - config = pipeline.get_config() - - expected_pipelines = [ - {"name": "query", "nodes": [{"name": "parent", "inputs": ["Query"]}, {"name": "child", "inputs": ["parent"]}]} - ] - expected_components = [ - {"name": "parent", "type": "ParentComponent", "params": {"dependent": "child"}}, - {"name": "child", "type": "ChildComponent", "params": {}}, - ] - - config = pipeline.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_creates_different_components_if_instances_differ(): - child_a = ChildComponent() - child_b = ChildComponent() - child_c = ChildComponent() - parent = ParentComponent(dependent=child_a) - parent2 = ParentComponent(dependent=child_b) - p_ensemble = Pipeline() - p_ensemble.add_node(component=parent, name="ParentA", inputs=["Query"]) - p_ensemble.add_node(component=parent2, name="ParentB", inputs=["Query"]) - p_ensemble.add_node(component=child_c, name="Child", inputs=["Query"]) - - expected_components = [ - {"name": "ParentA", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - {"name": "ChildComponent", "type": "ChildComponent", "params": {}}, - {"name": "ParentB", "type": "ParentComponent", "params": {"dependent": "ChildComponent_2"}}, - {"name": "ChildComponent_2", "type": "ChildComponent", "params": {}}, - {"name": "Child", "type": "ChildComponent", "params": {}}, - ] - - expected_pipelines = [ - { - "name": "query", - "nodes": [ - {"name": "ParentA", "inputs": ["Query"]}, - {"name": "ParentB", "inputs": ["Query"]}, - {"name": "Child", "inputs": ["Query"]}, - ], - } - ] - - config = p_ensemble.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_reuses_same_unnamed_dependent_components(): - child = ChildComponent() - parent = ParentComponent(dependent=child) - parent2 = ParentComponent(dependent=child) - p_ensemble = Pipeline() - p_ensemble.add_node(component=parent, name="ParentA", inputs=["Query"]) - p_ensemble.add_node(component=parent2, name="ParentB", inputs=["Query"]) - - expected_components = [ - {"name": "ParentA", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - {"name": "ChildComponent", "type": "ChildComponent", "params": {}}, - {"name": "ParentB", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - ] - - expected_pipelines = [ - {"name": "query", "nodes": [{"name": "ParentA", "inputs": ["Query"]}, {"name": "ParentB", "inputs": ["Query"]}]} - ] - - config = p_ensemble.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_multi_level_dependencies(): - child = ChildComponent() - intermediate = ParentComponent(dependent=child) - parent = ParentComponent(dependent=intermediate) - p_ensemble = Pipeline() - p_ensemble.add_node(component=parent, name="Parent", inputs=["Query"]) - - expected_components = [ - {"name": "Parent", "type": "ParentComponent", "params": {"dependent": "ParentComponent"}}, - {"name": "ChildComponent", "type": "ChildComponent", "params": {}}, - {"name": "ParentComponent", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - ] - - expected_pipelines = [{"name": "query", "nodes": [{"name": "Parent", "inputs": ["Query"]}]}] - - config = p_ensemble.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_multi_level_dependencies_of_same_type(): - child = ChildComponent() - second_intermediate = ParentComponent(dependent=child) - intermediate = ParentComponent(dependent=second_intermediate) - parent = ParentComponent(dependent=intermediate) - p_ensemble = Pipeline() - p_ensemble.add_node(component=parent, name="ParentComponent", inputs=["Query"]) - - expected_components = [ - {"name": "ParentComponent_3", "type": "ParentComponent", "params": {"dependent": "ChildComponent"}}, - {"name": "ParentComponent_2", "type": "ParentComponent", "params": {"dependent": "ParentComponent_3"}}, - {"name": "ParentComponent", "type": "ParentComponent", "params": {"dependent": "ParentComponent_2"}}, - {"name": "ChildComponent", "type": "ChildComponent", "params": {}}, - ] - - expected_pipelines = [{"name": "query", "nodes": [{"name": "ParentComponent", "inputs": ["Query"]}]}] - - config = p_ensemble.get_config() - for expected_pipeline in expected_pipelines: - assert expected_pipeline in config["pipelines"] - for expected_component in expected_components: - assert expected_component in config["components"] - - -@pytest.mark.unit -def test_get_config_component_with_superclass_arguments(): - class CustomBaseDocumentStore(MockDocumentStore): - def __init__(self, base_parameter: str): - self.base_parameter = base_parameter - - class CustomDocumentStore(CustomBaseDocumentStore): - def __init__(self, sub_parameter: int): - super().__init__(base_parameter="something") - self.sub_parameter = sub_parameter - - class CustomRetriever(MockRetriever): - def __init__(self, document_store): - super().__init__() - self.document_store = document_store - - document_store = CustomDocumentStore(sub_parameter=10) - retriever = CustomRetriever(document_store=document_store) - pipeline = Pipeline() - pipeline.add_node(retriever, name="Retriever", inputs=["Query"]) - - pipeline.get_config() - assert pipeline.get_document_store().sub_parameter == 10 - assert pipeline.get_document_store().base_parameter == "something" - - -@pytest.mark.unit -def test_get_config_custom_node_with_params(): - class CustomNode(MockNode): - def __init__(self, param: int): - super().__init__() - self.param = param - - pipeline = Pipeline() - pipeline.add_node(CustomNode(param=10), name="custom_node", inputs=["Query"]) - - assert len(pipeline.get_config()["components"]) == 1 - assert pipeline.get_config()["components"][0]["params"] == {"param": 10} - - -@pytest.mark.unit -def test_get_config_custom_node_with_positional_params(): - class CustomNode(MockNode): - def __init__(self, param: int = 1): - super().__init__() - self.param = param - - pipeline = Pipeline() - pipeline.add_node(CustomNode(10), name="custom_node", inputs=["Query"]) - - assert len(pipeline.get_config()["components"]) == 1 - assert pipeline.get_config()["components"][0]["params"] == {"param": 10} - - -@pytest.mark.unit -def test_get_config_multi_output_node(): - class MultiOutputNode(BaseComponent): - outgoing_edges = 2 - - def run(self, *a, **k): - pass - - def run_batch(self, *a, **k): - pass - - pipeline = Pipeline() - pipeline.add_node(MultiOutputNode(), name="multi_output_node", inputs=["Query"]) - pipeline.add_node(MockNode(), name="fork_1", inputs=["multi_output_node.output_1"]) - pipeline.add_node(MockNode(), name="fork_2", inputs=["multi_output_node.output_2"]) - pipeline.add_node(JoinNode(), name="join_node", inputs=["fork_1", "fork_2"]) - - config = pipeline.get_config() - assert len(config["components"]) == 4 - assert len(config["pipelines"]) == 1 - nodes = config["pipelines"][0]["nodes"] - assert len(nodes) == 4 - - assert nodes[0]["name"] == "multi_output_node" - assert len(nodes[0]["inputs"]) == 1 - assert "Query" in nodes[0]["inputs"] - - assert nodes[1]["name"] == "fork_1" - assert len(nodes[1]["inputs"]) == 1 - assert "multi_output_node.output_1" in nodes[1]["inputs"] - - assert nodes[2]["name"] == "fork_2" - assert len(nodes[2]["inputs"]) == 1 - assert "multi_output_node.output_2" in nodes[2]["inputs"] - - assert nodes[3]["name"] == "join_node" - assert len(nodes[3]["inputs"]) == 2 - assert "fork_1" in nodes[3]["inputs"] - assert "fork_2" in nodes[3]["inputs"] - - -@pytest.mark.unit -def test_generate_code_simple_pipeline(): - config = { - "version": "ignore", - "components": [ - { - "name": "retri", - "type": "BM25Retriever", - "params": {"document_store": "ElasticsearchDocumentStore", "top_k": 20}, - }, - { - "name": "ElasticsearchDocumentStore", - "type": "ElasticsearchDocumentStore", - "params": {"index": "my-index"}, - }, - ], - "pipelines": [{"name": "query", "nodes": [{"name": "retri", "inputs": ["Query"]}]}], - } - - code = generate_code(pipeline_config=config, pipeline_variable_name="p", generate_imports=False) - assert code == ( - 'elasticsearch_document_store = ElasticsearchDocumentStore(index="my-index")\n' - "retri = BM25Retriever(document_store=elasticsearch_document_store, top_k=20)\n" - "\n" - "p = Pipeline()\n" - 'p.add_node(component=retri, name="retri", inputs=["Query"])' - ) - - -@pytest.mark.unit -def test_generate_code_imports(): - pipeline_config = { - "version": "ignore", - "components": [ - {"name": "DocumentStore", "type": "ElasticsearchDocumentStore"}, - {"name": "retri", "type": "BM25Retriever", "params": {"document_store": "DocumentStore"}}, - {"name": "retri2", "type": "TfidfRetriever", "params": {"document_store": "DocumentStore"}}, - ], - "pipelines": [ - { - "name": "Query", - "nodes": [{"name": "retri", "inputs": ["Query"]}, {"name": "retri2", "inputs": ["Query"]}], - } - ], - } - - code = generate_code(pipeline_config=pipeline_config, pipeline_variable_name="p", generate_imports=True) - assert code == ( - "from haystack.document_stores import ElasticsearchDocumentStore\n" - "from haystack.nodes import BM25Retriever, TfidfRetriever\n" - "from haystack.pipelines import Pipeline\n" - "\n" - "document_store = ElasticsearchDocumentStore()\n" - 'document_store.name = "DocumentStore"\n' - "retri = BM25Retriever(document_store=document_store)\n" - "retri_2 = TfidfRetriever(document_store=document_store)\n" - "\n" - "p = Pipeline()\n" - 'p.add_node(component=retri, name="retri", inputs=["Query"])\n' - 'p.add_node(component=retri_2, name="retri2", inputs=["Query"])' - ) - - -@pytest.mark.unit -def test_generate_code_imports_no_pipeline_cls(): - pipeline_config = { - "version": "ignore", - "components": [ - {"name": "DocumentStore", "type": "ElasticsearchDocumentStore"}, - {"name": "retri", "type": "BM25Retriever", "params": {"document_store": "DocumentStore"}}, - ], - "pipelines": [{"name": "Query", "nodes": [{"name": "retri", "inputs": ["Query"]}]}], - } - - code = generate_code( - pipeline_config=pipeline_config, - pipeline_variable_name="p", - generate_imports=True, - add_pipeline_cls_import=False, - ) - assert code == ( - "from haystack.document_stores import ElasticsearchDocumentStore\n" - "from haystack.nodes import BM25Retriever\n" - "\n" - "document_store = ElasticsearchDocumentStore()\n" - 'document_store.name = "DocumentStore"\n' - "retri = BM25Retriever(document_store=document_store)\n" - "\n" - "p = Pipeline()\n" - 'p.add_node(component=retri, name="retri", inputs=["Query"])' - ) - - -@pytest.mark.unit -def test_generate_code_comment(): - pipeline_config = { - "version": "ignore", - "components": [ - {"name": "DocumentStore", "type": "ElasticsearchDocumentStore"}, - {"name": "retri", "type": "BM25Retriever", "params": {"document_store": "DocumentStore"}}, - ], - "pipelines": [{"name": "Query", "nodes": [{"name": "retri", "inputs": ["Query"]}]}], - } - - comment = "This is my comment\n...and here is a new line" - code = generate_code(pipeline_config=pipeline_config, pipeline_variable_name="p", comment=comment) - assert code == ( - "# This is my comment\n" - "# ...and here is a new line\n" - "from haystack.document_stores import ElasticsearchDocumentStore\n" - "from haystack.nodes import BM25Retriever\n" - "from haystack.pipelines import Pipeline\n" - "\n" - "document_store = ElasticsearchDocumentStore()\n" - 'document_store.name = "DocumentStore"\n' - "retri = BM25Retriever(document_store=document_store)\n" - "\n" - "p = Pipeline()\n" - 'p.add_node(component=retri, name="retri", inputs=["Query"])' - ) - - -@pytest.mark.unit -def test_generate_code_is_component_order_invariant(): - pipeline_config = { - "version": "ignore", - "pipelines": [ - { - "name": "Query", - "nodes": [ - {"name": "EsRetriever", "inputs": ["Query"]}, - {"name": "EmbeddingRetriever", "inputs": ["Query"]}, - {"name": "JoinResults", "inputs": ["EsRetriever", "EmbeddingRetriever"]}, - ], - } - ], - } - - doc_store = {"name": "ElasticsearchDocumentStore", "type": "ElasticsearchDocumentStore"} - es_retriever = { - "name": "EsRetriever", - "type": "BM25Retriever", - "params": {"document_store": "ElasticsearchDocumentStore"}, - } - emb_retriever = { - "name": "EmbeddingRetriever", - "type": "EmbeddingRetriever", - "params": { - "document_store": "ElasticsearchDocumentStore", - "embedding_model": "sentence-transformers/all-MiniLM-L6-v2", - }, - } - join_node = {"name": "JoinResults", "type": "JoinDocuments"} - - component_orders = [ - [doc_store, es_retriever, emb_retriever, join_node], - [es_retriever, emb_retriever, join_node, doc_store], - [join_node, es_retriever, emb_retriever, doc_store], - ] - - expected_code = ( - "elasticsearch_document_store = ElasticsearchDocumentStore()\n" - "es_retriever = BM25Retriever(document_store=elasticsearch_document_store)\n" - 'embedding_retriever = EmbeddingRetriever(document_store=elasticsearch_document_store, embedding_model="sentence-transformers/all-MiniLM-L6-v2")\n' - "join_results = JoinDocuments()\n" - "\n" - "p = Pipeline()\n" - 'p.add_node(component=es_retriever, name="EsRetriever", inputs=["Query"])\n' - 'p.add_node(component=embedding_retriever, name="EmbeddingRetriever", inputs=["Query"])\n' - 'p.add_node(component=join_results, name="JoinResults", inputs=["EsRetriever", "EmbeddingRetriever"])' - ) - - for components in component_orders: - pipeline_config["components"] = components - - code = generate_code(pipeline_config=pipeline_config, pipeline_variable_name="p", generate_imports=False) - assert code == expected_code - - -@pytest.mark.unit -def test_generate_code_can_handle_weak_cyclic_pipelines(): - config = { - "version": "ignore", - "components": [ - {"name": "parent", "type": "ParentComponent", "params": {"dependent": "child"}}, - {"name": "child", "type": "ChildComponent", "params": {}}, - ], - "pipelines": [ - { - "name": "query", - "nodes": [{"name": "parent", "inputs": ["Query"]}, {"name": "child", "inputs": ["parent"]}], - } - ], - } - code = generate_code(pipeline_config=config, generate_imports=False) - assert code == ( - "child = ChildComponent()\n" - "parent = ParentComponent(dependent=child)\n" - "\n" - "pipeline = Pipeline()\n" - 'pipeline.add_node(component=parent, name="parent", inputs=["Query"])\n' - 'pipeline.add_node(component=child, name="child", inputs=["parent"])' - ) - - -@pytest.mark.unit -def test_pipeline_classify_type(tmp_path): - pipe = GenerativeQAPipeline(generator=MockSeq2SegGenerator(), retriever=MockRetriever()) - assert pipe.get_type().startswith("GenerativeQAPipeline") - - pipe = FAQPipeline(retriever=MockRetriever()) - assert pipe.get_type().startswith("FAQPipeline") - - pipe = ExtractiveQAPipeline(reader=MockReader(), retriever=MockRetriever()) - assert pipe.get_type().startswith("ExtractiveQAPipeline") - - search_pipe = SearchSummarizationPipeline(summarizer=MockSummarizer(), retriever=MockRetriever()) - assert search_pipe.get_type().startswith("SearchSummarizationPipeline") - - pipe = RetrieverQuestionGenerationPipeline(retriever=MockRetriever(), question_generator=MockQuestionGenerator()) - assert pipe.get_type().startswith("RetrieverQuestionGenerationPipeline") - - qag_pipe = QuestionAnswerGenerationPipeline(question_generator=MockQuestionGenerator(), reader=MockReader()) - assert qag_pipe.get_type().startswith("QuestionAnswerGenerationPipeline") - - pipe = DocumentSearchPipeline(retriever=MockRetriever()) - assert pipe.get_type().startswith("DocumentSearchPipeline") - - pipe = QuestionGenerationPipeline(question_generator=MockQuestionGenerator()) - assert pipe.get_type().startswith("QuestionGenerationPipeline") - - pipe = TranslationWrapperPipeline( - input_translator=MockTranslator(), output_translator=MockTranslator(), pipeline=qag_pipe - ) - pipe.get_type().startswith("TranslationWrapperPipeline") - - pipe = MostSimilarDocumentsPipeline(document_store=MockDocumentStore()) - assert pipe.get_type().startswith("MostSimilarDocumentsPipeline") - - # previously misclassified as "UnknownPipeline" - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: document_store - type: MockDocumentStore - - name: retriever - type: MockRetriever - - name: retriever_2 - type: MockRetriever - pipelines: - - name: my_pipeline - nodes: - - name: retriever - inputs: - - Query - - name: retriever_2 - inputs: - - Query - - name: document_store - inputs: - - retriever - - """ - ) - pipe = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - # two retrievers but still a DocumentSearchPipeline - assert pipe.get_type().startswith("DocumentSearchPipeline") - - # previously misclassified as "UnknownPipeline" - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: document_store - type: MockDocumentStore - - name: retriever - type: MockRetriever - - name: retriever_2 - type: MockRetriever - - name: retriever_3 - type: MockRetriever - pipelines: - - name: my_pipeline - nodes: - - name: retriever - inputs: - - Query - - name: retriever_2 - inputs: - - Query - - name: retriever_3 - inputs: - - Query - - name: document_store - inputs: - - retriever - - """ - ) - pipe = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - # three retrievers but still a DocumentSearchPipeline - assert pipe.get_type().startswith("DocumentSearchPipeline") - - # previously misclassified as "UnknownPipeline" - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: document_store - type: MockDocumentStore - - name: retriever - type: BM25Retriever - pipelines: - - name: my_pipeline - nodes: - - name: retriever - inputs: - - Query - - name: document_store - inputs: - - retriever - - """ - ) - pipe = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - # BM25Retriever used - still a DocumentSearchPipeline - assert pipe.get_type().startswith("DocumentSearchPipeline") - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_load_from_deepset_cloud_query(samples_path): - if MOCK_DC: - with open(samples_path / "dc" / "pipeline_config.json", "r") as f: - pipeline_config_yaml_response = json.load(f) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/{DC_TEST_INDEX}/json", - json=pipeline_config_yaml_response, - status=200, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}/documents-query", - json=[{"id": "test_doc", "content": "man on hores"}], - status=200, - ) - - query_pipeline = Pipeline.load_from_deepset_cloud( - pipeline_config_name=DC_TEST_INDEX, api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - retriever = query_pipeline.get_node("Retriever") - document_store = retriever.document_store - assert isinstance(retriever, BM25Retriever) - assert isinstance(document_store, DeepsetCloudDocumentStore) - assert document_store == query_pipeline.get_document_store() - assert document_store.name == "DocumentStore" - - prediction = query_pipeline.run(query="man on horse", params={}) - - assert prediction["query"] == "man on horse" - assert len(prediction["documents"]) == 1 - assert prediction["documents"][0].id == "test_doc" - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_load_from_deepset_cloud_indexing(caplog, samples_path): - if MOCK_DC: - with open(samples_path / "dc" / "pipeline_config.json", "r") as f: - pipeline_config_yaml_response = json.load(f) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/{DC_TEST_INDEX}/json", - json=pipeline_config_yaml_response, - status=200, - ) - - indexing_pipeline = Pipeline.load_from_deepset_cloud( - pipeline_config_name=DC_TEST_INDEX, api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, pipeline_name="indexing" - ) - document_store = indexing_pipeline.get_node("DocumentStore") - assert isinstance(document_store, DeepsetCloudDocumentStore) - - with caplog.at_level(logging.INFO): - indexing_pipeline.run(file_paths=[samples_path / "docs" / "doc_1.txt"]) - assert "Note that DeepsetCloudDocumentStore does not support write operations." in caplog.text - assert "Input to write_documents: {" in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_list_pipelines_on_deepset_cloud(): - pipelines = Pipeline.list_pipelines_on_deepset_cloud(api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY) - assert len(pipelines) == 1 - assert pipelines[0]["name"] == DC_TEST_INDEX - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_save_to_deepset_cloud(samples_path): - if MOCK_DC: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_pipeline_config", - json={ - "name": "test_pipeline_config", - "pipeline_id": "2184e9c1-c6ec-40a1-9b28-5d2768e5efa2", - "status": "UNDEPLOYED", - "created_at": "2022-02-01T09:57:03.803991+00:00", - "deleted": False, - "is_default": False, - "indexing": {"status": "IN_PROGRESS", "pending_file_count": 4, "total_file_count": 33}, - }, - status=200, - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_pipeline_config_deployed", - json={ - "name": "test_pipeline_config_deployed", - "pipeline_id": "8184e0c1-c6ec-40a1-9b28-5d2768e5efa3", - "status": "DEPLOYED", - "created_at": "2022-02-09T09:57:03.803991+00:00", - "deleted": False, - "is_default": False, - "indexing": {"status": "INDEXED", "pending_file_count": 0, "total_file_count": 33}, - }, - status=200, - ) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_pipeline_config_copy", - json={"errors": ["Pipeline with the name test_pipeline_config_copy does not exists."]}, - status=404, - ) - - with open(samples_path / "dc" / "pipeline_config.json", "r") as f: - pipeline_config_yaml_response = json.load(f) - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/{DC_TEST_INDEX}/json", - json=pipeline_config_yaml_response, - status=200, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines", - json={"name": "test_pipeline_config_copy"}, - status=200, - ) - - responses.add( - method=responses.PUT, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_pipeline_config/yaml", - json={"name": "test_pipeline_config"}, - status=200, - ) - - responses.add( - method=responses.PUT, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_pipeline_config_deployed/yaml", - json={"errors": ["Updating the pipeline yaml is not allowed for pipelines with status: 'DEPLOYED'"]}, - status=406, - ) - - query_pipeline = Pipeline.load_from_deepset_cloud( - pipeline_config_name=DC_TEST_INDEX, api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - index_pipeline = Pipeline.load_from_deepset_cloud( - pipeline_config_name=DC_TEST_INDEX, api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY, pipeline_name="indexing" - ) - - Pipeline.save_to_deepset_cloud( - query_pipeline=query_pipeline, - index_pipeline=index_pipeline, - pipeline_config_name="test_pipeline_config_copy", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - ) - - with pytest.raises( - ValueError, - match="Pipeline config 'test_pipeline_config' already exists. Set `overwrite=True` to overwrite pipeline config", - ): - Pipeline.save_to_deepset_cloud( - query_pipeline=query_pipeline, - index_pipeline=index_pipeline, - pipeline_config_name="test_pipeline_config", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - ) - - Pipeline.save_to_deepset_cloud( - query_pipeline=query_pipeline, - index_pipeline=index_pipeline, - pipeline_config_name="test_pipeline_config", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - overwrite=True, - ) - - with pytest.raises( - ValueError, - match="Deployed pipeline configs are not allowed to be updated. Please undeploy pipeline config 'test_pipeline_config_deployed' first", - ): - Pipeline.save_to_deepset_cloud( - query_pipeline=query_pipeline, - index_pipeline=index_pipeline, - pipeline_config_name="test_pipeline_config_deployed", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - overwrite=True, - ) - - -@pytest.mark.integration -@pytest.mark.elasticsearch -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_save_nonexisting_pipeline_to_deepset_cloud(): - if MOCK_DC: - - def dc_document_store_matcher(request: PreparedRequest) -> Tuple[bool, str]: - matches = False - reason = "No DeepsetCloudDocumentStore found." - request_body = request.body or "" - json_body = yaml.safe_load(request_body) - components = json_body["components"] - for component in components: - if component["type"].endswith("DocumentStore"): - if component["type"] == "DeepsetCloudDocumentStore": - matches = True - else: - matches = False - reason = f"Component {component['name']} is of type {component['type']} and not DeepsetCloudDocumentStore" - break - return matches, reason - - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"errors": ["Pipeline with the name test_pipeline_config_copy does not exists."]}, - status=404, - ) - - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines", - json={"name": "test_new_non_existing_pipeline"}, - status=201, - match=[dc_document_store_matcher], - ) - - es_document_store = ElasticsearchDocumentStore() - es_retriever = BM25Retriever(document_store=es_document_store) - file_converter = TextConverter() - preprocessor = PreProcessor() - - query_pipeline = Pipeline() - query_pipeline.add_node(component=es_retriever, name="Retriever", inputs=["Query"]) - index_pipeline = Pipeline() - index_pipeline.add_node(component=file_converter, name="FileConverter", inputs=["File"]) - index_pipeline.add_node(component=preprocessor, name="Preprocessor", inputs=["FileConverter"]) - index_pipeline.add_node(component=es_document_store, name="DocumentStore", inputs=["Preprocessor"]) - - Pipeline.save_to_deepset_cloud( - query_pipeline=query_pipeline, - index_pipeline=index_pipeline, - pipeline_config_name="test_new_non_existing_pipeline", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_non_existing_pipeline(): - if MOCK_DC: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"errors": ["Pipeline with the name test_pipeline_config_copy does not exists."]}, - status=404, - ) - - with pytest.raises(DeepsetCloudError, match="Pipeline config 'test_new_non_existing_pipeline' does not exist."): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud_non_existing_pipeline(): - if MOCK_DC: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"errors": ["Pipeline with the name test_pipeline_config_copy does not exists."]}, - status=404, - ) - - with pytest.raises(DeepsetCloudError, match="Pipeline config 'test_new_non_existing_pipeline' does not exist."): - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud(caplog): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["UNDEPLOYED", "DEPLOYMENT_IN_PROGRESS", "DEPLOYMENT_IN_PROGRESS", "DEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - with caplog.at_level(logging.INFO): - pipeline_url = f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/search" - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - assert "Pipeline config 'test_new_non_existing_pipeline' successfully deployed." in caplog.text - assert pipeline_url in caplog.text - assert "curl" in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_no_curl_message(caplog): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["UNDEPLOYED", "DEPLOYMENT_IN_PROGRESS", "DEPLOYMENT_IN_PROGRESS", "DEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - with caplog.at_level(logging.INFO): - pipeline_url = f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/search" - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - show_curl_message=False, - ) - assert "Pipeline config 'test_new_non_existing_pipeline' successfully deployed." in caplog.text - assert pipeline_url in caplog.text - assert "curl" not in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/undeploy", - json={"status": "UNDEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["DEPLOYED", "UNDEPLOYMENT_IN_PROGRESS", "UNDEPLOYMENT_IN_PROGRESS", "UNDEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_sate_already_satisfied(): - if MOCK_DC: - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["DEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud_sate_already_satisfied(): - if MOCK_DC: - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["UNDEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_failed(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress and the third time undeployed - status_flow = ["UNDEPLOYED", "DEPLOYMENT_IN_PROGRESS", "UNDEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - with pytest.raises( - DeepsetCloudError, match="Deployment of pipeline config 'test_new_non_existing_pipeline' failed." - ): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud_failed(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/undeploy", - json={"status": "UNDEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress and the third time undeployed - status_flow = ["DEPLOYED", "UNDEPLOYMENT_IN_PROGRESS", "DEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - with pytest.raises( - DeepsetCloudError, match="Undeployment of pipeline config 'test_new_non_existing_pipeline' failed." - ): - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_invalid_initial_state(): - if MOCK_DC: - status_flow = ["UNDEPLOYMENT_SCHEDULED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - with pytest.raises( - DeepsetCloudError, - match="Pipeline config 'test_new_non_existing_pipeline' is in invalid state 'UNDEPLOYMENT_SCHEDULED' to be transitioned to 'DEPLOYED'.", - ): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud_invalid_initial_state(): - if MOCK_DC: - status_flow = ["DEPLOYMENT_SCHEDULED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - with pytest.raises( - DeepsetCloudError, - match="Pipeline config 'test_new_non_existing_pipeline' is in invalid state 'DEPLOYMENT_SCHEDULED' to be transitioned to 'UNDEPLOYED'.", - ): - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_invalid_state_in_progress(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["UNDEPLOYED", "UNDEPLOYMENT_IN_PROGRESS"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - DeepsetCloudError, - match="Deployment of pipeline config 'test_new_non_existing_pipeline' aborted. Undeployment was requested.", - ): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_failed_deploy_on_deepset_cloud(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployment failed - status_flow = ["UNDEPLOYED", "DEPLOYMENT_IN_PROGRESS", "DEPLOYMENT_IN_PROGRESS", "DEPLOYMENT_FAILED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - DeepsetCloudError, - match="Deployment of pipeline config 'test_new_non_existing_pipeline' failed. " - "This might be caused by an exception in deepset Cloud or a runtime error in the pipeline. " - "You can try to run this pipeline locally first.", - ): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_unexpected_failed_deploy_on_deepset_cloud(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in deployment failed - status_flow = ["UNDEPLOYED", "DEPLOYMENT_FAILED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - DeepsetCloudError, - match="Deployment of pipeline config 'test_new_non_existing_pipeline' failed. " - "This might be caused by an exception in deepset Cloud or a runtime error in the pipeline. " - "You can try to run this pipeline locally first.", - ): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_with_failed_start_state(caplog): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first in failed (but not invalid) state, after deploy() it's in progress twice and third time deployed - status_flow = ["DEPLOYMENT_FAILED", "DEPLOYMENT_IN_PROGRESS", "DEPLOYMENT_IN_PROGRESS", "DEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - - with caplog.at_level(logging.WARNING): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - assert ( - "Pipeline config 'test_new_non_existing_pipeline' is in a failed state 'PipelineStatus.DEPLOYMENT_FAILED'." - in caplog.text - ) - assert "This might be caused by a previous error during (un)deployment." in caplog.text - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud_invalid_state_in_progress(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/undeploy", - json={"status": "UNDEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["DEPLOYED", "DEPLOYMENT_IN_PROGRESS"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - DeepsetCloudError, - match="Undeployment of pipeline config 'test_new_non_existing_pipeline' aborted. Deployment was requested.", - ): - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_unknown_state_in_progress(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["UNDEPLOYED", "ASKDHFASJDF"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - DeepsetCloudError, - match="Deployment of pipeline config 'test_new_non_existing_pipeline ended in unexpected status: UNKNOWN", - ): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud_unknown_state_in_progress(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/undeploy", - json={"status": "UNDEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["DEPLOYED", "ASKDHFASJDF"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - DeepsetCloudError, - match="Undeployment of pipeline config 'test_new_non_existing_pipeline ended in unexpected status: UNKNOWN", - ): - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", api_endpoint=DC_API_ENDPOINT, api_key=DC_API_KEY - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_deploy_on_deepset_cloud_timeout(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/deploy", - json={"status": "DEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["UNDEPLOYED", "DEPLOYMENT_IN_PROGRESS", "DEPLOYMENT_IN_PROGRESS", "DEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - TimeoutError, match="Transitioning of 'test_new_non_existing_pipeline' to state 'DEPLOYED' timed out." - ): - Pipeline.deploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - timeout=5, - ) - - -@pytest.mark.usefixtures(deepset_cloud_fixture.__name__) -@responses.activate -def test_undeploy_on_deepset_cloud_timeout(): - if MOCK_DC: - responses.add( - method=responses.POST, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline/undeploy", - json={"status": "UNDEPLOYMENT_SCHEDULED"}, - status=200, - ) - - # status will be first undeployed, after deploy() it's in progress twice and the third time deployed - status_flow = ["DEPLOYED", "UNDEPLOYMENT_IN_PROGRESS", "UNDEPLOYMENT_IN_PROGRESS", "UNDEPLOYED"] - for status in status_flow: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines/test_new_non_existing_pipeline", - json={"status": status}, - status=200, - ) - with pytest.raises( - TimeoutError, match="Transitioning of 'test_new_non_existing_pipeline' to state 'UNDEPLOYED' timed out." - ): - Pipeline.undeploy_on_deepset_cloud( - pipeline_config_name="test_new_non_existing_pipeline", - api_endpoint=DC_API_ENDPOINT, - api_key=DC_API_KEY, - timeout=5, - ) - - -@pytest.mark.unit -def test_graph_validation_invalid_edge(): - docstore = MockDocumentStore() - retriever = DummyRetriever(document_store=docstore) - pipeline = Pipeline() - pipeline.add_node(name="DocStore", component=docstore, inputs=["Query"]) - - with pytest.raises(PipelineConfigError, match="DocStore has only 1 outgoing edge"): - pipeline.add_node(name="Retriever", component=retriever, inputs=["DocStore.output_2"]) - - -@pytest.mark.unit -def test_graph_validation_non_existing_edge(): - docstore = MockDocumentStore() - retriever = DummyRetriever(document_store=docstore) - pipeline = Pipeline() - pipeline.add_node(name="DocStore", component=docstore, inputs=["Query"]) - - with pytest.raises(PipelineConfigError, match="'wrong_edge_label' is not a valid edge name"): - pipeline.add_node(name="Retriever", component=retriever, inputs=["DocStore.wrong_edge_label"]) - - -@pytest.mark.unit -def test_graph_validation_invalid_node(): - docstore = MockDocumentStore() - retriever = DummyRetriever(document_store=docstore) - pipeline = Pipeline() - pipeline.add_node(name="DocStore", component=docstore, inputs=["Query"]) - - with pytest.raises(PipelineConfigError, match="Cannot find node 'InvalidNode'"): - pipeline.add_node(name="Retriever", component=retriever, inputs=["InvalidNode"]) - - -@pytest.mark.unit -def test_graph_validation_invalid_root_node(): - docstore = MockDocumentStore() - pipeline = Pipeline() - - with pytest.raises(PipelineConfigError, match="one single root node"): - pipeline.add_node(name="DocStore", component=docstore, inputs=["InvalidNode"]) - - -@pytest.mark.unit -def test_graph_validation_no_root_node(): - docstore = MockNode() - pipeline = Pipeline() - - with pytest.raises(PipelineConfigError, match="one single root node"): - pipeline.add_node(name="Node", component=docstore, inputs=[]) - - -@pytest.mark.unit -def test_graph_validation_two_root_nodes(): - docstore = MockNode() - pipeline = Pipeline() - - with pytest.raises(PipelineConfigError, match="one single root node"): - pipeline.add_node(name="Node", component=docstore, inputs=["Query", "File"]) - - with pytest.raises(PipelineConfigError, match="one single root node"): - pipeline.add_node(name="Node", component=docstore, inputs=["Query", "Query"]) - - -@pytest.mark.unit -def test_graph_validation_duplicate_node_instance(): - node = MockNode() - pipeline = Pipeline() - pipeline.add_node(name="node_a", component=node, inputs=["Query"]) - - with pytest.raises(PipelineConfigError, match="You have already added the same instance to the pipeline"): - pipeline.add_node(name="node_b", component=node, inputs=["node_a"]) - - -@pytest.mark.unit -def test_graph_validation_duplicate_node(): - node = MockNode() - other_node = MockNode() - pipeline = Pipeline() - pipeline.add_node(name="node", component=node, inputs=["Query"]) - with pytest.raises(PipelineConfigError, match="'node' is already in the pipeline"): - pipeline.add_node(name="node", component=other_node, inputs=["Query"]) - - -# See https://github.com/deepset-ai/haystack/issues/2568 -@pytest.mark.unit -def test_pipeline_nodes_can_have_uncopiable_objects_as_args(): - class DummyNode(MockNode): - def __init__(self, uncopiable: ssl.SSLContext): - self.uncopiable = uncopiable - - node = DummyNode(uncopiable=ssl.SSLContext()) - pipeline = Pipeline() - pipeline.add_node(component=node, name="node", inputs=["Query"]) - - # If the object is getting copied, it will raise TypeError: cannot pickle 'SSLContext' object - # `get_components_definitions()` should NOT copy objects to allow this usecase - get_component_definitions(pipeline.get_config()) - - -@pytest.mark.unit -def test_pipeline_env_vars_do_not_modify__component_config(caplog, monkeypatch): - class DummyNode(MockNode): - def __init__(self, replaceable: str): - self.replaceable = replaceable - - monkeypatch.setenv("NODE_PARAMS_REPLACEABLE", "env value") - - node = DummyNode(replaceable="init value") - pipeline = Pipeline() - pipeline.add_node(component=node, name="node", inputs=["Query"]) - - original_component_config = deepcopy(node._component_config) - original_pipeline_config = deepcopy(pipeline.get_config()) - - no_env_defs = get_component_definitions(pipeline.get_config(), overwrite_with_env_variables=False) - - with caplog.at_level(logging.INFO): - env_defs = get_component_definitions(pipeline.get_config(), overwrite_with_env_variables=True) - assert "overwritten with environment variable 'NODE_PARAMS_REPLACEABLE' value '***'." in caplog.text - - new_component_config = deepcopy(node._component_config) - new_pipeline_config = deepcopy(pipeline.get_config()) - - assert no_env_defs != env_defs - assert no_env_defs["node"]["params"]["replaceable"] == "init value" - assert env_defs["node"]["params"]["replaceable"] == "env value" - - assert original_component_config == new_component_config - assert original_component_config["params"]["replaceable"] == "init value" - assert new_component_config["params"]["replaceable"] == "init value" - - assert original_pipeline_config == new_pipeline_config - assert original_pipeline_config["components"][0]["params"]["replaceable"] == "init value" - assert new_pipeline_config["components"][0]["params"]["replaceable"] == "init value" - - -@pytest.mark.unit -def test_pipeline_env_vars_do_not_modify_pipeline_config(monkeypatch): - class DummyNode(MockNode): - def __init__(self, replaceable: str): - self.replaceable = replaceable - - monkeypatch.setenv("NODE_PARAMS_REPLACEABLE", "env value") - - node = DummyNode(replaceable="init value") - pipeline = Pipeline() - pipeline.add_node(component=node, name="node", inputs=["Query"]) - - pipeline_config = pipeline.get_config() - original_pipeline_config = deepcopy(pipeline_config) - - get_component_definitions(pipeline_config, overwrite_with_env_variables=True) - - assert original_pipeline_config == pipeline_config - assert original_pipeline_config["components"][0]["params"]["replaceable"] == "init value" - assert pipeline_config["components"][0]["params"]["replaceable"] == "init value" - - -@pytest.mark.unit -def test_parallel_paths_in_pipeline_graph(): - class A(RootNode): - def run(self): - test = "A" - return {"test": test}, "output_1" - - class B(RootNode): - def run(self, test): - test += "B" - return {"test": test}, "output_1" - - class C(RootNode): - def run(self, test): - test += "C" - return {"test": test}, "output_1" - - class D(RootNode): - def run(self, test): - test += "D" - return {"test": test}, "output_1" - - class E(RootNode): - def run(self, test): - test += "E" - return {"test": test}, "output_1" - - class JoinNode(RootNode): - def run(self, inputs): - test = inputs[0]["test"] + inputs[1]["test"] - return {"test": test}, "output_1" - - pipeline = Pipeline() - pipeline.add_node(name="A", component=A(), inputs=["Query"]) - pipeline.add_node(name="B", component=B(), inputs=["A"]) - pipeline.add_node(name="C", component=C(), inputs=["B"]) - pipeline.add_node(name="E", component=E(), inputs=["C"]) - pipeline.add_node(name="D", component=D(), inputs=["B"]) - pipeline.add_node(name="F", component=JoinNode(), inputs=["D", "E"]) - output = pipeline.run(query="test") - assert output["test"] == "ABDABCE" - - pipeline = Pipeline() - pipeline.add_node(name="A", component=A(), inputs=["Query"]) - pipeline.add_node(name="B", component=B(), inputs=["A"]) - pipeline.add_node(name="C", component=C(), inputs=["B"]) - pipeline.add_node(name="D", component=D(), inputs=["B"]) - pipeline.add_node(name="E", component=JoinNode(), inputs=["C", "D"]) - output = pipeline.run(query="test") - assert output["test"] == "ABCABD" - - -@pytest.mark.unit -def test_parallel_paths_in_pipeline_graph_with_branching(): - class AWithOutput1(RootNode): - outgoing_edges = 2 - - def run(self): - output = "A" - return {"output": output}, "output_1" - - class AWithOutput2(RootNode): - outgoing_edges = 2 - - def run(self): - output = "A" - return {"output": output}, "output_2" - - class AWithOutputAll(RootNode): - outgoing_edges = 2 - - def run(self): - output = "A" - return {"output": output}, "output_all" - - class B(RootNode): - def run(self, output): - output += "B" - return {"output": output}, "output_1" - - class C(RootNode): - def run(self, output): - output += "C" - return {"output": output}, "output_1" - - class D(RootNode): - def run(self, output): - output += "D" - return {"output": output}, "output_1" - - class E(RootNode): - def run(self, output): - output += "E" - return {"output": output}, "output_1" - - class JoinNode(RootNode): - def run(self, output=None, inputs=None): - if inputs: - output = "" - for input_dict in inputs: - output += input_dict["output"] - return {"output": output}, "output_1" - - pipeline = Pipeline() - pipeline.add_node(name="A", component=AWithOutput1(), inputs=["Query"]) - pipeline.add_node(name="B", component=B(), inputs=["A.output_1"]) - pipeline.add_node(name="C", component=C(), inputs=["A.output_2"]) - pipeline.add_node(name="D", component=E(), inputs=["B"]) - pipeline.add_node(name="E", component=D(), inputs=["B"]) - pipeline.add_node(name="F", component=JoinNode(), inputs=["D", "E", "C"]) - output = pipeline.run(query="test") - assert output["output"] == "ABEABD" - - pipeline = Pipeline() - pipeline.add_node(name="A", component=AWithOutput2(), inputs=["Query"]) - pipeline.add_node(name="B", component=B(), inputs=["A.output_1"]) - pipeline.add_node(name="C", component=C(), inputs=["A.output_2"]) - pipeline.add_node(name="D", component=E(), inputs=["B"]) - pipeline.add_node(name="E", component=D(), inputs=["B"]) - pipeline.add_node(name="F", component=JoinNode(), inputs=["D", "E", "C"]) - output = pipeline.run(query="test") - assert output["output"] == "AC" - - pipeline = Pipeline() - pipeline.add_node(name="A", component=AWithOutputAll(), inputs=["Query"]) - pipeline.add_node(name="B", component=B(), inputs=["A.output_1"]) - pipeline.add_node(name="C", component=C(), inputs=["A.output_2"]) - pipeline.add_node(name="D", component=E(), inputs=["B"]) - pipeline.add_node(name="E", component=D(), inputs=["B"]) - pipeline.add_node(name="F", component=JoinNode(), inputs=["D", "E", "C"]) - output = pipeline.run(query="test") - assert output["output"] == "ACABEABD" - - -@pytest.mark.unit -def test_pipeline_components(): - class Node(BaseComponent): - outgoing_edges = 1 - - def run(self): - test = "test" - return {"test": test}, "output_1" - - def run_batch(self): - return - - a = Node() - b = Node() - c = Node() - d = Node() - e = Node() - pipeline = Pipeline() - pipeline.add_node(name="A", component=a, inputs=["Query"]) - pipeline.add_node(name="B", component=b, inputs=["A"]) - pipeline.add_node(name="C", component=c, inputs=["B"]) - pipeline.add_node(name="D", component=d, inputs=["C"]) - pipeline.add_node(name="E", component=e, inputs=["D"]) - assert len(pipeline.components) == 5 - assert pipeline.components["A"] == a - assert pipeline.components["B"] == b - assert pipeline.components["C"] == c - assert pipeline.components["D"] == d - assert pipeline.components["E"] == e - - -@pytest.mark.unit -def test_pipeline_get_document_store_from_components(): - doc_store = MockDocumentStore() - pipeline = Pipeline() - pipeline.add_node(name="A", component=doc_store, inputs=["File"]) - - assert doc_store == pipeline.get_document_store() - - -@pytest.mark.unit -def test_pipeline_get_document_store_from_components_multiple_doc_stores(): - doc_store_a = MockDocumentStore() - doc_store_b = MockDocumentStore() - pipeline = Pipeline() - pipeline.add_node(name="A", component=doc_store_a, inputs=["File"]) - pipeline.add_node(name="B", component=doc_store_b, inputs=["File"]) - - with pytest.raises(Exception, match="Multiple Document Stores found in Pipeline"): - pipeline.get_document_store() - - -@pytest.mark.unit -def test_pipeline_get_document_store_from_retriever(): - doc_store = MockDocumentStore() - retriever = DummyRetriever(document_store=doc_store) - pipeline = Pipeline() - pipeline.add_node(name="A", component=retriever, inputs=["Query"]) - - assert doc_store == pipeline.get_document_store() - - -@pytest.mark.unit -def test_pipeline_get_document_store_from_dual_retriever(): - doc_store = MockDocumentStore() - retriever_a = DummyRetriever(document_store=doc_store) - retriever_b = DummyRetriever(document_store=doc_store) - join_node = JoinNode() - pipeline = Pipeline() - pipeline.add_node(name="A", component=retriever_a, inputs=["Query"]) - pipeline.add_node(name="B", component=retriever_b, inputs=["Query"]) - pipeline.add_node(name="C", component=join_node, inputs=["A", "B"]) - - assert doc_store == pipeline.get_document_store() - - -@pytest.mark.unit -def test_pipeline_get_document_store_multiple_doc_stores_from_dual_retriever(): - doc_store_a = MockDocumentStore() - doc_store_b = MockDocumentStore() - retriever_a = DummyRetriever(document_store=doc_store_a) - retriever_b = DummyRetriever(document_store=doc_store_b) - join_node = JoinNode() - pipeline = Pipeline() - pipeline.add_node(name="A", component=retriever_a, inputs=["Query"]) - pipeline.add_node(name="B", component=retriever_b, inputs=["Query"]) - pipeline.add_node(name="C", component=join_node, inputs=["A", "B"]) - - with pytest.raises(Exception, match="Multiple Document Stores found in Pipeline"): - pipeline.get_document_store() - - -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -def test_batch_querying_single_query(document_store_with_docs, samples_path): - query_pipeline = Pipeline.load_from_yaml( - samples_path / "pipeline" / "test.haystack-pipeline.yml", pipeline_name="query_pipeline" - ) - query_pipeline.components["ESRetriever"].document_store = document_store_with_docs - result = query_pipeline.run_batch(queries=["Who lives in Berlin?"]) - assert isinstance(result["answers"], list) - assert isinstance(result["answers"][0], list) - assert isinstance(result["answers"][0][0], Answer) - assert len(result["answers"]) == 1 # Predictions for 1 collection of docs (single query) - assert len(result["answers"][0]) == 5 # Reader top-k set to 5 - - -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -def test_batch_querying_multiple_queries(document_store_with_docs, samples_path): - query_pipeline = Pipeline.load_from_yaml( - samples_path / "pipeline" / "test.haystack-pipeline.yml", pipeline_name="query_pipeline" - ) - query_pipeline.components["ESRetriever"].document_store = document_store_with_docs - result = query_pipeline.run_batch(queries=["Who lives in Berlin?", "Who lives in New York?"]) - # As we have a list of queries as input, this Pipeline will retrieve a list of relevant documents for each of the - # queries (resulting in a list of lists of documents), apply the reader with each query and their corresponding - # retrieved documents and return the predicted answers for each document list - assert isinstance(result["answers"], list) - assert isinstance(result["answers"][0], list) - assert isinstance(result["answers"][0][0], Answer) - assert len(result["answers"]) == 2 # Predictions for 2 collections of documents - assert len(result["answers"][0]) == 5 # top-k of 5 for collection of docs - - -@pytest.mark.unit -def test_fix_to_pipeline_execution_when_join_follows_join(): - # wire up 4 retrievers, each with one document - document_store_1 = InMemoryDocumentStore() - retriever_1 = FilterRetriever(document_store_1, scale_score=True) - dicts_1 = [{"content": "Alpha", "score": 0.552}] - document_store_1.write_documents(dicts_1) - - document_store_2 = InMemoryDocumentStore() - retriever_2 = FilterRetriever(document_store_2, scale_score=True) - dicts_2 = [{"content": "Beta", "score": 0.542}] - document_store_2.write_documents(dicts_2) - - document_store_3 = InMemoryDocumentStore() - retriever_3 = FilterRetriever(document_store_3, scale_score=True) - dicts_3 = [{"content": "Gamma", "score": 0.532}] - document_store_3.write_documents(dicts_3) - - document_store_4 = InMemoryDocumentStore() - retriever_4 = FilterRetriever(document_store_4, scale_score=True) - dicts_4 = [{"content": "Delta", "score": 0.512}] - document_store_4.write_documents(dicts_4) - - # wire up a pipeline of the retrievers, with 4-way join - pipeline = Pipeline() - pipeline.add_node(component=retriever_1, name="Retriever1", inputs=["Query"]) - pipeline.add_node(component=retriever_2, name="Retriever2", inputs=["Query"]) - pipeline.add_node(component=retriever_3, name="Retriever3", inputs=["Query"]) - pipeline.add_node(component=retriever_4, name="Retriever4", inputs=["Query"]) - pipeline.add_node( - component=JoinDocuments(weights=[0.25, 0.25, 0.25, 0.25], join_mode="merge"), - name="Join", - inputs=["Retriever1", "Retriever2", "Retriever3", "Retriever4"], - ) - - res = pipeline.run(query="Alpha Beta Gamma Delta") - documents = res["documents"] - assert len(documents) == 4 # all four documents should be found - - # wire up a pipeline of the retrievers, with join following join - pipeline = Pipeline() - pipeline.add_node(component=retriever_1, name="Retriever1", inputs=["Query"]) - pipeline.add_node(component=retriever_2, name="Retriever2", inputs=["Query"]) - pipeline.add_node(component=retriever_3, name="Retriever3", inputs=["Query"]) - pipeline.add_node(component=retriever_4, name="Retriever4", inputs=["Query"]) - pipeline.add_node( - component=JoinDocuments(weights=[0.5, 0.5], join_mode="merge"), - name="Join12", - inputs=["Retriever1", "Retriever2"], - ) - pipeline.add_node( - component=JoinDocuments(weights=[0.5, 0.5], join_mode="merge"), - name="Join34", - inputs=["Retriever3", "Retriever4"], - ) - pipeline.add_node( - component=JoinDocuments(weights=[0.5, 0.5], join_mode="merge"), name="JoinFinal", inputs=["Join12", "Join34"] - ) - - res = pipeline.run(query="Alpha Beta Gamma Delta") - documents = res["documents"] - assert len(documents) == 4 # all four documents should be found - - -@pytest.mark.unit -def test_update_config_hash(): - fake_configs = { - "version": "ignore", - "components": [ - { - "name": "MyReader", - "type": "FARMReader", - "params": {"no_ans_boost": -10, "model_name_or_path": "deepset/roberta-base-squad2"}, - } - ], - "pipelines": [ - { - "name": "my_query_pipeline", - "nodes": [ - {"name": "MyRetriever", "inputs": ["Query"]}, - {"name": "MyReader", "inputs": ["MyRetriever"]}, - ], - } - ], - } - with mock.patch("haystack.pipelines.base.Pipeline.get_config", return_value=fake_configs): - test_pipeline = Pipeline() - assert test_pipeline.config_hash == None - test_pipeline.update_config_hash() - assert test_pipeline.config_hash == "a30d3273de0d70e63e8cd91d915255b3" - - -@pytest.mark.unit -def test_load_from_config_w_param_that_equals_component_name(): - config = { - "version": "ignore", - "components": [{"name": "node", "type": "InMemoryDocumentStore", "params": {"index": "node"}}], - "pipelines": [{"name": "indexing", "nodes": [{"name": "node", "inputs": ["File"]}]}], - } - - pipeline = Pipeline.load_from_config(pipeline_config=config) - assert pipeline.components["node"].name == "node" - assert pipeline.components["node"].index == "node" diff --git a/test/pipelines/test_pipeline_debug_and_validation.py b/test/pipelines/test_pipeline_debug_and_validation.py deleted file mode 100644 index cab4cdbe9d..0000000000 --- a/test/pipelines/test_pipeline_debug_and_validation.py +++ /dev/null @@ -1,239 +0,0 @@ -from pathlib import Path - -import json -import pytest - -from haystack.pipelines import Pipeline, RootNode, DocumentSearchPipeline -from haystack.nodes import FARMReader, BM25Retriever, JoinDocuments - -from ..conftest import MockRetriever as BaseMockRetriever, MockReader - - -class MockRetriever(BaseMockRetriever): - def retrieve(self, *args, **kwargs): - top_k = None - if "top_k" in kwargs.keys(): - top_k = kwargs["top_k"] - elif len(args) > 0: - top_k = args[-1] - - if top_k and not isinstance(top_k, int): - raise ValueError("TEST ERROR!") - - -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_node_names_validation(document_store_with_docs, tmp_path): - pipeline = Pipeline() - pipeline.add_node( - component=BM25Retriever(document_store=document_store_with_docs), name="Retriever", inputs=["Query"] - ) - pipeline.add_node( - component=FARMReader(model_name_or_path="deepset/minilm-uncased-squad2", num_processes=0), - name="Reader", - inputs=["Retriever"], - ) - - with pytest.raises(ValueError) as exc_info: - pipeline.run( - query="Who lives in Berlin?", - params={ - "Reader": {"top_k": 3}, - "non-existing-node": {"top_k": 10}, - "top_k": 5, - "non-existing-global_param": "wrong", - }, - debug=True, - ) - exception_raised = str(exc_info.value) - assert "non-existing-node" in exception_raised - assert "non-existing-global_param" in exception_raised - assert "Reader" not in exception_raised - assert "top_k" not in exception_raised - - -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_debug_attributes_global(document_store_with_docs, tmp_path): - bm25_retriever = BM25Retriever(document_store=document_store_with_docs) - reader = FARMReader(model_name_or_path="deepset/minilm-uncased-squad2", num_processes=0) - - pipeline = Pipeline() - pipeline.add_node(component=bm25_retriever, name="BM25Retriever", inputs=["Query"]) - pipeline.add_node(component=reader, name="Reader", inputs=["BM25Retriever"]) - - prediction = pipeline.run( - query="Who lives in Berlin?", params={"BM25Retriever": {"top_k": 10}, "Reader": {"top_k": 3}}, debug=True - ) - assert "_debug" in prediction.keys() - assert "BM25Retriever" in prediction["_debug"].keys() - assert "Reader" in prediction["_debug"].keys() - assert "input" in prediction["_debug"]["BM25Retriever"].keys() - assert "output" in prediction["_debug"]["BM25Retriever"].keys() - assert "exec_time_ms" in prediction["_debug"]["BM25Retriever"].keys() - assert "input" in prediction["_debug"]["Reader"].keys() - assert "output" in prediction["_debug"]["Reader"].keys() - assert "exec_time_ms" in prediction["_debug"]["Reader"].keys() - assert prediction["_debug"]["BM25Retriever"]["input"] - assert prediction["_debug"]["BM25Retriever"]["output"] - assert prediction["_debug"]["BM25Retriever"]["exec_time_ms"] is not None - assert prediction["_debug"]["Reader"]["input"] - assert prediction["_debug"]["Reader"]["output"] - assert prediction["_debug"]["Reader"]["exec_time_ms"] is not None - - # Avoid circular reference: easiest way to detect those is to use json.dumps - json.dumps(prediction, default=str) - - -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_debug_attributes_per_node(document_store_with_docs, tmp_path): - bm25_retriever = BM25Retriever(document_store=document_store_with_docs) - reader = FARMReader(model_name_or_path="deepset/minilm-uncased-squad2", num_processes=0) - - pipeline = Pipeline() - pipeline.add_node(component=bm25_retriever, name="BM25Retriever", inputs=["Query"]) - pipeline.add_node(component=reader, name="Reader", inputs=["BM25Retriever"]) - - prediction = pipeline.run( - query="Who lives in Berlin?", params={"BM25Retriever": {"top_k": 10, "debug": True}, "Reader": {"top_k": 3}} - ) - assert "_debug" in prediction.keys() - assert "BM25Retriever" in prediction["_debug"].keys() - assert "Reader" not in prediction["_debug"].keys() - assert "input" in prediction["_debug"]["BM25Retriever"].keys() - assert "output" in prediction["_debug"]["BM25Retriever"].keys() - assert prediction["_debug"]["BM25Retriever"]["input"] - assert prediction["_debug"]["BM25Retriever"]["output"] - - # Avoid circular reference: easiest way to detect those is to use json.dumps - json.dumps(prediction, default=str) - - -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_debug_attributes_for_join_nodes(document_store_with_docs, tmp_path): - bm25_retriever_1 = BM25Retriever(document_store=document_store_with_docs) - bm25_retriever_2 = BM25Retriever(document_store=document_store_with_docs) - - pipeline = Pipeline() - pipeline.add_node(component=bm25_retriever_1, name="BM25Retriever1", inputs=["Query"]) - pipeline.add_node(component=bm25_retriever_2, name="BM25Retriever2", inputs=["Query"]) - pipeline.add_node(component=JoinDocuments(), name="JoinDocuments", inputs=["BM25Retriever1", "BM25Retriever2"]) - - prediction = pipeline.run(query="Who lives in Berlin?", debug=True) - assert "_debug" in prediction.keys() - assert "BM25Retriever1" in prediction["_debug"].keys() - assert "BM25Retriever2" in prediction["_debug"].keys() - assert "JoinDocuments" in prediction["_debug"].keys() - assert "input" in prediction["_debug"]["BM25Retriever1"].keys() - assert "output" in prediction["_debug"]["BM25Retriever1"].keys() - assert "input" in prediction["_debug"]["BM25Retriever2"].keys() - assert "output" in prediction["_debug"]["BM25Retriever2"].keys() - assert "input" in prediction["_debug"]["JoinDocuments"].keys() - assert "output" in prediction["_debug"]["JoinDocuments"].keys() - assert prediction["_debug"]["BM25Retriever1"]["input"] - assert prediction["_debug"]["BM25Retriever1"]["output"] - assert prediction["_debug"]["BM25Retriever2"]["input"] - assert prediction["_debug"]["BM25Retriever2"]["output"] - assert prediction["_debug"]["JoinDocuments"]["input"] - assert prediction["_debug"]["JoinDocuments"]["output"] - - # Avoid circular reference: easiest way to detect those is to use json.dumps - json.dumps(prediction, default=str) - - -@pytest.mark.parametrize("document_store_with_docs", ["memory"], indirect=True) -def test_global_debug_attributes_override_node_ones(document_store_with_docs, tmp_path): - bm25_retriever = BM25Retriever(document_store=document_store_with_docs) - reader = FARMReader(model_name_or_path="deepset/minilm-uncased-squad2", num_processes=0) - - pipeline = Pipeline() - pipeline.add_node(component=bm25_retriever, name="BM25Retriever", inputs=["Query"]) - pipeline.add_node(component=reader, name="Reader", inputs=["BM25Retriever"]) - - prediction = pipeline.run( - query="Who lives in Berlin?", - params={"BM25Retriever": {"top_k": 10, "debug": True}, "Reader": {"top_k": 3, "debug": True}}, - debug=False, - ) - assert "_debug" not in prediction.keys() - - prediction = pipeline.run( - query="Who lives in Berlin?", - params={"BM25Retriever": {"top_k": 10, "debug": False}, "Reader": {"top_k": 3, "debug": False}}, - debug=True, - ) - assert "_debug" in prediction.keys() - assert "BM25Retriever" in prediction["_debug"].keys() - assert "Reader" in prediction["_debug"].keys() - assert "input" in prediction["_debug"]["BM25Retriever"].keys() - assert "output" in prediction["_debug"]["BM25Retriever"].keys() - assert "input" in prediction["_debug"]["Reader"].keys() - assert "output" in prediction["_debug"]["Reader"].keys() - assert prediction["_debug"]["BM25Retriever"]["input"] - assert prediction["_debug"]["BM25Retriever"]["output"] - assert prediction["_debug"]["Reader"]["input"] - assert prediction["_debug"]["Reader"]["output"] - - -@pytest.mark.unit -def test_missing_top_level_arg(): - pipeline = Pipeline() - pipeline.add_node(component=MockRetriever(), name="Retriever", inputs=["Query"]) - pipeline.add_node(component=MockReader(), name="Reader", inputs=["Retriever"]) - - with pytest.raises(Exception) as exc: - pipeline.run(params={"Retriever": {"top_k": 10}}) - assert "Must provide a 'query' parameter" in str(exc.value) - - -@pytest.mark.unit -def test_unexpected_top_level_arg(): - pipeline = Pipeline() - pipeline.add_node(component=MockRetriever(), name="Retriever", inputs=["Query"]) - pipeline.add_node(component=MockReader(), name="Reader", inputs=["Retriever"]) - - with pytest.raises(Exception) as exc: - pipeline.run(invalid_query="Who made the PDF specification?", params={"Retriever": {"top_k": 10}}) - assert "run() got an unexpected keyword argument 'invalid_query'" in str(exc.value) - - -@pytest.mark.unit -def test_unexpected_node_arg(): - pipeline = Pipeline() - pipeline.add_node(component=MockRetriever(), name="Retriever", inputs=["Query"]) - pipeline.add_node(component=MockReader(), name="Reader", inputs=["Retriever"]) - - with pytest.raises(Exception) as exc: - pipeline.run(query="Who made the PDF specification?", params={"Retriever": {"invalid": 10}}) - assert "Invalid parameter 'invalid' for the node 'Retriever'" in str(exc.value) - - -@pytest.mark.unit -def test_debug_info_propagation(): - class A(RootNode): - def run(self): - test = "A" - return {"test": test, "_debug": {"debug_key_a": "debug_value_a"}}, "output_1" - - class B(RootNode): - def run(self, test): - test += "B" - return {"test": test, "_debug": "debug_value_b"}, "output_1" - - class C(RootNode): - def run(self, test): - test += "C" - return {"test": test}, "output_1" - - class D(RootNode): - def run(self, test, _debug): - test += "C" - assert _debug["B"]["runtime"] == "debug_value_b" - return {"test": test}, "output_1" - - pipeline = Pipeline() - pipeline.add_node(name="A", component=A(), inputs=["Query"]) - pipeline.add_node(name="B", component=B(), inputs=["A"]) - pipeline.add_node(name="C", component=C(), inputs=["B"]) - pipeline.add_node(name="D", component=D(), inputs=["C"]) - output = pipeline.run(query="test") - assert output["_debug"]["A"]["runtime"]["debug_key_a"] == "debug_value_a" - assert output["_debug"]["B"]["runtime"] == "debug_value_b" diff --git a/test/pipelines/test_pipeline_yaml.py b/test/pipelines/test_pipeline_yaml.py deleted file mode 100644 index da82dc1303..0000000000 --- a/test/pipelines/test_pipeline_yaml.py +++ /dev/null @@ -1,1181 +0,0 @@ -from abc import abstractmethod -import logging -from numpy import mat -import pytest -import json -import inspect -import networkx as nx -from enum import Enum -from pydantic.dataclasses import dataclass -from typing import Any, Dict, List, Optional - -import haystack -from haystack import Pipeline -from haystack.nodes import _json_schema -from haystack.nodes import FileTypeClassifier -from haystack.errors import HaystackError, PipelineConfigError, PipelineSchemaError, DocumentStoreError -from haystack.nodes.base import BaseComponent - -from ..conftest import MockNode, MockDocumentStore, MockReader, MockRetriever -from .. import conftest - - -# -# Fixtures -# - - -@pytest.fixture(autouse=True) -def mock_json_schema(request, monkeypatch, tmp_path): - """ - JSON schema with the main version and only mocked nodes. - """ - # Do not patch integration tests - if "integration" in request.keywords: - return - - # Mock the subclasses list to make it very small, containing only mock nodes - monkeypatch.setattr( - haystack.nodes._json_schema, - "find_subclasses_in_modules", - lambda *a, **k: [(conftest, MockDocumentStore), (conftest, MockReader), (conftest, MockRetriever)], - ) - # Point the JSON schema path to tmp_path - monkeypatch.setattr(haystack.nodes._json_schema, "JSON_SCHEMAS_PATH", tmp_path) - - # Generate mock schema in tmp_path - filename = "haystack-pipeline-main.schema.json" - test_schema = _json_schema.get_json_schema(filename=filename, version="ignore") - - with open(tmp_path / filename, "w") as schema_file: - json.dump(test_schema, schema_file, indent=4) - - -# -# Integration -# - - -@pytest.mark.integration -@pytest.mark.elasticsearch -def test_load_and_save_from_yaml(tmp_path, samples_path): - config_path = samples_path / "pipeline" / "test.haystack-pipeline.yml" - - # Test the indexing pipeline: - # Load it - indexing_pipeline = Pipeline.load_from_yaml(path=config_path, pipeline_name="indexing_pipeline") - - # Check if it works - indexing_pipeline.get_document_store().delete_documents() - assert indexing_pipeline.get_document_store().get_document_count() == 0 - indexing_pipeline.run(file_paths=samples_path / "pdf" / "sample_pdf_1.pdf") - assert indexing_pipeline.get_document_store().get_document_count() > 0 - - # Save it - new_indexing_config = tmp_path / "test_indexing.yaml" - indexing_pipeline.save_to_yaml(new_indexing_config) - - # Re-load it and compare the resulting pipelines - new_indexing_pipeline = Pipeline.load_from_yaml(path=new_indexing_config) - assert nx.is_isomorphic(new_indexing_pipeline.graph, indexing_pipeline.graph) - - # Check that modifying a pipeline modifies the output YAML - modified_indexing_pipeline = Pipeline.load_from_yaml(path=new_indexing_config) - modified_indexing_pipeline.add_node(FileTypeClassifier(), name="file_classifier", inputs=["File"]) - assert not nx.is_isomorphic(new_indexing_pipeline.graph, modified_indexing_pipeline.graph) - - # Test the query pipeline: - # Load it - query_pipeline = Pipeline.load_from_yaml(path=config_path, pipeline_name="query_pipeline") - - # Check if it works - prediction = query_pipeline.run( - query="Who made the PDF specification?", params={"ESRetriever": {"top_k": 10}, "Reader": {"top_k": 3}} - ) - assert prediction["query"] == "Who made the PDF specification?" - assert prediction["answers"][0].answer == "Adobe Systems" - assert "_debug" not in prediction.keys() - - # Save it - new_query_config = tmp_path / "test_query.yaml" - query_pipeline.save_to_yaml(new_query_config) - - # Re-load it and compare the resulting pipelines - new_query_pipeline = Pipeline.load_from_yaml(path=new_query_config) - assert nx.is_isomorphic(new_query_pipeline.graph, query_pipeline.graph) - - # Check that different pipelines produce different files - assert not nx.is_isomorphic(new_query_pipeline.graph, new_indexing_pipeline.graph) - - -# -# Unit -# - - -@pytest.mark.unit -def test_load_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: retriever - type: MockRetriever - - name: reader - type: MockReader - pipelines: - - name: query - nodes: - - name: retriever - inputs: - - Query - - name: reader - inputs: - - retriever - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert len(pipeline.graph.nodes) == 3 - assert isinstance(pipeline.get_node("retriever"), MockRetriever) - assert isinstance(pipeline.get_node("reader"), MockReader) - - -def test_load_yaml_elasticsearch_not_responding(tmp_path): - # Test if DocumentStoreError is raised if elasticsearch instance is not responding (due to wrong port) - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: ESRetriever - type: BM25Retriever - params: - document_store: DocumentStore - - name: DocumentStore - type: ElasticsearchDocumentStore - params: - port: 1234 - - name: PDFConverter - type: PDFToTextConverter - - name: Preprocessor - type: PreProcessor - pipelines: - - name: query_pipeline - nodes: - - name: ESRetriever - inputs: [Query] - - name: indexing_pipeline - nodes: - - name: PDFConverter - inputs: [File] - - name: Preprocessor - inputs: [PDFConverter] - - name: ESRetriever - inputs: [Preprocessor] - - name: DocumentStore - inputs: [ESRetriever] - """ - ) - with pytest.raises(DocumentStoreError): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml", pipeline_name="indexing_pipeline") - - -@pytest.mark.unit -def test_load_yaml_non_existing_file(samples_path): - with pytest.raises(FileNotFoundError): - Pipeline.load_from_yaml(path=samples_path / "pipeline" / "I_dont_exist.yml") - - -@pytest.mark.unit -def test_load_yaml_invalid_yaml(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write("this is not valid YAML!") - with pytest.raises(PipelineConfigError): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_missing_version(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - components: - - name: docstore - type: MockDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: docstore - inputs: - - Query - """ - ) - with pytest.raises(PipelineConfigError, match="Validation failed") as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "version" in str(e) - - -@pytest.mark.unit -def test_load_yaml_non_existing_version(tmp_path, caplog): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: random - components: - - name: docstore - type: MockDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: docstore - inputs: - - Query - """ - ) - with caplog.at_level(logging.WARNING): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "version 'random'" in caplog.text - assert f"Haystack {haystack.__version__}" in caplog.text - - -@pytest.mark.unit -def test_load_yaml_non_existing_version_strict(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: random - components: - - name: docstore - type: MockDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: docstore - inputs: - - Query - """ - ) - with pytest.raises(PipelineConfigError, match="Cannot load pipeline configuration of version random"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml", strict_version_check=True) - - -@pytest.mark.unit -def test_load_yaml_incompatible_version(tmp_path, caplog): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: 1.1.0 - components: - - name: docstore - type: MockDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: docstore - inputs: - - Query - """ - ) - with caplog.at_level(logging.WARNING): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "version '1.1.0'" in caplog.text - assert f"Haystack {haystack.__version__}" in caplog.text - - -@pytest.mark.unit -def test_load_yaml_incompatible_version_strict(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: 1.1.0 - components: - - name: docstore - type: MockDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: docstore - inputs: - - Query - """ - ) - with pytest.raises(PipelineConfigError, match="Cannot load pipeline configuration of version 1.1.0"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml", strict_version_check=True) - - -@pytest.mark.unit -def test_load_yaml_no_components(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - pipelines: - - name: my_pipeline - nodes: - """ - ) - with pytest.raises(PipelineConfigError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "components" in str(e) - - -@pytest.mark.unit -def test_load_yaml_wrong_component(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: docstore - type: ImaginaryDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: docstore - inputs: - - Query - """ - ) - with pytest.raises(HaystackError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "ImaginaryDocumentStore" in str(e) - - -@pytest.mark.unit -def test_load_yaml_custom_component(tmp_path): - class CustomNode(MockNode): - def __init__(self, param: int): - super().__init__() - self.param = param - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - param: 1 - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert pipeline.get_node("custom_node").param == 1 - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_null_values(tmp_path): - class CustomNode(MockNode): - def __init__(self, param: Optional[str], lst_param: Optional[List[Any]], dict_param: Optional[Dict[str, Any]]): - super().__init__() - self.param = param - self.lst_param = lst_param - self.dict_param = dict_param - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - param: null - lst_param: null - dict_param: null - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert len(pipeline.graph.nodes) == 2 - assert pipeline.get_node("custom_node").param is None - assert pipeline.get_node("custom_node").lst_param is None - assert pipeline.get_node("custom_node").dict_param is None - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_no_init(tmp_path): - class CustomNode(MockNode): - pass - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert isinstance(pipeline.get_node("custom_node"), CustomNode) - - -@pytest.mark.unit -def test_load_yaml_custom_component_neednt_call_super(tmp_path): - """This is a side-effect. Here for behavior documentation only""" - - class CustomNode(BaseComponent): - outgoing_edges = 1 - - def __init__(self, param: int): - self.param = param - - def run(self, *a, **k): - pass - - def run_batch(self, *a, **k): - pass - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - param: 1 - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert isinstance(pipeline.get_node("custom_node"), CustomNode) - assert pipeline.get_node("custom_node").param == 1 - - -@pytest.mark.unit -def test_load_yaml_custom_component_cant_be_abstract(tmp_path): - class CustomNode(MockNode): - @abstractmethod - def abstract_method(self): - pass - - assert inspect.isabstract(CustomNode) - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineSchemaError, match="abstract"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_custom_component_name_can_include_base(tmp_path): - class BaseCustomNode(MockNode): - def __init__(self): - super().__init__() - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: BaseCustomNode - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert isinstance(pipeline.get_node("custom_node"), BaseCustomNode) - - -@pytest.mark.unit -def test_load_yaml_custom_component_must_subclass_basecomponent(tmp_path): - class SomeCustomNode: - def run(self, *a, **k): - pass - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: SomeCustomNode - params: - param: 1 - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineSchemaError, match="'SomeCustomNode' not found"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_custom_component_referencing_other_node_in_init(tmp_path): - class OtherNode(MockNode): - def __init__(self, another_param: str): - super().__init__() - self.param = another_param - - class CustomNode(MockNode): - def __init__(self, other_node: OtherNode): - super().__init__() - self.other_node = other_node - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: other_node - type: OtherNode - params: - another_param: value - - name: custom_node - type: CustomNode - params: - other_node: other_node - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert isinstance(pipeline.get_node("custom_node"), CustomNode) - assert isinstance(pipeline.get_node("custom_node").other_node, OtherNode) - assert pipeline.get_node("custom_node").name == "custom_node" - assert pipeline.get_node("custom_node").other_node.name == "other_node" - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_helper_class_in_init(tmp_path): - """ - This test can work from the perspective of YAML schema validation: - HelperClass is picked up correctly and everything gets loaded. - - However, for now we decide to disable this feature. - See haystack/_json_schema.py for details. - """ - - @dataclass # Makes this test class JSON serializable - class HelperClass: - def __init__(self, another_param: str): - self.param = another_param - - class CustomNode(MockNode): - def __init__(self, some_exotic_parameter: HelperClass = HelperClass(1)): - super().__init__() - self.some_exotic_parameter = some_exotic_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineSchemaError, match="takes object instances as parameters in its __init__ function"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_helper_class_in_yaml(tmp_path): - """ - This test can work from the perspective of YAML schema validation: - HelperClass is picked up correctly and everything gets loaded. - - However, for now we decide to disable this feature. - See haystack/_json_schema.py for details. - """ - - class HelperClass: - def __init__(self, another_param: str): - self.param = another_param - - class CustomNode(MockNode): - def __init__(self, some_exotic_parameter: HelperClass): - super().__init__() - self.some_exotic_parameter = some_exotic_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - some_exotic_parameter: HelperClass("hello") - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipe = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert pipe.get_node("custom_node").some_exotic_parameter == 'HelperClass("hello")' - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_enum_in_init(tmp_path): - """ - This test can work from the perspective of YAML schema validation: - Flags is picked up correctly and everything gets loaded. - - However, for now we decide to disable this feature. - See haystack/_json_schema.py for details. - """ - - class Flags(Enum): - FIRST_VALUE = 1 - SECOND_VALUE = 2 - - class CustomNode(MockNode): - def __init__(self, some_exotic_parameter: Flags = None): - super().__init__() - self.some_exotic_parameter = some_exotic_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineSchemaError, match="takes object instances as parameters in its __init__ function"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_enum_in_yaml(tmp_path): - """ - This test can work from the perspective of YAML schema validation: - Flags is picked up correctly and everything gets loaded. - - However, for now we decide to disable this feature. - See haystack/_json_schema.py for details. - """ - - class Flags(Enum): - FIRST_VALUE = 1 - SECOND_VALUE = 2 - - class CustomNode(MockNode): - def __init__(self, some_exotic_parameter: Flags): - super().__init__() - self.some_exotic_parameter = some_exotic_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - some_exotic_parameter: Flags.SECOND_VALUE - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineSchemaError, match="takes object instances as parameters in its __init__ function"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_external_constant(tmp_path): - """ - This is a potential pitfall. The code should work as described here. - """ - - class AnotherClass: - CLASS_CONSTANT = "str" - - class CustomNode(MockNode): - def __init__(self, some_exotic_parameter: str): - super().__init__() - self.some_exotic_parameter = some_exotic_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - some_exotic_parameter: AnotherClass.CLASS_CONSTANT # Will *NOT* be resolved - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - node = pipeline.get_node("custom_node") - assert node.some_exotic_parameter == "AnotherClass.CLASS_CONSTANT" - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_superclass(tmp_path): - class BaseCustomNode(MockNode): - def __init__(self): - super().__init__() - - class CustomNode(BaseCustomNode): - def __init__(self, some_exotic_parameter: str): - super().__init__() - self.some_exotic_parameter = some_exotic_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - some_exotic_parameter: value - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_variadic_args(tmp_path): - class BaseCustomNode(MockNode): - def __init__(self, base_parameter: int): - super().__init__() - self.base_parameter = base_parameter - - class CustomNode(BaseCustomNode): - def __init__(self, some_parameter: str, *args): - super().__init__(*args) - self.some_parameter = some_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - base_parameter: 1 - some_parameter: value - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineSchemaError, match="variadic"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_custom_component_with_variadic_kwargs(tmp_path): - class BaseCustomNode(MockNode): - def __init__(self, base_parameter: int): - super().__init__() - self.base_parameter = base_parameter - - class CustomNode(BaseCustomNode): - def __init__(self, some_parameter: str, **kwargs): - super().__init__(**kwargs) - self.some_parameter = some_parameter - - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: custom_node - type: CustomNode - params: - base_parameter: 1 - some_parameter: value - pipelines: - - name: my_pipeline - nodes: - - name: custom_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineSchemaError, match="variadic"): - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_no_pipelines(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: docstore - type: MockDocumentStore - pipelines: - """ - ) - with pytest.raises(PipelineConfigError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "pipeline" in str(e) - - -@pytest.mark.unit -def test_load_yaml_invalid_pipeline_name(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: docstore - type: MockDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: docstore - inputs: - - Query - """ - ) - with pytest.raises(PipelineConfigError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml", pipeline_name="invalid") - assert "invalid" in str(e) and "pipeline" in str(e) - - -@pytest.mark.unit -def test_load_yaml_pipeline_with_wrong_nodes(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: docstore - type: MockDocumentStore - pipelines: - - name: my_pipeline - nodes: - - name: not_existing_node - inputs: - - Query - """ - ) - with pytest.raises(PipelineConfigError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "not_existing_node" in str(e) - - -@pytest.mark.unit -def test_load_yaml_pipeline_not_acyclic_graph(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: retriever - type: MockRetriever - - name: reader - type: MockRetriever - pipelines: - - name: my_pipeline - nodes: - - name: retriever - inputs: - - reader - - name: reader - inputs: - - retriever - """ - ) - with pytest.raises(PipelineConfigError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "reader" in str(e) or "retriever" in str(e) - assert "loop" in str(e) - - -@pytest.mark.unit -def test_load_yaml_wrong_root(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: retriever - type: MockRetriever - pipelines: - - name: my_pipeline - nodes: - - name: retriever - inputs: - - Nothing - """ - ) - with pytest.raises(PipelineConfigError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "Nothing" in str(e) - assert "root" in str(e).lower() - - -@pytest.mark.unit -def test_load_yaml_two_roots_invalid(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: retriever - type: MockRetriever - - name: retriever_2 - type: MockRetriever - pipelines: - - name: my_pipeline - nodes: - - name: retriever - inputs: - - Query - - name: retriever_2 - inputs: - - File - """ - ) - with pytest.raises(PipelineConfigError) as e: - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert "File" in str(e) or "Query" in str(e) - - -@pytest.mark.unit -def test_load_yaml_two_roots_valid(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: retriever - type: MockRetriever - - name: retriever_2 - type: MockRetriever - pipelines: - - name: my_pipeline - nodes: - - name: retriever - inputs: - - Query - - name: retriever_2 - inputs: - - Query - """ - ) - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - - -@pytest.mark.unit -def test_load_yaml_two_roots_in_separate_pipelines(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: node_1 - type: MockNode - - name: node_2 - type: MockNode - pipelines: - - name: pipeline_1 - nodes: - - name: node_1 - inputs: - - Query - - name: node_2 - inputs: - - Query - - name: pipeline_2 - nodes: - - name: node_1 - inputs: - - File - - name: node_2 - inputs: - - File - """ - ) - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml", pipeline_name="pipeline_1") - Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml", pipeline_name="pipeline_2") - - -@pytest.mark.unit -def test_load_yaml_disconnected_component(tmp_path): - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: docstore - type: MockDocumentStore - - name: retriever - type: MockRetriever - pipelines: - - name: query - nodes: - - name: docstore - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert len(pipeline.graph.nodes) == 2 - assert isinstance(pipeline.get_document_store(), MockDocumentStore) - assert not pipeline.get_node("retriever") - - -@pytest.mark.unit -def test_load_yaml_unusual_chars_in_values(tmp_path): - class DummyNode(BaseComponent): - outgoing_edges = 1 - - def __init__(self, space_param, non_alphanumeric_param): - super().__init__() - self.space_param = space_param - self.non_alphanumeric_param = non_alphanumeric_param - - def run(self): - raise NotImplementedError - - def run_batch(self): - raise NotImplementedError - - with open(tmp_path / "tmp_config.yml", "w", encoding="utf-8") as tmp_file: - tmp_file.write( - r""" - version: '1.9.0' - - components: - - name: DummyNode - type: DummyNode - params: - space_param: with space - non_alphanumeric_param: \[ümlaut\] - - pipelines: - - name: indexing - nodes: - - name: DummyNode - inputs: [File] - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert pipeline.components["DummyNode"].space_param == "with space" - assert pipeline.components["DummyNode"].non_alphanumeric_param == "\\[ümlaut\\]" - - -@pytest.mark.unit -def test_save_yaml(tmp_path): - pipeline = Pipeline() - pipeline.add_node(MockRetriever(), name="retriever", inputs=["Query"]) - pipeline.save_to_yaml(tmp_path / "saved_pipeline.yml") - - with open(tmp_path / "saved_pipeline.yml", "r") as saved_yaml: - content = saved_yaml.read() - - assert content.count("retriever") == 2 - assert "MockRetriever" in content - assert "Query" in content - assert f"version: {haystack.__version__}" in content - - -@pytest.mark.unit -def test_save_yaml_overwrite(tmp_path): - pipeline = Pipeline() - retriever = MockRetriever() - pipeline.add_node(component=retriever, name="retriever", inputs=["Query"]) - - with open(tmp_path / "saved_pipeline.yml", "w") as _: - pass - - pipeline.save_to_yaml(tmp_path / "saved_pipeline.yml") - - with open(tmp_path / "saved_pipeline.yml", "r") as saved_yaml: - content = saved_yaml.read() - assert content != "" - - -@pytest.mark.unit -@pytest.mark.parametrize("pipeline_file", ["ray.simple.haystack-pipeline.yml", "ray.advanced.haystack-pipeline.yml"]) -def test_load_yaml_ray_args_in_pipeline(samples_path, pipeline_file): - with pytest.raises(PipelineConfigError): - Pipeline.load_from_yaml(samples_path / "pipeline" / pipeline_file, pipeline_name="ray_query_pipeline") diff --git a/test/pipelines/test_ray.py b/test/pipelines/test_ray.py deleted file mode 100644 index ddb1ebf54a..0000000000 --- a/test/pipelines/test_ray.py +++ /dev/null @@ -1,97 +0,0 @@ -import pytest - -from haystack.pipelines import RayPipeline - - -@pytest.fixture() -def ray(): - try: - import ray - - yield ray - - ray.serve.shutdown() - ray.shutdown() - except: - pass - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -@pytest.mark.parametrize("serve_detached", [True, False]) -def test_load_pipeline(ray, document_store_with_docs, serve_detached, samples_path): - pipeline = RayPipeline.load_from_yaml( - samples_path / "pipeline" / "ray.simple.haystack-pipeline.yml", - pipeline_name="ray_query_pipeline", - ray_args={"num_cpus": 8}, - serve_args={"detached": serve_detached}, - ) - prediction = pipeline.run( - query="Who lives in Berlin?", params={"ESRetriever": {"top_k": 10}, "Reader": {"top_k": 3}} - ) - - assert pipeline._serve_controller_client._detached == serve_detached - assert ray.serve.get_deployment(name="ESRetriever").num_replicas == 2 - assert ray.serve.get_deployment(name="Reader").num_replicas == 1 - assert ray.serve.get_deployment(name="ESRetriever").max_concurrent_queries == 17 - assert ray.serve.get_deployment(name="ESRetriever").ray_actor_options["num_cpus"] == 0.5 - assert prediction["query"] == "Who lives in Berlin?" - assert prediction["answers"][0].answer == "Carla" - - -@pytest.mark.integration -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -def test_load_advanced_pipeline(ray, document_store_with_docs, samples_path): - pipeline = RayPipeline.load_from_yaml( - samples_path / "pipeline" / "ray.advanced.haystack-pipeline.yml", - pipeline_name="ray_query_pipeline", - ray_args={"num_cpus": 8}, - serve_args={"detached": True}, - ) - prediction = pipeline.run( - query="Who lives in Berlin?", - params={"ESRetriever1": {"top_k": 1}, "ESRetriever2": {"top_k": 2}, "Reader": {"top_k": 3}}, - ) - - assert pipeline._serve_controller_client._detached is True - assert ray.serve.get_deployment(name="ESRetriever1").num_replicas == 2 - assert ray.serve.get_deployment(name="ESRetriever2").num_replicas == 2 - assert ray.serve.get_deployment(name="Reader").num_replicas == 1 - assert ray.serve.get_deployment(name="ESRetriever1").max_concurrent_queries == 17 - assert ray.serve.get_deployment(name="ESRetriever2").max_concurrent_queries == 15 - assert ray.serve.get_deployment(name="ESRetriever1").ray_actor_options["num_cpus"] == 0.25 - assert ray.serve.get_deployment(name="ESRetriever2").ray_actor_options["num_cpus"] == 0.25 - assert prediction["query"] == "Who lives in Berlin?" - assert prediction["answers"][0].answer == "Carla" - assert len(prediction["answers"]) > 1 - - -@pytest.mark.asyncio -@pytest.mark.integration -@pytest.mark.parametrize("document_store_with_docs", ["elasticsearch"], indirect=True) -async def test_load_advanced_pipeline_async(ray, document_store_with_docs, samples_path): - pipeline = RayPipeline.load_from_yaml( - samples_path / "pipeline" / "ray.advanced.haystack-pipeline.yml", - pipeline_name="ray_query_pipeline", - ray_args={"num_cpus": 8}, - serve_args={"detached": True}, - ) - prediction = await pipeline.run_async( - query="Who lives in Berlin?", - params={"ESRetriever1": {"top_k": 1}, "ESRetriever2": {"top_k": 2}, "Reader": {"top_k": 3}}, - debug=True, - ) - - assert pipeline._serve_controller_client._detached is True - assert ray.serve.get_deployment(name="ESRetriever1").num_replicas == 2 - assert ray.serve.get_deployment(name="ESRetriever2").num_replicas == 2 - assert ray.serve.get_deployment(name="Reader").num_replicas == 1 - assert ray.serve.get_deployment(name="ESRetriever1").max_concurrent_queries == 17 - assert ray.serve.get_deployment(name="ESRetriever2").max_concurrent_queries == 15 - assert ray.serve.get_deployment(name="ESRetriever1").ray_actor_options["num_cpus"] == 0.25 - assert ray.serve.get_deployment(name="ESRetriever2").ray_actor_options["num_cpus"] == 0.25 - assert prediction["query"] == "Who lives in Berlin?" - assert prediction["answers"][0].answer == "Carla" - assert len(prediction["answers"]) > 1 - assert "exec_time_ms" in prediction["_debug"]["ESRetriever1"].keys() - assert prediction["_debug"]["ESRetriever1"]["exec_time_ms"] diff --git a/test/pipelines/test_standard_pipelines.py b/test/pipelines/test_standard_pipelines.py deleted file mode 100644 index 2d6523d7a6..0000000000 --- a/test/pipelines/test_standard_pipelines.py +++ /dev/null @@ -1,93 +0,0 @@ -import os - -import pytest - -from haystack.nodes import PromptNode -from haystack.nodes.retriever.web import WebRetriever -from haystack.pipelines import ExtractiveQAPipeline, WebQAPipeline - -from haystack.schema import Answer - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -def test_extractive_qa_answers(reader, retriever_with_docs, document_store_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - prediction = pipeline.run(query="Who lives in Berlin?", params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 3}}) - assert prediction is not None - assert type(prediction["answers"][0]) == Answer - assert prediction["query"] == "Who lives in Berlin?" - assert prediction["answers"][0].answer == "Carla" - assert prediction["answers"][0].score <= 1 - assert prediction["answers"][0].score >= 0 - assert prediction["answers"][0].meta["meta_field"] == "test1" - assert prediction["answers"][0].context == "My name is Carla and I live in Berlin" - - assert len(prediction["answers"]) == 3 - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -def test_extractive_qa_answers_without_normalized_scores(reader_without_normalized_scores, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader_without_normalized_scores, retriever=retriever_with_docs) - prediction = pipeline.run(query="Who lives in Berlin?", params={"Reader": {"top_k": 3}}) - assert prediction is not None - assert prediction["query"] == "Who lives in Berlin?" - assert prediction["answers"][0].answer == "Carla" - assert prediction["answers"][0].score <= 9 - assert prediction["answers"][0].score >= 8 - assert prediction["answers"][0].meta["meta_field"] == "test1" - assert prediction["answers"][0].context == "My name is Carla and I live in Berlin" - - assert len(prediction["answers"]) == 3 - - -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -def test_extractive_qa_offsets(reader, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - prediction = pipeline.run(query="Who lives in Berlin?", params={"Retriever": {"top_k": 5}}) - - start = prediction["answers"][0].offsets_in_context[0].start - end = prediction["answers"][0].offsets_in_context[0].end - - assert start == 11 - assert end == 16 - - assert prediction["answers"][0].context[start:end] == prediction["answers"][0].answer - - -@pytest.mark.integration -@pytest.mark.parametrize("retriever_with_docs", ["tfidf"], indirect=True) -def test_extractive_qa_answers_single_result(reader, retriever_with_docs): - pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever_with_docs) - query = "testing finder" - prediction = pipeline.run(query=query, params={"Retriever": {"top_k": 1}, "Reader": {"top_k": 1}}) - assert prediction is not None - assert len(prediction["answers"]) == 1 - - -@pytest.mark.integration -@pytest.mark.skipif( - not os.environ.get("OPENAI_API_KEY", None), - reason="Please export an env var called OPENAI_API_KEY containing the OpenAI API key to run this test.", -) -@pytest.mark.skipif( - not os.environ.get("SERPERDEV_API_KEY", None), - reason="Please export an env var called SERPERDEV_API_KEY containing the SerperDev key to run this test.", -) -def test_webqa_pipeline(): - search_key = os.environ.get("SERPERDEV_API_KEY") - openai_key = os.environ.get("OPENAI_API_KEY") - pn = PromptNode( - "text-davinci-003", - api_key=openai_key, - max_length=256, - default_prompt_template="question-answering-with-document-scores", - ) - web_retriever = WebRetriever(api_key=search_key, top_search_results=2) - pipeline = WebQAPipeline(retriever=web_retriever, prompt_node=pn) - result = pipeline.run(query="Who is the father of Arya Stark?") - assert isinstance(result, dict) - assert len(result["results"]) == 1 - answer = result["results"][0] - assert "stark" in answer.lower() or "ned" in answer.lower() diff --git a/test/prompt/__init__.py b/test/prompt/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/prompt/conftest.py b/test/prompt/conftest.py deleted file mode 100644 index 9d38e6d0dd..0000000000 --- a/test/prompt/conftest.py +++ /dev/null @@ -1,41 +0,0 @@ -from unittest.mock import Mock -import os - -import pytest - -from haystack.nodes.prompt import PromptModel - - -def create_mock_layer_that_supports(model_name, response=["fake_response"]): - """ - Create a mock invocation layer that supports the model_name and returns response. - """ - - def mock_supports(model_name_or_path, **kwargs): - return model_name_or_path == model_name - - return Mock(**{"model_name_or_path": model_name, "supports": mock_supports, "invoke.return_value": response}) - - -@pytest.fixture -def prompt_model(request, haystack_azure_conf): - if request.param == "openai": - api_key = os.environ.get("OPENAI_API_KEY", "KEY_NOT_FOUND") - if api_key is None or api_key == "": - api_key = "KEY_NOT_FOUND" - return PromptModel("text-davinci-003", api_key=api_key) - elif request.param == "azure": - api_key = os.environ.get("AZURE_OPENAI_API_KEY", "KEY_NOT_FOUND") - if api_key is None or api_key == "": - api_key = "KEY_NOT_FOUND" - return PromptModel("text-davinci-003", api_key=api_key, model_kwargs=haystack_azure_conf) - else: - return PromptModel("google/flan-t5-base", devices=["cpu"]) - - -@pytest.fixture -def chatgpt_prompt_model(): - api_key = os.environ.get("OPENAI_API_KEY", "KEY_NOT_FOUND") - if api_key is None or api_key == "": - api_key = "KEY_NOT_FOUND" - return PromptModel("gpt-3.5-turbo", api_key=api_key) diff --git a/test/prompt/invocation_layer/conftest.py b/test/prompt/invocation_layer/conftest.py deleted file mode 100644 index e41baf68f6..0000000000 --- a/test/prompt/invocation_layer/conftest.py +++ /dev/null @@ -1,14 +0,0 @@ -from unittest.mock import patch, MagicMock -import pytest - - -@pytest.fixture -def mock_openai_tokenizer(): - with patch("haystack.nodes.prompt.invocation_layer.open_ai.load_openai_tokenizer") as mock_tokenizer_func: - mock_tokenizer = MagicMock() # this will be our mock tokenizer - # "This is a test for a mock openai tokenizer." - mock_tokenizer.encode.return_value = [2028, 374, 264, 1296, 369, 264, 8018, 1825, 2192, 47058, 13] - # Returning truncated prompt: [2028, 374, 264, 1296, 369, 264, 8018, 1825, 2192] - mock_tokenizer.decode.return_value = "This is a test for a mock openai" - mock_tokenizer_func.return_value = mock_tokenizer - yield mock_tokenizer_func diff --git a/test/prompt/invocation_layer/test_amazon_bedrock.py b/test/prompt/invocation_layer/test_amazon_bedrock.py deleted file mode 100644 index a605c68ccc..0000000000 --- a/test/prompt/invocation_layer/test_amazon_bedrock.py +++ /dev/null @@ -1,1033 +0,0 @@ -from typing import Optional, Type -from unittest.mock import call, patch, MagicMock - -import pytest - -from haystack.lazy_imports import LazyImport - -from haystack.errors import AmazonBedrockConfigurationError -from haystack.nodes.prompt.invocation_layer import AmazonBedrockInvocationLayer -from haystack.nodes.prompt.invocation_layer.amazon_bedrock import ( - AI21LabsJurassic2Adapter, - AnthropicClaudeAdapter, - BedrockModelAdapter, - CohereCommandAdapter, - AmazonTitanAdapter, - MetaLlama2ChatAdapter, -) - -with LazyImport() as boto3_import: - from botocore.exceptions import BotoCoreError - - -# create a fixture with mocked boto3 client and session -@pytest.fixture -def mock_boto3_session(): - with patch("boto3.Session") as mock_client: - yield mock_client - - -@pytest.fixture -def mock_prompt_handler(): - with patch("haystack.nodes.prompt.invocation_layer.handlers.DefaultPromptHandler") as mock_prompt_handler: - yield mock_prompt_handler - - -@pytest.mark.unit -def test_default_constructor(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the default constructor sets the correct values - """ - - layer = AmazonBedrockInvocationLayer( - model_name_or_path="anthropic.claude-v2", - max_length=99, - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - aws_profile_name="some_fake_profile", - aws_region_name="fake_region", - ) - - assert layer.max_length == 99 - assert layer.model_name_or_path == "anthropic.claude-v2" - - assert layer.prompt_handler is not None - assert layer.prompt_handler.model_max_length == 4096 - - # assert mocked boto3 client called exactly once - mock_boto3_session.assert_called_once() - - # assert mocked boto3 client was called with the correct parameters - mock_boto3_session.assert_called_with( - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - profile_name="some_fake_profile", - region_name="fake_region", - ) - - -@pytest.mark.unit -def test_constructor_prompt_handler_initialized(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the constructor sets the prompt_handler correctly, with the correct model_max_length for llama-2 - """ - layer = AmazonBedrockInvocationLayer(model_name_or_path="anthropic.claude-v2", prompt_handler=mock_prompt_handler) - assert layer.prompt_handler is not None - assert layer.prompt_handler.model_max_length == 4096 - - -@pytest.mark.unit -def test_constructor_with_model_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test that model_kwargs are correctly set in the constructor - """ - model_kwargs = {"temperature": 0.7} - - layer = AmazonBedrockInvocationLayer(model_name_or_path="anthropic.claude-v2", **model_kwargs) - assert "temperature" in layer.model_adapter.model_kwargs - assert layer.model_adapter.model_kwargs["temperature"] == 0.7 - - -@pytest.mark.unit -def test_constructor_with_empty_model_name(): - """ - Test that the constructor raises an error when the model_name_or_path is empty - """ - with pytest.raises(ValueError, match="cannot be None or empty string"): - AmazonBedrockInvocationLayer(model_name_or_path="") - - -@pytest.mark.unit -def test_invoke_with_no_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test invoke raises an error if no prompt is provided - """ - layer = AmazonBedrockInvocationLayer(model_name_or_path="anthropic.claude-v2") - with pytest.raises(ValueError, match="The model anthropic.claude-v2 requires a valid prompt."): - layer.invoke() - - -@pytest.mark.unit -def test_short_prompt_is_not_truncated(mock_boto3_session): - """ - Test that a short prompt is not truncated - """ - # Define a short mock prompt and its tokenized version - mock_prompt_text = "I am a tokenized prompt" - mock_prompt_tokens = mock_prompt_text.split() - - # Mock the tokenizer so it returns our predefined tokens - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = mock_prompt_tokens - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Since our mock prompt is 5 tokens long, it doesn't exceed the - # total limit (5 prompt tokens + 3 generated tokens < 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = AmazonBedrockInvocationLayer( - "anthropic.claude-v2", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(mock_prompt_text) - - # The prompt doesn't exceed the limit, _ensure_token_limit doesn't truncate it - assert prompt_after_resize == mock_prompt_text - - -@pytest.mark.unit -def test_long_prompt_is_truncated(mock_boto3_session): - """ - Test that a long prompt is truncated - """ - # Define a long mock prompt and its tokenized version - long_prompt_text = "I am a tokenized prompt of length eight" - long_prompt_tokens = long_prompt_text.split() - - # _ensure_token_limit will truncate the prompt to make it fit into the model's max token limit - truncated_prompt_text = "I am a tokenized prompt of length" - - # Mock the tokenizer to return our predefined tokens - # convert tokens to our predefined truncated text - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = long_prompt_tokens - mock_tokenizer.convert_tokens_to_string.return_value = truncated_prompt_text - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Our mock prompt is 8 tokens long, so it exceeds the total limit (8 prompt tokens + 3 generated tokens > 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = AmazonBedrockInvocationLayer( - "anthropic.claude-v2", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(long_prompt_text) - - # The prompt exceeds the limit, _ensure_token_limit truncates it - assert prompt_after_resize == truncated_prompt_text - - -@pytest.mark.unit -def test_supports_for_valid_aws_configuration(): - mock_session = MagicMock() - mock_session.client("bedrock").list_foundation_models.return_value = { - "modelSummaries": [{"modelId": "anthropic.claude-v2"}] - } - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ): - supported = AmazonBedrockInvocationLayer.supports( - model_name_or_path="anthropic.claude-v2", aws_profile_name="some_real_profile" - ) - args, kwargs = mock_session.client("bedrock").list_foundation_models.call_args - assert kwargs["byOutputModality"] == "TEXT" - - assert supported - - -@pytest.mark.unit -def test_supports_raises_on_invalid_aws_profile_name(): - with patch("boto3.Session") as mock_boto3_session: - mock_boto3_session.side_effect = BotoCoreError() - with pytest.raises(AmazonBedrockConfigurationError, match="Failed to initialize the session"): - AmazonBedrockInvocationLayer.supports( - model_name_or_path="anthropic.claude-v2", aws_profile_name="some_fake_profile" - ) - - -@pytest.mark.unit -def test_supports_for_invalid_bedrock_config(): - mock_session = MagicMock() - mock_session.client.side_effect = BotoCoreError() - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ), pytest.raises(AmazonBedrockConfigurationError, match="Could not connect to Amazon Bedrock."): - AmazonBedrockInvocationLayer.supports( - model_name_or_path="anthropic.claude-v2", aws_profile_name="some_real_profile" - ) - - -@pytest.mark.unit -def test_supports_for_invalid_bedrock_config_error_on_list_models(): - mock_session = MagicMock() - mock_session.client("bedrock").list_foundation_models.side_effect = BotoCoreError() - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ), pytest.raises(AmazonBedrockConfigurationError, match="Could not connect to Amazon Bedrock."): - AmazonBedrockInvocationLayer.supports( - model_name_or_path="anthropic.claude-v2", aws_profile_name="some_real_profile" - ) - - -@pytest.mark.unit -def test_supports_for_no_aws_params(): - supported = AmazonBedrockInvocationLayer.supports(model_name_or_path="anthropic.claude-v2") - - assert supported == False - - -@pytest.mark.unit -def test_supports_for_unknown_model(): - supported = AmazonBedrockInvocationLayer.supports( - model_name_or_path="unknown_model", aws_profile_name="some_real_profile" - ) - - assert supported == False - - -@pytest.mark.unit -def test_supports_with_stream_true_for_model_that_supports_streaming(): - mock_session = MagicMock() - mock_session.client("bedrock").list_foundation_models.return_value = { - "modelSummaries": [{"modelId": "anthropic.claude-v2", "responseStreamingSupported": True}] - } - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ): - supported = AmazonBedrockInvocationLayer.supports( - model_name_or_path="anthropic.claude-v2", aws_profile_name="some_real_profile", stream=True - ) - - assert supported == True - - -@pytest.mark.unit -def test_supports_with_stream_true_for_model_that_does_not_support_streaming(): - mock_session = MagicMock() - mock_session.client("bedrock").list_foundation_models.return_value = { - "modelSummaries": [{"modelId": "ai21.j2-mid-v1", "responseStreamingSupported": False}] - } - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ), pytest.raises(AmazonBedrockConfigurationError, match="The model ai21.j2-mid-v1 doesn't support streaming."): - AmazonBedrockInvocationLayer.supports( - model_name_or_path="ai21.j2-mid-v1", aws_profile_name="some_real_profile", stream=True - ) - - -@pytest.mark.unit -@pytest.mark.parametrize( - "model_name_or_path, expected_model_adapter", - [ - ("anthropic.claude-v1", AnthropicClaudeAdapter), - ("anthropic.claude-v2", AnthropicClaudeAdapter), - ("anthropic.claude-instant-v1", AnthropicClaudeAdapter), - ("anthropic.claude-super-v5", AnthropicClaudeAdapter), # artificial - ("cohere.command-text-v14", CohereCommandAdapter), - ("cohere.command-light-text-v14", CohereCommandAdapter), - ("cohere.command-text-v21", CohereCommandAdapter), # artificial - ("ai21.j2-mid-v1", AI21LabsJurassic2Adapter), - ("ai21.j2-ultra-v1", AI21LabsJurassic2Adapter), - ("ai21.j2-mega-v5", AI21LabsJurassic2Adapter), # artificial - ("amazon.titan-text-lite-v1", AmazonTitanAdapter), - ("amazon.titan-text-express-v1", AmazonTitanAdapter), - ("amazon.titan-text-agile-v1", AmazonTitanAdapter), - ("amazon.titan-text-lightning-v8", AmazonTitanAdapter), # artificial - ("meta.llama2-13b-chat-v1", MetaLlama2ChatAdapter), - ("meta.llama2-70b-chat-v1", MetaLlama2ChatAdapter), - ("meta.llama2-130b-v5", MetaLlama2ChatAdapter), # artificial - ("unknown_model", None), - ], -) -def test_get_model_adapter(model_name_or_path: str, expected_model_adapter: Optional[Type[BedrockModelAdapter]]): - """ - Test that the correct model adapter is returned for a given model_name_or_path - """ - model_adapter = AmazonBedrockInvocationLayer.get_model_adapter(model_name_or_path=model_name_or_path) - assert model_adapter == expected_model_adapter - - -class TestAnthropicClaudeAdapter: - def test_prepare_body_with_default_params(self) -> None: - layer = AnthropicClaudeAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "\n\nHuman: Hello, how are you?\n\nAssistant:", - "max_tokens_to_sample": 99, - "stop_sequences": ["\n\nHuman:"], - } - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_custom_inference_params(self) -> None: - layer = AnthropicClaudeAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "\n\nHuman: Hello, how are you?\n\nAssistant:", - "max_tokens_to_sample": 50, - "stop_sequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "top_p": 0.8, - "top_k": 5, - } - - body = layer.prepare_body( - prompt, - temperature=0.7, - top_p=0.8, - top_k=5, - max_tokens_to_sample=50, - stop_sequences=["CUSTOM_STOP"], - unknown_arg="unknown_value", - ) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs(self) -> None: - layer = AnthropicClaudeAdapter( - model_kwargs={ - "temperature": 0.7, - "top_p": 0.8, - "top_k": 5, - "max_tokens_to_sample": 50, - "stop_sequences": ["CUSTOM_STOP"], - "unknown_arg": "unknown_value", - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "\n\nHuman: Hello, how are you?\n\nAssistant:", - "max_tokens_to_sample": 50, - "stop_sequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "top_p": 0.8, - "top_k": 5, - } - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs_and_custom_inference_params(self) -> None: - layer = AnthropicClaudeAdapter( - model_kwargs={ - "temperature": 0.6, - "top_p": 0.7, - "top_k": 4, - "max_tokens_to_sample": 49, - "stop_sequences": ["CUSTOM_STOP_MODEL_KWARGS"], - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "\n\nHuman: Hello, how are you?\n\nAssistant:", - "max_tokens_to_sample": 50, - "stop_sequences": ["CUSTOM_STOP_MODEL_KWARGS"], - "temperature": 0.7, - "top_p": 0.8, - "top_k": 5, - } - - body = layer.prepare_body(prompt, temperature=0.7, top_p=0.8, top_k=5, max_tokens_to_sample=50) - - assert body == expected_body - - def test_get_responses(self) -> None: - adapter = AnthropicClaudeAdapter(model_kwargs={}, max_length=99) - response_body = {"completion": "This is a single response."} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_leading_whitespace(self) -> None: - adapter = AnthropicClaudeAdapter(model_kwargs={}, max_length=99) - response_body = {"completion": "\n\t This is a single response."} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_stream_responses(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [ - {"chunk": {"bytes": b'{"completion": " This"}'}}, - {"chunk": {"bytes": b'{"completion": " is"}'}}, - {"chunk": {"bytes": b'{"completion": " a"}'}}, - {"chunk": {"bytes": b'{"completion": " single"}'}}, - {"chunk": {"bytes": b'{"completion": " response."}'}}, - ] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = AnthropicClaudeAdapter(model_kwargs={}, max_length=99) - expected_responses = ["This is a single response."] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_has_calls( - [ - call(" This", event_data={"completion": " This"}), - call(" is", event_data={"completion": " is"}), - call(" a", event_data={"completion": " a"}), - call(" single", event_data={"completion": " single"}), - call(" response.", event_data={"completion": " response."}), - ] - ) - - def test_get_stream_responses_empty(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = AnthropicClaudeAdapter(model_kwargs={}, max_length=99) - expected_responses = [""] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_not_called() - - -class TestCohereCommandAdapter: - def test_prepare_body_with_default_params(self) -> None: - layer = CohereCommandAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = {"prompt": "Hello, how are you?", "max_tokens": 99} - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_custom_inference_params(self) -> None: - layer = CohereCommandAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "Hello, how are you?", - "max_tokens": 50, - "stop_sequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "p": 0.8, - "k": 5, - "return_likelihoods": "GENERATION", - "stream": True, - "logit_bias": {"token_id": 10.0}, - "num_generations": 1, - "truncate": "START", - } - - body = layer.prepare_body( - prompt, - temperature=0.7, - p=0.8, - k=5, - max_tokens=50, - stop_sequences=["CUSTOM_STOP"], - return_likelihoods="GENERATION", - stream=True, - logit_bias={"token_id": 10.0}, - num_generations=1, - truncate="START", - unknown_arg="unknown_value", - ) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs(self) -> None: - layer = CohereCommandAdapter( - model_kwargs={ - "temperature": 0.7, - "p": 0.8, - "k": 5, - "max_tokens": 50, - "stop_sequences": ["CUSTOM_STOP"], - "return_likelihoods": "GENERATION", - "stream": True, - "logit_bias": {"token_id": 10.0}, - "num_generations": 1, - "truncate": "START", - "unknown_arg": "unknown_value", - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "Hello, how are you?", - "max_tokens": 50, - "stop_sequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "p": 0.8, - "k": 5, - "return_likelihoods": "GENERATION", - "stream": True, - "logit_bias": {"token_id": 10.0}, - "num_generations": 1, - "truncate": "START", - } - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs_and_custom_inference_params(self) -> None: - layer = CohereCommandAdapter( - model_kwargs={ - "temperature": 0.6, - "p": 0.7, - "k": 4, - "max_tokens": 49, - "stop_sequences": ["CUSTOM_STOP_MODEL_KWARGS"], - "return_likelihoods": "ALL", - "stream": False, - "logit_bias": {"token_id": 9.0}, - "num_generations": 2, - "truncate": "NONE", - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "Hello, how are you?", - "max_tokens": 50, - "stop_sequences": ["CUSTOM_STOP_MODEL_KWARGS"], - "temperature": 0.7, - "p": 0.8, - "k": 5, - "return_likelihoods": "GENERATION", - "stream": True, - "logit_bias": {"token_id": 10.0}, - "num_generations": 1, - "truncate": "START", - } - - body = layer.prepare_body( - prompt, - temperature=0.7, - p=0.8, - k=5, - max_tokens=50, - return_likelihoods="GENERATION", - stream=True, - logit_bias={"token_id": 10.0}, - num_generations=1, - truncate="START", - ) - - assert body == expected_body - - def test_get_responses(self) -> None: - adapter = CohereCommandAdapter(model_kwargs={}, max_length=99) - response_body = {"generations": [{"text": "This is a single response."}]} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_leading_whitespace(self) -> None: - adapter = CohereCommandAdapter(model_kwargs={}, max_length=99) - response_body = {"generations": [{"text": "\n\t This is a single response."}]} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_multiple_responses(self) -> None: - adapter = CohereCommandAdapter(model_kwargs={}, max_length=99) - response_body = { - "generations": [{"text": "This is a single response."}, {"text": "This is a second response."}] - } - expected_responses = ["This is a single response.", "This is a second response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_stream_responses(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [ - {"chunk": {"bytes": b'{"text": " This"}'}}, - {"chunk": {"bytes": b'{"text": " is"}'}}, - {"chunk": {"bytes": b'{"text": " a"}'}}, - {"chunk": {"bytes": b'{"text": " single"}'}}, - {"chunk": {"bytes": b'{"text": " response."}'}}, - {"chunk": {"bytes": b'{"finish_reason": "MAX_TOKENS", "is_finished": true}'}}, - ] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = CohereCommandAdapter(model_kwargs={}, max_length=99) - expected_responses = ["This is a single response."] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_has_calls( - [ - call(" This", event_data={"text": " This"}), - call(" is", event_data={"text": " is"}), - call(" a", event_data={"text": " a"}), - call(" single", event_data={"text": " single"}), - call(" response.", event_data={"text": " response."}), - call("", event_data={"finish_reason": "MAX_TOKENS", "is_finished": True}), - ] - ) - - def test_get_stream_responses_empty(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = CohereCommandAdapter(model_kwargs={}, max_length=99) - expected_responses = [""] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_not_called() - - -class TestAI21LabsJurrasic2Adapter: - def test_prepare_body_with_default_params(self) -> None: - layer = AI21LabsJurassic2Adapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = {"prompt": "Hello, how are you?", "maxTokens": 99} - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_custom_inference_params(self) -> None: - layer = AI21LabsJurassic2Adapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "Hello, how are you?", - "maxTokens": 50, - "stopSequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "topP": 0.8, - "countPenalty": {"scale": 1.0}, - "presencePenalty": {"scale": 5.0}, - "frequencyPenalty": {"scale": 500.0}, - "numResults": 1, - } - - body = layer.prepare_body( - prompt, - maxTokens=50, - stopSequences=["CUSTOM_STOP"], - temperature=0.7, - topP=0.8, - countPenalty={"scale": 1.0}, - presencePenalty={"scale": 5.0}, - frequencyPenalty={"scale": 500.0}, - numResults=1, - unknown_arg="unknown_value", - ) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs(self) -> None: - layer = AI21LabsJurassic2Adapter( - model_kwargs={ - "maxTokens": 50, - "stopSequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "topP": 0.8, - "countPenalty": {"scale": 1.0}, - "presencePenalty": {"scale": 5.0}, - "frequencyPenalty": {"scale": 500.0}, - "numResults": 1, - "unknown_arg": "unknown_value", - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "Hello, how are you?", - "maxTokens": 50, - "stopSequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "topP": 0.8, - "countPenalty": {"scale": 1.0}, - "presencePenalty": {"scale": 5.0}, - "frequencyPenalty": {"scale": 500.0}, - "numResults": 1, - } - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs_and_custom_inference_params(self) -> None: - layer = AI21LabsJurassic2Adapter( - model_kwargs={ - "maxTokens": 49, - "stopSequences": ["CUSTOM_STOP_MODEL_KWARGS"], - "temperature": 0.6, - "topP": 0.7, - "countPenalty": {"scale": 0.9}, - "presencePenalty": {"scale": 4.0}, - "frequencyPenalty": {"scale": 499.0}, - "numResults": 2, - "unknown_arg": "unknown_value", - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "prompt": "Hello, how are you?", - "maxTokens": 50, - "stopSequences": ["CUSTOM_STOP_MODEL_KWARGS"], - "temperature": 0.7, - "topP": 0.8, - "countPenalty": {"scale": 1.0}, - "presencePenalty": {"scale": 5.0}, - "frequencyPenalty": {"scale": 500.0}, - "numResults": 1, - } - - body = layer.prepare_body( - prompt, - temperature=0.7, - topP=0.8, - maxTokens=50, - countPenalty={"scale": 1.0}, - presencePenalty={"scale": 5.0}, - frequencyPenalty={"scale": 500.0}, - numResults=1, - ) - - assert body == expected_body - - def test_get_responses(self) -> None: - adapter = AI21LabsJurassic2Adapter(model_kwargs={}, max_length=99) - response_body = {"completions": [{"data": {"text": "This is a single response."}}]} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_leading_whitespace(self) -> None: - adapter = AI21LabsJurassic2Adapter(model_kwargs={}, max_length=99) - response_body = {"completions": [{"data": {"text": "\n\t This is a single response."}}]} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_multiple_responses(self) -> None: - adapter = AI21LabsJurassic2Adapter(model_kwargs={}, max_length=99) - response_body = { - "completions": [ - {"data": {"text": "This is a single response."}}, - {"data": {"text": "This is a second response."}}, - ] - } - expected_responses = ["This is a single response.", "This is a second response."] - assert adapter.get_responses(response_body) == expected_responses - - -class TestAmazonTitanAdapter: - def test_prepare_body_with_default_params(self) -> None: - layer = AmazonTitanAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = {"inputText": "Hello, how are you?", "textGenerationConfig": {"maxTokenCount": 99}} - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_custom_inference_params(self) -> None: - layer = AmazonTitanAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = { - "inputText": "Hello, how are you?", - "textGenerationConfig": { - "maxTokenCount": 50, - "stopSequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "topP": 0.8, - }, - } - - body = layer.prepare_body( - prompt, - maxTokenCount=50, - stopSequences=["CUSTOM_STOP"], - temperature=0.7, - topP=0.8, - unknown_arg="unknown_value", - ) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs(self) -> None: - layer = AmazonTitanAdapter( - model_kwargs={ - "maxTokenCount": 50, - "stopSequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "topP": 0.8, - "unknown_arg": "unknown_value", - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "inputText": "Hello, how are you?", - "textGenerationConfig": { - "maxTokenCount": 50, - "stopSequences": ["CUSTOM_STOP"], - "temperature": 0.7, - "topP": 0.8, - }, - } - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs_and_custom_inference_params(self) -> None: - layer = AmazonTitanAdapter( - model_kwargs={ - "maxTokenCount": 49, - "stopSequences": ["CUSTOM_STOP_MODEL_KWARGS"], - "temperature": 0.6, - "topP": 0.7, - }, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = { - "inputText": "Hello, how are you?", - "textGenerationConfig": { - "maxTokenCount": 50, - "stopSequences": ["CUSTOM_STOP_MODEL_KWARGS"], - "temperature": 0.7, - "topP": 0.8, - }, - } - - body = layer.prepare_body(prompt, temperature=0.7, topP=0.8, maxTokenCount=50) - - assert body == expected_body - - def test_get_responses(self) -> None: - adapter = AmazonTitanAdapter(model_kwargs={}, max_length=99) - response_body = {"results": [{"outputText": "This is a single response."}]} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_leading_whitespace(self) -> None: - adapter = AmazonTitanAdapter(model_kwargs={}, max_length=99) - response_body = {"results": [{"outputText": "\n\t This is a single response."}]} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_multiple_responses(self) -> None: - adapter = AmazonTitanAdapter(model_kwargs={}, max_length=99) - response_body = { - "results": [{"outputText": "This is a single response."}, {"outputText": "This is a second response."}] - } - expected_responses = ["This is a single response.", "This is a second response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_stream_responses(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [ - {"chunk": {"bytes": b'{"outputText": " This"}'}}, - {"chunk": {"bytes": b'{"outputText": " is"}'}}, - {"chunk": {"bytes": b'{"outputText": " a"}'}}, - {"chunk": {"bytes": b'{"outputText": " single"}'}}, - {"chunk": {"bytes": b'{"outputText": " response."}'}}, - ] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = AmazonTitanAdapter(model_kwargs={}, max_length=99) - expected_responses = ["This is a single response."] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_has_calls( - [ - call(" This", event_data={"outputText": " This"}), - call(" is", event_data={"outputText": " is"}), - call(" a", event_data={"outputText": " a"}), - call(" single", event_data={"outputText": " single"}), - call(" response.", event_data={"outputText": " response."}), - ] - ) - - def test_get_stream_responses_empty(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = AmazonTitanAdapter(model_kwargs={}, max_length=99) - expected_responses = [""] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_not_called() - - -class TestMetaLlama2ChatAdapter: - def test_prepare_body_with_default_params(self) -> None: - layer = MetaLlama2ChatAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = {"prompt": "Hello, how are you?", "max_gen_len": 99} - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_custom_inference_params(self) -> None: - layer = MetaLlama2ChatAdapter(model_kwargs={}, max_length=99) - prompt = "Hello, how are you?" - expected_body = {"prompt": "Hello, how are you?", "max_gen_len": 50, "temperature": 0.7, "top_p": 0.8} - - body = layer.prepare_body(prompt, temperature=0.7, top_p=0.8, max_gen_len=50, unknown_arg="unknown_value") - - assert body == expected_body - - def test_prepare_body_with_model_kwargs(self) -> None: - layer = MetaLlama2ChatAdapter( - model_kwargs={"temperature": 0.7, "top_p": 0.8, "max_gen_len": 50, "unknown_arg": "unknown_value"}, - max_length=99, - ) - prompt = "Hello, how are you?" - expected_body = {"prompt": "Hello, how are you?", "max_gen_len": 50, "temperature": 0.7, "top_p": 0.8} - - body = layer.prepare_body(prompt) - - assert body == expected_body - - def test_prepare_body_with_model_kwargs_and_custom_inference_params(self) -> None: - layer = MetaLlama2ChatAdapter( - model_kwargs={"temperature": 0.6, "top_p": 0.7, "top_k": 4, "max_gen_len": 49}, max_length=99 - ) - prompt = "Hello, how are you?" - expected_body = {"prompt": "Hello, how are you?", "max_gen_len": 50, "temperature": 0.7, "top_p": 0.7} - - body = layer.prepare_body(prompt, temperature=0.7, max_gen_len=50) - - assert body == expected_body - - def test_get_responses(self) -> None: - adapter = MetaLlama2ChatAdapter(model_kwargs={}, max_length=99) - response_body = {"generation": "This is a single response."} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_responses_leading_whitespace(self) -> None: - adapter = MetaLlama2ChatAdapter(model_kwargs={}, max_length=99) - response_body = {"generation": "\n\t This is a single response."} - expected_responses = ["This is a single response."] - assert adapter.get_responses(response_body) == expected_responses - - def test_get_stream_responses(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [ - {"chunk": {"bytes": b'{"generation": " This"}'}}, - {"chunk": {"bytes": b'{"generation": " is"}'}}, - {"chunk": {"bytes": b'{"generation": " a"}'}}, - {"chunk": {"bytes": b'{"generation": " single"}'}}, - {"chunk": {"bytes": b'{"generation": " response."}'}}, - ] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = MetaLlama2ChatAdapter(model_kwargs={}, max_length=99) - expected_responses = ["This is a single response."] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_has_calls( - [ - call(" This", event_data={"generation": " This"}), - call(" is", event_data={"generation": " is"}), - call(" a", event_data={"generation": " a"}), - call(" single", event_data={"generation": " single"}), - call(" response.", event_data={"generation": " response."}), - ] - ) - - def test_get_stream_responses_empty(self) -> None: - stream_mock = MagicMock() - stream_handler_mock = MagicMock() - - stream_mock.__iter__.return_value = [] - - stream_handler_mock.side_effect = lambda token_received, **kwargs: token_received - - adapter = MetaLlama2ChatAdapter(model_kwargs={}, max_length=99) - expected_responses = [""] - assert adapter.get_stream_responses(stream_mock, stream_handler_mock) == expected_responses - - stream_handler_mock.assert_not_called() diff --git a/test/prompt/invocation_layer/test_anthropic_claude.py b/test/prompt/invocation_layer/test_anthropic_claude.py deleted file mode 100644 index 19e1e929ea..0000000000 --- a/test/prompt/invocation_layer/test_anthropic_claude.py +++ /dev/null @@ -1,277 +0,0 @@ -from unittest.mock import patch, Mock, call -import json -import os - -import pytest - -from haystack.nodes.prompt.invocation_layer.handlers import DefaultTokenStreamingHandler -from haystack.nodes.prompt.invocation_layer import AnthropicClaudeInvocationLayer - - -@pytest.fixture -def mock_claude_tokenizer(): - with patch("haystack.nodes.prompt.invocation_layer.anthropic_claude.Tokenizer", autospec=True) as mock_tokenizer: - yield mock_tokenizer - - -@pytest.fixture -def mock_claude_request(): - with patch("haystack.nodes.prompt.invocation_layer.anthropic_claude.request_with_retry") as mock_request: - yield mock_request - - -@pytest.mark.unit -def test_default_constructor(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - - assert layer.api_key == "some_fake_key" - assert layer.max_length == 200 - assert layer.max_tokens_limit == 100000 - assert layer.model_input_kwargs == {} - - -@pytest.mark.unit -def test_ignored_kwargs_are_filtered_in_init(mock_claude_tokenizer, mock_claude_request): - kwargs = { - "temperature": 1, - "top_p": 5, - "top_k": 2, - "stop_sequences": ["\n\nHuman: "], - "stream": True, - "stream_handler": DefaultTokenStreamingHandler(), - "unkwnown_args": "this will be filtered out", - } - - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key", **kwargs) - - # Verify unexpected kwargs are filtered out - assert len(layer.model_input_kwargs) == 6 - assert "temperature" in layer.model_input_kwargs - assert "top_p" in layer.model_input_kwargs - assert "top_k" in layer.model_input_kwargs - assert "stop_sequences" in layer.model_input_kwargs - assert "stream" in layer.model_input_kwargs - assert "stream_handler" in layer.model_input_kwargs - assert "unkwnown_args" not in layer.model_input_kwargs - - -@pytest.mark.unit -def test_invoke_with_no_kwargs(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - - with pytest.raises(ValueError) as e: - layer.invoke() - assert e.match("No prompt provided.") - - -@pytest.mark.unit -def test_invoke_with_prompt_only(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - - # Create a fake response - mock_response = Mock(**{"status_code": 200, "ok": True, "json.return_value": {"completion": "some_result "}}) - mock_claude_request.return_value = mock_response - - res = layer.invoke(prompt="Some prompt") - assert len(res) == 1 - assert res[0] == "some_result" - - -@pytest.mark.unit -def test_invoke_with_kwargs(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - - # Create a fake response - mock_response = Mock(**{"status_code": 200, "ok": True, "json.return_value": {"completion": "some_result "}}) - with patch("haystack.nodes.prompt.invocation_layer.anthropic_claude.request_with_retry") as mock_invocation_request: - mock_invocation_request.return_value = mock_response - res = layer.invoke(prompt="Some prompt", max_length=300, stop_words=["stop", "here"]) - assert len(res) == 1 - assert res[0] == "some_result" - - expected_data = { - "model": "claude-2", - "prompt": "\n\nHuman: Some prompt\n\nAssistant: ", - "max_tokens_to_sample": 300, - "temperature": 1, - "top_p": -1, - "top_k": -1, - "stream": False, - "stop_sequences": ["stop", "here", "\n\nHuman: "], - } - mock_invocation_request.assert_called_once() - assert mock_invocation_request.call_args.kwargs["data"] == json.dumps(expected_data) - - -@pytest.mark.unit -def test_invoke_with_none_stop_words(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - - # Create a fake response - mock_response = Mock(**{"status_code": 200, "ok": True, "json.return_value": {"completion": "some_result "}}) - with patch("haystack.nodes.prompt.invocation_layer.anthropic_claude.request_with_retry") as mock_invocation_request: - mock_invocation_request.return_value = mock_response - res = layer.invoke(prompt="Some prompt", max_length=300, stop_words=None) - assert len(res) == 1 - assert res[0] == "some_result" - - expected_data = { - "model": "claude-2", - "prompt": "\n\nHuman: Some prompt\n\nAssistant: ", - "max_tokens_to_sample": 300, - "temperature": 1, - "top_p": -1, - "top_k": -1, - "stream": False, - "stop_sequences": ["\n\nHuman: "], - } - mock_invocation_request.assert_called_once() - assert mock_invocation_request.call_args.kwargs["data"] == json.dumps(expected_data) - - -@pytest.mark.unit -def test_invoke_with_stream(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - - # Create a fake streamed response - def mock_iter(self): - fake_data = json.dumps({"completion": " The sky appears"}) - yield f"data: {fake_data}\n\n".encode() - fake_data = json.dumps({"completion": " blue to"}) - yield f"data: {fake_data}\n\n".encode() - fake_data = json.dumps({"completion": " us due to how"}) - yield f"data: {fake_data}\n\n".encode() - # Done was removed from the stream - # https://docs.anthropic.com/claude/reference/versioning - - mock_response = Mock(**{"__iter__": mock_iter}) - - # Verifies expected result is returned - with patch("haystack.nodes.prompt.invocation_layer.anthropic_claude.request_with_retry") as mock_invocation_request: - mock_invocation_request.return_value = mock_response - res = layer.invoke(prompt="Some prompt", stream=True) - - assert len(res) == 1 - assert res[0] == " The sky appears blue to us due to how" - - -@pytest.mark.unit -def test_invoke_with_custom_stream_handler(mock_claude_tokenizer, mock_claude_request): - # Create a generator that will yield the expected return values in order - def mock_handler_responses(): - yield " The sky appears" - yield " blue to" - yield " us due to how" - - handler_responses = mock_handler_responses() - - # Create a mock stream handler that will return the next value from the generator when called - mock_stream_handler = Mock(side_effect=lambda x: next(handler_responses)) - - # Create a layer with a mocked stream handler - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key", stream_handler=mock_stream_handler) - - # Create a fake streamed response - def mock_iter(self): - fake_data = json.dumps({"completion": " The sky appears"}) - yield f"data: {fake_data}\n\n".encode() - fake_data = json.dumps({"completion": " blue to"}) - yield f"data: {fake_data}\n\n".encode() - fake_data = json.dumps({"completion": " us due to how"}) - yield f"data: {fake_data}\n\n".encode() - # Done was removed from the stream - # https://docs.anthropic.com/claude/reference/versioning - - mock_response = Mock(**{"__iter__": mock_iter}) - - with patch("haystack.nodes.prompt.invocation_layer.anthropic_claude.request_with_retry") as mock_invocation_request: - mock_invocation_request.return_value = mock_response - res = layer.invoke(prompt="Some prompt") - - assert len(res) == 1 - # This is not the real result but the values returned by the mock handler - assert res[0] == " The sky appears blue to us due to how" - - # Verifies the handler has been called the expected times with the expected args - assert mock_stream_handler.call_count == 3 - expected_call_list = [call(" The sky appears"), call(" blue to"), call(" us due to how")] - assert mock_stream_handler.call_args_list == expected_call_list - - -@pytest.mark.unit -def test_ensure_token_limit_fails_if_called_with_list(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - with pytest.raises(ValueError): - layer._ensure_token_limit(prompt=[]) - - -@pytest.mark.integration -def test_ensure_token_limit_with_small_max_length(caplog): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key", max_length=10) - res = layer._ensure_token_limit(prompt="Short prompt") - - assert res == "Short prompt" - assert not caplog.records - - res = layer._ensure_token_limit(prompt="This is a very very very very very much longer prompt") - assert res == "This is a very very very very very much longer prompt" - assert not caplog.records - - -@pytest.mark.integration -def test_ensure_token_limit_with_huge_max_length(caplog): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key", max_length=(100000 - 5)) - res = layer._ensure_token_limit(prompt="Short prompt") - - assert res == "Short prompt" - assert not caplog.records - - res = layer._ensure_token_limit(prompt="This is a very very very very very much longer prompt") - assert res == "This is a very very" - assert len(caplog.records) == 1 - expected_message_log = ( - "The prompt has been truncated from 7 tokens to 5 tokens so that the prompt length and " - "answer length (99995 tokens) fits within the max token limit (100000 tokens). " - "Reduce the length of the prompt to prevent it from being cut off." - ) - assert caplog.records[0].message == expected_message_log - - -@pytest.mark.unit -def test_supports(mock_claude_tokenizer, mock_claude_request): - layer = AnthropicClaudeInvocationLayer(api_key="some_fake_key") - - assert not layer.supports("claude") - - assert layer.supports("claude-v1") - assert layer.supports("claude-v1.0") - assert layer.supports("claude-v1.2") - assert layer.supports("claude-v1.3") - assert layer.supports("claude-v2.0") - assert layer.supports("claude-instant-v1") - assert layer.supports("claude-instant-v1.0") - assert layer.supports("claude-instant-v1.1") - - -@pytest.mark.integration -@pytest.mark.skipif(os.environ.get("ANTHROPIC_CLAUDE_API_KEY", "") == "", reason="Anthropic Claude API key not found") -def test_invoke_non_streamed(): - api_key = os.environ.get("ANTHROPIC_CLAUDE_API_KEY") - layer = AnthropicClaudeInvocationLayer(api_key=api_key) - - res = layer.invoke(prompt="Why is the sky blue?") - - # Verifies answer has been received - assert len(res) == 1 - - -@pytest.mark.integration -@pytest.mark.skipif(os.environ.get("ANTHROPIC_CLAUDE_API_KEY", "") == "", reason="Anthropic Claude API key not found") -def test_invoke_streamed(): - api_key = os.environ.get("ANTHROPIC_CLAUDE_API_KEY") - layer = AnthropicClaudeInvocationLayer(api_key=api_key) - - res = layer.invoke(prompt="Why is the sky blue?", stream=True) - - # Verifies answer has been received - assert len(res) == 1 diff --git a/test/prompt/invocation_layer/test_chatgpt.py b/test/prompt/invocation_layer/test_chatgpt.py deleted file mode 100644 index c1b816d493..0000000000 --- a/test/prompt/invocation_layer/test_chatgpt.py +++ /dev/null @@ -1,76 +0,0 @@ -import logging -from unittest.mock import patch - -import pytest - -from haystack.nodes.prompt.invocation_layer import ChatGPTInvocationLayer - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.chatgpt.openai_request") -def test_default_api_base(mock_request): - with patch("haystack.nodes.prompt.invocation_layer.open_ai.load_openai_tokenizer"): - invocation_layer = ChatGPTInvocationLayer(api_key="fake_api_key") - assert invocation_layer.api_base == "https://api.openai.com/v1" - assert invocation_layer.url == "https://api.openai.com/v1/chat/completions" - - invocation_layer.invoke(prompt="dummy_prompt") - assert mock_request.call_args.kwargs["url"] == "https://api.openai.com/v1/chat/completions" - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.chatgpt.openai_request") -def test_custom_api_base(mock_request): - with patch("haystack.nodes.prompt.invocation_layer.open_ai.load_openai_tokenizer"): - invocation_layer = ChatGPTInvocationLayer(api_key="fake_api_key", api_base="https://fake_api_base.com") - assert invocation_layer.api_base == "https://fake_api_base.com" - assert invocation_layer.url == "https://fake_api_base.com/chat/completions" - - invocation_layer.invoke(prompt="dummy_prompt") - assert mock_request.call_args.kwargs["url"] == "https://fake_api_base.com/chat/completions" - - -@pytest.mark.unit -def test_supports_correct_model_names(): - for model_name in ["gpt-3.5-turbo", "gpt-4", "gpt-4-32k", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0613"]: - assert ChatGPTInvocationLayer.supports(model_name) - - -@pytest.mark.unit -def test_does_not_support_wrong_model_names(): - for model_name in ["got-3.5-turbo", "wrong_model_name", "gpt-3.5-turbo-instruct"]: - assert not ChatGPTInvocationLayer.supports(model_name) - - -@pytest.mark.unit -def test_chatgpt_token_limit_warning_single_prompt(mock_openai_tokenizer, caplog): - invocation_layer = ChatGPTInvocationLayer( - model_name_or_path="gpt-3.5-turbo", - api_key="fake_api_key", - api_base="https://fake_api_base.com", - max_length=4090, - ) - with caplog.at_level(logging.WARNING): - _ = invocation_layer._ensure_token_limit(prompt="This is a test for a mock openai tokenizer.") - assert "The prompt has been truncated from" in caplog.text - assert "and answer length (4090 tokens) fit within the max token limit (4096 tokens)." in caplog.text - - -@pytest.mark.unit -def test_chatgpt_token_limit_warning_with_messages(mock_openai_tokenizer, caplog): - messages = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "Who won the world series in 2020?"}, - {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, - {"role": "user", "content": "Where was it played?"}, - ] - with patch("haystack.utils.openai_utils.count_openai_tokens_messages") as mock_count_tokens: - mock_count_tokens.return_value = 40 - invocation_layer = ChatGPTInvocationLayer( - model_name_or_path="gpt-3.5-turbo", - api_key="fake_api_key", - api_base="https://fake_api_base.com", - max_length=4060, - ) - with pytest.raises(ValueError): - _ = invocation_layer._ensure_token_limit(prompt=messages) diff --git a/test/prompt/invocation_layer/test_cohere.py b/test/prompt/invocation_layer/test_cohere.py deleted file mode 100644 index 43834df5e5..0000000000 --- a/test/prompt/invocation_layer/test_cohere.py +++ /dev/null @@ -1,256 +0,0 @@ -import unittest -from unittest.mock import Mock - -import pytest - -from haystack.nodes.prompt.invocation_layer.handlers import DefaultTokenStreamingHandler -from haystack.nodes.prompt.invocation_layer import CohereInvocationLayer - - -@pytest.mark.unit -def test_default_constructor(mock_auto_tokenizer): - """ - Test that the default constructor sets the correct values - """ - - layer = CohereInvocationLayer(model_name_or_path="command", api_key="some_fake_key") - - assert layer.api_key == "some_fake_key" - assert layer.max_length == 100 - assert layer.model_input_kwargs == {} - assert layer.prompt_handler.model_max_length == 4096 - - layer = CohereInvocationLayer(model_name_or_path="base", api_key="some_fake_key") - assert layer.api_key == "some_fake_key" - assert layer.max_length == 100 - assert layer.model_input_kwargs == {} - assert layer.prompt_handler.model_max_length == 2048 - - -@pytest.mark.unit -def test_constructor_with_model_kwargs(mock_auto_tokenizer): - """ - Test that model_kwargs are correctly set in the constructor - and that model_kwargs_rejected are correctly filtered out - """ - model_kwargs = {"temperature": 0.7, "end_sequences": ["end"], "stream": True} - model_kwargs_rejected = {"fake_param": 0.7, "another_fake_param": 1} - layer = CohereInvocationLayer( - model_name_or_path="command", api_key="some_fake_key", **model_kwargs, **model_kwargs_rejected - ) - assert layer.model_input_kwargs == model_kwargs - assert len(model_kwargs_rejected) == 2 - - -@pytest.mark.unit -def test_invoke_with_no_kwargs(mock_auto_tokenizer): - """ - Test that invoke raises an error if no prompt is provided - """ - layer = CohereInvocationLayer(model_name_or_path="command", api_key="some_fake_key") - with pytest.raises(ValueError) as e: - layer.invoke() - assert e.match("No prompt provided.") - - -@pytest.mark.unit -def test_invoke_with_stop_words(mock_auto_tokenizer): - """ - Test stop words are correctly passed from PromptNode to wire in CohereInvocationLayer - """ - stop_words = ["but", "not", "bye"] - layer = CohereInvocationLayer(model_name_or_path="command", api_key="fake_key") - with unittest.mock.patch("haystack.nodes.prompt.invocation_layer.CohereInvocationLayer._post") as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = Mock(text='{"generations":[{"text": "Hello"}]}') - - layer.invoke(prompt="Tell me hello", stop_words=stop_words) - - assert mock_post.called - called_args, _ = mock_post.call_args - assert "end_sequences" in called_args[0] - assert called_args[0]["end_sequences"] == stop_words - - -@pytest.mark.unit -def test_streaming_stream_param_from_init(mock_auto_tokenizer): - """ - Test stream parameter is correctly passed from PromptNode to wire in CohereInvocationLayer from init - """ - - layer = CohereInvocationLayer(model_name_or_path="command", api_key="fake_key", stream=True) - - with unittest.mock.patch("haystack.nodes.prompt.invocation_layer.CohereInvocationLayer._post") as mock_post: - # Mock the response - mock_post.return_value = Mock(iter_lines=Mock(return_value=['{"text": "Hello"}', '{"text": " there"}'])) - layer.invoke(prompt="Tell me hello") - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs and called_kwargs["stream"] - - -@pytest.mark.unit -def test_streaming_stream_param_from_init_no_stream(mock_auto_tokenizer): - """ - Test stream parameter is correctly passed from PromptNode to wire in CohereInvocationLayer from init - """ - - layer = CohereInvocationLayer(model_name_or_path="command", api_key="fake_key") - - with unittest.mock.patch("haystack.nodes.prompt.invocation_layer.CohereInvocationLayer._post") as mock_post: - # Mock the response - mock_post.return_value = Mock(text='{"generations":[{"text": "Hello there"}]}') - layer.invoke(prompt="Tell me hello") - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs - assert not bool(called_kwargs["stream"]) - - -@pytest.mark.unit -def test_streaming_stream_param_from_invoke(mock_auto_tokenizer): - """ - Test stream parameter is correctly passed from PromptNode to wire in CohereInvocationLayer from invoke - """ - layer = CohereInvocationLayer(model_name_or_path="command", api_key="fake_key") - - with unittest.mock.patch("haystack.nodes.prompt.invocation_layer.CohereInvocationLayer._post") as mock_post: - # Mock the response - mock_post.return_value = Mock(iter_lines=Mock(return_value=['{"text": "Hello"}', '{"text": " there"}'])) - layer.invoke(prompt="Tell me hello", stream=True) - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs - assert bool(called_kwargs["stream"]) - - -@pytest.mark.unit -def test_streaming_stream_param_from_invoke_no_stream(mock_auto_tokenizer): - """ - Test stream parameter is correctly passed from PromptNode to wire in CohereInvocationLayer from invoke - """ - layer = CohereInvocationLayer(model_name_or_path="command", api_key="fake_key", stream=True) - - with unittest.mock.patch("haystack.nodes.prompt.invocation_layer.CohereInvocationLayer._post") as mock_post: - # Mock the response - mock_post.return_value = Mock(text='{"generations":[{"text": "Hello there"}]}') - layer.invoke(prompt="Tell me hello", stream=False) - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs - assert not bool(called_kwargs["stream"]) - - -@pytest.mark.unit -def test_streaming_stream_handler_param_from_init(mock_auto_tokenizer): - """ - Test stream_handler parameter is correctly from PromptNode passed to wire in CohereInvocationLayer - """ - stream_handler = DefaultTokenStreamingHandler() - layer = CohereInvocationLayer(model_name_or_path="command", api_key="fake_key", stream_handler=stream_handler) - - with unittest.mock.patch("haystack.nodes.prompt.invocation_layer.CohereInvocationLayer._post") as mock_post: - # Mock the response - mock_post.return_value = Mock(iter_lines=Mock(return_value=['{"text": "Hello"}', '{"text": " there"}'])) - responses = layer.invoke(prompt="Tell me hello") - - assert mock_post.called - _, called_kwargs = mock_post.call_args - assert "stream" in called_kwargs - assert bool(called_kwargs["stream"]) - assert responses == ["Hello there"] - - -@pytest.mark.unit -def test_streaming_stream_handler_param_from_invoke(mock_auto_tokenizer): - """ - Test stream_handler parameter is correctly from PromptNode passed to wire in CohereInvocationLayer - """ - stream_handler = DefaultTokenStreamingHandler() - layer = CohereInvocationLayer(model_name_or_path="command", api_key="fake_key") - - with unittest.mock.patch("haystack.nodes.prompt.invocation_layer.CohereInvocationLayer._post") as mock_post: - # Mock the response - mock_post.return_value = Mock(iter_lines=Mock(return_value=['{"text": "Hello"}', '{"text": " there"}'])) - responses = layer.invoke(prompt="Tell me hello", stream_handler=stream_handler) - - assert mock_post.called - _, called_kwargs = mock_post.call_args - assert "stream" in called_kwargs - assert bool(called_kwargs["stream"]) - assert responses == ["Hello there"] - - -@pytest.mark.unit -def test_supports(): - """ - Test that supports returns True correctly for CohereInvocationLayer - """ - # See command and generate models at https://docs.cohere.com/docs/models - # doesn't support fake model - assert not CohereInvocationLayer.supports("fake_model", api_key="fake_key") - - # supports cohere command with api_key - assert CohereInvocationLayer.supports("command", api_key="fake_key") - - # supports cohere command-light with api_key - assert CohereInvocationLayer.supports("command-light", api_key="fake_key") - - # supports cohere base with api_key - assert CohereInvocationLayer.supports("base", api_key="fake_key") - - assert CohereInvocationLayer.supports("base-light", api_key="fake_key") - - # doesn't support other models that have base substring only i.e. google/flan-t5-base - assert not CohereInvocationLayer.supports("google/flan-t5-base") - - -@pytest.mark.unit -def test_ensure_token_limit_fails_if_called_with_list(mock_auto_tokenizer): - layer = CohereInvocationLayer(model_name_or_path="command", api_key="some_fake_key") - with pytest.raises(ValueError): - layer._ensure_token_limit(prompt=[]) - - -@pytest.mark.integration -def test_ensure_token_limit_with_small_max_length(caplog): - layer = CohereInvocationLayer(model_name_or_path="command", api_key="some_fake_key", max_length=10) - res = layer._ensure_token_limit(prompt="Short prompt") - - assert res == "Short prompt" - assert not caplog.records - - res = layer._ensure_token_limit(prompt="This is a very very very very very much longer prompt") - assert res == "This is a very very very very very much longer prompt" - assert not caplog.records - - -@pytest.mark.integration -def test_ensure_token_limit_with_huge_max_length(caplog): - layer = CohereInvocationLayer(model_name_or_path="command", api_key="some_fake_key", max_length=4090) - res = layer._ensure_token_limit(prompt="Short prompt") - - assert res == "Short prompt" - assert not caplog.records - - res = layer._ensure_token_limit(prompt="This is a very very very very very much longer prompt") - assert res == "This is a very very very" - assert len(caplog.records) == 1 - expected_message_log = ( - "The prompt has been truncated from 11 tokens to 6 tokens so that the prompt length and " - "answer length (4090 tokens) fit within the max token limit (4096 tokens). " - "Reduce the length of the prompt to prevent it from being cut off." - ) - assert caplog.records[0].message == expected_message_log diff --git a/test/prompt/invocation_layer/test_hugging_face.py b/test/prompt/invocation_layer/test_hugging_face.py deleted file mode 100644 index 3b56cab785..0000000000 --- a/test/prompt/invocation_layer/test_hugging_face.py +++ /dev/null @@ -1,690 +0,0 @@ -from typing import List -from unittest.mock import MagicMock, patch, Mock -import logging - -import pytest -import torch -from torch import device -from transformers import AutoTokenizer, BloomForCausalLM, StoppingCriteriaList, GenerationConfig - -from haystack.nodes.prompt.invocation_layer import HFLocalInvocationLayer -from haystack.nodes.prompt.invocation_layer.handlers import HFTokenStreamingHandler, DefaultTokenStreamingHandler -from haystack.nodes.prompt.invocation_layer.hugging_face import StopWordsCriteria - - -@pytest.fixture -def mock_pipeline(): - # mock transformers pipeline - # model returning some mocked text for pipeline invocation - with patch("haystack.nodes.prompt.invocation_layer.hugging_face.pipeline") as mocked_pipeline: - pipeline_mock = Mock(**{"model_name_or_path": None, "tokenizer.model_max_length": 100}) - pipeline_mock.side_effect = lambda *args, **kwargs: [{"generated_text": "some mocked text"}] - mocked_pipeline.return_value = pipeline_mock - yield mocked_pipeline - - -@pytest.fixture -def mock_get_task(): - # mock get_task function - with patch("haystack.nodes.prompt.invocation_layer.hugging_face.get_task") as mock_get_task: - mock_get_task.return_value = "text2text-generation" - yield mock_get_task - - -@pytest.mark.unit -def test_constructor_with_invalid_task_name(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with invalid task_name - """ - with pytest.raises(ValueError, match="Task name custom-text2text-generation is not supported"): - HFLocalInvocationLayer("google/flan-t5-base", task_name="custom-text2text-generation") - - -@pytest.mark.unit -def test_constructor_with_model_name_only(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with model_name_or_path only - """ - HFLocalInvocationLayer("google/flan-t5-base") - - mock_pipeline.assert_called_once() - - _, kwargs = mock_pipeline.call_args - - # device is set to cpu by default and device_map is empty - assert kwargs["device"] == device("cpu") - assert not kwargs["device_map"] - - # correct task and model are set - assert kwargs["task"] == "text2text-generation" - assert kwargs["model"] == "google/flan-t5-base" - - # no matter what kwargs we pass or don't pass, there are always 14 predefined kwargs passed to the pipeline - assert len(kwargs) == 14 - - # and these kwargs are passed to the pipeline - assert list(kwargs.keys()) == [ - "task", - "model", - "config", - "tokenizer", - "feature_extractor", - "device_map", - "device", - "torch_dtype", - "model_kwargs", - "pipeline_class", - "use_fast", - "revision", - "use_auth_token", - "trust_remote_code", - ] - - -@pytest.mark.unit -def test_constructor_with_model_name_and_device_map(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with model_name_or_path and device_map - """ - - layer = HFLocalInvocationLayer("google/flan-t5-base", device="cpu", device_map="auto") - - assert layer.pipe == mock_pipeline.return_value - mock_pipeline.assert_called_once() - mock_get_task.assert_called_once() - - _, kwargs = mock_pipeline.call_args - - # device is NOT set; device_map is auto because device_map takes precedence over device - assert not kwargs["device"] - assert kwargs["device_map"] and kwargs["device_map"] == "auto" - - # correct task and model are set as well - assert kwargs["task"] == "text2text-generation" - assert kwargs["model"] == "google/flan-t5-base" - - -@pytest.mark.unit -def test_constructor_with_torch_dtype(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with torch_dtype parameter using the actual torch object - """ - - layer = HFLocalInvocationLayer("google/flan-t5-base", torch_dtype=torch.float16) - - assert layer.pipe == mock_pipeline.return_value - mock_pipeline.assert_called_once() - mock_get_task.assert_called_once() - - _, kwargs = mock_pipeline.call_args - assert kwargs["torch_dtype"] == torch.float16 - - -@pytest.mark.unit -def test_constructor_with_torch_dtype_as_str(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with torch_dtype parameter using the string definition - """ - - layer = HFLocalInvocationLayer("google/flan-t5-base", torch_dtype="torch.float16") - - assert layer.pipe == mock_pipeline.return_value - mock_pipeline.assert_called_once() - mock_get_task.assert_called_once() - - _, kwargs = mock_pipeline.call_args - assert kwargs["torch_dtype"] == torch.float16 - - -@pytest.mark.unit -def test_constructor_with_torch_dtype_auto(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with torch_dtype parameter using the auto string definition - """ - - layer = HFLocalInvocationLayer("google/flan-t5-base", torch_dtype="auto") - - assert layer.pipe == mock_pipeline.return_value - mock_pipeline.assert_called_once() - mock_get_task.assert_called_once() - - _, kwargs = mock_pipeline.call_args - assert kwargs["torch_dtype"] == "auto" - - -@pytest.mark.unit -def test_constructor_with_invalid_torch_dtype(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with invalid torch_dtype parameter - """ - - # we need to provide torch_dtype as a string but with torch. prefix - # this should raise an error - with pytest.raises(ValueError, match="torch_dtype should be a torch.dtype, a string with 'torch.' prefix"): - HFLocalInvocationLayer("google/flan-t5-base", torch_dtype="float16") - - -@pytest.mark.unit -def test_constructor_with_invalid_torch_dtype_object(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with invalid parameter - """ - - # we need to provide torch_dtype as a string but with torch. prefix - # this should raise an error - with pytest.raises(ValueError, match="Invalid torch_dtype value {'invalid': 'object'}"): - HFLocalInvocationLayer("google/flan-t5-base", torch_dtype={"invalid": "object"}) - - -@pytest.mark.integration -def test_ensure_token_limit_positive(): - """ - Test that ensure_token_limit works as expected, short prompt text is not changed - """ - prompt_text = "this is a short prompt" - layer = HFLocalInvocationLayer("google/flan-t5-base", max_length=10, model_max_length=20) - - processed_prompt_text = layer._ensure_token_limit(prompt_text) - assert prompt_text == processed_prompt_text - - -@pytest.mark.integration -def test_ensure_token_limit_negative(caplog): - """ - Test that ensure_token_limit chops the prompt text if it's longer than the max length allowed by the model - """ - prompt_text = "this is a prompt test that is longer than the max length allowed by the model" - layer = HFLocalInvocationLayer("google/flan-t5-base", max_length=10, model_max_length=20) - - processed_prompt_text = layer._ensure_token_limit(prompt_text) - assert prompt_text != processed_prompt_text - assert len(processed_prompt_text.split()) <= len(prompt_text.split()) - expected_message = ( - "The prompt has been truncated from 17 tokens to 10 tokens so that the prompt length and " - "answer length (10 tokens) fit within the max token limit (20 tokens). Shorten the prompt " - "to prevent it from being cut off" - ) - assert caplog.records[0].message == expected_message - - -@pytest.mark.unit -def test_constructor_with_custom_pretrained_model(mock_pipeline, mock_get_task): - """ - Test that the constructor sets the pipeline with the pretrained model (if provided) - """ - model = Mock() - tokenizer = Mock() - - HFLocalInvocationLayer( - model_name_or_path="irrelevant_when_model_is_provided", - model=model, - tokenizer=tokenizer, - task_name="text2text-generation", - ) - - mock_pipeline.assert_called_once() - # mock_get_task is not called as we provided task_name parameter - mock_get_task.assert_not_called() - - _, kwargs = mock_pipeline.call_args - - # correct tokenizer and model are set as well - assert kwargs["tokenizer"] == tokenizer - assert kwargs["model"] == model - - -@pytest.mark.unit -def test_constructor_with_invalid_kwargs(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with invalid kwargs - """ - - HFLocalInvocationLayer("google/flan-t5-base", some_invalid_kwarg="invalid") - - mock_pipeline.assert_called_once() - mock_get_task.assert_called_once() - - _, kwargs = mock_pipeline.call_args - - # invalid kwargs are ignored and not passed to the pipeline - assert "some_invalid_kwarg" not in kwargs - - # still our 14 kwargs passed to the pipeline - assert len(kwargs) == 14 - - -@pytest.mark.unit -def test_constructor_with_various_kwargs(mock_pipeline, mock_get_task): - """ - Test HFLocalInvocationLayer init with various kwargs, make sure all of them are passed to the pipeline - except for the invalid ones - """ - - HFLocalInvocationLayer( - "google/flan-t5-base", - task_name="text2text-generation", - tokenizer=Mock(), - config=Mock(), - revision="1.1", - device="cpu", - device_map="auto", - first_invalid_kwarg="invalid", - second_invalid_kwarg="invalid", - ) - - mock_pipeline.assert_called_once() - # mock_get_task is not called as we provided task_name parameter - mock_get_task.assert_not_called() - - _, kwargs = mock_pipeline.call_args - - # invalid kwargs are ignored and not passed to the pipeline - assert "first_invalid_kwarg" not in kwargs - assert "second_invalid_kwarg" not in kwargs - - # correct task and model are set as well - assert kwargs["task"] == "text2text-generation" - assert not kwargs["device"] - assert kwargs["device_map"] and kwargs["device_map"] == "auto" - assert kwargs["revision"] == "1.1" - - # still on 14 kwargs passed to the pipeline - assert len(kwargs) == 14 - - -@pytest.mark.integration -def test_text_generation_model(): - # test simple prompting with text generation model - # by default, we force the model not return prompt text - # Thus text-generation models can be used with PromptNode - # just like text2text-generation models - layer = HFLocalInvocationLayer("bigscience/bigscience-small-testing") - r = layer.invoke(prompt="Hello big science!") - assert len(r[0]) > 0 - - # test prompting with parameter to return prompt text as well - # users can use this param to get the prompt text and the generated text - r = layer.invoke(prompt="Hello big science!", return_full_text=True) - assert len(r[0]) > 0 and r[0].startswith("Hello big science!") - - -@pytest.mark.integration -def test_text_generation_model_via_custom_pretrained_model(): - tokenizer = AutoTokenizer.from_pretrained("bigscience/bigscience-small-testing") - model = BloomForCausalLM.from_pretrained("bigscience/bigscience-small-testing") - layer = HFLocalInvocationLayer( - "irrelevant_when_model_is_provided", model=model, tokenizer=tokenizer, task_name="text-generation" - ) - r = layer.invoke(prompt="Hello big science") - assert len(r[0]) > 0 - - # test prompting with parameter to return prompt text as well - # users can use this param to get the prompt text and the generated text - r = layer.invoke(prompt="Hello big science", return_full_text=True) - assert len(r[0]) > 0 and r[0].startswith("Hello big science") - - -@pytest.mark.unit -def test_streaming_stream_param_in_constructor(mock_pipeline, mock_get_task): - """ - Test stream parameter is correctly passed to pipeline invocation via HF streamer parameter - """ - layer = HFLocalInvocationLayer(stream=True) - - layer.invoke(prompt="Tell me hello") - - _, kwargs = layer.pipe.call_args - assert "streamer" in kwargs and isinstance(kwargs["streamer"], HFTokenStreamingHandler) - - -@pytest.mark.unit -def test_streaming_stream_handler_param_in_constructor(mock_pipeline, mock_get_task): - """ - Test stream parameter is correctly passed to pipeline invocation - """ - dtsh = DefaultTokenStreamingHandler() - layer = HFLocalInvocationLayer(stream_handler=dtsh) - - layer.invoke(prompt="Tell me hello") - - _, kwargs = layer.pipe.call_args - assert "streamer" in kwargs - hf_streamer = kwargs["streamer"] - - # we wrap our TokenStreamingHandler with HFTokenStreamingHandler - assert isinstance(hf_streamer, HFTokenStreamingHandler) - - # but under the hood, the wrapped handler is DefaultTokenStreamingHandler we passed - assert isinstance(hf_streamer.token_handler, DefaultTokenStreamingHandler) - assert hf_streamer.token_handler == dtsh - - -@pytest.mark.unit -def test_supports(tmp_path, mock_get_task): - """ - Test that supports returns True correctly for HFLocalInvocationLayer - """ - - assert HFLocalInvocationLayer.supports("google/flan-t5-base") - assert HFLocalInvocationLayer.supports("mosaicml/mpt-7b") - assert HFLocalInvocationLayer.supports("CarperAI/stable-vicuna-13b-delta") - mock_get_task.side_effect = RuntimeError - assert not HFLocalInvocationLayer.supports("google/flan-t5-base") - assert mock_get_task.call_count == 4 - - # some HF local model directory, let's use the one from test/prompt/invocation_layer - assert HFLocalInvocationLayer.supports(str(tmp_path)) - - # we can also specify the task name to override the default - # short-circuit the get_task call - assert HFLocalInvocationLayer.supports( - "vblagoje/bert-english-uncased-finetuned-pos", task_name="text2text-generation" - ) - - -@pytest.mark.unit -def test_supports_not(mock_get_task): - """ - Test that supports returns False correctly for HFLocalInvocationLayer - """ - assert not HFLocalInvocationLayer.supports("google/flan-t5-base", api_key="some_key") - - # also not some non text2text-generation or non text-generation model - # i.e image classification model - mock_get_task = Mock(return_value="image-classification") - with patch("haystack.nodes.prompt.invocation_layer.hugging_face.get_task", mock_get_task): - assert not HFLocalInvocationLayer.supports("nateraw/vit-age-classifier") - assert mock_get_task.call_count == 1 - - # or some POS tagging model - mock_get_task = Mock(return_value="pos-tagging") - with patch("haystack.nodes.prompt.invocation_layer.hugging_face.get_task", mock_get_task): - assert not HFLocalInvocationLayer.supports("vblagoje/bert-english-uncased-finetuned-pos") - assert mock_get_task.call_count == 1 - - -@pytest.mark.unit -def test_stop_words_criteria_set(mock_pipeline, mock_get_task): - """ - Test that stop words criteria is correctly set in pipeline invocation - """ - layer = HFLocalInvocationLayer( - model_name_or_path="hf-internal-testing/tiny-random-t5", task_name="text2text-generation" - ) - - layer.invoke(prompt="Tell me hello", stop_words=["hello", "world"]) - - _, kwargs = layer.pipe.call_args - assert "stopping_criteria" in kwargs - assert isinstance(kwargs["stopping_criteria"], StoppingCriteriaList) - assert len(kwargs["stopping_criteria"]) == 1 - assert isinstance(kwargs["stopping_criteria"][0], StopWordsCriteria) - - -@pytest.mark.integration -@pytest.mark.parametrize("stop_words", [["good"], ["hello", "good"]]) -def test_stop_words_single_token(stop_words: List[str]): - """ - Test that stop words criteria is used and that it works with single token stop words - """ - - # simple test with words not broken down into multiple tokens - default_model = "google/flan-t5-base" - tokenizer = AutoTokenizer.from_pretrained(default_model) - for stop_word in stop_words: - # confirm we are dealing with single-token words - tokens = tokenizer.tokenize(stop_word) - assert len(tokens) == 1 - - layer = HFLocalInvocationLayer(model_name_or_path=default_model) - result = layer.invoke(prompt="Generate a sentence `I wish you a good health`", stop_words=stop_words) - assert len(result) > 0 - assert result[0].startswith("I wish you a") - assert "good" not in result[0] - assert "health" not in result[0] - - -@pytest.mark.integration -@pytest.mark.parametrize( - "stop_words", [["unambiguously"], ["unambiguously", "unrelated"], ["unambiguously", "hearted"]] -) -def test_stop_words_multiple_token(stop_words: List[str]): - """ - Test that stop words criteria is used and that it works for multi-token words - """ - default_model = "google/flan-t5-base" - tokenizer = AutoTokenizer.from_pretrained(default_model) - for stop_word in stop_words: - # confirm we are dealing with multi-token words - tokens = tokenizer.tokenize(stop_word) - assert len(tokens) > 1 - - layer = HFLocalInvocationLayer(model_name_or_path=default_model) - result = layer.invoke(prompt="Generate a sentence `I wish you unambiguously good health`", stop_words=stop_words) - # yet the stop word is correctly stopped on and removed - assert len(result) > 0 - assert result[0].startswith("I wish you") - assert "unambiguously" not in result[0] - assert "good" not in result[0] - assert "health" not in result[0] - - -@pytest.mark.unit -def test_stop_words_criteria(): - """ - Test that StopWordsCriteria will check stop word tokens in a continuous and sequential order - """ - # input ids for "unambiguously" - stop_words_id = torch.tensor([[73, 24621, 11937]]) - - # input ids for "This is ambiguously, but is unrelated." - input_ids1 = torch.tensor([[100, 19, 24621, 11937, 6, 68, 19, 73, 3897, 5]]) - # input ids for "This is unambiguously" - input_ids2 = torch.tensor([[100, 19, 73, 24621, 11937]]) - - # We used to implement stop words algorithm using the torch.isin function like this: - # `all(torch.isin(stop_words_id, input_ids1)[0])` - # However, this algorithm is not correct as it will return True for presence of "unambiguously" in input_ids1 - # and True for presence of "unambiguously" in input_ids2. This is because the algorithm will check - # if the stop word tokens are present in the input_ids, but it does not check if the stop word tokens are - # present in a continuous/sequential order. - - # In "This is ambiguously, but is unrelated." sentence the "un" token comes from "unrelated" and the - # "ambiguously" token comes from "ambiguously". The algorithm will return True for presence of - # "unambiguously" in input_ids1 which is not correct. - - stop_words_criteria = StopWordsCriteria(tokenizer=Mock(), stop_words=["mock data"]) - # because we are mocking the tokenizer, we need to set the stop words manually - stop_words_criteria.stop_words = stop_words_id - - # this is the correct algorithm to check if the stop word tokens are present in a continuous and sequential order - # For the input_ids1, the stop word tokens are present BUT not in a continuous order - present_and_continuous = stop_words_criteria(input_ids1, scores=None) - assert not present_and_continuous - - # For the input_ids2, the stop word tokens are both present and in a continuous order - present_and_continuous = stop_words_criteria(input_ids2, scores=None) - assert present_and_continuous - - -@pytest.mark.integration -@pytest.mark.parametrize("stop_words", [["Berlin"], ["Berlin", "Brandenburg"], ["Berlin", "Brandenburg", "Germany"]]) -def test_stop_words_not_being_found(stop_words: List[str]): - """ - Test that stop works on tokens that are not found in the generated text, stop words are not found - """ - layer = HFLocalInvocationLayer() - result = layer.invoke(prompt="Generate a sentence `I wish you a good health`", stop_words=stop_words) - assert len(result) > 0 - for word in "I wish you a good health".split(): - assert word in result[0] - - -@pytest.mark.unit -def test_generation_kwargs_from_constructor(mock_auto_tokenizer, mock_pipeline, mock_get_task): - """ - Test that generation_kwargs are correctly passed to pipeline invocation from constructor - """ - query = "What does 42 mean?" - # test that generation_kwargs are passed to the underlying HF model - layer = HFLocalInvocationLayer(generation_kwargs={"do_sample": True}) - layer.invoke(prompt=query) - assert any( - (call.kwargs == {"do_sample": True, "max_length": 100}) and (query in call.args) - for call in mock_pipeline.mock_calls - ) - - # test that generation_kwargs in the form of GenerationConfig are passed to the underlying HF model - layer = HFLocalInvocationLayer(generation_kwargs=GenerationConfig(do_sample=True, top_p=0.9)) - layer.invoke(prompt=query) - assert any( - (call.kwargs == {"do_sample": True, "max_length": 100, "top_p": 0.9}) and (query in call.args) - for call in mock_pipeline.mock_calls - ) - - -@pytest.mark.unit -def test_generation_kwargs_from_invoke(mock_auto_tokenizer, mock_pipeline, mock_get_task): - """ - Test that generation_kwargs passed to invoke are passed to the underlying HF model - """ - query = "What does 42 mean?" - # test that generation_kwargs are passed to the underlying HF model - layer = HFLocalInvocationLayer() - layer.invoke(prompt=query, generation_kwargs={"do_sample": True}) - assert any( - (call.kwargs == {"do_sample": True, "max_length": 100}) and (query in call.args) - for call in mock_pipeline.mock_calls - ) - - layer = HFLocalInvocationLayer() - layer.invoke(prompt=query, generation_kwargs=GenerationConfig(do_sample=True, top_p=0.9)) - assert any( - (call.kwargs == {"do_sample": True, "max_length": 100, "top_p": 0.9}) and (query in call.args) - for call in mock_pipeline.mock_calls - ) - - -@pytest.mark.unit -def test_max_length_from_invoke(mock_auto_tokenizer, mock_pipeline, mock_get_task): - """ - Test that max_length passed to invoke are passed to the underlying HF model - """ - query = "What does 42 mean?" - # test that generation_kwargs are passed to the underlying HF model - layer = HFLocalInvocationLayer() - layer.invoke(prompt=query, generation_kwargs={"max_length": 200}) - # find the call to pipeline invocation, and check that the kwargs are correct - assert any((call.kwargs == {"max_length": 200}) and (query in call.args) for call in mock_pipeline.mock_calls) - - layer = HFLocalInvocationLayer() - layer.invoke(prompt=query, generation_kwargs=GenerationConfig(max_length=235)) - assert any((call.kwargs == {"max_length": 235}) and (query in call.args) for call in mock_pipeline.mock_calls) - - -@pytest.mark.unit -def test_ensure_token_limit_positive_mock(mock_pipeline, mock_get_task, mock_auto_tokenizer): - # prompt of length 5 + max_length of 3 = 8, which is less than model_max_length of 10, so no resize - mock_tokens = ["I", "am", "a", "tokenized", "prompt"] - mock_prompt = "I am a tokenized prompt" - - mock_auto_tokenizer.tokenize = Mock(return_value=mock_tokens) - mock_auto_tokenizer.convert_tokens_to_string = Mock(return_value=mock_prompt) - mock_pipeline.return_value.tokenizer = mock_auto_tokenizer - - layer = HFLocalInvocationLayer("google/flan-t5-base", max_length=3, model_max_length=10) - result = layer._ensure_token_limit(mock_prompt) - - assert result == mock_prompt - - -@pytest.mark.unit -def test_ensure_token_limit_negative_mock(mock_pipeline, mock_get_task, mock_auto_tokenizer): - # prompt of length 8 + max_length of 3 = 11, which is more than model_max_length of 10, so we resize to 7 - mock_tokens = ["I", "am", "a", "tokenized", "prompt", "of", "length", "eight"] - correct_result = "I am a tokenized prompt of length" - - mock_auto_tokenizer.tokenize = Mock(return_value=mock_tokens) - mock_auto_tokenizer.convert_tokens_to_string = Mock(return_value=correct_result) - mock_pipeline.return_value.tokenizer = mock_auto_tokenizer - - layer = HFLocalInvocationLayer("google/flan-t5-base", max_length=3, model_max_length=10) - result = layer._ensure_token_limit("I am a tokenized prompt of length eight") - - assert result == correct_result - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.hugging_face.AutoConfig.from_pretrained") -@patch("haystack.nodes.prompt.invocation_layer.hugging_face.AutoTokenizer.from_pretrained") -def test_tokenizer_loading_unsupported_model(mock_tokenizer, mock_config, mock_pipeline, mock_get_task, caplog): - """ - Test loading of tokenizers for models that are not natively supported by the transformers library. - """ - mock_config.return_value = Mock(tokenizer_class=None) - - with caplog.at_level(logging.WARNING): - HFLocalInvocationLayer("unsupported_model", trust_remote_code=True) - assert ( - "The transformers library doesn't know which tokenizer class should be " - "loaded for the model unsupported_model. Therefore, the tokenizer will be loaded in Haystack's " - "invocation layer and then passed to the underlying pipeline. Alternatively, you could " - "pass `tokenizer_class` to `model_kwargs` to workaround this, if your tokenizer is supported " - "by the transformers library." - ) in caplog.text - assert mock_tokenizer.called - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.hugging_face.AutoTokenizer.from_pretrained") -def test_tokenizer_loading_unsupported_model_with_initialized_model( - mock_tokenizer, mock_pipeline, mock_get_task, caplog -): - """ - Test loading of tokenizers for models that are not natively supported by the transformers library. In this case, - the model is already initialized and the model config is loaded from the model. - """ - model = Mock() - model.config = Mock(tokenizer_class=None, _name_or_path="unsupported_model") - - with caplog.at_level(logging.WARNING): - HFLocalInvocationLayer(model_name_or_path="unsupported", model=model, trust_remote_code=True) - assert ( - "The transformers library doesn't know which tokenizer class should be " - "loaded for the model unsupported_model. Therefore, the tokenizer will be loaded in Haystack's " - "invocation layer and then passed to the underlying pipeline. Alternatively, you could " - "pass `tokenizer_class` to `model_kwargs` to workaround this, if your tokenizer is supported " - "by the transformers library." - ) in caplog.text - assert mock_tokenizer.called - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.hugging_face.AutoConfig.from_pretrained") -@patch("haystack.nodes.prompt.invocation_layer.hugging_face.AutoTokenizer.from_pretrained") -def test_tokenizer_loading_unsupported_model_with_tokenizer_class_in_config( - mock_tokenizer, mock_config, mock_pipeline, mock_get_task, caplog -): - """ - Test that tokenizer is not loaded if tokenizer_class is set in model config. - """ - mock_config.return_value = Mock(tokenizer_class="Some-Supported-Tokenizer") - - with caplog.at_level(logging.WARNING): - HFLocalInvocationLayer(model_name_or_path="unsupported_model", trust_remote_code=True) - assert not mock_tokenizer.called - assert not caplog.text - - -@pytest.mark.unit -def test_skip_prompt_is_set_in_hf_text_streamer(mock_pipeline, mock_get_task): - """ - Test that skip_prompt is set in HFTextStreamingHandler. Otherwise, we will output prompt text. - """ - layer = HFLocalInvocationLayer(stream=True) - - layer.invoke(prompt="Tell me hello") - - _, kwargs = layer.pipe.call_args - assert "streamer" in kwargs and isinstance(kwargs["streamer"], HFTokenStreamingHandler) - assert kwargs["streamer"].skip_prompt diff --git a/test/prompt/invocation_layer/test_hugging_face_inference.py b/test/prompt/invocation_layer/test_hugging_face_inference.py deleted file mode 100644 index fb98796748..0000000000 --- a/test/prompt/invocation_layer/test_hugging_face_inference.py +++ /dev/null @@ -1,375 +0,0 @@ -import logging -import unittest -from unittest.mock import patch, MagicMock - -import pytest - -from haystack.nodes.prompt.invocation_layer.handlers import DefaultTokenStreamingHandler, TokenStreamingHandler -from haystack.nodes.prompt.invocation_layer import HFInferenceEndpointInvocationLayer - - -@pytest.fixture -def mock_get_task(): - # mock get_task function - with patch("haystack.nodes.prompt.invocation_layer.hugging_face_inference.get_task") as mock_get_task: - mock_get_task.return_value = "text2text-generation" - yield mock_get_task - - -@pytest.fixture -def mock_get_task_invalid(): - with patch("haystack.nodes.prompt.invocation_layer.hugging_face_inference.get_task") as mock_get_task: - mock_get_task.return_value = "some-nonexistent-type" - yield mock_get_task - - -@pytest.mark.unit -def test_default_constructor(mock_auto_tokenizer): - """ - Test that the default constructor sets the correct values - """ - - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="some_fake_key") - - assert layer.api_key == "some_fake_key" - assert layer.max_length == 100 - assert layer.model_input_kwargs == {} - - -@pytest.mark.unit -def test_constructor_with_model_kwargs(mock_auto_tokenizer): - """ - Test that model_kwargs are correctly set in the constructor - and that model_kwargs_rejected are correctly filtered out - """ - model_kwargs = {"temperature": 0.7, "do_sample": True, "stream": True} - model_kwargs_rejected = {"fake_param": 0.7, "another_fake_param": 1} - - layer = HFInferenceEndpointInvocationLayer( - model_name_or_path="google/flan-t5-xxl", api_key="some_fake_key", **model_kwargs, **model_kwargs_rejected - ) - assert "temperature" in layer.model_input_kwargs - assert "do_sample" in layer.model_input_kwargs - assert "stream" in layer.model_input_kwargs - assert "fake_param" not in layer.model_input_kwargs - assert "another_fake_param" not in layer.model_input_kwargs - - -@pytest.mark.unit -def test_set_model_max_length(mock_auto_tokenizer): - """ - Test that model max length is set correctly - """ - layer = HFInferenceEndpointInvocationLayer( - model_name_or_path="google/flan-t5-xxl", api_key="some_fake_key", model_max_length=2048 - ) - assert layer.prompt_handler.model_max_length == 2048 - - -@pytest.mark.unit -def test_url(mock_auto_tokenizer): - """ - Test that the url is correctly set in the constructor - """ - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="some_fake_key") - assert layer.url == "https://api-inference.huggingface.co/models/google/flan-t5-xxl" - - layer = HFInferenceEndpointInvocationLayer( - model_name_or_path="https://23445.us-east-1.aws.endpoints.huggingface.cloud", api_key="some_fake_key" - ) - - assert layer.url == "https://23445.us-east-1.aws.endpoints.huggingface.cloud" - - -@pytest.mark.unit -def test_invoke_with_no_kwargs(mock_auto_tokenizer): - """ - Test that invoke raises an error if no prompt is provided - """ - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="some_fake_key") - with pytest.raises(ValueError) as e: - layer.invoke() - assert e.match("No prompt provided.") - - -@pytest.mark.unit -def test_invoke_with_stop_words(mock_auto_tokenizer): - """ - Test stop words are correctly passed to HTTP POST request - """ - stop_words = ["but", "not", "bye"] - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="fake_key") - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - - layer.invoke(prompt="Tell me hello", stop_words=stop_words) - - assert mock_post.called - - # Check if stop_words are passed to _post as stop parameter - _, called_kwargs = mock_post.call_args - assert "stop" in called_kwargs["data"]["parameters"] - assert called_kwargs["data"]["parameters"]["stop"] == stop_words - - -@pytest.mark.unit -@pytest.mark.parametrize("stream", [True, False]) -def test_streaming_stream_param_in_constructor(mock_auto_tokenizer, stream): - """ - Test stream parameter is correctly passed to HTTP POST request via constructor - """ - layer = HFInferenceEndpointInvocationLayer( - model_name_or_path="google/flan-t5-xxl", api_key="fake_key", stream=stream - ) - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - layer.invoke(prompt="Tell me hello") - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs - - assert called_kwargs["stream"] == stream - - -@pytest.mark.unit -@pytest.mark.parametrize("stream", [True, False]) -def test_streaming_stream_param_in_method(mock_auto_tokenizer, stream): - """ - Test stream parameter is correctly passed to HTTP POST request via method - """ - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="fake_key") - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - layer.invoke(prompt="Tell me hello", stream=stream) - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs - - # Assert that the 'stream' parameter passed to _post is the same as the one used in layer.invoke() - assert called_kwargs["stream"] == stream - - -@pytest.mark.unit -def test_streaming_stream_handler_param_in_constructor(mock_auto_tokenizer): - """ - Test stream_handler parameter is correctly passed to HTTP POST request via constructor - """ - stream_handler = DefaultTokenStreamingHandler() - layer = HFInferenceEndpointInvocationLayer( - model_name_or_path="google/flan-t5-xxl", api_key="fake_key", stream_handler=stream_handler - ) - - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post, unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._process_streaming_response" - ) as mock_post_stream: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - layer.invoke(prompt="Tell me hello") - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs - - assert called_kwargs["stream"] - - # stream_handler is passed as an instance of TokenStreamingHandler - called_args, _ = mock_post_stream.call_args - assert isinstance(called_args[1], TokenStreamingHandler) - - -@pytest.mark.unit -def test_streaming_no_stream_handler_param_in_constructor(mock_auto_tokenizer): - """ - Test stream_handler parameter is correctly passed to HTTP POST request via constructor - """ - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="fake_key") - - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - layer.invoke(prompt="Tell me hello") - - assert mock_post.called - _, called_kwargs = mock_post.call_args - - # stream is always passed to _post - assert "stream" in called_kwargs - - # but it is False if stream_handler is None - assert not called_kwargs["stream"] - - -@pytest.mark.unit -def test_streaming_stream_handler_param_in_method(mock_auto_tokenizer): - """ - Test stream_handler parameter is correctly passed to HTTP POST request via method - """ - stream_handler = DefaultTokenStreamingHandler() - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="fake_key") - - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post, unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._process_streaming_response" - ) as mock_post_stream: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - - layer.invoke(prompt="Tell me hello", stream_handler=stream_handler) - - assert mock_post.called - called_args, called_kwargs = mock_post.call_args - - # stream is correctly passed to _post - assert "stream" in called_kwargs - assert called_kwargs["stream"] - - called_args, called_kwargs = mock_post_stream.call_args - assert isinstance(called_args[1], TokenStreamingHandler) - - -@pytest.mark.unit -def test_streaming_no_stream_handler_param_in_method(mock_auto_tokenizer): - """ - Test stream_handler parameter is correctly passed to HTTP POST request via method - """ - layer = HFInferenceEndpointInvocationLayer(model_name_or_path="google/flan-t5-xxl", api_key="fake_key") - - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - - layer.invoke(prompt="Tell me hello", stream_handler=None) - - assert mock_post.called - - _, called_kwargs = mock_post.call_args - - # stream is always correctly passed to _post - assert "stream" in called_kwargs - assert not called_kwargs["stream"] - - -@pytest.mark.integration -@pytest.mark.parametrize( - "model_name_or_path", ["google/flan-t5-xxl", "OpenAssistant/oasst-sft-1-pythia-12b", "bigscience/bloomz"] -) -def test_ensure_token_limit_no_resize(model_name_or_path): - # In this test case we assume that no prompt resizing is needed for all models - handler = HFInferenceEndpointInvocationLayer("fake_api_key", model_name_or_path, max_length=100) - - # Define prompt and expected results - prompt = "This is a test prompt." - - resized_prompt = handler._ensure_token_limit(prompt) - - # Verify the results - assert resized_prompt == prompt - - -@pytest.mark.integration -@pytest.mark.parametrize( - "model_name_or_path", ["google/flan-t5-xxl", "OpenAssistant/oasst-sft-1-pythia-12b", "bigscience/bloomz"] -) -def test_ensure_token_limit_resize(caplog, model_name_or_path): - # In this test case we assume prompt resizing is needed for all models - handler = HFInferenceEndpointInvocationLayer("fake_api_key", model_name_or_path, max_length=5, model_max_length=10) - - # Define prompt and expected results - prompt = "This is a test prompt that will be resized because model_max_length is 10 and max_length is 5." - with caplog.at_level(logging.WARN): - resized_prompt = handler._ensure_token_limit(prompt) - assert "The prompt has been truncated" in caplog.text - - # Verify the results - assert resized_prompt != prompt - assert ( - "This is a test" in resized_prompt - and "because model_max_length is 10 and max_length is 5" not in resized_prompt - ) - - -@pytest.mark.unit -def test_oasst_prompt_preprocessing(mock_auto_tokenizer): - model_name = "OpenAssistant/oasst-sft-1-pythia-12b" - - layer = HFInferenceEndpointInvocationLayer("fake_api_key", model_name) - with unittest.mock.patch( - "haystack.nodes.prompt.invocation_layer.HFInferenceEndpointInvocationLayer._post" - ) as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - result = layer.invoke(prompt="Tell me hello") - - assert result == ["Hello"] - assert mock_post.called - - _, called_kwargs = mock_post.call_args - # OpenAssistant/oasst-sft-1-pythia-12b prompts are preprocessed and wrapped in tokens below - assert called_kwargs["data"]["inputs"] == "<|prompter|>Tell me hello<|endoftext|><|assistant|>" - - -@pytest.mark.unit -def test_invalid_key(): - with pytest.raises(ValueError, match="must be a valid Hugging Face token"): - HFInferenceEndpointInvocationLayer("", "irrelevant_model_name") - - -@pytest.mark.unit -def test_invalid_model(): - with pytest.raises(ValueError, match="cannot be None or empty string"): - HFInferenceEndpointInvocationLayer("fake_api", "") - - -@pytest.mark.unit -def test_supports(mock_get_task): - """ - Test that supports returns True correctly for HFInferenceEndpointInvocationLayer - """ - - # supports google/flan-t5-xxl with api_key - assert HFInferenceEndpointInvocationLayer.supports("google/flan-t5-xxl", api_key="fake_key") - - # supports HF Inference Endpoint with api_key - assert HFInferenceEndpointInvocationLayer.supports( - "https://.us-east-1.aws.endpoints.huggingface.cloud", api_key="fake_key" - ) - - -@pytest.mark.unit -def test_supports_not(mock_get_task_invalid): - assert not HFInferenceEndpointInvocationLayer.supports("fake_model", api_key="fake_key") - - # doesn't support google/flan-t5-xxl without api_key - assert not HFInferenceEndpointInvocationLayer.supports("google/flan-t5-xxl") - - # doesn't support HF Inference Endpoint without proper api_key - assert not HFInferenceEndpointInvocationLayer.supports("google/flan-t5-xxl", api_key="") - assert not HFInferenceEndpointInvocationLayer.supports("google/flan-t5-xxl", api_key=None) - - # doesn't support model if hf server timeout - mock_get_task.side_effect = RuntimeError - assert not HFInferenceEndpointInvocationLayer.supports("google/flan-t5-xxl", api_key="fake_key") diff --git a/test/prompt/invocation_layer/test_invocation_layers.py b/test/prompt/invocation_layer/test_invocation_layers.py deleted file mode 100644 index e2a36998fd..0000000000 --- a/test/prompt/invocation_layer/test_invocation_layers.py +++ /dev/null @@ -1,19 +0,0 @@ -import pytest - -from haystack.nodes.prompt.prompt_model import PromptModelInvocationLayer -from haystack.nodes.prompt.invocation_layer import HFLocalInvocationLayer, HFInferenceEndpointInvocationLayer - - -@pytest.mark.unit -def test_invocation_layer_order(): - """ - Checks that the huggingface invocation layer is positioned further down the list of providers - as they can time out or be slow to respond. - """ - invocation_layers = PromptModelInvocationLayer.invocation_layer_providers - assert HFLocalInvocationLayer in invocation_layers - assert HFInferenceEndpointInvocationLayer in invocation_layers - index_hf = invocation_layers.index(HFLocalInvocationLayer) + 1 - index_hf_inference = invocation_layers.index(HFInferenceEndpointInvocationLayer) + 1 - assert index_hf >= 7 - assert index_hf_inference >= 7 diff --git a/test/prompt/invocation_layer/test_openai.py b/test/prompt/invocation_layer/test_openai.py deleted file mode 100644 index 5ae3458788..0000000000 --- a/test/prompt/invocation_layer/test_openai.py +++ /dev/null @@ -1,138 +0,0 @@ -from unittest.mock import patch - -import logging -import pytest - -from haystack.nodes.prompt.invocation_layer import OpenAIInvocationLayer - - -@pytest.fixture -def load_openai_tokenizer(): - with patch("haystack.nodes.prompt.invocation_layer.open_ai.load_openai_tokenizer") as mock_load_openai_tokenizer: - yield mock_load_openai_tokenizer - - -@pytest.fixture() -def mock_open_ai_request(): - with patch("haystack.nodes.prompt.invocation_layer.open_ai.openai_request") as mock_openai_request: - yield mock_openai_request - - -@pytest.mark.unit -def test_default_api_base(mock_open_ai_request, load_openai_tokenizer): - invocation_layer = OpenAIInvocationLayer(api_key="fake_api_key") - assert invocation_layer.api_base == "https://api.openai.com/v1" - assert invocation_layer.url == "https://api.openai.com/v1/completions" - - invocation_layer.invoke(prompt="dummy_prompt") - assert mock_open_ai_request.call_args.kwargs["url"] == "https://api.openai.com/v1/completions" - - -@pytest.mark.unit -def test_custom_api_base(mock_open_ai_request, load_openai_tokenizer): - invocation_layer = OpenAIInvocationLayer(api_key="fake_api_key", api_base="https://fake_api_base.com") - assert invocation_layer.api_base == "https://fake_api_base.com" - assert invocation_layer.url == "https://fake_api_base.com/completions" - - invocation_layer.invoke(prompt="dummy_prompt") - assert mock_open_ai_request.call_args.kwargs["url"] == "https://fake_api_base.com/completions" - - -@pytest.mark.unit -def test_openai_token_limit_warning(mock_openai_tokenizer, caplog): - invocation_layer = OpenAIInvocationLayer( - model_name_or_path="text-ada-001", api_key="fake_api_key", api_base="https://fake_api_base.com", max_length=2045 - ) - with caplog.at_level(logging.WARNING): - _ = invocation_layer._ensure_token_limit(prompt="This is a test for a mock openai tokenizer.") - assert "The prompt has been truncated from" in caplog.text - assert "and answer length (2045 tokens) fit within the max token limit (2049 tokens)." in caplog.text - - -@pytest.mark.unit -@pytest.mark.parametrize( - "model_name,max_tokens_limit", - [ - ("text-davinci-003", 4097), - ("gpt-3.5-turbo", 4096), - ("gpt-3.5-turbo-16k", 16384), - ("gpt-4-32k", 32768), - ("gpt-4", 8192), - ], -) -def test_openai_token_limit_warning_not_triggered(caplog, mock_openai_tokenizer, model_name, max_tokens_limit): - layer = OpenAIInvocationLayer( - model_name_or_path=model_name, api_key="fake_api_key", api_base="https://fake_api_base.com", max_length=256 - ) - - assert layer.max_tokens_limit == max_tokens_limit - - # the warning is not triggered because max_length is 256, our prompt is 11 tokens, and we have big context window - _ = layer._ensure_token_limit(prompt="This is a test for a mock openai tokenizer.") - assert not caplog.text - - -@pytest.mark.unit -@pytest.mark.parametrize( - "model_name,max_tokens_limit", - [ - ("text-davinci-003", 4097), - ("gpt-3.5-turbo", 4096), - ("gpt-3.5-turbo-16k", 16384), - ("gpt-4-32k", 32768), - ("gpt-4", 8192), - ], -) -def test_openai_token_limit_warning_is_triggered(caplog, mock_openai_tokenizer, model_name, max_tokens_limit): - layer = OpenAIInvocationLayer( - model_name_or_path=model_name, - api_key="fake_api_key", - api_base="https://fake_api_base.com", - max_length=int(max_tokens_limit) - 1, - ) - - assert layer.max_tokens_limit == max_tokens_limit - - # the warning is triggered because max_length is one token smaller than context window and our prompt has 11 tokens - _ = layer._ensure_token_limit(prompt="This is a test for a mock openai tokenizer.") - - # since we are truncating the prompt of 11 tokens, we should see a warning that only 1 token is left - assert "The prompt has been truncated from 11 tokens to 1 tokens" in caplog.text - - -@pytest.mark.unit -def test_no_openai_organization(mock_open_ai_request, load_openai_tokenizer): - invocation_layer = OpenAIInvocationLayer(api_key="fake_api_key") - - assert invocation_layer.openai_organization is None - assert "OpenAI-Organization" not in invocation_layer.headers - - invocation_layer.invoke(prompt="dummy_prompt") - assert "OpenAI-Organization" not in mock_open_ai_request.call_args.kwargs["headers"] - - -@pytest.mark.unit -def test_openai_organization(mock_open_ai_request, load_openai_tokenizer): - invocation_layer = OpenAIInvocationLayer(api_key="fake_api_key", openai_organization="fake_organization") - - assert invocation_layer.openai_organization == "fake_organization" - assert invocation_layer.headers["OpenAI-Organization"] == "fake_organization" - - invocation_layer.invoke(prompt="dummy_prompt") - assert mock_open_ai_request.call_args.kwargs["headers"]["OpenAI-Organization"] == "fake_organization" - - -@pytest.mark.unit -def test_supports(load_openai_tokenizer): - layer = OpenAIInvocationLayer(api_key="some_fake_key") - - assert layer.supports("ada") - assert layer.supports("babbage") - assert layer.supports("curie") - assert layer.supports("davinci") - assert layer.supports("text-ada-001") - assert layer.supports("text-davinci-002") - assert layer.supports("gpt-3.5-turbo-instruct") - - # the following model contains "ada" in the name, but it's not from OpenAI - assert not layer.supports("ybelkada/mpt-7b-bf16-sharded") diff --git a/test/prompt/invocation_layer/test_sagemaker_hf_infer.py b/test/prompt/invocation_layer/test_sagemaker_hf_infer.py deleted file mode 100644 index b2b803212a..0000000000 --- a/test/prompt/invocation_layer/test_sagemaker_hf_infer.py +++ /dev/null @@ -1,431 +0,0 @@ -import os -from unittest.mock import patch, MagicMock, Mock - -import pytest - -from haystack.lazy_imports import LazyImport - -from haystack.errors import SageMakerConfigurationError -from haystack.nodes.prompt.invocation_layer import SageMakerHFInferenceInvocationLayer - -with LazyImport() as boto3_import: - from botocore.exceptions import BotoCoreError - - -# create a fixture with mocked boto3 client and session -@pytest.fixture -def mock_boto3_session(): - with patch("boto3.Session") as mock_client: - yield mock_client - - -@pytest.fixture -def mock_prompt_handler(): - with patch("haystack.nodes.prompt.invocation_layer.handlers.DefaultPromptHandler") as mock_prompt_handler: - yield mock_prompt_handler - - -@pytest.mark.unit -def test_default_constructor(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the default constructor sets the correct values - """ - - layer = SageMakerHFInferenceInvocationLayer( - model_name_or_path="some_fake_model", - max_length=99, - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - aws_profile_name="some_fake_profile", - aws_region_name="fake_region", - ) - - assert layer.max_length == 99 - assert layer.model_name_or_path == "some_fake_model" - - # assert mocked boto3 client called exactly once - mock_boto3_session.assert_called_once() - - # assert mocked boto3 client was called with the correct parameters - mock_boto3_session.assert_called_with( - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - profile_name="some_fake_profile", - region_name="fake_region", - ) - - -@pytest.mark.unit -def test_constructor_with_model_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test that model_kwargs are correctly set in the constructor - and that model_kwargs_rejected are correctly filtered out - """ - model_kwargs = {"temperature": 0.7, "do_sample": True, "stream": True} - model_kwargs_rejected = {"fake_param": 0.7, "another_fake_param": 1} - - layer = SageMakerHFInferenceInvocationLayer( - model_name_or_path="some_fake_model", **model_kwargs, **model_kwargs_rejected - ) - assert layer.model_input_kwargs["temperature"] == 0.7 - assert "do_sample" in layer.model_input_kwargs - assert "fake_param" not in layer.model_input_kwargs - assert "another_fake_param" not in layer.model_input_kwargs - - -@pytest.mark.unit -def test_invoke_with_no_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test that invoke raises an error if no prompt is provided - """ - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="some_fake_model") - with pytest.raises(ValueError, match="No prompt provided."): - layer.invoke() - - -@pytest.mark.unit -def test_invoke_with_stop_words(mock_auto_tokenizer, mock_boto3_session): - """ - Test stop words are correctly passed to HTTP POST request - """ - stop_words = ["but", "not", "bye"] - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="some_model", api_key="fake_key") - with patch("haystack.nodes.prompt.invocation_layer.SageMakerHFInferenceInvocationLayer._post") as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - - layer.invoke(prompt="Tell me hello", stop_words=stop_words) - - assert mock_post.called - _, call_kwargs = mock_post.call_args - assert call_kwargs["params"]["stopping_criteria"] == stop_words - - -@pytest.mark.unit -def test_short_prompt_is_not_truncated(mock_boto3_session): - # Define a short mock prompt and its tokenized version - mock_prompt_text = "I am a tokenized prompt" - mock_prompt_tokens = mock_prompt_text.split() - - # Mock the tokenizer so it returns our predefined tokens - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = mock_prompt_tokens - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Since our mock prompt is 5 tokens long, it doesn't exceed the - # total limit (5 prompt tokens + 3 generated tokens < 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = SageMakerHFInferenceInvocationLayer( - "some_fake_endpoint", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(mock_prompt_text) - - # The prompt doesn't exceed the limit, _ensure_token_limit doesn't truncate it - assert prompt_after_resize == mock_prompt_text - - -@pytest.mark.unit -def test_long_prompt_is_truncated(mock_boto3_session): - # Define a long mock prompt and its tokenized version - long_prompt_text = "I am a tokenized prompt of length eight" - long_prompt_tokens = long_prompt_text.split() - - # We will truncate the prompt to make it fit into the model's max token limit - truncated_prompt_text = "I am a tokenized prompt of length" - - # Mock the tokenizer to return our predefined tokens - # convert tokens to our predefined truncated text - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = long_prompt_tokens - mock_tokenizer.convert_tokens_to_string.return_value = truncated_prompt_text - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Our mock prompt is 8 tokens long, so it exceeds the total limit (8 prompt tokens + 3 generated tokens > 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = SageMakerHFInferenceInvocationLayer( - "some_fake_endpoint", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(long_prompt_text) - - # The prompt exceeds the token limit, so it should be truncated by _ensure_token_limit - assert prompt_after_resize == truncated_prompt_text - - -@pytest.mark.unit -def test_empty_model_name(): - with pytest.raises(ValueError, match="cannot be None or empty string"): - SageMakerHFInferenceInvocationLayer(model_name_or_path="") - - -@pytest.mark.unit -def test_streaming_init_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream parameter passed as init kwarg is correctly logged as not supported - """ - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant", stream=True) - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello") - - -@pytest.mark.unit -def test_streaming_invoke_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream parameter passed as invoke kwarg is correctly logged as not supported - """ - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello", stream=True) - - -@pytest.mark.unit -def test_streaming_handler_init_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream_handler parameter passed as init kwarg is correctly logged as not supported - """ - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant", stream_handler=Mock()) - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello") - - -@pytest.mark.unit -def test_streaming_handler_invoke_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream_handler parameter passed as invoke kwarg is correctly logged as not supported - """ - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello", stream_handler=Mock()) - - -@pytest.mark.unit -def test_supports_for_valid_aws_configuration(): - """ - Test that the SageMakerHFInferenceInvocationLayer identifies a valid SageMaker Inference endpoint - via the supports() method - """ - mock_client = MagicMock() - mock_client.describe_endpoint.return_value = {"EndpointStatus": "InService"} - - mock_session = MagicMock() - mock_session.client.return_value = mock_client - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ): - supported = SageMakerHFInferenceInvocationLayer.supports( - model_name_or_path="some_sagemaker_deployed_model", aws_profile_name="some_real_profile" - ) - args, kwargs = mock_client.describe_endpoint.call_args - assert kwargs["EndpointName"] == "some_sagemaker_deployed_model" - - args, kwargs = mock_session.client.call_args - assert args[0] == "sagemaker-runtime" - assert supported - - -@pytest.mark.unit -def test_supports_not_on_invalid_aws_profile_name(): - """ - Test that the SageMakerHFInferenceInvocationLayer raises SageMakerConfigurationError when the profile name is invalid - """ - - with patch("boto3.Session") as mock_boto3_session: - mock_boto3_session.side_effect = BotoCoreError() - with pytest.raises(SageMakerConfigurationError, match="Failed to initialize the session"): - SageMakerHFInferenceInvocationLayer.supports( - model_name_or_path="some_fake_model", aws_profile_name="some_fake_profile" - ) - - -@pytest.mark.skipif( - not os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT", None), reason="Skipping because SageMaker not configured" -) -@pytest.mark.integration -def test_supports_triggered_for_valid_sagemaker_endpoint(): - """ - Test that the SageMakerHFInferenceInvocationLayer identifies a valid SageMaker Inference endpoint via the supports() method - """ - model_name_or_path = os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT") - assert SageMakerHFInferenceInvocationLayer.supports(model_name_or_path=model_name_or_path) - - -@pytest.mark.skipif( - not os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT", None), reason="Skipping because SageMaker not configured" -) -@pytest.mark.integration -def test_supports_not_triggered_for_invalid_iam_profile(): - """ - Test that the SageMakerHFInferenceInvocationLayer identifies an invalid SageMaker Inference endpoint - (in this case because of an invalid IAM AWS Profile via the supports() method) - """ - assert not SageMakerHFInferenceInvocationLayer.supports(model_name_or_path="fake_endpoint") - assert not SageMakerHFInferenceInvocationLayer.supports( - model_name_or_path="fake_endpoint", aws_profile_name="invalid-profile" - ) - - -@pytest.mark.unit -def test_dolly_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is dolly json response - response = {"generated_texts": ["Berlin"]} - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_dolly_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is dolly json response - response = {"generated_texts": ["Berlin", "More elaborate Berlin"]} - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "More elaborate Berlin"] - - -@pytest.mark.unit -def test_flan_t5_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is flan t5 json response - response = {"generated_texts": ["berlin"]} - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["berlin"] - - -@pytest.mark.unit -def test_gpt_j_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is gpt-j json response - response = [[{"generated_text": "Berlin"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_gpt_j_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is gpt-j json response - response = [[{"generated_text": "Berlin"}, {"generated_text": "Berlin 2"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "Berlin 2"] - - -@pytest.mark.unit -def test_mpt_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is mpt json response - response = [[{"generated_text": "Berlin"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_mpt_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is mpt json response - response = [[{"generated_text": "Berlin"}, {"generated_text": "Berlin 2"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "Berlin 2"] - - -@pytest.mark.unit -def test_open_llama_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is open-llama json response - response = {"generated_texts": ["Berlin"]} - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_open_llama_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is open-llama json response - response = {"generated_texts": ["Berlin", "Berlin 2"]} - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "Berlin 2"] - - -@pytest.mark.unit -def test_pajama_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is pajama json response - response = [[{"generated_text": ["Berlin"]}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_pajama_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is pajama json response - response = [[{"generated_text": "Berlin"}, {"generated_text": "Berlin 2"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "Berlin 2"] - - -@pytest.mark.unit -def test_flan_ul2_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is flan-ul2 json response - response = {"generated_texts": ["Berlin"]} - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_flan_ul2_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is flan-ul2 json response - response = {"generated_texts": ["Berlin", "Berlin 2"]} - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "Berlin 2"] - - -@pytest.mark.unit -def test_gpt_neo_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is gpt neo json response - response = [[{"generated_text": "Berlin"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_gpt_neo_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is gpt neo json response - response = [[{"generated_text": "Berlin"}, {"generated_text": "Berlin 2"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "Berlin 2"] - - -@pytest.mark.unit -def test_bloomz_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is bloomz json response - response = [[{"generated_text": "Berlin"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin"] - - -@pytest.mark.unit -def test_bloomz_multiple_response_parsing(mock_auto_tokenizer, mock_boto3_session): - # this is bloomz json response - response = [[{"generated_text": "Berlin"}, {"generated_text": "Berlin 2"}]] - - layer = SageMakerHFInferenceInvocationLayer(model_name_or_path="irrelevant") - assert layer._extract_response(response) == ["Berlin", "Berlin 2"] diff --git a/test/prompt/invocation_layer/test_sagemaker_hf_text_gen.py b/test/prompt/invocation_layer/test_sagemaker_hf_text_gen.py deleted file mode 100644 index 13b31b81da..0000000000 --- a/test/prompt/invocation_layer/test_sagemaker_hf_text_gen.py +++ /dev/null @@ -1,277 +0,0 @@ -import os -from unittest.mock import patch, MagicMock, Mock - -import pytest - -from haystack.lazy_imports import LazyImport - -from haystack.errors import SageMakerConfigurationError -from haystack.nodes.prompt.invocation_layer import SageMakerHFTextGenerationInvocationLayer - -with LazyImport() as boto3_import: - from botocore.exceptions import BotoCoreError - - -# create a fixture with mocked boto3 client and session -@pytest.fixture -def mock_boto3_session(): - with patch("boto3.Session") as mock_client: - yield mock_client - - -@pytest.fixture -def mock_prompt_handler(): - with patch("haystack.nodes.prompt.invocation_layer.handlers.DefaultPromptHandler") as mock_prompt_handler: - yield mock_prompt_handler - - -@pytest.mark.unit -def test_default_constructor(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the default constructor sets the correct values - """ - - layer = SageMakerHFTextGenerationInvocationLayer( - model_name_or_path="some_fake_model", - max_length=99, - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - aws_profile_name="some_fake_profile", - aws_region_name="fake_region", - ) - - assert layer.max_length == 99 - assert layer.model_name_or_path == "some_fake_model" - - # assert mocked boto3 client called exactly once - mock_boto3_session.assert_called_once() - - # assert mocked boto3 client was called with the correct parameters - mock_boto3_session.assert_called_with( - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - profile_name="some_fake_profile", - region_name="fake_region", - ) - - -@pytest.mark.unit -def test_constructor_with_model_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test that model_kwargs are correctly set in the constructor - and that model_kwargs_rejected are correctly filtered out - """ - model_kwargs = {"temperature": 0.7, "do_sample": True, "stream": True} - model_kwargs_rejected = {"fake_param": 0.7, "another_fake_param": 1} - - layer = SageMakerHFTextGenerationInvocationLayer( - model_name_or_path="some_fake_model", **model_kwargs, **model_kwargs_rejected - ) - assert "temperature" in layer.model_input_kwargs - assert "do_sample" in layer.model_input_kwargs - assert "fake_param" not in layer.model_input_kwargs - assert "another_fake_param" not in layer.model_input_kwargs - - -@pytest.mark.unit -def test_invoke_with_no_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test that invoke raises an error if no prompt is provided - """ - layer = SageMakerHFTextGenerationInvocationLayer(model_name_or_path="some_fake_model") - with pytest.raises(ValueError, match="No prompt provided."): - layer.invoke() - - -@pytest.mark.unit -def test_invoke_with_stop_words(mock_auto_tokenizer, mock_boto3_session): - """ - Test stop words are correctly passed to HTTP POST request - """ - stop_words = ["but", "not", "bye"] - layer = SageMakerHFTextGenerationInvocationLayer(model_name_or_path="some_model", api_key="fake_key") - with patch("haystack.nodes.prompt.invocation_layer.SageMakerHFTextGenerationInvocationLayer._post") as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - - layer.invoke(prompt="Tell me hello", stop_words=stop_words) - - assert mock_post.called - _, call_kwargs = mock_post.call_args - assert call_kwargs["params"]["stop"] == stop_words - - -@pytest.mark.unit -def test_short_prompt_is_not_truncated(mock_boto3_session): - # Define a short mock prompt and its tokenized version - mock_prompt_text = "I am a tokenized prompt" - mock_prompt_tokens = mock_prompt_text.split() - - # Mock the tokenizer so it returns our predefined tokens - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = mock_prompt_tokens - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Since our mock prompt is 5 tokens long, it doesn't exceed the - # total limit (5 prompt tokens + 3 generated tokens < 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = SageMakerHFTextGenerationInvocationLayer( - "some_fake_endpoint", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(mock_prompt_text) - - # The prompt doesn't exceed the limit, _ensure_token_limit doesn't truncate it - assert prompt_after_resize == mock_prompt_text - - -@pytest.mark.unit -def test_long_prompt_is_truncated(mock_boto3_session): - # Define a long mock prompt and its tokenized version - long_prompt_text = "I am a tokenized prompt of length eight" - long_prompt_tokens = long_prompt_text.split() - - # _ensure_token_limit will truncate the prompt to make it fit into the model's max token limit - truncated_prompt_text = "I am a tokenized prompt of length" - - # Mock the tokenizer to return our predefined tokens - # convert tokens to our predefined truncated text - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = long_prompt_tokens - mock_tokenizer.convert_tokens_to_string.return_value = truncated_prompt_text - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Our mock prompt is 8 tokens long, so it exceeds the total limit (8 prompt tokens + 3 generated tokens > 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = SageMakerHFTextGenerationInvocationLayer( - "some_fake_endpoint", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(long_prompt_text) - - # The prompt exceeds the limit, _ensure_token_limit truncates it - assert prompt_after_resize == truncated_prompt_text - - -@pytest.mark.unit -def test_empty_model_name(): - with pytest.raises(ValueError, match="cannot be None or empty string"): - SageMakerHFTextGenerationInvocationLayer(model_name_or_path="") - - -@pytest.mark.unit -def test_streaming_init_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream parameter passed as init kwarg is correctly logged as not supported - """ - layer = SageMakerHFTextGenerationInvocationLayer(model_name_or_path="irrelevant", stream=True) - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello") - - -@pytest.mark.unit -def test_streaming_invoke_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream parameter passed as invoke kwarg is correctly logged as not supported - """ - layer = SageMakerHFTextGenerationInvocationLayer(model_name_or_path="irrelevant") - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello", stream=True) - - -@pytest.mark.unit -def test_streaming_handler_init_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream_handler parameter passed as init kwarg is correctly logged as not supported - """ - layer = SageMakerHFTextGenerationInvocationLayer(model_name_or_path="irrelevant", stream_handler=Mock()) - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello") - - -@pytest.mark.unit -def test_streaming_handler_invoke_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream_handler parameter passed as invoke kwarg is correctly logged as not supported - """ - layer = SageMakerHFTextGenerationInvocationLayer(model_name_or_path="irrelevant") - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello", stream_handler=Mock()) - - -@pytest.mark.unit -def test_supports_for_valid_aws_configuration(): - """ - Test that the SageMakerHFTextGenerationInvocationLayer identifies a valid SageMaker Inference endpoint via the supports() method - """ - mock_client = MagicMock() - mock_client.describe_endpoint.return_value = {"EndpointStatus": "InService"} - - mock_session = MagicMock() - mock_session.client.return_value = mock_client - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ): - supported = SageMakerHFTextGenerationInvocationLayer.supports( - model_name_or_path="some_sagemaker_deployed_model", aws_profile_name="some_real_profile" - ) - args, kwargs = mock_client.describe_endpoint.call_args - assert kwargs["EndpointName"] == "some_sagemaker_deployed_model" - - args, kwargs = mock_session.client.call_args - assert args[0] == "sagemaker-runtime" - assert supported - - -@pytest.mark.unit -def test_supports_not_on_invalid_aws_profile_name(): - """ - Test that the SageMakerHFTextGenerationInvocationLayer raises SageMakerConfigurationError when the profile name is invalid - """ - - with patch("boto3.Session") as mock_boto3_session: - mock_boto3_session.side_effect = BotoCoreError() - with pytest.raises(SageMakerConfigurationError, match="Failed to initialize the session"): - SageMakerHFTextGenerationInvocationLayer.supports( - model_name_or_path="some_fake_model", aws_profile_name="some_fake_profile" - ) - - -@pytest.mark.skipif( - not os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT", None), reason="Skipping because SageMaker not configured" -) -@pytest.mark.integration -def test_supports_triggered_for_valid_sagemaker_endpoint(): - """ - Test that the SageMakerHFTextGenerationInvocationLayer identifies a valid SageMaker Inference endpoint via the supports() method - """ - model_name_or_path = os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT") - assert SageMakerHFTextGenerationInvocationLayer.supports(model_name_or_path=model_name_or_path) - - -@pytest.mark.skipif( - not os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT", None), reason="Skipping because SageMaker not configured" -) -@pytest.mark.integration -def test_supports_not_triggered_for_invalid_iam_profile(): - """ - Test that the SageMakerHFTextGenerationInvocationLayer identifies an invalid SageMaker Inference endpoint - (in this case because of an invalid IAM AWS Profile via the supports() method) - """ - assert not SageMakerHFTextGenerationInvocationLayer.supports(model_name_or_path="fake_endpoint") - assert not SageMakerHFTextGenerationInvocationLayer.supports( - model_name_or_path="fake_endpoint", aws_profile_name="invalid-profile" - ) diff --git a/test/prompt/invocation_layer/test_sagemaker_meta.py b/test/prompt/invocation_layer/test_sagemaker_meta.py deleted file mode 100644 index 6221a07e71..0000000000 --- a/test/prompt/invocation_layer/test_sagemaker_meta.py +++ /dev/null @@ -1,470 +0,0 @@ -import os -from unittest.mock import patch, MagicMock, Mock - -import pytest - -from haystack.lazy_imports import LazyImport - -from haystack.errors import SageMakerConfigurationError -from haystack.nodes.prompt.invocation_layer import SageMakerMetaInvocationLayer - -with LazyImport() as boto3_import: - from botocore.exceptions import BotoCoreError - - -# create a fixture with mocked boto3 client and session -@pytest.fixture -def mock_boto3_session(): - with patch("boto3.Session") as mock_client: - yield mock_client - - -@pytest.fixture -def mock_prompt_handler(): - with patch("haystack.nodes.prompt.invocation_layer.handlers.DefaultPromptHandler") as mock_prompt_handler: - yield mock_prompt_handler - - -@pytest.mark.unit -def test_default_constructor(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the default constructor sets the correct values - """ - - layer = SageMakerMetaInvocationLayer( - model_name_or_path="some_fake_model", - max_length=99, - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - aws_profile_name="some_fake_profile", - aws_region_name="fake_region", - ) - - assert layer.max_length == 99 - assert layer.model_name_or_path == "some_fake_model" - - assert layer.prompt_handler is not None - assert layer.prompt_handler.model_max_length == 4096 - - # assert mocked boto3 client called exactly once - mock_boto3_session.assert_called_once() - - # assert mocked boto3 client was called with the correct parameters - mock_boto3_session.assert_called_with( - aws_access_key_id="some_fake_id", - aws_secret_access_key="some_fake_key", - aws_session_token="some_fake_token", - profile_name="some_fake_profile", - region_name="fake_region", - ) - - -@pytest.mark.unit -def test_constructor_prompt_handler_initialized(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the constructor sets the prompt_handler correctly, with the correct model_max_length for llama-2 - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model", prompt_handler=mock_prompt_handler) - assert layer.prompt_handler is not None - assert layer.prompt_handler.model_max_length == 4096 - - -@pytest.mark.unit -def test_constructor_with_model_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test that model_kwargs are correctly set in the constructor - """ - model_kwargs = {"temperature": 0.7} - - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model", **model_kwargs) - assert "temperature" in layer.model_input_kwargs - assert layer.model_input_kwargs["temperature"] == 0.7 - - -@pytest.mark.unit -def test_constructor_with_empty_model_name(): - """ - Test that the constructor raises an error when the model_name_or_path is empty - """ - with pytest.raises(ValueError, match="cannot be None or empty string"): - SageMakerMetaInvocationLayer(model_name_or_path="") - - -@pytest.mark.unit -def test_invoke_with_no_kwargs(mock_auto_tokenizer, mock_boto3_session): - """ - Test invoke raises an error if no prompt is provided - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model") - with pytest.raises(ValueError, match="No valid prompt provided."): - layer.invoke() - - -@pytest.mark.unit -def test_invoke_with_stop_words(mock_auto_tokenizer, mock_boto3_session): - """ - SageMakerMetaInvocationLayer does not support stop words. Tests that they'll be ignored - """ - stop_words = ["but", "not", "bye"] - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_model") - with patch("haystack.nodes.prompt.invocation_layer.SageMakerMetaInvocationLayer._post") as mock_post: - # Mock the response, need to return a list of dicts - mock_post.return_value = MagicMock(text='[{"generated_text": "Hello"}]') - - layer.invoke(prompt="Tell me hello", stop_words=stop_words) - - assert mock_post.called - _, call_kwargs = mock_post.call_args - assert "stop_words" not in call_kwargs["params"] - - -@pytest.mark.unit -def test_short_prompt_is_not_truncated(mock_boto3_session): - """ - Test that a short prompt is not truncated - """ - # Define a short mock prompt and its tokenized version - mock_prompt_text = "I am a tokenized prompt" - mock_prompt_tokens = mock_prompt_text.split() - - # Mock the tokenizer so it returns our predefined tokens - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = mock_prompt_tokens - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Since our mock prompt is 5 tokens long, it doesn't exceed the - # total limit (5 prompt tokens + 3 generated tokens < 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = SageMakerMetaInvocationLayer( - "some_fake_endpoint", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(mock_prompt_text) - - # The prompt doesn't exceed the limit, _ensure_token_limit doesn't truncate it - assert prompt_after_resize == mock_prompt_text - - -@pytest.mark.unit -def test_long_prompt_is_truncated(mock_boto3_session): - """ - Test that a long prompt is truncated - """ - # Define a long mock prompt and its tokenized version - long_prompt_text = "I am a tokenized prompt of length eight" - long_prompt_tokens = long_prompt_text.split() - - # _ensure_token_limit will truncate the prompt to make it fit into the model's max token limit - truncated_prompt_text = "I am a tokenized prompt of length" - - # Mock the tokenizer to return our predefined tokens - # convert tokens to our predefined truncated text - mock_tokenizer = MagicMock() - mock_tokenizer.tokenize.return_value = long_prompt_tokens - mock_tokenizer.convert_tokens_to_string.return_value = truncated_prompt_text - - # We set a small max_length for generated text (3 tokens) and a total model_max_length of 10 tokens - # Our mock prompt is 8 tokens long, so it exceeds the total limit (8 prompt tokens + 3 generated tokens > 10 tokens) - max_length_generated_text = 3 - total_model_max_length = 10 - - with patch("transformers.AutoTokenizer.from_pretrained", return_value=mock_tokenizer): - layer = SageMakerMetaInvocationLayer( - "some_fake_endpoint", max_length=max_length_generated_text, model_max_length=total_model_max_length - ) - prompt_after_resize = layer._ensure_token_limit(long_prompt_text) - - # The prompt exceeds the limit, _ensure_token_limit truncates it - assert prompt_after_resize == truncated_prompt_text - - -@pytest.mark.unit -def test_streaming_init_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream parameter passed as init kwarg raises an error on layer invocation - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="irrelevant", stream=True) - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello") - - -@pytest.mark.unit -def test_streaming_invoke_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream parameter passed as invoke kwarg raises an error on layer invocation - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="irrelevant") - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello", stream=True) - - -@pytest.mark.unit -def test_streaming_handler_init_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream_handler parameter passed as init kwarg raises an error on layer invocation - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="irrelevant", stream_handler=Mock()) - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello") - - -@pytest.mark.unit -def test_streaming_handler_invoke_kwarg(mock_auto_tokenizer, mock_boto3_session): - """ - Test stream_handler parameter passed as invoke kwarg raises an error on layer invocation - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="irrelevant") - - with pytest.raises(SageMakerConfigurationError, match="SageMaker model response streaming is not supported yet"): - layer.invoke(prompt="Tell me hello", stream_handler=Mock()) - - -@pytest.mark.unit -def test_supports_for_valid_aws_configuration(): - """ - Test that the SageMakerMetaInvocationLayer identifies a valid SageMaker Inference endpoint via the supports() method - """ - mock_client = MagicMock() - mock_client.describe_endpoint.return_value = {"EndpointStatus": "InService"} - - mock_session = MagicMock() - mock_session.client.return_value = mock_client - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ): - supported = SageMakerMetaInvocationLayer.supports( - model_name_or_path="some_sagemaker_deployed_model", - aws_profile_name="some_real_profile", - aws_custom_attributes={"accept_eula": True}, - ) - args, kwargs = mock_client.describe_endpoint.call_args - assert kwargs["EndpointName"] == "some_sagemaker_deployed_model" - - args, kwargs = mock_session.client.call_args - assert args[0] == "sagemaker-runtime" - assert supported - - -@pytest.mark.unit -def test_supports_not_on_invalid_aws_profile_name(): - """ - Test that the SageMakerMetaInvocationLayer raises SageMakerConfigurationError when the profile name is invalid - """ - - with patch("boto3.Session") as mock_boto3_session: - mock_boto3_session.side_effect = BotoCoreError() - with pytest.raises(SageMakerConfigurationError, match="Failed to initialize the session"): - SageMakerMetaInvocationLayer.supports( - model_name_or_path="some_fake_model", - aws_profile_name="some_fake_profile", - aws_custom_attributes={"accept_eula": True}, - ) - - -@pytest.mark.unit -def test_supports_not_on_missing_eula(): - """ - Test that the SageMakerMetaInvocationLayer is not supported when the EULA is missing - """ - - mock_client = MagicMock() - mock_client.describe_endpoint.return_value = {"EndpointStatus": "InService"} - - mock_session = MagicMock() - mock_session.client.return_value = mock_client - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ): - supported = SageMakerMetaInvocationLayer.supports( - model_name_or_path="some_sagemaker_deployed_model", aws_profile_name="some_real_profile" - ) - - assert not supported - - -@pytest.mark.unit -def test_supports_not_on_eula_not_accepted(): - """ - Test that the SageMakerMetaInvocationLayer is not supported when the EULA is not accepted - """ - - mock_client = MagicMock() - mock_client.describe_endpoint.return_value = {"EndpointStatus": "InService"} - - mock_session = MagicMock() - mock_session.client.return_value = mock_client - - # Patch the class method to return the mock session - with patch( - "haystack.nodes.prompt.invocation_layer.aws_base.AWSBaseInvocationLayer.get_aws_session", - return_value=mock_session, - ): - supported = SageMakerMetaInvocationLayer.supports( - model_name_or_path="some_sagemaker_deployed_model", - aws_profile_name="some_real_profile", - aws_custom_attributes={"accept_eula": False}, - ) - assert not supported - - -@pytest.mark.unit -def test_format_custom_attributes_with_non_empty_dict(): - """ - Test that the SageMakerMetaInvocationLayer correctly formats the custom attributes, attributes specified - """ - attributes = {"key1": "value1", "key2": "value2"} - expected_output = "key1=value1;key2=value2" - assert SageMakerMetaInvocationLayer.format_custom_attributes(attributes) == expected_output - - -@pytest.mark.unit -def test_format_custom_attributes_with_empty_dict(): - """ - Test that the SageMakerMetaInvocationLayer correctly formats the custom attributes, attributes not specified - """ - attributes = {} - expected_output = "" - assert SageMakerMetaInvocationLayer.format_custom_attributes(attributes) == expected_output - - -@pytest.mark.unit -def test_format_custom_attributes_with_none(): - """ - Test that the SageMakerMetaInvocationLayer correctly formats the custom attributes, attributes are None - """ - attributes = None - expected_output = "" - assert SageMakerMetaInvocationLayer.format_custom_attributes(attributes) == expected_output - - -@pytest.mark.unit -def test_format_custom_attributes_with_bool_value(): - """ - Test that the SageMakerMetaInvocationLayer correctly formats the custom attributes, attributes are bool - """ - attributes = {"key1": True, "key2": False} - expected_output = "key1=true;key2=false" - assert SageMakerMetaInvocationLayer.format_custom_attributes(attributes) == expected_output - - -@pytest.mark.unit -def test_format_custom_attributes_with_single_bool_value(): - """ - Test that the SageMakerMetaInvocationLayer correctly formats the custom attributes, attributes are single bool - """ - attributes = {"key1": True} - expected_output = "key1=true" - assert SageMakerMetaInvocationLayer.format_custom_attributes(attributes) == expected_output - - -@pytest.mark.unit -def test_format_custom_attributes_with_int_value(): - """ - Test that the SageMakerMetaInvocationLayer correctly formats the custom attributes, attributes are ints - """ - attributes = {"key1": 1, "key2": 2} - expected_output = "key1=1;key2=2" - assert SageMakerMetaInvocationLayer.format_custom_attributes(attributes) == expected_output - - -@pytest.mark.unit -def test_invoke_chat_format(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the SageMakerMetaInvocationLayer accepts a chat in the correct format - """ - # test the format of the chat, no exception should be raised - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model") - prompt = [[{"role": "user", "content": "Hello"}]] - expected_response = [[{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hello there"}]] - - with patch("haystack.nodes.prompt.invocation_layer.sagemaker_meta.SageMakerMetaInvocationLayer._post") as mock_post: - mock_post.return_value = expected_response - layer.invoke(prompt=prompt) - - -@pytest.mark.unit -def test_invoke_invalid_chat_format(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the SageMakerMetaInvocationLayer raises an exception when the chat is in the wrong format - """ - # test the invalid format of the chat, should raise an exception - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model") - prompt = [{"roe": "user", "cotent": "Hello"}] - expected_response = [[{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hello there"}]] - - with patch("haystack.nodes.prompt.invocation_layer.sagemaker_meta.SageMakerMetaInvocationLayer._post") as mock_post: - mock_post.return_value = expected_response - with pytest.raises(ValueError, match="The prompt format is different than what the model expects"): - layer.invoke(prompt=prompt) - - -@pytest.mark.unit -def test_invoke_prompt_string(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the SageMakerMetaInvocationLayer accepts a prompt in the correct string format - """ - # test the format of the prompt instruction, no exception should be raised - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model") - with patch("haystack.nodes.prompt.invocation_layer.sagemaker_meta.SageMakerMetaInvocationLayer._post") as mock_post: - mock_post.return_value = ["Hello there"] - layer.invoke(prompt="Hello") - - -@pytest.mark.unit -def test_invoke_empty_prompt(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the SageMakerMetaInvocationLayer raises an exception when the prompt is empty string - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model") - with pytest.raises(ValueError): - layer.invoke(prompt="") - - -@pytest.mark.unit -def test_invoke_improper_prompt_type(mock_auto_tokenizer, mock_boto3_session): - """ - Test that the SageMakerMetaInvocationLayer raises an exception when the prompt is int instead of str - """ - layer = SageMakerMetaInvocationLayer(model_name_or_path="some_fake_model") - prompt = 123 - with pytest.raises(ValueError): - layer.invoke(prompt=prompt) - - -@pytest.mark.skipif( - not os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT", None), reason="Skipping because SageMaker not configured" -) -@pytest.mark.integration -def test_supports_triggered_for_valid_sagemaker_endpoint(): - """ - Test that the SageMakerMetaInvocationLayer identifies a valid SageMaker Inference endpoint via the supports() method - """ - model_name_or_path = os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT") - assert SageMakerMetaInvocationLayer.supports(model_name_or_path=model_name_or_path) - - -@pytest.mark.skipif( - not os.environ.get("TEST_SAGEMAKER_MODEL_ENDPOINT", None), reason="Skipping because SageMaker not configured" -) -@pytest.mark.integration -def test_supports_not_triggered_for_invalid_iam_profile(): - """ - Test that the SageMakerMetaInvocationLayer identifies an invalid SageMaker Inference endpoint - (in this case because of an invalid IAM AWS Profile via the supports() method) - """ - assert not SageMakerMetaInvocationLayer.supports(model_name_or_path="fake_endpoint") - assert not SageMakerMetaInvocationLayer.supports( - model_name_or_path="fake_endpoint", aws_profile_name="invalid-profile" - ) diff --git a/test/prompt/test_handlers.py b/test/prompt/test_handlers.py deleted file mode 100644 index f7b8a3e9bf..0000000000 --- a/test/prompt/test_handlers.py +++ /dev/null @@ -1,148 +0,0 @@ -from unittest.mock import patch - -import pytest - -from haystack.nodes.prompt.invocation_layer.handlers import DefaultPromptHandler - - -@pytest.mark.unit -def test_prompt_handler_positive(): - # prompt of length 5 + max_length of 3 = 8, which is less than model_max_length of 10, so no resize - mock_tokens = ["I", "am", "a", "tokenized", "prompt"] - mock_prompt = "I am a tokenized prompt" - - with patch( - "haystack.nodes.prompt.invocation_layer.handlers.AutoTokenizer.from_pretrained", autospec=True - ) as mock_tokenizer: - tokenizer_instance = mock_tokenizer.return_value - tokenizer_instance.tokenize.return_value = mock_tokens - tokenizer_instance.convert_tokens_to_string.return_value = mock_prompt - - prompt_handler = DefaultPromptHandler("model_path", 10, 3) - - # Test with a prompt that does not exceed model_max_length when tokenized - result = prompt_handler(mock_prompt) - - assert result == { - "resized_prompt": mock_prompt, - "prompt_length": 5, - "new_prompt_length": 5, - "model_max_length": 10, - "max_length": 3, - } - - -@pytest.mark.unit -def test_prompt_handler_negative(): - # prompt of length 8 + max_length of 3 = 11, which is more than model_max_length of 10, so we resize to 7 - mock_tokens = ["I", "am", "a", "tokenized", "prompt", "of", "length", "eight"] - mock_prompt = "I am a tokenized prompt of length" - - with patch( - "haystack.nodes.prompt.invocation_layer.handlers.AutoTokenizer.from_pretrained", autospec=True - ) as mock_tokenizer: - tokenizer_instance = mock_tokenizer.return_value - tokenizer_instance.tokenize.return_value = mock_tokens - tokenizer_instance.convert_tokens_to_string.return_value = mock_prompt - - prompt_handler = DefaultPromptHandler("model_path", 10, 3) - result = prompt_handler(mock_prompt) - - assert result == { - "resized_prompt": mock_prompt, - "prompt_length": 8, - "new_prompt_length": 7, - "model_max_length": 10, - "max_length": 3, - } - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.handlers.AutoTokenizer.from_pretrained") -def test_prompt_handler_model_max_length_set_in_tokenizer(mock_tokenizer): - prompt_handler = DefaultPromptHandler(model_name_or_path="model_path", model_max_length=10, max_length=3) - assert prompt_handler.tokenizer.model_max_length == 10 - - -@pytest.mark.integration -def test_prompt_handler_basics(): - handler = DefaultPromptHandler(model_name_or_path="gpt2", model_max_length=20, max_length=10) - assert callable(handler) - - handler = DefaultPromptHandler(model_name_or_path="gpt2", model_max_length=20) - assert handler.max_length == 100 - - # test model_max_length is set in tokenizer - assert handler.tokenizer.model_max_length == 20 - - -@pytest.mark.integration -def test_gpt2_prompt_handler(): - # test gpt2 BPE based tokenizer - handler = DefaultPromptHandler(model_name_or_path="gpt2", model_max_length=20, max_length=10) - - # test no resize - assert handler("This is a test") == { - "prompt_length": 4, - "resized_prompt": "This is a test", - "max_length": 10, - "model_max_length": 20, - "new_prompt_length": 4, - } - - # test resize - assert handler("This is a prompt that will be resized because it is longer than allowed") == { - "prompt_length": 15, - "resized_prompt": "This is a prompt that will be resized because", - "max_length": 10, - "model_max_length": 20, - "new_prompt_length": 10, - } - - -@pytest.mark.integration -def test_flan_prompt_handler_no_resize(): - handler = DefaultPromptHandler(model_name_or_path="google/flan-t5-xxl", model_max_length=20, max_length=10) - assert handler("This is a test") == { - "prompt_length": 5, - "resized_prompt": "This is a test", - "max_length": 10, - "model_max_length": 20, - "new_prompt_length": 5, - } - - -@pytest.mark.integration -def test_flan_prompt_handler_resize(): - handler = DefaultPromptHandler(model_name_or_path="google/flan-t5-xxl", model_max_length=20, max_length=10) - assert handler("This is a prompt that will be resized because it is longer than allowed") == { - "prompt_length": 17, - "resized_prompt": "This is a prompt that will be re", - "max_length": 10, - "model_max_length": 20, - "new_prompt_length": 10, - } - - -@pytest.mark.integration -def test_flan_prompt_handler_empty_string(): - handler = DefaultPromptHandler(model_name_or_path="google/flan-t5-xxl", model_max_length=20, max_length=10) - assert handler("") == { - "prompt_length": 0, - "resized_prompt": "", - "max_length": 10, - "model_max_length": 20, - "new_prompt_length": 0, - } - - -@pytest.mark.integration -def test_flan_prompt_handler_none(): - handler = DefaultPromptHandler(model_name_or_path="google/flan-t5-xxl", model_max_length=20, max_length=10) - assert handler(None) == { - "prompt_length": 0, - "resized_prompt": None, - "max_length": 10, - "model_max_length": 20, - "new_prompt_length": 0, - } diff --git a/test/prompt/test_prompt_model.py b/test/prompt/test_prompt_model.py deleted file mode 100644 index 9e7c2b0f51..0000000000 --- a/test/prompt/test_prompt_model.py +++ /dev/null @@ -1,60 +0,0 @@ -import asyncio -from unittest.mock import patch, MagicMock - -import pytest - -from haystack.nodes.prompt.prompt_model import PromptModel -from haystack.nodes.prompt.invocation_layer import PromptModelInvocationLayer, HFLocalInvocationLayer - -from .conftest import create_mock_layer_that_supports - - -@pytest.mark.unit -def test_constructor_with_default_model(): - mock_layer = create_mock_layer_that_supports("google/flan-t5-base") - another_layer = create_mock_layer_that_supports("another-model") - - with patch.object(PromptModelInvocationLayer, "invocation_layer_providers", new=[mock_layer, another_layer]): - model = PromptModel() - mock_layer.assert_called_once() - another_layer.assert_not_called() - model.model_invocation_layer.model_name_or_path = "google/flan-t5-base" - - -@pytest.mark.unit -def test_construtor_with_custom_model(): - mock_layer = create_mock_layer_that_supports("some-model") - another_layer = create_mock_layer_that_supports("another-model") - - with patch.object(PromptModelInvocationLayer, "invocation_layer_providers", new=[mock_layer, another_layer]): - model = PromptModel("another-model") - mock_layer.assert_not_called() - another_layer.assert_called_once() - model.model_invocation_layer.model_name_or_path = "another-model" - - -@pytest.mark.unit -def test_constructor_with_no_supported_model(): - with pytest.raises(ValueError, match="Model some-random-model is not supported"): - PromptModel("some-random-model") - - -@pytest.mark.asyncio -async def test_ainvoke(): - def async_return(result): - f = asyncio.Future() - f.set_result(result) - return f - - mock_layer = MagicMock() # no async-defined methods, await will fail and fall back to regular `invoke` - mock_layer.return_value.invoke.return_value = async_return("Async Bar!") - model = PromptModel(invocation_layer_class=mock_layer) - assert await model.ainvoke("Foo") == "Async Bar!" - - -@pytest.mark.asyncio -async def test_ainvoke_falls_back_to_sync(): - mock_layer = MagicMock() # no async-defined methods, await will fail and fall back to regular `invoke` - mock_layer.return_value.invoke.return_value = "Bar!" - model = PromptModel(invocation_layer_class=mock_layer) - assert await model.ainvoke("Foo") == "Bar!" diff --git a/test/prompt/test_prompt_node.py b/test/prompt/test_prompt_node.py deleted file mode 100644 index 972a04be18..0000000000 --- a/test/prompt/test_prompt_node.py +++ /dev/null @@ -1,1204 +0,0 @@ -import logging -import os -from typing import Any, Dict, List, Optional, Tuple, Union -from unittest.mock import AsyncMock, MagicMock, Mock, patch - -import pytest -from prompthub import Prompt - -from haystack import BaseComponent, Document, MultiLabel, Pipeline -from haystack.nodes.prompt import PromptModel, PromptNode, PromptTemplate -from haystack.nodes.prompt.invocation_layer import ( - AzureChatGPTInvocationLayer, - AzureOpenAIInvocationLayer, - ChatGPTInvocationLayer, - OpenAIInvocationLayer, -) -from haystack.nodes.prompt.prompt_template import LEGACY_DEFAULT_TEMPLATES - - -@pytest.fixture -def mock_prompthub(): - with patch("haystack.nodes.prompt.prompt_template.fetch_from_prompthub") as mock_prompthub: - mock_prompthub.return_value = Prompt( - name="deepset/test", - tags=["test"], - meta={"author": "test"}, - version="v0.0.0", - text="This is a test prompt. Use your knowledge to answer this question: {question}", - description="test prompt", - ) - yield mock_prompthub - - -def skip_test_for_invalid_key(prompt_model): - if prompt_model.api_key is not None and prompt_model.api_key == "KEY_NOT_FOUND": - pytest.skip("No API key found, skipping test") - - -@pytest.fixture -def get_api_key(request): - if request.param == "openai": - return os.environ.get("OPENAI_API_KEY", None) - elif request.param == "azure": - return os.environ.get("AZURE_OPENAI_API_KEY", None) - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_prompt_passing_template(mock_model): - # Make model always return something positive on invoke - mock_model.return_value.invoke.return_value = ["positive"] - - # Create a template - template = PromptTemplate( - "Please give a sentiment for this context. Answer with positive, " - "negative or neutral. Context: {documents}; Answer:" - ) - - # Execute prompt - node = PromptNode() - result = node.prompt(template, documents=["Berlin is an amazing city."]) - - assert result == ["positive"] - - -@pytest.mark.unit -@patch.object(PromptNode, "prompt") -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_prompt_call_with_no_kwargs(mock_model, mocked_prompt): - node = PromptNode() - node() - mocked_prompt.assert_called_once_with(node.default_prompt_template) - - -@pytest.mark.unit -@patch.object(PromptNode, "prompt") -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_prompt_call_with_custom_kwargs(mock_model, mocked_prompt): - node = PromptNode() - node(some_kwarg="some_value") - mocked_prompt.assert_called_once_with(node.default_prompt_template, some_kwarg="some_value") - - -@pytest.mark.unit -@patch.object(PromptNode, "prompt") -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_prompt_call_with_custom_template(mock_model, mocked_prompt): - node = PromptNode() - mock_template = Mock() - node(prompt_template=mock_template) - mocked_prompt.assert_called_once_with(mock_template) - - -@pytest.mark.unit -@patch.object(PromptNode, "prompt") -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_prompt_call_with_custom_kwargs_and_template(mock_model, mocked_prompt): - node = PromptNode() - mock_template = Mock() - node(prompt_template=mock_template, some_kwarg="some_value") - mocked_prompt.assert_called_once_with(mock_template, some_kwarg="some_value") - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_no_default_template(mock_model): - node = PromptNode() - assert node.get_prompt_template() is None - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_from_legacy_default_template(mock_model): - node = PromptNode() - template = node.get_prompt_template("question-answering") - assert template.name == "question-answering" - assert template.prompt_text == LEGACY_DEFAULT_TEMPLATES["question-answering"]["prompt"] - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_with_default_template(mock_model, mock_prompthub): - node = PromptNode() - node.default_prompt_template = "deepset/test-prompt" - - template = node.get_prompt_template() - assert template.name == "deepset/test-prompt" - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_name_from_hub(mock_model, mock_prompthub): - node = PromptNode() - template = node.get_prompt_template("deepset/test-prompt") - assert template.name == "deepset/test-prompt" - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_local_file(mock_model, tmp_path, mock_prompthub): - with open(tmp_path / "local_prompt_template.yml", "w") as ptf: - ptf.write( - """ -name: my_prompts/question-answering -text: | - Given the context please answer the question. Context: {join(documents)}; - Question: {query}; - Answer: -description: A simple prompt to answer a question given a set of documents -tags: - - question-answering -meta: - authors: - - vblagoje -version: v0.1.1 -""" - ) - node = PromptNode() - template = node.get_prompt_template(str(tmp_path / "local_prompt_template.yml")) - assert template.name == "my_prompts/question-answering" - assert "Given the context" in template.prompt_text - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_object(mock_model, mock_prompthub): - node = PromptNode() - original_template = PromptTemplate("fake-template") - template = node.get_prompt_template(original_template) - assert template == original_template - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_wrong_template_name(mock_model): - with patch("haystack.nodes.prompt.prompt_template.prompthub") as mock_prompthub: - - def not_found(*a, **k): - raise ValueError("'some-unsupported-template' not supported!") - - mock_prompthub.fetch.side_effect = not_found - node = PromptNode() - with pytest.raises(ValueError, match="not supported"): - node.get_prompt_template("some-unsupported-template") - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_get_prompt_template_only_template_text(mock_model, mock_prompthub): - node = PromptNode() - template = node.get_prompt_template("some prompt") - assert template.name == "custom-at-query-time" - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_invalid_template_params(mock_model, mock_prompthub): - node = PromptNode() - with pytest.raises(ValueError, match="Expected prompt parameters"): - node.prompt("question-answering-per-document", some_crazy_key="Berlin is the capital of Germany.") - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.open_ai.load_openai_tokenizer", lambda tokenizer_name: None) -def test_azure_vs_open_ai_invocation_layer_selection(): - """ - Tests that the correct invocation layer is selected based on the model name and additional parameters. - As we support both OpenAI and Azure models, we need to make sure that the correct invocation layer is selected - based on the model name and additional parameters. - """ - azure_model_kwargs = { - "azure_base_url": "https://some_unimportant_url", - "azure_deployment_name": "https://some_unimportant_url.azurewebsites.net/api/prompt", - } - - node = PromptNode("gpt-4", api_key="some_key", model_kwargs=azure_model_kwargs) - assert isinstance(node.prompt_model.model_invocation_layer, AzureChatGPTInvocationLayer) - - node = PromptNode("text-davinci-003", api_key="some_key", model_kwargs=azure_model_kwargs) - assert isinstance(node.prompt_model.model_invocation_layer, AzureOpenAIInvocationLayer) - - node = PromptNode("gpt-4", api_key="some_key") - assert isinstance(node.prompt_model.model_invocation_layer, ChatGPTInvocationLayer) and not isinstance( - node.prompt_model.model_invocation_layer, AzureChatGPTInvocationLayer - ) - - node = PromptNode("text-davinci-003", api_key="some_key") - assert isinstance(node.prompt_model.model_invocation_layer, OpenAIInvocationLayer) and not isinstance( - node.prompt_model.model_invocation_layer, AzureChatGPTInvocationLayer - ) - - -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["hf"], indirect=True) -def test_simple_pipeline(prompt_model): - """ - Tests that a pipeline with a prompt node and prompt template has the right output structure - """ - output_variable_name = "out" - node = PromptNode(prompt_model, default_prompt_template="sentiment-analysis", output_variable=output_variable_name) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run(query="not relevant", documents=[Document("Berlin is an amazing city.")]) - - # validate output variable present - assert output_variable_name in result - assert len(result[output_variable_name]) == 1 - - # validate pipeline parameters are present - assert "query" in result - assert "documents" in result - - # and that so-called invocation context contains the right keys - assert "invocation_context" in result - assert all(item in result["invocation_context"] for item in ["query", "documents", output_variable_name, "prompts"]) - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["hf", "openai", "azure"], indirect=True) -def test_complex_pipeline(prompt_model): - # TODO: This is a unit test? - skip_test_for_invalid_key(prompt_model) - - node = PromptNode(prompt_model, default_prompt_template="question-generation", output_variable="query") - node2 = PromptNode(prompt_model, default_prompt_template="question-answering-per-document") - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - pipe.add_node(component=node2, name="prompt_node_2", inputs=["prompt_node"]) - result = pipe.run(query="not relevant", documents=[Document("Berlin is the capital of Germany")]) - - assert "berlin" in result["answers"][0].answer.casefold() - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["hf", "openai", "azure"], indirect=True) -def test_simple_pipeline_with_topk(prompt_model): - # TODO: This can be a unit test? - skip_test_for_invalid_key(prompt_model) - - node = PromptNode(prompt_model, default_prompt_template="question-generation", output_variable="query", top_k=2) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run(query="not relevant", documents=[Document("Berlin is the capital of Germany")]) - - assert len(result["query"]) == 2 - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["hf", "openai", "azure"], indirect=True) -def test_pipeline_with_standard_qa(prompt_model): - # TODO: Unit test? - skip_test_for_invalid_key(prompt_model) - node = PromptNode(prompt_model, default_prompt_template="question-answering", top_k=1) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run( - query="Who lives in Berlin?", # this being a string instead of a list what is being tested - documents=[ - Document("My name is Carla and I live in Berlin", id="1"), - Document("My name is Christelle and I live in Paris", id="2"), - ], - ) - - assert len(result["answers"]) == 1 - assert "carla" in result["answers"][0].answer.casefold() - - assert result["answers"][0].document_ids == ["1", "2"] - assert ( - result["answers"][0].meta["prompt"] - == "Given the context please answer the question. Context: My name is Carla and I live in Berlin My name is Christelle and I live in Paris; " - "Question: Who lives in Berlin?; Answer:" - ) - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["openai", "azure"], indirect=True) -def test_pipeline_with_qa_with_references(prompt_model): - skip_test_for_invalid_key(prompt_model) - node = PromptNode(prompt_model, default_prompt_template="question-answering-with-references", top_k=1) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run( - query="Who lives in Berlin?", # this being a string instead of a list what is being tested - documents=[ - Document("My name is Carla and I live in Berlin", id="1"), - Document("My name is Christelle and I live in Paris", id="2"), - ], - ) - - assert len(result["answers"]) == 1 - assert "carla, as stated in document[1]" in result["answers"][0].answer.casefold() - - assert result["answers"][0].document_ids == ["1"] - assert ( - result["answers"][0].meta["prompt"] - == "Create a concise and informative answer (no more than 50 words) for a given question based solely on the given documents. " - "You must only use information from the given documents. Use an unbiased and journalistic tone. Do not repeat text. Cite the documents using Document[number] notation. " - "If multiple documents contain the answer, cite those documents like ‘as stated in Document[number], Document[number], etc.’. If the documents do not contain the answer to the question, " - "say that ‘answering is not possible given the available information.’\n\nDocument[1]: My name is Carla and I live in Berlin\n\nDocument[2]: My name is Christelle and I live in Paris \n " - "Question: Who lives in Berlin?; Answer: " - ) - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["openai", "azure"], indirect=True) -def test_pipeline_with_prompt_text_at_query_time(prompt_model): - skip_test_for_invalid_key(prompt_model) - node = PromptNode(prompt_model, default_prompt_template="test prompt template text", top_k=1) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run( - query="Who lives in Berlin?", # this being a string instead of a list what is being tested - documents=[ - Document("My name is Carla and I live in Berlin", id="1"), - Document("My name is Christelle and I live in Paris", id="2"), - ], - params={ - "prompt_template": "Create a concise and informative answer (no more than 50 words) for a given question based solely on the given documents. Cite the documents using Document[number] notation.\n\n{join(documents, delimiter=new_line+new_line, pattern='Document[$idx]: $content')}\n\nQuestion: {query}\n\nAnswer: " - }, - ) - - assert len(result["answers"]) == 1 - assert "carla" in result["answers"][0].answer.casefold() - - assert result["answers"][0].document_ids == ["1"] - assert ( - result["answers"][0].meta["prompt"] - == "Create a concise and informative answer (no more than 50 words) for a given question based solely on the given documents. Cite the documents using Document[number] notation.\n\n" - "Document[1]: My name is Carla and I live in Berlin\n\nDocument[2]: My name is Christelle and I live in Paris\n\n" - "Question: Who lives in Berlin?\n\nAnswer: " - ) - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["openai", "azure"], indirect=True) -def test_pipeline_with_prompt_template_at_query_time(prompt_model): - # TODO: This should be just an AnswerParser unit test and some PromptTemplate unit tests - skip_test_for_invalid_key(prompt_model) - node = PromptNode(prompt_model, default_prompt_template="question-answering-with-references", top_k=1) - - prompt_template_yaml = """ - name: "question-answering-with-references-custom" - prompt_text: 'Create a concise and informative answer (no more than 50 words) for - a given question based solely on the given documents. Cite the documents using Doc[number] notation. - - - {join(documents, delimiter=new_line+new_line, pattern=''Doc[$idx]: $content'')} - - - Question: {query} - - - Answer: ' - output_parser: - type: AnswerParser - params: - reference_pattern: Doc\\[([^\\]]+)\\] - """ - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run( - query="Who lives in Berlin?", # this being a string instead of a list what is being tested - documents=[ - Document("My name is Carla and I live in Berlin", id="doc-1"), - Document("My name is Christelle and I live in Paris", id="doc-2"), - ], - params={"prompt_template": prompt_template_yaml}, - ) - - assert len(result["answers"]) == 1 - assert "carla" in result["answers"][0].answer.casefold() - - assert result["answers"][0].document_ids == ["doc-1"] - assert ( - result["answers"][0].meta["prompt"] - == "Create a concise and informative answer (no more than 50 words) for a given question based solely on the given documents. Cite the documents using Doc[number] notation.\n\n" - "Doc[1]: My name is Carla and I live in Berlin\n\nDoc[2]: My name is Christelle and I live in Paris\n\n" - "Question: Who lives in Berlin?\n\nAnswer: " - ) - - -@pytest.mark.skip -@pytest.mark.integration -def test_pipeline_with_prompt_template_and_nested_shaper_yaml(tmp_path): - # TODO: This can be a Shaper unit test? - with open(tmp_path / "tmp_config_with_prompt_template.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: template_with_nested_shaper - type: PromptTemplate - params: - prompt: "Given the context please answer the question. Context: {{documents}}; Question: {{query}}; Answer: " - output_parser: - type: AnswerParser - - name: p1 - params: - model_name_or_path: google/flan-t5-small - default_prompt_template: template_with_nested_shaper - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config_with_prompt_template.yml") - result = pipeline.run(query="What is an amazing city?", documents=[Document("Berlin is an amazing city.")]) - answer = result["answers"][0].answer - assert any(word for word in ["berlin", "germany", "population", "city", "amazing"] if word in answer.casefold()) - assert ( - result["answers"][0].meta["prompt"] - == "Given the context please answer the question. Context: Berlin is an amazing city.; Question: What is an amazing city?; Answer: " - ) - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["hf"], indirect=True) -def test_prompt_node_no_debug(prompt_model): - # TODO: This is another unit test - """Pipeline with PromptNode should not generate debug info if debug is false.""" - - node = PromptNode(prompt_model, default_prompt_template="question-generation", top_k=2) - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - - # debug explicitly False - result = pipe.run(query="not relevant", documents=[Document("Berlin is the capital of Germany")], debug=False) - assert result.get("_debug", "No debug info") == "No debug info" - - # debug None - result = pipe.run(query="not relevant", documents=[Document("Berlin is the capital of Germany")], debug=None) - assert result.get("_debug", "No debug info") == "No debug info" - - # debug True - result = pipe.run(query="not relevant", documents=[Document("Berlin is the capital of Germany")], debug=True) - assert ( - result["_debug"]["prompt_node"]["runtime"]["prompts_used"][0] - == "Given the context please generate a question. Context: Berlin is the capital of Germany; Question:" - ) - - -@pytest.mark.skip -@pytest.mark.integration -@pytest.mark.parametrize("prompt_model", ["hf", "openai", "azure"], indirect=True) -def test_complex_pipeline_with_qa(prompt_model): - # TODO: Not a PromptNode test, this maybe can be a unit test - """Test the PromptNode where the `query` is a string instead of a list what the PromptNode would expects, - because in a question-answering pipeline the retrievers need `query` as a string, so the PromptNode - need to be able to handle the `query` being a string instead of a list.""" - skip_test_for_invalid_key(prompt_model) - - prompt_template = PromptTemplate( - "Given the context please answer the question. Context: {documents}; Question: {query}; Answer:" - ) - node = PromptNode(prompt_model, default_prompt_template=prompt_template) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run( - query="Who lives in Berlin?", # this being a string instead of a list what is being tested - documents=[ - Document("My name is Carla and I live in Berlin"), - Document("My name is Christelle and I live in Paris"), - ], - debug=True, # so we can verify that the constructed prompt is returned in debug - ) - - assert len(result["results"]) == 2 - assert "carla" in result["results"][0].casefold() - - # also verify that the PromptNode has included its constructed prompt LLM model input in the returned debug - assert ( - result["_debug"]["prompt_node"]["runtime"]["prompts_used"][0] - == "Given the context please answer the question. Context: My name is Carla and I live in Berlin; " - "Question: Who lives in Berlin?; Answer:" - ) - - -@pytest.mark.skip -@pytest.mark.integration -def test_complex_pipeline_with_shared_model(): - # TODO: What is this testing? Can this be a unit test? - model = PromptModel() - node = PromptNode(model_name_or_path=model, default_prompt_template="question-generation", output_variable="query") - node2 = PromptNode(model_name_or_path=model, default_prompt_template="question-answering-per-document") - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - pipe.add_node(component=node2, name="prompt_node_2", inputs=["prompt_node"]) - result = pipe.run(query="not relevant", documents=[Document("Berlin is the capital of Germany")]) - - assert result["answers"][0].answer == "Berlin" - - -@pytest.mark.skip -@pytest.mark.integration -def test_simple_pipeline_yaml(tmp_path): - # TODO: This can be a unit test just to verify that loading - # PromptNode from yaml creates a correctly runnable Pipeline. - # Also it could probably be renamed to test_prompt_node_yaml_loading - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: p1 - params: - default_prompt_template: sentiment-analysis - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(query="not relevant", documents=[Document("Berlin is an amazing city.")]) - assert result["results"][0] == "positive" - - -@pytest.mark.skip -@pytest.mark.integration -def test_simple_pipeline_yaml_with_default_params(tmp_path): - # TODO: Is this testing yaml loading? - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: p1 - type: PromptNode - params: - default_prompt_template: sentiment-analysis - model_kwargs: - torch_dtype: torch.bfloat16 - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert pipeline.graph.nodes["p1"]["component"].prompt_model.model_kwargs == {"torch_dtype": "torch.bfloat16"} - - result = pipeline.run(query=None, documents=[Document("Berlin is an amazing city.")]) - assert result["results"][0] == "positive" - - -@pytest.mark.skip -@pytest.mark.integration -def test_complex_pipeline_yaml(tmp_path): - # TODO: Is this testing PromptNode or Pipeline? - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: p1 - params: - default_prompt_template: question-generation - output_variable: query - type: PromptNode - - name: p2 - params: - default_prompt_template: question-answering-per-document - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - - name: p2 - inputs: - - p1 - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(query="not relevant", documents=[Document("Berlin is an amazing city.")]) - response = result["answers"][0].answer - assert any(word for word in ["berlin", "germany", "population", "city", "amazing"] if word in response.casefold()) - assert len(result["invocation_context"]) > 0 - assert len(result["query"]) > 0 - assert "query" in result["invocation_context"] and len(result["invocation_context"]["query"]) > 0 - - -@pytest.mark.skip -@pytest.mark.integration -def test_complex_pipeline_with_shared_prompt_model_yaml(tmp_path): - # TODO: Is this similar to test_complex_pipeline_with_shared_model? - # Why are we testing this two times? - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: pmodel - type: PromptModel - - name: p1 - params: - model_name_or_path: pmodel - default_prompt_template: question-generation - output_variable: query - type: PromptNode - - name: p2 - params: - model_name_or_path: pmodel - default_prompt_template: question-answering-per-document - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - - name: p2 - inputs: - - p1 - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - result = pipeline.run(query="not relevant", documents=[Document("Berlin is an amazing city.")]) - response = result["answers"][0].answer - assert any(word for word in ["berlin", "germany", "population", "city", "amazing"] if word in response.casefold()) - assert len(result["invocation_context"]) > 0 - assert len(result["query"]) > 0 - assert "query" in result["invocation_context"] and len(result["invocation_context"]["query"]) > 0 - - -@pytest.mark.skip -@pytest.mark.integration -def test_complex_pipeline_with_shared_prompt_model_and_prompt_template_yaml(tmp_path): - # TODO: Is this testing PromptNode or Pipeline parsing? - with open(tmp_path / "tmp_config_with_prompt_template.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: pmodel - type: PromptModel - params: - model_name_or_path: google/flan-t5-small - model_kwargs: - torch_dtype: auto - - name: question_generation_template - type: PromptTemplate - params: - prompt: "Given the context please generate a question. Context: {{documents}}; Question:" - - name: p1 - params: - model_name_or_path: pmodel - default_prompt_template: question_generation_template - output_variable: query - type: PromptNode - - name: p2 - params: - model_name_or_path: pmodel - default_prompt_template: question-answering-per-document - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - - name: p2 - inputs: - - p1 - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config_with_prompt_template.yml") - result = pipeline.run(query="not relevant", documents=[Document("Berlin is an amazing city.")]) - response = result["answers"][0].answer - assert any(word for word in ["berlin", "germany", "population", "city", "amazing"] if word in response.casefold()) - assert len(result["invocation_context"]) > 0 - assert len(result["query"]) > 0 - assert "query" in result["invocation_context"] and len(result["invocation_context"]["query"]) > 0 - - -@pytest.mark.skip -@pytest.mark.integration -def test_complex_pipeline_with_with_dummy_node_between_prompt_nodes_yaml(tmp_path): - # TODO: This can be a unit test. Is it necessary though? Is it testing PromptNode? - # test that we can stick some random node in between prompt nodes and that everything still works - # most specifically, we want to ensure that invocation_context is still populated correctly and propagated - class InBetweenNode(BaseComponent): - outgoing_edges = 1 - - def run( - self, - query: Optional[str] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[MultiLabel] = None, - documents: Optional[List[Document]] = None, - meta: Optional[dict] = None, - ) -> Tuple[Dict, str]: - return {}, "output_1" - - def run_batch( - self, - queries: Optional[Union[str, List[str]]] = None, - file_paths: Optional[List[str]] = None, - labels: Optional[Union[MultiLabel, List[MultiLabel]]] = None, - documents: Optional[Union[List[Document], List[List[Document]]]] = None, - meta: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, - params: Optional[dict] = None, - debug: Optional[bool] = None, - ): - return {}, "output_1" - - with open(tmp_path / "tmp_config_with_prompt_template.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: in_between - type: InBetweenNode - - name: pmodel - type: PromptModel - params: - model_name_or_path: google/flan-t5-small - model_kwargs: - torch_dtype: torch.bfloat16 - - name: question_generation_template - type: PromptTemplate - params: - prompt: "Given the context please generate a question. Context: {{documents}}; Question:" - - name: p1 - params: - model_name_or_path: pmodel - default_prompt_template: question_generation_template - output_variable: query - type: PromptNode - - name: p2 - params: - model_name_or_path: pmodel - default_prompt_template: question-answering-per-document - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - - name: in_between - inputs: - - p1 - - name: p2 - inputs: - - in_between - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config_with_prompt_template.yml") - result = pipeline.run(query="not relevant", documents=[Document("Berlin is an amazing city.")]) - response = result["answers"][0].answer - assert any(word for word in ["berlin", "germany", "population", "city", "amazing"] if word in response.casefold()) - assert len(result["invocation_context"]) > 0 - assert len(result["query"]) > 0 - assert "query" in result["invocation_context"] and len(result["invocation_context"]["query"]) > 0 - - -@pytest.mark.skip -@pytest.mark.parametrize("haystack_openai_config", ["openai", "azure"], indirect=True) -def test_complex_pipeline_with_all_features(tmp_path, haystack_openai_config): - # TODO: Is this testing PromptNode or pipeline yaml parsing? - if not haystack_openai_config: - pytest.skip("No API key found, skipping test") - - if "azure_base_url" in haystack_openai_config: - # don't change this indentation, it's important for the yaml to be valid - azure_conf_yaml_snippet = f""" - azure_base_url: {haystack_openai_config['azure_base_url']} - azure_deployment_name: {haystack_openai_config['azure_deployment_name']} - """ - else: - azure_conf_yaml_snippet = "" - with open(tmp_path / "tmp_config_with_prompt_template.yml", "w") as tmp_file: - tmp_file.write( - f""" - version: ignore - components: - - name: pmodel - type: PromptModel - params: - model_name_or_path: google/flan-t5-small - model_kwargs: - torch_dtype: torch.bfloat16 - - name: pmodel_openai - type: PromptModel - params: - model_name_or_path: text-davinci-003 - model_kwargs: - temperature: 0.9 - max_tokens: 64 - {azure_conf_yaml_snippet} - api_key: {haystack_openai_config["api_key"]} - - name: question_generation_template - type: PromptTemplate - params: - prompt: "Given the context please generate a question. Context: {{documents}}; Question:" - - name: p1 - params: - model_name_or_path: pmodel_openai - default_prompt_template: question_generation_template - output_variable: query - type: PromptNode - - name: p2 - params: - model_name_or_path: pmodel - default_prompt_template: question-answering-per-document - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - - name: p2 - inputs: - - p1 - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config_with_prompt_template.yml") - result = pipeline.run(query="not relevant", documents=[Document("Berlin is a city in Germany.")]) - response = result["answers"][0].answer - assert any(word for word in ["berlin", "germany", "population", "city", "amazing"] if word in response.casefold()) - assert len(result["invocation_context"]) > 0 - assert len(result["query"]) > 0 - assert "query" in result["invocation_context"] and len(result["invocation_context"]["query"]) > 0 - - -@pytest.mark.skip -@pytest.mark.integration -def test_complex_pipeline_with_multiple_same_prompt_node_components_yaml(tmp_path): - # TODO: Can this become a unit test? Is it actually worth as a test? - # p2 and p3 are essentially the same PromptNode component, make sure we can use them both as is in the pipeline - with open(tmp_path / "tmp_config.yml", "w") as tmp_file: - tmp_file.write( - """ - version: ignore - components: - - name: p1 - params: - default_prompt_template: question-generation - type: PromptNode - - name: p2 - params: - default_prompt_template: question-answering-per-document - type: PromptNode - - name: p3 - params: - default_prompt_template: question-answering-per-document - type: PromptNode - pipelines: - - name: query - nodes: - - name: p1 - inputs: - - Query - - name: p2 - inputs: - - p1 - - name: p3 - inputs: - - p2 - """ - ) - pipeline = Pipeline.load_from_yaml(path=tmp_path / "tmp_config.yml") - assert pipeline is not None - - -@pytest.mark.integration -def test_hf_token_limit_warning(caplog): - prompt = "Repeating text" * 200 + "Docs: Berlin is an amazing city.; Answer:" - with caplog.at_level(logging.WARNING): - node = PromptNode("google/flan-t5-small", devices=["cpu"]) - _ = node.prompt_model._ensure_token_limit(prompt=prompt) - assert "The prompt has been truncated from 812 tokens to 412 tokens" in caplog.text - assert "and answer length (100 tokens) fit within the max token limit (512 tokens)." in caplog.text - - -class TestRunBatch: - @pytest.mark.skip(reason="Skipped as test is extremely flaky") - @pytest.mark.integration - @pytest.mark.parametrize("prompt_model", ["hf", "openai", "azure"], indirect=True) - def test_simple_pipeline_batch_no_query_single_doc_list(self, prompt_model): - skip_test_for_invalid_key(prompt_model) - - node = PromptNode( - prompt_model, - default_prompt_template="Please give a sentiment for this context. Answer with positive, negative or neutral. Context: {documents}; Answer:", - ) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run_batch( - queries=None, documents=[Document("Berlin is an amazing city."), Document("I am not feeling well.")] - ) - assert isinstance(result["results"], list) - assert isinstance(result["results"][0], list) - assert isinstance(result["results"][0][0], str) - assert "positive" in result["results"][0][0].casefold() - assert "negative" in result["results"][1][0].casefold() - - @pytest.mark.integration - @pytest.mark.parametrize("prompt_model", ["hf", "openai", "azure"], indirect=True) - def test_simple_pipeline_batch_no_query_multiple_doc_list(self, prompt_model): - skip_test_for_invalid_key(prompt_model) - - node = PromptNode( - prompt_model, - default_prompt_template="Please give a sentiment for this context. Answer with positive, negative or neutral. Context: {documents}; Answer:", - output_variable="out", - ) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run_batch( - queries=None, - documents=[ - [Document("Berlin is an amazing city."), Document("Paris is an amazing city.")], - [Document("I am not feeling well.")], - ], - ) - assert isinstance(result["out"], list) - assert isinstance(result["out"][0], list) - assert isinstance(result["out"][0][0], str) - assert all("positive" in x.casefold() for x in result["out"][0]) - assert "negative" in result["out"][1][0].casefold() - - @pytest.mark.integration - @pytest.mark.parametrize("prompt_model", ["hf", "openai", "azure"], indirect=True) - def test_simple_pipeline_batch_query_multiple_doc_list(self, prompt_model): - skip_test_for_invalid_key(prompt_model) - - prompt_template = PromptTemplate( - "Given the context please answer the question. Context: {documents}; Question: {query}; Answer:" - ) - node = PromptNode(prompt_model, default_prompt_template=prompt_template) - - pipe = Pipeline() - pipe.add_node(component=node, name="prompt_node", inputs=["Query"]) - result = pipe.run_batch( - queries=["Who lives in Berlin?"], - documents=[ - [Document("My name is Carla and I live in Berlin"), Document("My name is James and I live in London")], - [Document("My name is Christelle and I live in Paris")], - ], - debug=True, - ) - assert isinstance(result["results"], list) - assert isinstance(result["results"][0], list) - assert isinstance(result["results"][0][0], str) - - -@pytest.mark.skip -@pytest.mark.integration -def test_chatgpt_direct_prompting(chatgpt_prompt_model): - # TODO: This is testing ChatGPT, should be removed - skip_test_for_invalid_key(chatgpt_prompt_model) - pn = PromptNode(chatgpt_prompt_model) - result = pn("Hey, I need some Python help. When should I use list comprehension?") - assert len(result) == 1 and all(w in result[0] for w in ["comprehension", "list"]) - - -@pytest.mark.skip -@pytest.mark.integration -def test_chatgpt_direct_prompting_w_messages(chatgpt_prompt_model): - # TODO: This is a ChatGPTInvocationLayer unit test - skip_test_for_invalid_key(chatgpt_prompt_model) - pn = PromptNode(chatgpt_prompt_model) - - messages = [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "Who won the world series in 2020?"}, - {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, - {"role": "user", "content": "Where was it played?"}, - ] - - result = pn(messages) - assert len(result) == 1 and all(w in result[0].casefold() for w in ["arlington", "texas"]) - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.open_ai.load_openai_tokenizer", lambda tokenizer_name: None) -@patch("haystack.nodes.prompt.prompt_model.PromptModel._ensure_token_limit", lambda self, prompt: prompt) -def test_content_moderation_gpt_3(): - """ - Check all possible cases of the moderation checks passing / failing in a PromptNode uses - OpenAIInvocationLayer. - """ - prompt_node = PromptNode( - model_name_or_path="text-davinci-003", api_key="key", model_kwargs={"moderate_content": True} - ) - with patch("haystack.nodes.prompt.invocation_layer.open_ai.check_openai_policy_violation") as mock_check, patch( - "haystack.nodes.prompt.invocation_layer.open_ai.openai_request" - ) as mock_request: - VIOLENT_TEXT = "some violent text" - mock_check.side_effect = lambda input, headers: input == VIOLENT_TEXT or input == [VIOLENT_TEXT] - # case 1: prompt fails the moderation check - # prompt should not be sent to OpenAi & function should return an empty list - mock_check.return_value = True - assert prompt_node(VIOLENT_TEXT) == [] - # case 2: prompt passes the moderation check but the generated output fails the check - # function should also return an empty list - mock_request.return_value = {"choices": [{"text": VIOLENT_TEXT, "finish_reason": ""}]} - assert prompt_node("normal prompt") == [] - # case 3: both prompt and output pass the moderation check - # function should return the output - mock_request.return_value = {"choices": [{"text": "normal output", "finish_reason": ""}]} - assert prompt_node("normal prompt") == ["normal output"] - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.invocation_layer.open_ai.load_openai_tokenizer", lambda tokenizer_name: None) -@patch("haystack.nodes.prompt.prompt_model.PromptModel._ensure_token_limit", lambda self, prompt: prompt) -def test_content_moderation_gpt_35(): - """ - Check all possible cases of the moderation checks passing / failing in a PromptNode uses - ChatGPTInvocationLayer. - """ - prompt_node = PromptNode(model_name_or_path="gpt-3.5-turbo", api_key="key", model_kwargs={"moderate_content": True}) - with patch("haystack.nodes.prompt.invocation_layer.chatgpt.check_openai_policy_violation") as mock_check, patch( - "haystack.nodes.prompt.invocation_layer.chatgpt.openai_request" - ) as mock_request: - VIOLENT_TEXT = "some violent text" - mock_check.side_effect = lambda input, headers: input == VIOLENT_TEXT or input == [VIOLENT_TEXT] - # case 1: prompt fails the moderation check - # prompt should not be sent to OpenAi & function should return an empty list - mock_check.return_value = True - assert prompt_node(VIOLENT_TEXT) == [] - # case 2: prompt passes the moderation check but the generated output fails the check - # function should also return an empty list - mock_request.return_value = { - "choices": [{"message": {"content": VIOLENT_TEXT, "role": "assistant"}, "finish_reason": ""}] - } - assert prompt_node("normal prompt") == [] - # case 3: both prompt and output pass the moderation check - # function should return the output - mock_request.return_value = { - "choices": [{"message": {"content": "normal output", "role": "assistant"}, "finish_reason": ""}] - } - assert prompt_node("normal prompt") == ["normal output"] - - -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_prompt_node_warns_about_missing_documents(mock_model, caplog): - lfqa_prompt = PromptTemplate( - prompt="""Synthesize a comprehensive answer from the following text for the given question. - Provide a clear and concise response that summarizes the key points and information presented in the text. - Your answer should be in your own words and be no longer than 50 words. - If answer is not in .text. say i dont know. - \n\n Related text: {join(documents)} \n\n Question: {query} \n\n Answer:""" - ) - prompt_node = PromptNode(default_prompt_template=lfqa_prompt) - - with caplog.at_level(logging.WARNING): - results, _ = prompt_node.run(query="non-matching query") - assert ( - "Expected prompt parameter 'documents' to be provided but it is missing. " - "Continuing with an empty list of documents." in caplog.text - ) - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test__prepare_invocation_context_is_empty(mock_model): - node = PromptNode() - node.get_prompt_template = MagicMock(return_value="Test Template") - - kwargs = { - "query": "query", - "file_paths": ["foo", "bar"], - "labels": ["label", "another"], - "documents": ["A", "B"], - "meta": {"meta_key": "meta_value"}, - "prompt_template": "my-test-prompt", - "invocation_context": None, - "generation_kwargs": {"gen_key": "gen_value"}, - } - - invocation_context = node._prepare(**kwargs) - - node.get_prompt_template.assert_called_once_with("my-test-prompt") - assert invocation_context == { - "query": "query", - "file_paths": ["foo", "bar"], - "labels": ["label", "another"], - "documents": ["A", "B"], - "meta": {"meta_key": "meta_value"}, - "prompt_template": "Test Template", - "gen_key": "gen_value", - } - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test__prepare_invocation_context_was_passed(mock_model): - node = PromptNode() - - # Test invocation_context is left untouched - invocation_context = { - "query": "query", - "file_paths": ["foo", "bar"], - "labels": ["label", "another"], - "documents": ["A", "B"], - "meta": {"meta_key": "meta_value"}, - "prompt_template": "my-test-prompt", - "invocation_context": None, - } - kwargs = { - "query": None, - "file_paths": None, - "labels": None, - "documents": None, - "meta": None, - "prompt_template": None, - "invocation_context": invocation_context, - "generation_kwargs": None, - } - - assert node._prepare(**kwargs) == invocation_context - - -@pytest.mark.unit -@pytest.mark.asyncio -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -async def test_arun(mock_model): - node = PromptNode() - node._aprompt = AsyncMock() - await node.arun("a query") - node._aprompt.assert_awaited_once_with(prompt_collector=[], query="a query", prompt_template=None) - - -@pytest.mark.unit -@pytest.mark.asyncio -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -async def test_aprompt(mock_model): - node = PromptNode() - mock_model.return_value.ainvoke = AsyncMock() - await node._aprompt(PromptTemplate("test template")) - mock_model.return_value.ainvoke.assert_awaited_once() diff --git a/test/prompt/test_prompt_template.py b/test/prompt/test_prompt_template.py deleted file mode 100644 index 71180b08aa..0000000000 --- a/test/prompt/test_prompt_template.py +++ /dev/null @@ -1,494 +0,0 @@ -from typing import Set, Type, List -import textwrap -import os -from unittest.mock import patch, MagicMock - -import pytest -import prompthub - -from haystack.nodes.prompt import PromptTemplate -from haystack.nodes.prompt.prompt_node import PromptNode -from haystack.nodes.prompt.prompt_template import PromptTemplateValidationError, LEGACY_DEFAULT_TEMPLATES -from haystack.nodes.prompt import prompt_template -from haystack.nodes.prompt.shapers import AnswerParser -from haystack.pipelines.base import Pipeline -from haystack.schema import Answer, Document - - -@pytest.fixture -def enable_prompthub_cache(monkeypatch): - monkeypatch.setenv("PROMPTHUB_CACHE_ENABLED", True) - - -@pytest.fixture -def prompthub_cache_path(monkeypatch, tmp_path): - cache_path = tmp_path / "cache" - monkeypatch.setattr(prompt_template, "PROMPTHUB_CACHE_PATH", cache_path) - yield cache_path - - -@pytest.fixture -def mock_prompthub(): - with patch("haystack.nodes.prompt.prompt_template.fetch_from_prompthub") as mock_prompthub: - mock_prompthub.return_value = prompthub.Prompt( - name="deepset/test-prompt", - tags=["test"], - meta={"author": "test"}, - version="v0.0.0", - text="This is a test prompt. Use your knowledge to answer this question: {question}", - description="test prompt", - ) - yield mock_prompthub - - -@pytest.mark.unit -def test_prompt_templates_from_hub(): - with patch("haystack.nodes.prompt.prompt_template.prompthub") as mock_prompthub: - PromptTemplate("deepset/question-answering") - mock_prompthub.fetch.assert_called_with("deepset/question-answering", timeout=30) - - -@pytest.mark.unit -def test_prompt_templates_from_hub_prompts_are_cached(prompthub_cache_path, enable_prompthub_cache, mock_prompthub): - PromptTemplate("deepset/test-prompt") - assert (prompthub_cache_path / "deepset" / "test-prompt.yml").exists() - - -@pytest.mark.unit -def test_prompt_templates_from_hub_prompts_are_not_cached_if_disabled(prompthub_cache_path, mock_prompthub): - PromptTemplate("deepset/test-prompt") - assert not (prompthub_cache_path / "deepset" / "test-prompt.yml").exists() - - -@pytest.mark.unit -def test_prompt_templates_from_hub_cached_prompts_are_used( - prompthub_cache_path, enable_prompthub_cache, mock_prompthub -): - test_path = prompthub_cache_path / "deepset" / "another-test.yml" - test_path.parent.mkdir(parents=True, exist_ok=True) - data = prompthub.Prompt( - name="deepset/another-test", - text="this is the prompt text", - description="test prompt description", - tags=["another-test"], - meta={"authors": ["vblagoje"]}, - version="v0.1.1", - ) - data.to_yaml(test_path) - - template = PromptTemplate("deepset/another-test") - mock_prompthub.fetch.assert_not_called() - assert template.prompt_text == "this is the prompt text" - - -@pytest.mark.unit -def test_prompt_templates_from_legacy_set(mock_prompthub): - p = PromptTemplate("question-answering") - assert p.name == "question-answering" - assert p.prompt_text == LEGACY_DEFAULT_TEMPLATES["question-answering"]["prompt"] - mock_prompthub.assert_not_called() - - -@pytest.mark.unit -def test_prompt_templates_from_file(tmp_path): - path = tmp_path / "test-prompt.yml" - with open(path, "a") as yamlfile: - yamlfile.write( - textwrap.dedent( - """ - name: deepset/question-answering - text: | - Given the context please answer the question. Context: {join(documents)}; - Question: {query}; - Answer: - description: A simple prompt to answer a question given a set of documents - tags: - - question-answering - meta: - authors: - - vblagoje - version: v0.1.1 - """ - ) - ) - p = PromptTemplate(str(path.absolute())) - assert p.name == "deepset/question-answering" - assert "Given the context please answer the question" in p.prompt_text - - -@pytest.mark.unit -def test_prompt_templates_on_the_fly(): - with patch("haystack.nodes.prompt.prompt_template.yaml") as mocked_yaml, patch( - "haystack.nodes.prompt.prompt_template.prompthub" - ) as mocked_ph: - p = PromptTemplate("This is a test prompt. Use your knowledge to answer this question: {question}") - assert p.name == "custom-at-query-time" - mocked_ph.fetch.assert_not_called() - mocked_yaml.safe_load.assert_not_called() - - -@pytest.mark.unit -def test_custom_prompt_templates(): - p = PromptTemplate("Here is some fake template with variable {foo}") - assert set(p.prompt_params) == {"foo"} - - p = PromptTemplate("Here is some fake template with variable {foo} and {bar}") - assert set(p.prompt_params) == {"foo", "bar"} - - p = PromptTemplate("Here is some fake template with variable {foo1} and {bar2}") - assert set(p.prompt_params) == {"foo1", "bar2"} - - p = PromptTemplate("Here is some fake template with variable {foo_1} and {bar_2}") - assert set(p.prompt_params) == {"foo_1", "bar_2"} - - p = PromptTemplate("Here is some fake template with variable {Foo_1} and {Bar_2}") - assert set(p.prompt_params) == {"Foo_1", "Bar_2"} - - p = PromptTemplate("'Here is some fake template with variable {baz}'") - assert set(p.prompt_params) == {"baz"} - # strip single quotes, happens in YAML as we need to use single quotes for the template string - assert p.prompt_text == "Here is some fake template with variable {baz}" - - p = PromptTemplate('"Here is some fake template with variable {baz}"') - assert set(p.prompt_params) == {"baz"} - # strip double quotes, happens in YAML as we need to use single quotes for the template string - assert p.prompt_text == "Here is some fake template with variable {baz}" - - -@pytest.mark.unit -def test_missing_prompt_template_params(): - template = PromptTemplate("Here is some fake template with variable {foo} and {bar}") - - # both params provided - ok - template.prepare(foo="foo", bar="bar") - - # missing one param - with pytest.raises(ValueError, match=r".*parameters \['bar', 'foo'\] to be provided but got only \['foo'\].*"): - template.prepare(foo="foo") - - # missing both params - with pytest.raises( - ValueError, match=r".*parameters \['bar', 'foo'\] to be provided but got none of these parameters.*" - ): - template.prepare(lets="go") - - # more than both params provided - also ok - template.prepare(foo="foo", bar="bar", lets="go") - - -@pytest.mark.unit -def test_prompt_template_repr(): - p = PromptTemplate("Here is variable {baz}") - desired_repr = ( - "PromptTemplate(name=custom-at-query-time, prompt_text=Here is variable {baz}, prompt_params=['baz'])" - ) - assert repr(p) == desired_repr - assert str(p) == desired_repr - - -@pytest.mark.unit -@patch("haystack.nodes.prompt.prompt_node.PromptModel") -def test_prompt_template_deserialization(mock_prompt_model): - custom_prompt_template = PromptTemplate( - "Given the context please answer the question. Context: {context}; Question: {query}; Answer:", - output_parser=AnswerParser(), - ) - - prompt_node = PromptNode(default_prompt_template=custom_prompt_template) - - pipe = Pipeline() - pipe.add_node(component=prompt_node, name="Generator", inputs=["Query"]) - - config = pipe.get_config() - loaded_pipe = Pipeline.load_from_config(config) - - loaded_generator = loaded_pipe.get_node("Generator") - assert isinstance(loaded_generator, PromptNode) - assert isinstance(loaded_generator.default_prompt_template, PromptTemplate) - assert ( - loaded_generator.default_prompt_template.prompt_text - == "Given the context please answer the question. Context: {context}; Question: {query}; Answer:" - ) - assert isinstance(loaded_generator.default_prompt_template.output_parser, AnswerParser) - - -@pytest.mark.unit -def test_prompt_template_fills_in_missing_documents(): - lfqa_prompt = PromptTemplate( - prompt="""Synthesize a comprehensive answer from the following text for the given question. - Provide a clear and concise response that summarizes the key points and information presented in the text. - Your answer should be in your own words and be no longer than 50 words. - If answer is not in .text. say i dont know. - \n\n Related text: {join(documents)} \n\n Question: {query} \n\n Answer:""" - ) - prepared_prompt = next(lfqa_prompt.fill(query="What is the meaning of life?")) # no documents provided but expected - assert "Related text: \n\n Question: What is the meaning of life?" in prepared_prompt - - -class TestPromptTemplateSyntax: - @pytest.mark.unit - @pytest.mark.parametrize( - "prompt_text, expected_prompt_params, expected_used_functions", - [ - ("{documents}", {"documents"}, set()), - ("Please answer the question: {documents} Question: how?", {"documents"}, set()), - ("Please answer the question: {documents} Question: {query}", {"documents", "query"}, set()), - ("Please answer the question: {documents} {{Question}}: {query}", {"documents", "query"}, set()), - ( - "Please answer the question: {join(documents)} Question: {query.replace('A', 'a')}", - {"documents", "query"}, - {"join", "replace"}, - ), - ( - "Please answer the question: {join(documents, 'delim', {'{': '('})} Question: {query.replace('A', 'a')}", - {"documents", "query"}, - {"join", "replace"}, - ), - ( - 'Please answer the question: {join(documents, "delim", {"{": "("})} Question: {query.replace("A", "a")}', - {"documents", "query"}, - {"join", "replace"}, - ), - ( - "Please answer the question: {join(documents, 'delim', {'a': {'b': 'c'}})} Question: {query.replace('A', 'a')}", - {"documents", "query"}, - {"join", "replace"}, - ), - ( - "Please answer the question: {join(document=documents, delimiter='delim', str_replace={'{': '('})} Question: {query.replace('A', 'a')}", - {"documents", "query"}, - {"join", "replace"}, - ), - ], - ) - def test_prompt_template_syntax_parser( - self, prompt_text: str, expected_prompt_params: Set[str], expected_used_functions: Set[str] - ): - prompt_template = PromptTemplate(prompt_text) - assert set(prompt_template.prompt_params) == expected_prompt_params - assert set(prompt_template._used_functions) == expected_used_functions - - @pytest.mark.unit - @pytest.mark.parametrize( - "prompt_text, documents, query, expected_prompts", - [ - ("{documents}", [Document("doc1"), Document("doc2")], None, ["doc1", "doc2"]), - ( - "context: {documents} question: how?", - [Document("doc1"), Document("doc2")], - None, - ["context: doc1 question: how?", "context: doc2 question: how?"], - ), - ( - "context: {' '.join([d.content for d in documents])} question: how?", - [Document("doc1"), Document("doc2")], - None, - ["context: doc1 doc2 question: how?"], - ), - ( - "context: {documents} question: {query}", - [Document("doc1"), Document("doc2")], - "how?", - ["context: doc1 question: how?", "context: doc2 question: how?"], - ), - ( - "context: {documents} {{question}}: {query}", - [Document("doc1")], - "how?", - ["context: doc1 {question}: how?"], - ), - ( - "context: {join(documents)} question: {query}", - [Document("doc1"), Document("doc2")], - "how?", - ["context: doc1 doc2 question: how?"], - ), - ( - "Please answer the question: {join(documents, ' delim ', '[$idx] $content', {'{': '('})} question: {query}", - [Document("doc1"), Document("doc2")], - "how?", - ["Please answer the question: [1] doc1 delim [2] doc2 question: how?"], - ), - ( - "Please answer the question: {join(documents=documents, delimiter=' delim ', pattern='[$idx] $content', str_replace={'{': '('})} question: {query}", - [Document("doc1"), Document("doc2")], - "how?", - ["Please answer the question: [1] doc1 delim [2] doc2 question: how?"], - ), - ( - "Please answer the question: {' delim '.join(['['+str(idx+1)+'] '+d.content.replace('{', '(') for idx, d in enumerate(documents)])} question: {query}", - [Document("doc1"), Document("doc2")], - "how?", - ["Please answer the question: [1] doc1 delim [2] doc2 question: how?"], - ), - ( - 'Please answer the question: {join(documents, " delim ", "[$idx] $content", {"{": "("})} question: {query}', - [Document("doc1"), Document("doc2")], - "how?", - ["Please answer the question: [1] doc1 delim [2] doc2 question: how?"], - ), - ( - "context: {join(documents)} question: {query.replace('how', 'what')}", - [Document("doc1"), Document("doc2")], - "how?", - ["context: doc1 doc2 question: what?"], - ), - ( - "context: {join(documents)[:6]} question: {query.replace('how', 'what').replace('?', '!')}", - [Document("doc1"), Document("doc2")], - "how?", - ["context: doc1 d question: what!"], - ), - ("context: ", None, None, ["context: "]), - ], - ) - def test_prompt_template_syntax_fill( - self, prompt_text: str, documents: List[Document], query: str, expected_prompts: List[str] - ): - prompt_template = PromptTemplate(prompt_text) - prompts = list(prompt_template.fill(documents=documents, query=query)) - assert prompts == expected_prompts - - @pytest.mark.unit - @pytest.mark.parametrize( - "prompt_text, documents, expected_prompts", - [ - ("{join(documents)}", [Document("doc1"), Document("doc2")], ["doc1 doc2"]), - ( - "{join(documents, ' delim ', '[$idx] $content', {'c': 'C'})}", - [Document("doc1"), Document("doc2")], - ["[1] doC1 delim [2] doC2"], - ), - ( - "{join(documents, ' delim ', '[$id] $content', {'c': 'C'})}", - [Document("doc1", id="123"), Document("doc2", id="456")], - ["[123] doC1 delim [456] doC2"], - ), - ( - "{join(documents, ' delim ', '[$file_id] $content', {'c': 'C'})}", - [Document("doc1", meta={"file_id": "123.txt"}), Document("doc2", meta={"file_id": "456.txt"})], - ["[123.txt] doC1 delim [456.txt] doC2"], - ), - ], - ) - def test_join(self, prompt_text: str, documents: List[Document], expected_prompts: List[str]): - prompt_template = PromptTemplate(prompt_text) - prompts = list(prompt_template.fill(documents=documents)) - assert prompts == expected_prompts - - @pytest.mark.unit - @pytest.mark.parametrize( - "prompt_text, documents, expected_prompts", - [ - ("{to_strings(documents)}", [Document("doc1"), Document("doc2")], ["doc1", "doc2"]), - ( - "{to_strings(documents, '[$idx] $content', {'c': 'C'})}", - [Document("doc1"), Document("doc2")], - ["[1] doC1", "[2] doC2"], - ), - ( - "{to_strings(documents, '[$id] $content', {'c': 'C'})}", - [Document("doc1", id="123"), Document("doc2", id="456")], - ["[123] doC1", "[456] doC2"], - ), - ( - "{to_strings(documents, '[$file_id] $content', {'c': 'C'})}", - [Document("doc1", meta={"file_id": "123.txt"}), Document("doc2", meta={"file_id": "456.txt"})], - ["[123.txt] doC1", "[456.txt] doC2"], - ), - ("{to_strings(documents, '[$file_id] $content', {'c': 'C'})}", ["doc1", "doc2"], ["doC1", "doC2"]), - ( - "{to_strings(documents, '[$idx] $answer', {'c': 'C'})}", - [Answer("doc1"), Answer("doc2")], - ["[1] doC1", "[2] doC2"], - ), - ], - ) - def test_to_strings(self, prompt_text: str, documents: List[Document], expected_prompts: List[str]): - prompt_template = PromptTemplate(prompt_text) - prompts = list(prompt_template.fill(documents=documents)) - assert prompts == expected_prompts - - @pytest.mark.unit - @pytest.mark.parametrize( - "prompt_text, exc_type, expected_exc_match", - [ - ("{__import__('os').listdir('.')}", PromptTemplateValidationError, "Invalid function in prompt text"), - ("{__import__('os')}", PromptTemplateValidationError, "Invalid function in prompt text"), - ( - "{requests.get('https://haystack.deepset.ai/')}", - PromptTemplateValidationError, - "Invalid function in prompt text", - ), - ("{join(__import__('os').listdir('.'))}", PromptTemplateValidationError, "Invalid function in prompt text"), - ("{for}", SyntaxError, "invalid syntax"), - ("This is an invalid {variable .", SyntaxError, "f-string: expecting '}'"), - ], - ) - def test_prompt_template_syntax_init_raises( - self, prompt_text: str, exc_type: Type[BaseException], expected_exc_match: str - ): - with pytest.raises(exc_type, match=expected_exc_match): - PromptTemplate(prompt_text) - - @pytest.mark.unit - @pytest.mark.parametrize( - "prompt_text, documents, query, exc_type, expected_exc_match", - [("{join}", None, None, ValueError, "Expected prompt parameters")], - ) - def test_prompt_template_syntax_fill_raises( - self, - prompt_text: str, - documents: List[Document], - query: str, - exc_type: Type[BaseException], - expected_exc_match: str, - ): - with pytest.raises(exc_type, match=expected_exc_match): - prompt_template = PromptTemplate(prompt_text) - next(prompt_template.fill(documents=documents, query=query)) - - @pytest.mark.unit - @pytest.mark.parametrize( - "prompt_text, documents, query, expected_prompts", - [ - ("__import__('os').listdir('.')", None, None, ["__import__('os').listdir('.')"]), - ( - "requests.get('https://haystack.deepset.ai/')", - None, - None, - ["requests.get('https://haystack.deepset.ai/')"], - ), - ("{query}", None, print, [""]), - ("\b\b__import__('os').listdir('.')", None, None, ["\x08\x08__import__('os').listdir('.')"]), - ], - ) - def test_prompt_template_syntax_fill_ignores_dangerous_input( - self, prompt_text: str, documents: List[Document], query: str, expected_prompts: List[str] - ): - prompt_template = PromptTemplate(prompt_text) - prompts = list(prompt_template.fill(documents=documents, query=query)) - assert prompts == expected_prompts - - def test_prompt_template_remove_template_params(self): - kwargs = {"query": "query", "documents": "documents", "other": "other"} - expected_kwargs = {"other": "other"} - prompt_text = "Here is prompt text with two variables that are also in kwargs: {query} and {documents}" - prompt_template = PromptTemplate(prompt_text) - assert prompt_template.remove_template_params(kwargs) == expected_kwargs - - def test_prompt_template_remove_template_params_edge_cases(self): - """ - Test that the function works with a variety of edge cases - """ - kwargs = {"query": "query", "documents": "documents"} - prompt_text = "Here is prompt text with two variables that are also in kwargs: {query} and {documents}" - prompt_template = PromptTemplate(prompt_text) - assert prompt_template.remove_template_params(kwargs) == {} - - assert prompt_template.remove_template_params({}) == {} - - assert prompt_template.remove_template_params(None) == {} - - totally_unrelated = {"totally_unrelated": "totally_unrelated"} - assert prompt_template.remove_template_params(totally_unrelated) == totally_unrelated diff --git a/test/utils/__init__.py b/test/utils/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/utils/test_deepset_cloud.py b/test/utils/test_deepset_cloud.py deleted file mode 100644 index e4951a1fcf..0000000000 --- a/test/utils/test_deepset_cloud.py +++ /dev/null @@ -1,70 +0,0 @@ -import json -from pathlib import Path -from typing import Any, Dict -from unittest.mock import Mock - -import pytest -import yaml - -from haystack.utils.deepsetcloud import DeepsetCloudClient, PipelineClient - - -@pytest.fixture -def pipeline_config(samples_path: Path) -> Dict[str, Any]: - with (samples_path / "dc" / "pipeline_config.json").open() as f: - return json.load(f) - - -@pytest.fixture() -def mocked_client() -> Mock: - api_client = Mock(spec=DeepsetCloudClient) - - api_client.build_workspace_url.return_value = "https://dc" - - return api_client - - -@pytest.fixture() -def mock_success_response() -> Mock: - mock_response = Mock() - mock_response.json.return_value = {"name": "test_pipeline"} - - return mock_response - - -class TestSaveConfig: - def test_save_config( - self, pipeline_config: Dict[str, Any], mocked_client: Mock, mock_success_response: Mock - ) -> None: - mocked_client.post.return_value = mock_success_response - - pipeline_name = "test_pipeline" - workspace_name = "test_workspace" - - pipeline_client = PipelineClient(client=mocked_client) - - pipeline_client.save_pipeline_config( - config=pipeline_config, pipeline_config_name=pipeline_name, workspace=workspace_name - ) - - expected_payload = {"name": pipeline_name, "config": yaml.dump(pipeline_config)} - mocked_client.post.assert_called_once_with(url="https://dc/pipelines", json=expected_payload, headers=None) - - -class TestUpdateConfig: - def test_update_config( - self, pipeline_config: Dict[str, Any], mocked_client: Mock, mock_success_response: Mock - ) -> None: - mocked_client.put.return_value = mock_success_response - pipeline_name = "test_pipeline" - workspace_name = "test_workspace" - - pipeline_client = PipelineClient(client=mocked_client) - - pipeline_client.update_pipeline_config( - config=pipeline_config, pipeline_config_name=pipeline_name, workspace=workspace_name - ) - - mocked_client.put.assert_called_once_with( - url=f"https://dc/pipelines/{pipeline_name}/yaml", data=yaml.dump(pipeline_config), headers=None - ) diff --git a/test/utils/test_mmh3.py b/test/utils/test_mmh3.py deleted file mode 100644 index 127b1161a8..0000000000 --- a/test/utils/test_mmh3.py +++ /dev/null @@ -1,10 +0,0 @@ -import pytest - -from haystack.mmh3 import hash128 - - -@pytest.mark.unit -def test_mmh3(): - content = "This is the document text" * 100 - hashed_content = hash128(content) - assert hashed_content == 305042678480070366459393623793278501577 diff --git a/test/utils/test_openai_utils.py b/test/utils/test_openai_utils.py deleted file mode 100644 index 7126542f0c..0000000000 --- a/test/utils/test_openai_utils.py +++ /dev/null @@ -1,148 +0,0 @@ -import copy - -from unittest.mock import patch - -import pytest -from tenacity import wait_none - -from haystack.errors import OpenAIError, OpenAIRateLimitError, OpenAIUnauthorizedError -from haystack.utils.openai_utils import ( - openai_request, - _openai_text_completion_tokenization_details, - check_openai_policy_violation, -) - - -@pytest.mark.unit -def test_openai_text_completion_tokenization_details_gpt_default(): - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details(model_name="not-recognized-name") - assert tokenizer_name == "gpt2" - assert max_tokens_limit == 2049 - - -@pytest.mark.unit -def test_openai_text_completion_tokenization_details_gpt_davinci(): - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details(model_name="text-davinci-003") - assert tokenizer_name == "p50k_base" - assert max_tokens_limit == 4097 - - -@pytest.mark.unit -def test_openai_text_completion_tokenization_details_gpt3_5_azure(): - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details(model_name="gpt-35-turbo") - assert tokenizer_name == "cl100k_base" - assert max_tokens_limit == 4096 - - -@pytest.mark.unit -def test_openai_text_completion_tokenization_details_gpt3_5(): - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details(model_name="gpt-3.5-turbo") - assert tokenizer_name == "cl100k_base" - assert max_tokens_limit == 4096 - - -@pytest.mark.unit -def test_openai_text_completion_tokenization_details_gpt_4(): - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details(model_name="gpt-4") - assert tokenizer_name == "cl100k_base" - assert max_tokens_limit == 8192 - - -@pytest.mark.unit -def test_openai_text_completion_tokenization_details_gpt_4_32k(): - tokenizer_name, max_tokens_limit = _openai_text_completion_tokenization_details(model_name="gpt-4-32k") - assert tokenizer_name == "cl100k_base" - assert max_tokens_limit == 32768 - - -@pytest.mark.unit -@patch("haystack.utils.openai_utils.requests") -def test_openai_request_retries_generic_error(mock_requests): - mock_requests.request.return_value.status_code = 418 - - with pytest.raises(OpenAIError): - # We need to use a custom wait amount otherwise the test would take forever to run - # as the original wait time is exponential - openai_request.retry_with(wait=wait_none())(url="some_url", headers={}, payload={}, read_response=False) - - assert mock_requests.request.call_count == 5 - - -@pytest.mark.unit -@patch("haystack.utils.openai_utils.requests") -def test_openai_request_retries_on_rate_limit_error(mock_requests): - mock_requests.request.return_value.status_code = 429 - - with pytest.raises(OpenAIRateLimitError): - # We need to use a custom wait amount otherwise the test would take forever to run - # as the original wait time is exponential - openai_request.retry_with(wait=wait_none())(url="some_url", headers={}, payload={}, read_response=False) - - assert mock_requests.request.call_count == 5 - - -@pytest.mark.unit -@patch("haystack.utils.openai_utils.requests") -def test_openai_request_does_not_retry_on_unauthorized_error(mock_requests): - mock_requests.request.return_value.status_code = 401 - - with pytest.raises(OpenAIUnauthorizedError): - # We need to use a custom wait amount otherwise the test would take forever to run - # as the original wait time is exponential - openai_request.retry_with(wait=wait_none())(url="some_url", headers={}, payload={}, read_response=False) - - assert mock_requests.request.call_count == 1 - - -@pytest.mark.unit -@patch("haystack.utils.openai_utils.requests") -def test_openai_request_does_not_retry_on_success(mock_requests): - mock_requests.request.return_value.status_code = 200 - # We need to use a custom wait amount otherwise the test would take forever to run - # as the original wait time is exponential - openai_request.retry_with(wait=wait_none())(url="some_url", headers={}, payload={}, read_response=False) - - assert mock_requests.request.call_count == 1 - - -@pytest.mark.unit -def test_check_openai_policy_violation(): - moderation_endpoint_mock_response_flagged = { - "id": "modr-7Ok9zndoeSn5ij654vuNCgFVomU4U", - "model": "text-moderation-004", - "results": [ - { - "flagged": True, - "categories": { - "sexual": False, - "hate": False, - "violence": True, - "self-harm": True, - "sexual/minors": False, - "hate/threatening": False, - "violence/graphic": False, - }, - "category_scores": { - "sexual": 2.6659495e-06, - "hate": 1.9359974e-05, - "violence": 0.95964026, - "self-harm": 0.9696306, - "sexual/minors": 4.1061935e-07, - "hate/threatening": 4.9856953e-07, - "violence/graphic": 0.2683866, - }, - } - ], - } - moderation_endpoint_mock_response_not_flagged = copy.deepcopy(moderation_endpoint_mock_response_flagged) - moderation_endpoint_mock_response_not_flagged["results"][0]["flagged"] = False - moderation_endpoint_mock_response_not_flagged["results"][0]["categories"].update( - {"violence": False, "self-harm": False} - ) - with patch("haystack.utils.openai_utils.openai_request") as mock_openai_request: - # check that the function returns True if the input is flagged - mock_openai_request.return_value = moderation_endpoint_mock_response_flagged - assert check_openai_policy_violation(input="violent input", headers={}) == True - # check that the function returns False if the input is not flagged - mock_openai_request.return_value = moderation_endpoint_mock_response_not_flagged - assert check_openai_policy_violation(input="ok input", headers={}) == False diff --git a/test/utils/test_requests.py b/test/utils/test_requests.py deleted file mode 100644 index db766b7a08..0000000000 --- a/test/utils/test_requests.py +++ /dev/null @@ -1,72 +0,0 @@ -from unittest.mock import patch, Mock - -import pytest -import requests - -from haystack.utils.requests_utils import request_with_retry - - -@pytest.mark.unit -@patch("haystack.utils.requests_utils.requests.request") -def test_request_with_retry_defaults_successfully(mock_request): - # Make requests with default retry configuration - request_with_retry(method="GET", url="https://example.com") - - # Verifies request has not been retried - mock_request.assert_called_once_with(method="GET", url="https://example.com", timeout=10) - - -@pytest.mark.unit -@patch("haystack.utils.requests_utils.requests.request") -def test_request_with_retry_custom_timeout(mock_request): - # Make requests with default retry configuration - request_with_retry(method="GET", url="https://example.com", timeout=5) - - # Verifies request has not been retried - mock_request.assert_called_once_with(method="GET", url="https://example.com", timeout=5) - - -@pytest.mark.unit -@patch("haystack.utils.requests_utils.requests.request") -def test_request_with_retry_failing_request_and_expected_status_code(mock_request): - # Create fake failed response with status code that triggers retry - fake_response = requests.Response() - fake_response.status_code = 408 - mock_request.return_value = fake_response - - # Make request with expected status code and verify error is raised - with pytest.raises(requests.HTTPError): - request_with_retry(method="GET", url="https://example.com", timeout=1, attempts=2, status_codes_to_retry=[408]) - - # Veries request has been retried the expected number of times - assert mock_request.call_count == 2 - - -@pytest.mark.unit -@patch("haystack.utils.requests_utils.requests.request") -def test_request_with_retry_failing_request_and_ignored_status_code(mock_request): - # Create fake failed response with status code that doesn't trigger retry - fake_response = requests.Response() - fake_response.status_code = 500 - mock_request.return_value = fake_response - - # Make request with status code that won't trigger a retry and verify error is raised - with pytest.raises(requests.HTTPError): - request_with_retry(method="GET", url="https://example.com", timeout=1, status_codes_to_retry=[404]) - - # Verify request has not been retried - mock_request.assert_called_once() - - -@pytest.mark.unit -@patch("haystack.utils.requests_utils.requests.request") -def test_request_with_retry_timed_out_request(mock_request: Mock): - # Make request fail cause of a timeout - mock_request.side_effect = TimeoutError() - - # Make request and verifies it fails - with pytest.raises(TimeoutError): - request_with_retry(method="GET", url="https://example.com", timeout=1, attempts=2) - - # Verifies request has been retried the expected number of times - assert mock_request.call_count == 2 diff --git a/test/utils/test_tqdm.py b/test/utils/test_tqdm.py deleted file mode 100644 index 23cc8680a7..0000000000 --- a/test/utils/test_tqdm.py +++ /dev/null @@ -1,85 +0,0 @@ -from tqdm import tqdm - - -def test_silenceable_tqdm_not_disabled_by_default(): - progress_bar = tqdm(range(1)) - assert not progress_bar.disable - - -def test_silenceable_tqdm_can_be_silenced_with_0(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "0") - progress_bar = tqdm(range(1)) - assert progress_bar.disable - - -def test_silenceable_tqdm_can_be_silenced_with_false(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "false") - progress_bar = tqdm(range(1)) - assert progress_bar.disable - - -def test_silenceable_tqdm_can_be_silenced_with_False(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "False") - progress_bar = tqdm(range(1)) - assert progress_bar.disable - - -def test_silenceable_tqdm_can_be_silenced_with_FALSE(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "FALSE") - progress_bar = tqdm(range(1)) - assert progress_bar.disable - - -def test_silenceable_tqdm_not_disabled_with_number_above_zero(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "1") - progress_bar = tqdm(range(1)) - assert not progress_bar.disable - - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "10") - progress_bar = tqdm(range(1)) - assert not progress_bar.disable - - -def test_silenceable_tqdm_not_disabled_with_empty_string(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "") - progress_bar = tqdm(range(1)) - assert not progress_bar.disable - - -def test_silenceable_tqdm_not_disabled_with_other_string(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "true") - progress_bar = tqdm(range(1)) - assert not progress_bar.disable - - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "don't print the progress bars please") - progress_bar = tqdm(range(1)) - assert not progress_bar.disable - - -def test_silenceable_tqdm_can_be_disabled_explicitly(): - progress_bar = tqdm(range(1), disable=True) - assert progress_bar.disable - - -def test_silenceable_tqdm_global_disable_overrides_local_enable(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "0") - progress_bar = tqdm(range(1), disable=False) - assert progress_bar.disable - - -def test_silenceable_tqdm_global_enable_does_not_overrides_local_disable(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "1") - progress_bar = tqdm(range(1), disable=True) - assert progress_bar.disable - - -def test_silenceable_tqdm_global_and_local_disable_do_not_clash(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "0") - progress_bar = tqdm(range(1), disable=True) - assert progress_bar.disable - - -def test_silenceable_tqdm_global_and_local_enable_do_not_clash(monkeypatch): - monkeypatch.setenv("HAYSTACK_PROGRESS_BARS", "1") - progress_bar = tqdm(range(1), disable=False) - assert not progress_bar.disable From f71e11c7174ef48323218e89b1e88b5c6e41356e Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 24 Nov 2023 11:49:41 +0100 Subject: [PATCH 002/397] Removed preview package --------- Co-authored-by: Silvano Cerza --- haystack/{preview => }/README.md | 0 haystack/{preview => }/__init__.py | 0 haystack/{preview => }/components/__init__.py | 0 haystack/{preview => }/components/audio/__init__.py | 0 haystack/{preview => }/components/audio/whisper_local.py | 0 haystack/{preview => }/components/audio/whisper_remote.py | 0 haystack/{preview => }/components/builders/__init__.py | 0 haystack/{preview => }/components/builders/answer_builder.py | 0 .../{preview => }/components/builders/dynamic_prompt_builder.py | 0 haystack/{preview => }/components/builders/prompt_builder.py | 0 haystack/{preview => }/components/caching/__init__.py | 0 haystack/{preview => }/components/caching/url_cache_checker.py | 0 haystack/{preview => }/components/classifiers/__init__.py | 0 .../components/classifiers/document_language_classifier.py | 0 haystack/{preview => }/components/converters/__init__.py | 0 haystack/{preview => }/components/converters/azure.py | 0 haystack/{preview => }/components/converters/html.py | 0 haystack/{preview => }/components/converters/markdown.py | 0 haystack/{preview => }/components/converters/pypdf.py | 0 haystack/{preview => }/components/converters/tika.py | 0 haystack/{preview => }/components/converters/txt.py | 0 haystack/{preview => }/components/embedders/__init__.py | 0 haystack/{preview => }/components/embedders/backends/__init__.py | 0 .../embedders/backends/sentence_transformers_backend.py | 0 .../components/embedders/openai_document_embedder.py | 0 .../{preview => }/components/embedders/openai_text_embedder.py | 0 .../embedders/sentence_transformers_document_embedder.py | 0 .../components/embedders/sentence_transformers_text_embedder.py | 0 haystack/{preview => }/components/fetchers/__init__.py | 0 haystack/{preview => }/components/fetchers/link_content.py | 0 haystack/{preview => }/components/generators/__init__.py | 0 haystack/{preview => }/components/generators/chat/__init__.py | 0 .../{preview => }/components/generators/chat/hugging_face_tgi.py | 0 haystack/{preview => }/components/generators/chat/openai.py | 0 haystack/{preview => }/components/generators/cohere.py | 0 haystack/{preview => }/components/generators/hf_utils.py | 0 .../{preview => }/components/generators/hugging_face_local.py | 0 haystack/{preview => }/components/generators/hugging_face_tgi.py | 0 haystack/{preview => }/components/generators/openai.py | 0 haystack/{preview => }/components/generators/utils.py | 0 haystack/{preview => }/components/preprocessors/__init__.py | 0 .../{preview => }/components/preprocessors/document_cleaner.py | 0 .../{preview => }/components/preprocessors/document_splitter.py | 0 haystack/{preview => }/components/rankers/__init__.py | 0 haystack/{preview => }/components/rankers/meta_field.py | 0 .../{preview => }/components/rankers/transformers_similarity.py | 0 haystack/{preview => }/components/readers/__init__.py | 0 haystack/{preview => }/components/readers/extractive.py | 0 haystack/{preview => }/components/retrievers/__init__.py | 0 .../components/retrievers/in_memory_bm25_retriever.py | 0 .../components/retrievers/in_memory_embedding_retriever.py | 0 haystack/{preview => }/components/routers/__init__.py | 0 haystack/{preview => }/components/routers/conditional_router.py | 0 haystack/{preview => }/components/routers/document_joiner.py | 0 haystack/{preview => }/components/routers/file_type_router.py | 0 haystack/{preview => }/components/routers/metadata_router.py | 0 haystack/{preview => }/components/routers/text_language_router.py | 0 haystack/{preview => }/components/samplers/__init__.py | 0 haystack/{preview => }/components/samplers/top_p.py | 0 haystack/{preview => }/components/websearch/__init__.py | 0 haystack/{preview => }/components/websearch/searchapi.py | 0 haystack/{preview => }/components/websearch/serper_dev.py | 0 haystack/{preview => }/components/writers/__init__.py | 0 haystack/{preview => }/components/writers/document_writer.py | 0 haystack/{preview => }/dataclasses/__init__.py | 0 haystack/{preview => }/dataclasses/answer.py | 0 haystack/{preview => }/dataclasses/byte_stream.py | 0 haystack/{preview => }/dataclasses/chat_message.py | 0 haystack/{preview => }/dataclasses/document.py | 0 haystack/{preview => }/dataclasses/streaming_chunk.py | 0 haystack/{preview => }/document_stores/__init__.py | 0 haystack/{preview => }/document_stores/decorator.py | 0 haystack/{preview => }/document_stores/errors.py | 0 haystack/{preview => }/document_stores/in_memory/__init__.py | 0 .../{preview => }/document_stores/in_memory/document_store.py | 0 haystack/{preview => }/document_stores/protocols.py | 0 haystack/{preview => }/errors.py | 0 haystack/{preview => }/lazy_imports.py | 0 haystack/{preview => }/marshal/__init__.py | 0 haystack/{preview => }/marshal/protocol.py | 0 haystack/{preview => }/marshal/yaml.py | 0 haystack/{preview => }/pipeline.py | 0 haystack/{preview => }/telemetry/__init__.py | 0 haystack/{preview => }/telemetry/_environment.py | 0 haystack/{preview => }/telemetry/_telemetry.py | 0 haystack/{preview => }/testing/__init__.py | 0 haystack/{preview => }/testing/document_store.py | 0 haystack/{preview => }/testing/factory.py | 0 haystack/{preview => }/testing/test_utils.py | 0 haystack/{preview => }/utils/__init__.py | 0 haystack/{preview => }/utils/expit.py | 0 haystack/{preview => }/utils/filters.py | 0 haystack/{preview => }/utils/requests_utils.py | 0 haystack/{preview => }/version.py | 0 94 files changed, 0 insertions(+), 0 deletions(-) rename haystack/{preview => }/README.md (100%) rename haystack/{preview => }/__init__.py (100%) rename haystack/{preview => }/components/__init__.py (100%) rename haystack/{preview => }/components/audio/__init__.py (100%) rename haystack/{preview => }/components/audio/whisper_local.py (100%) rename haystack/{preview => }/components/audio/whisper_remote.py (100%) rename haystack/{preview => }/components/builders/__init__.py (100%) rename haystack/{preview => }/components/builders/answer_builder.py (100%) rename haystack/{preview => }/components/builders/dynamic_prompt_builder.py (100%) rename haystack/{preview => }/components/builders/prompt_builder.py (100%) rename haystack/{preview => }/components/caching/__init__.py (100%) rename haystack/{preview => }/components/caching/url_cache_checker.py (100%) rename haystack/{preview => }/components/classifiers/__init__.py (100%) rename haystack/{preview => }/components/classifiers/document_language_classifier.py (100%) rename haystack/{preview => }/components/converters/__init__.py (100%) rename haystack/{preview => }/components/converters/azure.py (100%) rename haystack/{preview => }/components/converters/html.py (100%) rename haystack/{preview => }/components/converters/markdown.py (100%) rename haystack/{preview => }/components/converters/pypdf.py (100%) rename haystack/{preview => }/components/converters/tika.py (100%) rename haystack/{preview => }/components/converters/txt.py (100%) rename haystack/{preview => }/components/embedders/__init__.py (100%) rename haystack/{preview => }/components/embedders/backends/__init__.py (100%) rename haystack/{preview => }/components/embedders/backends/sentence_transformers_backend.py (100%) rename haystack/{preview => }/components/embedders/openai_document_embedder.py (100%) rename haystack/{preview => }/components/embedders/openai_text_embedder.py (100%) rename haystack/{preview => }/components/embedders/sentence_transformers_document_embedder.py (100%) rename haystack/{preview => }/components/embedders/sentence_transformers_text_embedder.py (100%) rename haystack/{preview => }/components/fetchers/__init__.py (100%) rename haystack/{preview => }/components/fetchers/link_content.py (100%) rename haystack/{preview => }/components/generators/__init__.py (100%) rename haystack/{preview => }/components/generators/chat/__init__.py (100%) rename haystack/{preview => }/components/generators/chat/hugging_face_tgi.py (100%) rename haystack/{preview => }/components/generators/chat/openai.py (100%) rename haystack/{preview => }/components/generators/cohere.py (100%) rename haystack/{preview => }/components/generators/hf_utils.py (100%) rename haystack/{preview => }/components/generators/hugging_face_local.py (100%) rename haystack/{preview => }/components/generators/hugging_face_tgi.py (100%) rename haystack/{preview => }/components/generators/openai.py (100%) rename haystack/{preview => }/components/generators/utils.py (100%) rename haystack/{preview => }/components/preprocessors/__init__.py (100%) rename haystack/{preview => }/components/preprocessors/document_cleaner.py (100%) rename haystack/{preview => }/components/preprocessors/document_splitter.py (100%) rename haystack/{preview => }/components/rankers/__init__.py (100%) rename haystack/{preview => }/components/rankers/meta_field.py (100%) rename haystack/{preview => }/components/rankers/transformers_similarity.py (100%) rename haystack/{preview => }/components/readers/__init__.py (100%) rename haystack/{preview => }/components/readers/extractive.py (100%) rename haystack/{preview => }/components/retrievers/__init__.py (100%) rename haystack/{preview => }/components/retrievers/in_memory_bm25_retriever.py (100%) rename haystack/{preview => }/components/retrievers/in_memory_embedding_retriever.py (100%) rename haystack/{preview => }/components/routers/__init__.py (100%) rename haystack/{preview => }/components/routers/conditional_router.py (100%) rename haystack/{preview => }/components/routers/document_joiner.py (100%) rename haystack/{preview => }/components/routers/file_type_router.py (100%) rename haystack/{preview => }/components/routers/metadata_router.py (100%) rename haystack/{preview => }/components/routers/text_language_router.py (100%) rename haystack/{preview => }/components/samplers/__init__.py (100%) rename haystack/{preview => }/components/samplers/top_p.py (100%) rename haystack/{preview => }/components/websearch/__init__.py (100%) rename haystack/{preview => }/components/websearch/searchapi.py (100%) rename haystack/{preview => }/components/websearch/serper_dev.py (100%) rename haystack/{preview => }/components/writers/__init__.py (100%) rename haystack/{preview => }/components/writers/document_writer.py (100%) rename haystack/{preview => }/dataclasses/__init__.py (100%) rename haystack/{preview => }/dataclasses/answer.py (100%) rename haystack/{preview => }/dataclasses/byte_stream.py (100%) rename haystack/{preview => }/dataclasses/chat_message.py (100%) rename haystack/{preview => }/dataclasses/document.py (100%) rename haystack/{preview => }/dataclasses/streaming_chunk.py (100%) rename haystack/{preview => }/document_stores/__init__.py (100%) rename haystack/{preview => }/document_stores/decorator.py (100%) rename haystack/{preview => }/document_stores/errors.py (100%) rename haystack/{preview => }/document_stores/in_memory/__init__.py (100%) rename haystack/{preview => }/document_stores/in_memory/document_store.py (100%) rename haystack/{preview => }/document_stores/protocols.py (100%) rename haystack/{preview => }/errors.py (100%) rename haystack/{preview => }/lazy_imports.py (100%) rename haystack/{preview => }/marshal/__init__.py (100%) rename haystack/{preview => }/marshal/protocol.py (100%) rename haystack/{preview => }/marshal/yaml.py (100%) rename haystack/{preview => }/pipeline.py (100%) rename haystack/{preview => }/telemetry/__init__.py (100%) rename haystack/{preview => }/telemetry/_environment.py (100%) rename haystack/{preview => }/telemetry/_telemetry.py (100%) rename haystack/{preview => }/testing/__init__.py (100%) rename haystack/{preview => }/testing/document_store.py (100%) rename haystack/{preview => }/testing/factory.py (100%) rename haystack/{preview => }/testing/test_utils.py (100%) rename haystack/{preview => }/utils/__init__.py (100%) rename haystack/{preview => }/utils/expit.py (100%) rename haystack/{preview => }/utils/filters.py (100%) rename haystack/{preview => }/utils/requests_utils.py (100%) rename haystack/{preview => }/version.py (100%) diff --git a/haystack/preview/README.md b/haystack/README.md similarity index 100% rename from haystack/preview/README.md rename to haystack/README.md diff --git a/haystack/preview/__init__.py b/haystack/__init__.py similarity index 100% rename from haystack/preview/__init__.py rename to haystack/__init__.py diff --git a/haystack/preview/components/__init__.py b/haystack/components/__init__.py similarity index 100% rename from haystack/preview/components/__init__.py rename to haystack/components/__init__.py diff --git a/haystack/preview/components/audio/__init__.py b/haystack/components/audio/__init__.py similarity index 100% rename from haystack/preview/components/audio/__init__.py rename to haystack/components/audio/__init__.py diff --git a/haystack/preview/components/audio/whisper_local.py b/haystack/components/audio/whisper_local.py similarity index 100% rename from haystack/preview/components/audio/whisper_local.py rename to haystack/components/audio/whisper_local.py diff --git a/haystack/preview/components/audio/whisper_remote.py b/haystack/components/audio/whisper_remote.py similarity index 100% rename from haystack/preview/components/audio/whisper_remote.py rename to haystack/components/audio/whisper_remote.py diff --git a/haystack/preview/components/builders/__init__.py b/haystack/components/builders/__init__.py similarity index 100% rename from haystack/preview/components/builders/__init__.py rename to haystack/components/builders/__init__.py diff --git a/haystack/preview/components/builders/answer_builder.py b/haystack/components/builders/answer_builder.py similarity index 100% rename from haystack/preview/components/builders/answer_builder.py rename to haystack/components/builders/answer_builder.py diff --git a/haystack/preview/components/builders/dynamic_prompt_builder.py b/haystack/components/builders/dynamic_prompt_builder.py similarity index 100% rename from haystack/preview/components/builders/dynamic_prompt_builder.py rename to haystack/components/builders/dynamic_prompt_builder.py diff --git a/haystack/preview/components/builders/prompt_builder.py b/haystack/components/builders/prompt_builder.py similarity index 100% rename from haystack/preview/components/builders/prompt_builder.py rename to haystack/components/builders/prompt_builder.py diff --git a/haystack/preview/components/caching/__init__.py b/haystack/components/caching/__init__.py similarity index 100% rename from haystack/preview/components/caching/__init__.py rename to haystack/components/caching/__init__.py diff --git a/haystack/preview/components/caching/url_cache_checker.py b/haystack/components/caching/url_cache_checker.py similarity index 100% rename from haystack/preview/components/caching/url_cache_checker.py rename to haystack/components/caching/url_cache_checker.py diff --git a/haystack/preview/components/classifiers/__init__.py b/haystack/components/classifiers/__init__.py similarity index 100% rename from haystack/preview/components/classifiers/__init__.py rename to haystack/components/classifiers/__init__.py diff --git a/haystack/preview/components/classifiers/document_language_classifier.py b/haystack/components/classifiers/document_language_classifier.py similarity index 100% rename from haystack/preview/components/classifiers/document_language_classifier.py rename to haystack/components/classifiers/document_language_classifier.py diff --git a/haystack/preview/components/converters/__init__.py b/haystack/components/converters/__init__.py similarity index 100% rename from haystack/preview/components/converters/__init__.py rename to haystack/components/converters/__init__.py diff --git a/haystack/preview/components/converters/azure.py b/haystack/components/converters/azure.py similarity index 100% rename from haystack/preview/components/converters/azure.py rename to haystack/components/converters/azure.py diff --git a/haystack/preview/components/converters/html.py b/haystack/components/converters/html.py similarity index 100% rename from haystack/preview/components/converters/html.py rename to haystack/components/converters/html.py diff --git a/haystack/preview/components/converters/markdown.py b/haystack/components/converters/markdown.py similarity index 100% rename from haystack/preview/components/converters/markdown.py rename to haystack/components/converters/markdown.py diff --git a/haystack/preview/components/converters/pypdf.py b/haystack/components/converters/pypdf.py similarity index 100% rename from haystack/preview/components/converters/pypdf.py rename to haystack/components/converters/pypdf.py diff --git a/haystack/preview/components/converters/tika.py b/haystack/components/converters/tika.py similarity index 100% rename from haystack/preview/components/converters/tika.py rename to haystack/components/converters/tika.py diff --git a/haystack/preview/components/converters/txt.py b/haystack/components/converters/txt.py similarity index 100% rename from haystack/preview/components/converters/txt.py rename to haystack/components/converters/txt.py diff --git a/haystack/preview/components/embedders/__init__.py b/haystack/components/embedders/__init__.py similarity index 100% rename from haystack/preview/components/embedders/__init__.py rename to haystack/components/embedders/__init__.py diff --git a/haystack/preview/components/embedders/backends/__init__.py b/haystack/components/embedders/backends/__init__.py similarity index 100% rename from haystack/preview/components/embedders/backends/__init__.py rename to haystack/components/embedders/backends/__init__.py diff --git a/haystack/preview/components/embedders/backends/sentence_transformers_backend.py b/haystack/components/embedders/backends/sentence_transformers_backend.py similarity index 100% rename from haystack/preview/components/embedders/backends/sentence_transformers_backend.py rename to haystack/components/embedders/backends/sentence_transformers_backend.py diff --git a/haystack/preview/components/embedders/openai_document_embedder.py b/haystack/components/embedders/openai_document_embedder.py similarity index 100% rename from haystack/preview/components/embedders/openai_document_embedder.py rename to haystack/components/embedders/openai_document_embedder.py diff --git a/haystack/preview/components/embedders/openai_text_embedder.py b/haystack/components/embedders/openai_text_embedder.py similarity index 100% rename from haystack/preview/components/embedders/openai_text_embedder.py rename to haystack/components/embedders/openai_text_embedder.py diff --git a/haystack/preview/components/embedders/sentence_transformers_document_embedder.py b/haystack/components/embedders/sentence_transformers_document_embedder.py similarity index 100% rename from haystack/preview/components/embedders/sentence_transformers_document_embedder.py rename to haystack/components/embedders/sentence_transformers_document_embedder.py diff --git a/haystack/preview/components/embedders/sentence_transformers_text_embedder.py b/haystack/components/embedders/sentence_transformers_text_embedder.py similarity index 100% rename from haystack/preview/components/embedders/sentence_transformers_text_embedder.py rename to haystack/components/embedders/sentence_transformers_text_embedder.py diff --git a/haystack/preview/components/fetchers/__init__.py b/haystack/components/fetchers/__init__.py similarity index 100% rename from haystack/preview/components/fetchers/__init__.py rename to haystack/components/fetchers/__init__.py diff --git a/haystack/preview/components/fetchers/link_content.py b/haystack/components/fetchers/link_content.py similarity index 100% rename from haystack/preview/components/fetchers/link_content.py rename to haystack/components/fetchers/link_content.py diff --git a/haystack/preview/components/generators/__init__.py b/haystack/components/generators/__init__.py similarity index 100% rename from haystack/preview/components/generators/__init__.py rename to haystack/components/generators/__init__.py diff --git a/haystack/preview/components/generators/chat/__init__.py b/haystack/components/generators/chat/__init__.py similarity index 100% rename from haystack/preview/components/generators/chat/__init__.py rename to haystack/components/generators/chat/__init__.py diff --git a/haystack/preview/components/generators/chat/hugging_face_tgi.py b/haystack/components/generators/chat/hugging_face_tgi.py similarity index 100% rename from haystack/preview/components/generators/chat/hugging_face_tgi.py rename to haystack/components/generators/chat/hugging_face_tgi.py diff --git a/haystack/preview/components/generators/chat/openai.py b/haystack/components/generators/chat/openai.py similarity index 100% rename from haystack/preview/components/generators/chat/openai.py rename to haystack/components/generators/chat/openai.py diff --git a/haystack/preview/components/generators/cohere.py b/haystack/components/generators/cohere.py similarity index 100% rename from haystack/preview/components/generators/cohere.py rename to haystack/components/generators/cohere.py diff --git a/haystack/preview/components/generators/hf_utils.py b/haystack/components/generators/hf_utils.py similarity index 100% rename from haystack/preview/components/generators/hf_utils.py rename to haystack/components/generators/hf_utils.py diff --git a/haystack/preview/components/generators/hugging_face_local.py b/haystack/components/generators/hugging_face_local.py similarity index 100% rename from haystack/preview/components/generators/hugging_face_local.py rename to haystack/components/generators/hugging_face_local.py diff --git a/haystack/preview/components/generators/hugging_face_tgi.py b/haystack/components/generators/hugging_face_tgi.py similarity index 100% rename from haystack/preview/components/generators/hugging_face_tgi.py rename to haystack/components/generators/hugging_face_tgi.py diff --git a/haystack/preview/components/generators/openai.py b/haystack/components/generators/openai.py similarity index 100% rename from haystack/preview/components/generators/openai.py rename to haystack/components/generators/openai.py diff --git a/haystack/preview/components/generators/utils.py b/haystack/components/generators/utils.py similarity index 100% rename from haystack/preview/components/generators/utils.py rename to haystack/components/generators/utils.py diff --git a/haystack/preview/components/preprocessors/__init__.py b/haystack/components/preprocessors/__init__.py similarity index 100% rename from haystack/preview/components/preprocessors/__init__.py rename to haystack/components/preprocessors/__init__.py diff --git a/haystack/preview/components/preprocessors/document_cleaner.py b/haystack/components/preprocessors/document_cleaner.py similarity index 100% rename from haystack/preview/components/preprocessors/document_cleaner.py rename to haystack/components/preprocessors/document_cleaner.py diff --git a/haystack/preview/components/preprocessors/document_splitter.py b/haystack/components/preprocessors/document_splitter.py similarity index 100% rename from haystack/preview/components/preprocessors/document_splitter.py rename to haystack/components/preprocessors/document_splitter.py diff --git a/haystack/preview/components/rankers/__init__.py b/haystack/components/rankers/__init__.py similarity index 100% rename from haystack/preview/components/rankers/__init__.py rename to haystack/components/rankers/__init__.py diff --git a/haystack/preview/components/rankers/meta_field.py b/haystack/components/rankers/meta_field.py similarity index 100% rename from haystack/preview/components/rankers/meta_field.py rename to haystack/components/rankers/meta_field.py diff --git a/haystack/preview/components/rankers/transformers_similarity.py b/haystack/components/rankers/transformers_similarity.py similarity index 100% rename from haystack/preview/components/rankers/transformers_similarity.py rename to haystack/components/rankers/transformers_similarity.py diff --git a/haystack/preview/components/readers/__init__.py b/haystack/components/readers/__init__.py similarity index 100% rename from haystack/preview/components/readers/__init__.py rename to haystack/components/readers/__init__.py diff --git a/haystack/preview/components/readers/extractive.py b/haystack/components/readers/extractive.py similarity index 100% rename from haystack/preview/components/readers/extractive.py rename to haystack/components/readers/extractive.py diff --git a/haystack/preview/components/retrievers/__init__.py b/haystack/components/retrievers/__init__.py similarity index 100% rename from haystack/preview/components/retrievers/__init__.py rename to haystack/components/retrievers/__init__.py diff --git a/haystack/preview/components/retrievers/in_memory_bm25_retriever.py b/haystack/components/retrievers/in_memory_bm25_retriever.py similarity index 100% rename from haystack/preview/components/retrievers/in_memory_bm25_retriever.py rename to haystack/components/retrievers/in_memory_bm25_retriever.py diff --git a/haystack/preview/components/retrievers/in_memory_embedding_retriever.py b/haystack/components/retrievers/in_memory_embedding_retriever.py similarity index 100% rename from haystack/preview/components/retrievers/in_memory_embedding_retriever.py rename to haystack/components/retrievers/in_memory_embedding_retriever.py diff --git a/haystack/preview/components/routers/__init__.py b/haystack/components/routers/__init__.py similarity index 100% rename from haystack/preview/components/routers/__init__.py rename to haystack/components/routers/__init__.py diff --git a/haystack/preview/components/routers/conditional_router.py b/haystack/components/routers/conditional_router.py similarity index 100% rename from haystack/preview/components/routers/conditional_router.py rename to haystack/components/routers/conditional_router.py diff --git a/haystack/preview/components/routers/document_joiner.py b/haystack/components/routers/document_joiner.py similarity index 100% rename from haystack/preview/components/routers/document_joiner.py rename to haystack/components/routers/document_joiner.py diff --git a/haystack/preview/components/routers/file_type_router.py b/haystack/components/routers/file_type_router.py similarity index 100% rename from haystack/preview/components/routers/file_type_router.py rename to haystack/components/routers/file_type_router.py diff --git a/haystack/preview/components/routers/metadata_router.py b/haystack/components/routers/metadata_router.py similarity index 100% rename from haystack/preview/components/routers/metadata_router.py rename to haystack/components/routers/metadata_router.py diff --git a/haystack/preview/components/routers/text_language_router.py b/haystack/components/routers/text_language_router.py similarity index 100% rename from haystack/preview/components/routers/text_language_router.py rename to haystack/components/routers/text_language_router.py diff --git a/haystack/preview/components/samplers/__init__.py b/haystack/components/samplers/__init__.py similarity index 100% rename from haystack/preview/components/samplers/__init__.py rename to haystack/components/samplers/__init__.py diff --git a/haystack/preview/components/samplers/top_p.py b/haystack/components/samplers/top_p.py similarity index 100% rename from haystack/preview/components/samplers/top_p.py rename to haystack/components/samplers/top_p.py diff --git a/haystack/preview/components/websearch/__init__.py b/haystack/components/websearch/__init__.py similarity index 100% rename from haystack/preview/components/websearch/__init__.py rename to haystack/components/websearch/__init__.py diff --git a/haystack/preview/components/websearch/searchapi.py b/haystack/components/websearch/searchapi.py similarity index 100% rename from haystack/preview/components/websearch/searchapi.py rename to haystack/components/websearch/searchapi.py diff --git a/haystack/preview/components/websearch/serper_dev.py b/haystack/components/websearch/serper_dev.py similarity index 100% rename from haystack/preview/components/websearch/serper_dev.py rename to haystack/components/websearch/serper_dev.py diff --git a/haystack/preview/components/writers/__init__.py b/haystack/components/writers/__init__.py similarity index 100% rename from haystack/preview/components/writers/__init__.py rename to haystack/components/writers/__init__.py diff --git a/haystack/preview/components/writers/document_writer.py b/haystack/components/writers/document_writer.py similarity index 100% rename from haystack/preview/components/writers/document_writer.py rename to haystack/components/writers/document_writer.py diff --git a/haystack/preview/dataclasses/__init__.py b/haystack/dataclasses/__init__.py similarity index 100% rename from haystack/preview/dataclasses/__init__.py rename to haystack/dataclasses/__init__.py diff --git a/haystack/preview/dataclasses/answer.py b/haystack/dataclasses/answer.py similarity index 100% rename from haystack/preview/dataclasses/answer.py rename to haystack/dataclasses/answer.py diff --git a/haystack/preview/dataclasses/byte_stream.py b/haystack/dataclasses/byte_stream.py similarity index 100% rename from haystack/preview/dataclasses/byte_stream.py rename to haystack/dataclasses/byte_stream.py diff --git a/haystack/preview/dataclasses/chat_message.py b/haystack/dataclasses/chat_message.py similarity index 100% rename from haystack/preview/dataclasses/chat_message.py rename to haystack/dataclasses/chat_message.py diff --git a/haystack/preview/dataclasses/document.py b/haystack/dataclasses/document.py similarity index 100% rename from haystack/preview/dataclasses/document.py rename to haystack/dataclasses/document.py diff --git a/haystack/preview/dataclasses/streaming_chunk.py b/haystack/dataclasses/streaming_chunk.py similarity index 100% rename from haystack/preview/dataclasses/streaming_chunk.py rename to haystack/dataclasses/streaming_chunk.py diff --git a/haystack/preview/document_stores/__init__.py b/haystack/document_stores/__init__.py similarity index 100% rename from haystack/preview/document_stores/__init__.py rename to haystack/document_stores/__init__.py diff --git a/haystack/preview/document_stores/decorator.py b/haystack/document_stores/decorator.py similarity index 100% rename from haystack/preview/document_stores/decorator.py rename to haystack/document_stores/decorator.py diff --git a/haystack/preview/document_stores/errors.py b/haystack/document_stores/errors.py similarity index 100% rename from haystack/preview/document_stores/errors.py rename to haystack/document_stores/errors.py diff --git a/haystack/preview/document_stores/in_memory/__init__.py b/haystack/document_stores/in_memory/__init__.py similarity index 100% rename from haystack/preview/document_stores/in_memory/__init__.py rename to haystack/document_stores/in_memory/__init__.py diff --git a/haystack/preview/document_stores/in_memory/document_store.py b/haystack/document_stores/in_memory/document_store.py similarity index 100% rename from haystack/preview/document_stores/in_memory/document_store.py rename to haystack/document_stores/in_memory/document_store.py diff --git a/haystack/preview/document_stores/protocols.py b/haystack/document_stores/protocols.py similarity index 100% rename from haystack/preview/document_stores/protocols.py rename to haystack/document_stores/protocols.py diff --git a/haystack/preview/errors.py b/haystack/errors.py similarity index 100% rename from haystack/preview/errors.py rename to haystack/errors.py diff --git a/haystack/preview/lazy_imports.py b/haystack/lazy_imports.py similarity index 100% rename from haystack/preview/lazy_imports.py rename to haystack/lazy_imports.py diff --git a/haystack/preview/marshal/__init__.py b/haystack/marshal/__init__.py similarity index 100% rename from haystack/preview/marshal/__init__.py rename to haystack/marshal/__init__.py diff --git a/haystack/preview/marshal/protocol.py b/haystack/marshal/protocol.py similarity index 100% rename from haystack/preview/marshal/protocol.py rename to haystack/marshal/protocol.py diff --git a/haystack/preview/marshal/yaml.py b/haystack/marshal/yaml.py similarity index 100% rename from haystack/preview/marshal/yaml.py rename to haystack/marshal/yaml.py diff --git a/haystack/preview/pipeline.py b/haystack/pipeline.py similarity index 100% rename from haystack/preview/pipeline.py rename to haystack/pipeline.py diff --git a/haystack/preview/telemetry/__init__.py b/haystack/telemetry/__init__.py similarity index 100% rename from haystack/preview/telemetry/__init__.py rename to haystack/telemetry/__init__.py diff --git a/haystack/preview/telemetry/_environment.py b/haystack/telemetry/_environment.py similarity index 100% rename from haystack/preview/telemetry/_environment.py rename to haystack/telemetry/_environment.py diff --git a/haystack/preview/telemetry/_telemetry.py b/haystack/telemetry/_telemetry.py similarity index 100% rename from haystack/preview/telemetry/_telemetry.py rename to haystack/telemetry/_telemetry.py diff --git a/haystack/preview/testing/__init__.py b/haystack/testing/__init__.py similarity index 100% rename from haystack/preview/testing/__init__.py rename to haystack/testing/__init__.py diff --git a/haystack/preview/testing/document_store.py b/haystack/testing/document_store.py similarity index 100% rename from haystack/preview/testing/document_store.py rename to haystack/testing/document_store.py diff --git a/haystack/preview/testing/factory.py b/haystack/testing/factory.py similarity index 100% rename from haystack/preview/testing/factory.py rename to haystack/testing/factory.py diff --git a/haystack/preview/testing/test_utils.py b/haystack/testing/test_utils.py similarity index 100% rename from haystack/preview/testing/test_utils.py rename to haystack/testing/test_utils.py diff --git a/haystack/preview/utils/__init__.py b/haystack/utils/__init__.py similarity index 100% rename from haystack/preview/utils/__init__.py rename to haystack/utils/__init__.py diff --git a/haystack/preview/utils/expit.py b/haystack/utils/expit.py similarity index 100% rename from haystack/preview/utils/expit.py rename to haystack/utils/expit.py diff --git a/haystack/preview/utils/filters.py b/haystack/utils/filters.py similarity index 100% rename from haystack/preview/utils/filters.py rename to haystack/utils/filters.py diff --git a/haystack/preview/utils/requests_utils.py b/haystack/utils/requests_utils.py similarity index 100% rename from haystack/preview/utils/requests_utils.py rename to haystack/utils/requests_utils.py diff --git a/haystack/preview/version.py b/haystack/version.py similarity index 100% rename from haystack/preview/version.py rename to haystack/version.py From 8adb8bbab8fac409ab77bb32771f6ce9b82b5a82 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 24 Nov 2023 11:52:55 +0100 Subject: [PATCH 003/397] Remove preview folder in test/ --------- Co-authored-by: Silvano Cerza --- .../components/audio/__init__.py | 0 .../components/audio/test_whisper_local.py | 0 .../components/audio/test_whisper_remote.py | 0 .../components/builders/__init__.py | 0 .../builders/test_answer_builder.py | 0 .../builders/test_dynamic_prompt_builder.py | 0 .../builders/test_prompt_builder.py | 0 .../caching/test_url_cache_checker.py | 0 .../test_document_language_classifier.py | 0 .../components/converters/__init__.py | 0 .../test_azure_ocr_doc_converter.py | 0 .../converters/test_html_to_document.py | 0 .../converters/test_markdown_to_document.py | 0 .../converters/test_pypdf_to_document.py | 0 .../converters/test_textfile_to_document.py | 0 .../converters/test_tika_doc_converter.py | 0 .../components/embedders/__init__.py | 0 .../test_openai_document_embedder.py | 0 .../embedders/test_openai_text_embedder.py | 0 ...sentence_transformers_document_embedder.py | 0 ...sentence_transformers_embedding_backend.py | 0 ...est_sentence_transformers_text_embedder.py | 0 .../components/fetchers/__init__.py | 0 .../fetchers/test_link_content_fetcher.py | 0 .../components/generators/chat/__init__.py | 0 .../components/generators/chat/conftest.py | 0 .../generators/chat/test_hugging_face_tgi.py | 0 .../components/generators/chat/test_openai.py | 0 .../components/generators/conftest.py | 0 .../generators/test_cohere_generators.py | 0 .../components/generators/test_hf_utils.py | 0 .../test_hugging_face_local_generator.py | 0 .../generators/test_hugging_face_tgi.py | 0 .../components/generators/test_openai.py | 0 .../components/generators/test_utils.py | 0 .../components/preprocessors/__init__.py | 0 .../preprocessors/test_document_cleaner.py | 0 .../preprocessors/test_document_splitter.py | 0 .../components/rankers/test_metafield.py | 0 .../rankers/test_transformers_similarity.py | 0 .../components/readers/test_extractive.py | 0 .../components/retrievers/__init__.py | 0 .../test_in_memory_bm25_retriever.py | 0 .../test_in_memory_embedding_retriever.py | 0 .../components/routers/__init__.py | 0 .../routers/test_conditional_router.py | 0 .../routers/test_document_joiner.py | 0 .../components/routers/test_file_router.py | 0 .../routers/test_metadata_router.py | 0 .../routers/test_text_language_router.py | 0 .../components/samplers/__init__.py | 0 .../components/samplers/test_top_p.py | 0 .../components/websearch/__init__.py | 0 .../components/websearch/test_searchapi.py | 0 .../components/websearch/test_serperdev.py | 0 .../components/writers/__init__.py | 0 .../writers/test_document_writer.py | 0 test/conftest.py | 927 +----------------- .../dataclasses/test_byte_stream.py | 0 .../dataclasses/test_chat_message.py | 0 .../dataclasses/test_document.py | 0 .../dataclasses/test_streaming_chunk.py | 0 .../document_stores/test_in_memory.py | 0 test/preview/conftest.py | 23 - .../{preview => }/test_files/audio/answer.wav | Bin .../the context for this answer is here.wav | Bin .../this is the content of the document.wav | Bin .../test_files/docx/sample_docx.docx | Bin .../test_files/html/what_is_haystack.html | 0 .../{preview => }/test_files/images/apple.jpg | Bin .../test_files/images/haystack-logo.png | Bin .../test_files/markdown/sample.md | 0 .../test_files/pdf/react_paper.pdf | Bin .../test_files/pdf/sample_pdf_1.pdf | Bin .../test_files/pdf/sample_pdf_2.pdf | Bin test/{preview => }/test_files/txt/doc_1.txt | 0 test/{preview => }/test_files/txt/doc_2.txt | 0 test/{preview => }/test_files/txt/doc_3.txt | 0 .../test_files/yaml/test_pipeline.yaml | 0 test/{preview => }/test_pipeline.py | 0 test/{preview => }/test_telemetry.py | 0 test/{preview => }/testing/test_factory.py | 0 test/{preview => }/utils/test_filters.py | 0 83 files changed, 13 insertions(+), 937 deletions(-) rename test/{preview => }/components/audio/__init__.py (100%) rename test/{preview => }/components/audio/test_whisper_local.py (100%) rename test/{preview => }/components/audio/test_whisper_remote.py (100%) rename test/{preview => }/components/builders/__init__.py (100%) rename test/{preview => }/components/builders/test_answer_builder.py (100%) rename test/{preview => }/components/builders/test_dynamic_prompt_builder.py (100%) rename test/{preview => }/components/builders/test_prompt_builder.py (100%) rename test/{preview => }/components/caching/test_url_cache_checker.py (100%) rename test/{preview => }/components/classifiers/test_document_language_classifier.py (100%) rename test/{preview => }/components/converters/__init__.py (100%) rename test/{preview => }/components/converters/test_azure_ocr_doc_converter.py (100%) rename test/{preview => }/components/converters/test_html_to_document.py (100%) rename test/{preview => }/components/converters/test_markdown_to_document.py (100%) rename test/{preview => }/components/converters/test_pypdf_to_document.py (100%) rename test/{preview => }/components/converters/test_textfile_to_document.py (100%) rename test/{preview => }/components/converters/test_tika_doc_converter.py (100%) rename test/{preview => }/components/embedders/__init__.py (100%) rename test/{preview => }/components/embedders/test_openai_document_embedder.py (100%) rename test/{preview => }/components/embedders/test_openai_text_embedder.py (100%) rename test/{preview => }/components/embedders/test_sentence_transformers_document_embedder.py (100%) rename test/{preview => }/components/embedders/test_sentence_transformers_embedding_backend.py (100%) rename test/{preview => }/components/embedders/test_sentence_transformers_text_embedder.py (100%) rename test/{preview => }/components/fetchers/__init__.py (100%) rename test/{preview => }/components/fetchers/test_link_content_fetcher.py (100%) rename test/{preview => }/components/generators/chat/__init__.py (100%) rename test/{preview => }/components/generators/chat/conftest.py (100%) rename test/{preview => }/components/generators/chat/test_hugging_face_tgi.py (100%) rename test/{preview => }/components/generators/chat/test_openai.py (100%) rename test/{preview => }/components/generators/conftest.py (100%) rename test/{preview => }/components/generators/test_cohere_generators.py (100%) rename test/{preview => }/components/generators/test_hf_utils.py (100%) rename test/{preview => }/components/generators/test_hugging_face_local_generator.py (100%) rename test/{preview => }/components/generators/test_hugging_face_tgi.py (100%) rename test/{preview => }/components/generators/test_openai.py (100%) rename test/{preview => }/components/generators/test_utils.py (100%) rename test/{preview => }/components/preprocessors/__init__.py (100%) rename test/{preview => }/components/preprocessors/test_document_cleaner.py (100%) rename test/{preview => }/components/preprocessors/test_document_splitter.py (100%) rename test/{preview => }/components/rankers/test_metafield.py (100%) rename test/{preview => }/components/rankers/test_transformers_similarity.py (100%) rename test/{preview => }/components/readers/test_extractive.py (100%) rename test/{preview => }/components/retrievers/__init__.py (100%) rename test/{preview => }/components/retrievers/test_in_memory_bm25_retriever.py (100%) rename test/{preview => }/components/retrievers/test_in_memory_embedding_retriever.py (100%) rename test/{preview => }/components/routers/__init__.py (100%) rename test/{preview => }/components/routers/test_conditional_router.py (100%) rename test/{preview => }/components/routers/test_document_joiner.py (100%) rename test/{preview => }/components/routers/test_file_router.py (100%) rename test/{preview => }/components/routers/test_metadata_router.py (100%) rename test/{preview => }/components/routers/test_text_language_router.py (100%) rename test/{preview => }/components/samplers/__init__.py (100%) rename test/{preview => }/components/samplers/test_top_p.py (100%) rename test/{preview => }/components/websearch/__init__.py (100%) rename test/{preview => }/components/websearch/test_searchapi.py (100%) rename test/{preview => }/components/websearch/test_serperdev.py (100%) rename test/{preview => }/components/writers/__init__.py (100%) rename test/{preview => }/components/writers/test_document_writer.py (100%) rename test/{preview => }/dataclasses/test_byte_stream.py (100%) rename test/{preview => }/dataclasses/test_chat_message.py (100%) rename test/{preview => }/dataclasses/test_document.py (100%) rename test/{preview => }/dataclasses/test_streaming_chunk.py (100%) rename test/{preview => }/document_stores/test_in_memory.py (100%) delete mode 100644 test/preview/conftest.py rename test/{preview => }/test_files/audio/answer.wav (100%) rename test/{preview => }/test_files/audio/the context for this answer is here.wav (100%) rename test/{preview => }/test_files/audio/this is the content of the document.wav (100%) rename test/{preview => }/test_files/docx/sample_docx.docx (100%) rename test/{preview => }/test_files/html/what_is_haystack.html (100%) rename test/{preview => }/test_files/images/apple.jpg (100%) rename test/{preview => }/test_files/images/haystack-logo.png (100%) rename test/{preview => }/test_files/markdown/sample.md (100%) rename test/{preview => }/test_files/pdf/react_paper.pdf (100%) rename test/{preview => }/test_files/pdf/sample_pdf_1.pdf (100%) rename test/{preview => }/test_files/pdf/sample_pdf_2.pdf (100%) rename test/{preview => }/test_files/txt/doc_1.txt (100%) rename test/{preview => }/test_files/txt/doc_2.txt (100%) rename test/{preview => }/test_files/txt/doc_3.txt (100%) rename test/{preview => }/test_files/yaml/test_pipeline.yaml (100%) rename test/{preview => }/test_pipeline.py (100%) rename test/{preview => }/test_telemetry.py (100%) rename test/{preview => }/testing/test_factory.py (100%) rename test/{preview => }/utils/test_filters.py (100%) diff --git a/test/preview/components/audio/__init__.py b/test/components/audio/__init__.py similarity index 100% rename from test/preview/components/audio/__init__.py rename to test/components/audio/__init__.py diff --git a/test/preview/components/audio/test_whisper_local.py b/test/components/audio/test_whisper_local.py similarity index 100% rename from test/preview/components/audio/test_whisper_local.py rename to test/components/audio/test_whisper_local.py diff --git a/test/preview/components/audio/test_whisper_remote.py b/test/components/audio/test_whisper_remote.py similarity index 100% rename from test/preview/components/audio/test_whisper_remote.py rename to test/components/audio/test_whisper_remote.py diff --git a/test/preview/components/builders/__init__.py b/test/components/builders/__init__.py similarity index 100% rename from test/preview/components/builders/__init__.py rename to test/components/builders/__init__.py diff --git a/test/preview/components/builders/test_answer_builder.py b/test/components/builders/test_answer_builder.py similarity index 100% rename from test/preview/components/builders/test_answer_builder.py rename to test/components/builders/test_answer_builder.py diff --git a/test/preview/components/builders/test_dynamic_prompt_builder.py b/test/components/builders/test_dynamic_prompt_builder.py similarity index 100% rename from test/preview/components/builders/test_dynamic_prompt_builder.py rename to test/components/builders/test_dynamic_prompt_builder.py diff --git a/test/preview/components/builders/test_prompt_builder.py b/test/components/builders/test_prompt_builder.py similarity index 100% rename from test/preview/components/builders/test_prompt_builder.py rename to test/components/builders/test_prompt_builder.py diff --git a/test/preview/components/caching/test_url_cache_checker.py b/test/components/caching/test_url_cache_checker.py similarity index 100% rename from test/preview/components/caching/test_url_cache_checker.py rename to test/components/caching/test_url_cache_checker.py diff --git a/test/preview/components/classifiers/test_document_language_classifier.py b/test/components/classifiers/test_document_language_classifier.py similarity index 100% rename from test/preview/components/classifiers/test_document_language_classifier.py rename to test/components/classifiers/test_document_language_classifier.py diff --git a/test/preview/components/converters/__init__.py b/test/components/converters/__init__.py similarity index 100% rename from test/preview/components/converters/__init__.py rename to test/components/converters/__init__.py diff --git a/test/preview/components/converters/test_azure_ocr_doc_converter.py b/test/components/converters/test_azure_ocr_doc_converter.py similarity index 100% rename from test/preview/components/converters/test_azure_ocr_doc_converter.py rename to test/components/converters/test_azure_ocr_doc_converter.py diff --git a/test/preview/components/converters/test_html_to_document.py b/test/components/converters/test_html_to_document.py similarity index 100% rename from test/preview/components/converters/test_html_to_document.py rename to test/components/converters/test_html_to_document.py diff --git a/test/preview/components/converters/test_markdown_to_document.py b/test/components/converters/test_markdown_to_document.py similarity index 100% rename from test/preview/components/converters/test_markdown_to_document.py rename to test/components/converters/test_markdown_to_document.py diff --git a/test/preview/components/converters/test_pypdf_to_document.py b/test/components/converters/test_pypdf_to_document.py similarity index 100% rename from test/preview/components/converters/test_pypdf_to_document.py rename to test/components/converters/test_pypdf_to_document.py diff --git a/test/preview/components/converters/test_textfile_to_document.py b/test/components/converters/test_textfile_to_document.py similarity index 100% rename from test/preview/components/converters/test_textfile_to_document.py rename to test/components/converters/test_textfile_to_document.py diff --git a/test/preview/components/converters/test_tika_doc_converter.py b/test/components/converters/test_tika_doc_converter.py similarity index 100% rename from test/preview/components/converters/test_tika_doc_converter.py rename to test/components/converters/test_tika_doc_converter.py diff --git a/test/preview/components/embedders/__init__.py b/test/components/embedders/__init__.py similarity index 100% rename from test/preview/components/embedders/__init__.py rename to test/components/embedders/__init__.py diff --git a/test/preview/components/embedders/test_openai_document_embedder.py b/test/components/embedders/test_openai_document_embedder.py similarity index 100% rename from test/preview/components/embedders/test_openai_document_embedder.py rename to test/components/embedders/test_openai_document_embedder.py diff --git a/test/preview/components/embedders/test_openai_text_embedder.py b/test/components/embedders/test_openai_text_embedder.py similarity index 100% rename from test/preview/components/embedders/test_openai_text_embedder.py rename to test/components/embedders/test_openai_text_embedder.py diff --git a/test/preview/components/embedders/test_sentence_transformers_document_embedder.py b/test/components/embedders/test_sentence_transformers_document_embedder.py similarity index 100% rename from test/preview/components/embedders/test_sentence_transformers_document_embedder.py rename to test/components/embedders/test_sentence_transformers_document_embedder.py diff --git a/test/preview/components/embedders/test_sentence_transformers_embedding_backend.py b/test/components/embedders/test_sentence_transformers_embedding_backend.py similarity index 100% rename from test/preview/components/embedders/test_sentence_transformers_embedding_backend.py rename to test/components/embedders/test_sentence_transformers_embedding_backend.py diff --git a/test/preview/components/embedders/test_sentence_transformers_text_embedder.py b/test/components/embedders/test_sentence_transformers_text_embedder.py similarity index 100% rename from test/preview/components/embedders/test_sentence_transformers_text_embedder.py rename to test/components/embedders/test_sentence_transformers_text_embedder.py diff --git a/test/preview/components/fetchers/__init__.py b/test/components/fetchers/__init__.py similarity index 100% rename from test/preview/components/fetchers/__init__.py rename to test/components/fetchers/__init__.py diff --git a/test/preview/components/fetchers/test_link_content_fetcher.py b/test/components/fetchers/test_link_content_fetcher.py similarity index 100% rename from test/preview/components/fetchers/test_link_content_fetcher.py rename to test/components/fetchers/test_link_content_fetcher.py diff --git a/test/preview/components/generators/chat/__init__.py b/test/components/generators/chat/__init__.py similarity index 100% rename from test/preview/components/generators/chat/__init__.py rename to test/components/generators/chat/__init__.py diff --git a/test/preview/components/generators/chat/conftest.py b/test/components/generators/chat/conftest.py similarity index 100% rename from test/preview/components/generators/chat/conftest.py rename to test/components/generators/chat/conftest.py diff --git a/test/preview/components/generators/chat/test_hugging_face_tgi.py b/test/components/generators/chat/test_hugging_face_tgi.py similarity index 100% rename from test/preview/components/generators/chat/test_hugging_face_tgi.py rename to test/components/generators/chat/test_hugging_face_tgi.py diff --git a/test/preview/components/generators/chat/test_openai.py b/test/components/generators/chat/test_openai.py similarity index 100% rename from test/preview/components/generators/chat/test_openai.py rename to test/components/generators/chat/test_openai.py diff --git a/test/preview/components/generators/conftest.py b/test/components/generators/conftest.py similarity index 100% rename from test/preview/components/generators/conftest.py rename to test/components/generators/conftest.py diff --git a/test/preview/components/generators/test_cohere_generators.py b/test/components/generators/test_cohere_generators.py similarity index 100% rename from test/preview/components/generators/test_cohere_generators.py rename to test/components/generators/test_cohere_generators.py diff --git a/test/preview/components/generators/test_hf_utils.py b/test/components/generators/test_hf_utils.py similarity index 100% rename from test/preview/components/generators/test_hf_utils.py rename to test/components/generators/test_hf_utils.py diff --git a/test/preview/components/generators/test_hugging_face_local_generator.py b/test/components/generators/test_hugging_face_local_generator.py similarity index 100% rename from test/preview/components/generators/test_hugging_face_local_generator.py rename to test/components/generators/test_hugging_face_local_generator.py diff --git a/test/preview/components/generators/test_hugging_face_tgi.py b/test/components/generators/test_hugging_face_tgi.py similarity index 100% rename from test/preview/components/generators/test_hugging_face_tgi.py rename to test/components/generators/test_hugging_face_tgi.py diff --git a/test/preview/components/generators/test_openai.py b/test/components/generators/test_openai.py similarity index 100% rename from test/preview/components/generators/test_openai.py rename to test/components/generators/test_openai.py diff --git a/test/preview/components/generators/test_utils.py b/test/components/generators/test_utils.py similarity index 100% rename from test/preview/components/generators/test_utils.py rename to test/components/generators/test_utils.py diff --git a/test/preview/components/preprocessors/__init__.py b/test/components/preprocessors/__init__.py similarity index 100% rename from test/preview/components/preprocessors/__init__.py rename to test/components/preprocessors/__init__.py diff --git a/test/preview/components/preprocessors/test_document_cleaner.py b/test/components/preprocessors/test_document_cleaner.py similarity index 100% rename from test/preview/components/preprocessors/test_document_cleaner.py rename to test/components/preprocessors/test_document_cleaner.py diff --git a/test/preview/components/preprocessors/test_document_splitter.py b/test/components/preprocessors/test_document_splitter.py similarity index 100% rename from test/preview/components/preprocessors/test_document_splitter.py rename to test/components/preprocessors/test_document_splitter.py diff --git a/test/preview/components/rankers/test_metafield.py b/test/components/rankers/test_metafield.py similarity index 100% rename from test/preview/components/rankers/test_metafield.py rename to test/components/rankers/test_metafield.py diff --git a/test/preview/components/rankers/test_transformers_similarity.py b/test/components/rankers/test_transformers_similarity.py similarity index 100% rename from test/preview/components/rankers/test_transformers_similarity.py rename to test/components/rankers/test_transformers_similarity.py diff --git a/test/preview/components/readers/test_extractive.py b/test/components/readers/test_extractive.py similarity index 100% rename from test/preview/components/readers/test_extractive.py rename to test/components/readers/test_extractive.py diff --git a/test/preview/components/retrievers/__init__.py b/test/components/retrievers/__init__.py similarity index 100% rename from test/preview/components/retrievers/__init__.py rename to test/components/retrievers/__init__.py diff --git a/test/preview/components/retrievers/test_in_memory_bm25_retriever.py b/test/components/retrievers/test_in_memory_bm25_retriever.py similarity index 100% rename from test/preview/components/retrievers/test_in_memory_bm25_retriever.py rename to test/components/retrievers/test_in_memory_bm25_retriever.py diff --git a/test/preview/components/retrievers/test_in_memory_embedding_retriever.py b/test/components/retrievers/test_in_memory_embedding_retriever.py similarity index 100% rename from test/preview/components/retrievers/test_in_memory_embedding_retriever.py rename to test/components/retrievers/test_in_memory_embedding_retriever.py diff --git a/test/preview/components/routers/__init__.py b/test/components/routers/__init__.py similarity index 100% rename from test/preview/components/routers/__init__.py rename to test/components/routers/__init__.py diff --git a/test/preview/components/routers/test_conditional_router.py b/test/components/routers/test_conditional_router.py similarity index 100% rename from test/preview/components/routers/test_conditional_router.py rename to test/components/routers/test_conditional_router.py diff --git a/test/preview/components/routers/test_document_joiner.py b/test/components/routers/test_document_joiner.py similarity index 100% rename from test/preview/components/routers/test_document_joiner.py rename to test/components/routers/test_document_joiner.py diff --git a/test/preview/components/routers/test_file_router.py b/test/components/routers/test_file_router.py similarity index 100% rename from test/preview/components/routers/test_file_router.py rename to test/components/routers/test_file_router.py diff --git a/test/preview/components/routers/test_metadata_router.py b/test/components/routers/test_metadata_router.py similarity index 100% rename from test/preview/components/routers/test_metadata_router.py rename to test/components/routers/test_metadata_router.py diff --git a/test/preview/components/routers/test_text_language_router.py b/test/components/routers/test_text_language_router.py similarity index 100% rename from test/preview/components/routers/test_text_language_router.py rename to test/components/routers/test_text_language_router.py diff --git a/test/preview/components/samplers/__init__.py b/test/components/samplers/__init__.py similarity index 100% rename from test/preview/components/samplers/__init__.py rename to test/components/samplers/__init__.py diff --git a/test/preview/components/samplers/test_top_p.py b/test/components/samplers/test_top_p.py similarity index 100% rename from test/preview/components/samplers/test_top_p.py rename to test/components/samplers/test_top_p.py diff --git a/test/preview/components/websearch/__init__.py b/test/components/websearch/__init__.py similarity index 100% rename from test/preview/components/websearch/__init__.py rename to test/components/websearch/__init__.py diff --git a/test/preview/components/websearch/test_searchapi.py b/test/components/websearch/test_searchapi.py similarity index 100% rename from test/preview/components/websearch/test_searchapi.py rename to test/components/websearch/test_searchapi.py diff --git a/test/preview/components/websearch/test_serperdev.py b/test/components/websearch/test_serperdev.py similarity index 100% rename from test/preview/components/websearch/test_serperdev.py rename to test/components/websearch/test_serperdev.py diff --git a/test/preview/components/writers/__init__.py b/test/components/writers/__init__.py similarity index 100% rename from test/preview/components/writers/__init__.py rename to test/components/writers/__init__.py diff --git a/test/preview/components/writers/test_document_writer.py b/test/components/writers/test_document_writer.py similarity index 100% rename from test/preview/components/writers/test_document_writer.py rename to test/components/writers/test_document_writer.py diff --git a/test/conftest.py b/test/conftest.py index 9e6fdb7426..3a2f166120 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,924 +1,23 @@ -import warnings -from typing import Any, List, Optional, Dict, Union - -import gc -import logging from pathlib import Path -import os -import re -from functools import wraps -from unittest.mock import patch - -import responses -import posthog - -import numpy as np +from unittest.mock import Mock import pytest -from haystack import Answer, BaseComponent, __version__ as haystack_version -from haystack.document_stores import ( - BaseDocumentStore, - InMemoryDocumentStore, - ElasticsearchDocumentStore, - WeaviateDocumentStore, - PineconeDocumentStore, - OpenSearchDocumentStore, - FAISSDocumentStore, -) -from haystack.nodes import ( - BaseReader, - BaseRetriever, - BaseGenerator, - BaseSummarizer, - BaseTranslator, - DenseRetriever, - FilterRetriever, - BM25Retriever, - TfidfRetriever, - DensePassageRetriever, - EmbeddingRetriever, - MultihopEmbeddingRetriever, - TableTextRetriever, - FARMReader, - TransformersReader, - TableReader, - RCIReader, - QuestionGenerator, - PromptTemplate, -) -from haystack.nodes.prompt import PromptNode -from haystack.schema import Document, FilterType, MultiLabel, Label, Span - -from .mocks import pinecone as pinecone_mock - +from haystack.preview.testing.test_utils import set_all_seeds -# To manually run the tests with default PostgreSQL instead of SQLite, switch the lines below -SQL_TYPE = "sqlite" -DC_API_ENDPOINT = "https://DC_API/v1" -DC_TEST_INDEX = "document_retrieval_1" -DC_API_KEY = "NO_KEY" -MOCK_DC = True +set_all_seeds(0) -# Set metadata fields used during testing for PineconeDocumentStore meta_config -META_FIELDS = [ - "meta_field", - "name", - "date_field", - "numeric_field", - "f1", - "f3", - "meta_id", - "meta_field_for_count", - "meta_key_1", - "meta_key_2", -] -# Disable telemetry reports when running tests -posthog.disabled = True - -# Disable caching from prompthub to avoid polluting the local environment. -os.environ["PROMPTHUB_CACHE_ENABLED"] = "false" - - -def fail_at_version(target_major, target_minor): +@pytest.fixture() +def mock_tokenizer(): """ - Reminder to remove deprecated features. - If you're using this fixture please open an issue in the repo to keep track - of the deprecated feature that must be removed. - After opening the issue assign it to the target version milestone, if the - milestone doesn't exist either create it or notify someone that has permissions - to do so. - This way will be assured that the feature is actually removed for that release. - This will fail tests if the current major and/or minor version is equal or greater - of target_major and/or target_minor. - If the current version has `rc0` set the test won't fail but only issue a warning, this - is done because we use `rc0` to mark the development version in `main`. If we wouldn't - do this tests would continuously fail in main. - - ```python - from ..conftest import fail_at_version - - @fail_at_version(1, 10) # Will fail once Haystack version is greater than or equal to 1.10 - def test_test(): - assert True - ``` + Tokenizes the string by splitting on spaces. """ - - def decorator(function): - (current_major, current_minor) = [int(num) for num in haystack_version.split(".")[:2]] - current_rc = int(haystack_version.split("rc")[1]) if "rc" in haystack_version else -1 - - @wraps(function) - def wrapper(*args, **kwargs): - if current_major > target_major or (current_major == target_major and current_minor >= target_minor): - message = f"This feature is marked for removal in v{target_major}.{target_minor}" - if current_rc == 0: - warnings.warn(message) - else: - pytest.fail(reason=message) - return_value = function(*args, **kwargs) - return return_value - - return wrapper - - return decorator - - -def pytest_collection_modifyitems(config, items): - # add pytest markers for tests that are not explicitly marked but include some keywords - name_to_markers = { - "generator": [pytest.mark.generator], - "summarizer": [pytest.mark.summarizer], - "tika": [pytest.mark.tika, pytest.mark.integration], - "parsr": [pytest.mark.parsr, pytest.mark.integration], - "ocr": [pytest.mark.ocr, pytest.mark.integration], - "elasticsearch": [pytest.mark.elasticsearch], - "faiss": [pytest.mark.faiss], - "weaviate": [pytest.mark.weaviate], - "pinecone": [pytest.mark.pinecone], - } - for item in items: - for name, markers in name_to_markers.items(): - if name in item.nodeid.lower(): - for marker in markers: - item.add_marker(marker) - - # if the cli argument "--document_store_type" is used, we want to skip all tests that have markers of other docstores - # Example: pytest -v test_document_store.py --document_store_type="memory" => skip all tests marked with "elasticsearch" - document_store_types_to_run = config.getoption("--document_store_type") - document_store_types_to_run = [docstore.strip() for docstore in document_store_types_to_run.split(",")] - keywords = [] - - for i in item.keywords: - if "-" in i: - keywords.extend(i.split("-")) - else: - keywords.append(i) - - required_doc_store = infer_required_doc_store(item, keywords) - - if required_doc_store and required_doc_store not in document_store_types_to_run: - skip_docstore = pytest.mark.skip( - reason=f'{required_doc_store} is disabled. Enable via pytest --document_store_type="{required_doc_store}"' - ) - item.add_marker(skip_docstore) - - -def infer_required_doc_store(item, keywords): - # assumption: a test runs only with one document_store - # if there are multiple docstore markers, we apply the following heuristics: - # 1. if the test was parameterized, we use the the parameter - # 2. if the test name contains the docstore name, we use that - # 3. use an arbitrary one by calling set.pop() - required_doc_store = None - all_doc_stores = {"elasticsearch", "faiss", "sql", "memory", "weaviate", "pinecone"} - docstore_markers = set(keywords).intersection(all_doc_stores) - if len(docstore_markers) > 1: - # if parameterized infer the docstore from the parameter - if hasattr(item, "callspec"): - for doc_store in all_doc_stores: - # callspec.id contains the parameter values of the test - if re.search(f"(^|-){doc_store}($|[-_])", item.callspec.id): - required_doc_store = doc_store - break - # if still not found, infer the docstore from the test name - if required_doc_store is None: - for doc_store in all_doc_stores: - if doc_store in item.name: - required_doc_store = doc_store - break - # if still not found or there is only one, use an arbitrary one from the markers - if required_doc_store is None: - required_doc_store = docstore_markers.pop() if docstore_markers else None - return required_doc_store - - -# -# Empty mocks, as a base for unit tests. -# -# Monkeypatch the methods you need with either a mock implementation -# or a unittest.mock.MagicMock object (https://docs.python.org/3/library/unittest.mock.html) -# - - -class MockNode(BaseComponent): - outgoing_edges = 1 - - def run(self, *a, **k): - pass - - def run_batch(self, *a, **k): - pass - - -class MockDocumentStore(BaseDocumentStore): - outgoing_edges = 1 - - def _create_document_field_map(self, *a, **k): - pass - - def delete_documents(self, *a, **k): - pass - - def delete_labels(self, *a, **k): - pass - - def get_all_documents(self, *a, **k): - pass - - def get_all_documents_generator(self, *a, **k): - pass - - def get_all_labels(self, *a, **k): - pass - - def get_document_by_id(self, *a, **k): - pass - - def get_document_count(self, *a, **k): - pass - - def get_documents_by_id(self, *a, **k): - pass - - def get_label_count(self, *a, **k): - pass - - def query_by_embedding(self, *a, **k): - pass - - def write_documents(self, *a, **k): - pass - - def write_labels(self, *a, **k): - pass - - def delete_index(self, *a, **k): - pass - - def update_document_meta(self, *a, **kw): - pass - - -class MockRetriever(BaseRetriever): - outgoing_edges = 1 - - def retrieve( - self, - query: str, - filters: Optional[FilterType] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[Document]: - return [] - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: Optional[bool] = None, - document_store: Optional[BaseDocumentStore] = None, - ) -> List[List[Document]]: - return [[]] - - -class MockBaseRetriever(MockRetriever): - def __init__(self, document_store: BaseDocumentStore, mock_document: Document): - self.document_store = document_store - self.mock_document = mock_document - - def retrieve( - self, - query: str, - filters: dict, - top_k: Optional[int], - index: str, - headers: Optional[Dict[str, str]], - scale_score: bool, - ): - return [self.mock_document] - - def retrieve_batch( - self, - queries: List[str], - filters: Optional[Union[FilterType, List[Optional[FilterType]]]] = None, - top_k: Optional[int] = None, - index: str = None, - headers: Optional[Dict[str, str]] = None, - batch_size: Optional[int] = None, - scale_score: bool = None, - ): - return [[self.mock_document] for _ in range(len(queries))] - - def embed_documents(self, documents: List[Document]): - return np.full((len(documents), 768), 0.5) - - -class MockSeq2SegGenerator(BaseGenerator): - def predict(self, query: str, documents: List[Document], top_k: Optional[int], max_tokens: Optional[int]) -> Dict: - pass - - -class MockSummarizer(BaseSummarizer): - def predict_batch( - self, documents: Union[List[Document], List[List[Document]]], batch_size: Optional[int] = None - ) -> Union[List[Document], List[List[Document]]]: - pass - - def predict(self, documents: List[Document]) -> List[Document]: - pass - - -class MockTranslator(BaseTranslator): - def translate( - self, - results: List[Dict[str, Any]] = None, - query: Optional[str] = None, - documents: Optional[Union[List[Document], List[Answer], List[str], List[Dict[str, Any]]]] = None, - dict_key: Optional[str] = None, - ) -> Union[str, List[Document], List[Answer], List[str], List[Dict[str, Any]]]: - pass - - def translate_batch( - self, - queries: Optional[List[str]] = None, - documents: Optional[Union[List[Document], List[Answer], List[List[Document]], List[List[Answer]]]] = None, - batch_size: Optional[int] = None, - ) -> List[Union[str, List[Document], List[Answer], List[str], List[Dict[str, Any]]]]: - pass - - -class MockDenseRetriever(MockRetriever, DenseRetriever): - def __init__(self, document_store: BaseDocumentStore, embedding_dim: int = 768): - self.embedding_dim = embedding_dim - self.document_store = document_store - - def embed_queries(self, queries): - return np.random.rand(len(queries), self.embedding_dim) - - def embed_documents(self, documents): - return np.random.rand(len(documents), self.embedding_dim) - - -class MockQuestionGenerator(QuestionGenerator): - def __init__(self): - pass - - def predict(self, query: str, documents: List[Document], top_k: Optional[int]) -> Dict: - pass - - -class MockReader(BaseReader): - outgoing_edges = 1 - - def predict(self, query: str, documents: List[Document], top_k: Optional[int] = None): - pass - - def predict_batch(self, query_doc_list: List[dict], top_k: Optional[int] = None, batch_size: Optional[int] = None): - pass - - -class MockPromptNode(PromptNode): - def __init__(self): - self.default_prompt_template = None - self.model_name_or_path = "" - - def prompt(self, prompt_template: Optional[Union[str, PromptTemplate]], *args, **kwargs) -> List[str]: - return [""] - - def get_prompt_template(self, prompt_template: Union[str, PromptTemplate, None]) -> Optional[PromptTemplate]: - if prompt_template == "think-step-by-step": - p = PromptTemplate( - "You are a helpful and knowledgeable agent. To achieve your goal of answering complex questions " - "correctly, you have access to the following tools:\n\n" - "{tool_names_with_descriptions}\n\n" - "To answer questions, you'll need to go through multiple steps involving step-by-step thinking and " - "selecting appropriate tools and their inputs; tools will respond with observations. When you are ready " - "for a final answer, respond with the `Final Answer:`\n\n" - "Use the following format:\n\n" - "Question: the question to be answered\n" - "Thought: Reason if you have the final answer. If yes, answer the question. If not, find out the missing information needed to answer it.\n" - "Tool: [{tool_names}]\n" - "Tool Input: the input for the tool\n" - "Observation: the tool will respond with the result\n" - "...\n" - "Final Answer: the final answer to the question, make it short (1-5 words)\n\n" - "Thought, Tool, Tool Input, and Observation steps can be repeated multiple times, but sometimes we can find an answer in the first pass\n" - "---\n\n" - "Question: {query}\n" - "Thought: Let's think step-by-step, I first need to {generated_text}" - ) - p.name = "think-step-by-step" - else: - return PromptTemplate("test prompt") - - -@pytest.fixture -def test_rootdir() -> Path: - return Path(__file__).parent.absolute() - - -# -# Document collections -# - - -@pytest.fixture -def docs_all_formats() -> List[Union[Document, Dict[str, Any]]]: - return [ - # metafield at the top level for backward compatibility - { - "content": "My name is Paul and I live in New York", - "meta_field": "test2", - "name": "filename2", - "date_field": "2019-10-01", - "numeric_field": 5.0, - "list_field": ["item0.1", "item0.2"], - }, - # "dict" format - { - "content": "My name is Carla and I live in Berlin", - "meta": { - "meta_field": "test1", - "name": "filename1", - "date_field": "2020-03-01", - "numeric_field": 5.5, - "list_field": ["item1.1", "item1.2"], - }, - }, - # Document object - Document( - content="My name is Christelle and I live in Paris", - meta={ - "meta_field": "test3", - "name": "filename3", - "date_field": "2018-10-01", - "numeric_field": 4.5, - "list_field": ["item2.1", "item2.2"], - }, - ), - Document( - content="My name is Camila and I live in Madrid", - meta={ - "meta_field": "test4", - "name": "filename4", - "date_field": "2021-02-01", - "numeric_field": 3.0, - "list_field": ["item3.1", "item3.2"], - }, - ), - Document( - content="My name is Matteo and I live in Rome", - meta={ - "meta_field": "test5", - "name": "filename5", - "date_field": "2019-01-01", - "numeric_field": 0.0, - "list_field": ["item4.1", "item4.2"], - }, - ), - ] - - -@pytest.fixture -def docs(docs_all_formats) -> List[Document]: - return [Document.from_dict(doc) if isinstance(doc, dict) else doc for doc in docs_all_formats] - - -@pytest.fixture(autouse=True) -def gc_cleanup(request): - """ - Run garbage collector between tests in order to reduce memory footprint for CI. - """ - yield - gc.collect() - - -@pytest.fixture -def eval_labels() -> List[MultiLabel]: - EVAL_LABELS = [ - MultiLabel( - labels=[ - Label( - query="Who lives in Berlin?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="a0747b83aea0b60c4b114b15476dd32d", - content_type="text", - content="My name is Carla and I live in Berlin", - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - MultiLabel( - labels=[ - Label( - query="Who lives in Munich?", - answer=Answer(answer="Carla", offsets_in_context=[Span(11, 16)]), - document=Document( - id="something_else", content_type="text", content="My name is Carla and I live in Munich" - ), - is_correct_answer=True, - is_correct_document=True, - origin="gold-label", - ) - ] - ), - ] - return EVAL_LABELS - - -@pytest.fixture -def deepset_cloud_fixture(): - if MOCK_DC: - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/indexes/{DC_TEST_INDEX}", - match=[responses.matchers.header_matcher({"authorization": f"Bearer {DC_API_KEY}"})], - json={"indexing": {"status": "INDEXED", "pending_file_count": 0, "total_file_count": 31}}, - status=200, - ) - responses.add( - method=responses.GET, - url=f"{DC_API_ENDPOINT}/workspaces/default/pipelines", - match=[responses.matchers.header_matcher({"authorization": f"Bearer {DC_API_KEY}"})], - json={ - "data": [ - { - "name": DC_TEST_INDEX, - "status": "DEPLOYED", - "indexing": {"status": "INDEXED", "pending_file_count": 0, "total_file_count": 31}, - } - ], - "has_more": False, - "total": 1, - }, - ) - else: - responses.add_passthru(DC_API_ENDPOINT) - - -@pytest.fixture -def question_generator(): - return QuestionGenerator(model_name_or_path="valhalla/t5-small-e2e-qg") - - -@pytest.fixture(params=["farm", "transformers"], scope="module") -def reader(request): - if request.param == "farm": - return FARMReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", - use_gpu=False, - top_k_per_sample=5, - num_processes=0, - ) - if request.param == "transformers": - return TransformersReader( - model_name_or_path="deepset/bert-medium-squad2-distilled", - tokenizer="deepset/bert-medium-squad2-distilled", - use_gpu=-1, - ) - - -@pytest.fixture(params=["tapas_small", "tapas_base", "tapas_scored", "rci"]) -def table_reader_and_param(request): - if request.param == "tapas_small": - return TableReader(model_name_or_path="google/tapas-small-finetuned-wtq"), request.param - elif request.param == "tapas_base": - return TableReader(model_name_or_path="google/tapas-base-finetuned-wtq"), request.param - elif request.param == "tapas_scored": - return TableReader(model_name_or_path="deepset/tapas-large-nq-hn-reader"), request.param - elif request.param == "rci": - return ( - RCIReader( - row_model_name_or_path="michaelrglass/albert-base-rci-wikisql-row", - column_model_name_or_path="michaelrglass/albert-base-rci-wikisql-col", - ), - request.param, - ) - - -@pytest.fixture(params=["es_filter_only", "bm25", "dpr", "embedding", "tfidf", "table_text_retriever"]) -def retriever(request, document_store): - return get_retriever(request.param, document_store) - - -# @pytest.fixture(params=["es_filter_only", "elasticsearch", "dpr", "embedding", "tfidf"]) -@pytest.fixture(params=["tfidf"]) -def retriever_with_docs(request, document_store_with_docs): - return get_retriever(request.param, document_store_with_docs) - - -def get_retriever(retriever_type, document_store): - if retriever_type == "dpr": - retriever = DensePassageRetriever( - document_store=document_store, - query_embedding_model="facebook/dpr-question_encoder-single-nq-base", - passage_embedding_model="facebook/dpr-ctx_encoder-single-nq-base", - use_gpu=False, - embed_title=True, - ) - elif retriever_type == "mdr": - retriever = MultihopEmbeddingRetriever( - document_store=document_store, - embedding_model="deutschmann/mdr_roberta_q_encoder", # or "facebook/dpr-ctx_encoder-single-nq-base" - use_gpu=False, - ) - elif retriever_type == "tfidf": - retriever = TfidfRetriever(document_store=document_store) - elif retriever_type == "embedding": - retriever = EmbeddingRetriever( - document_store=document_store, embedding_model="deepset/sentence_bert", use_gpu=False - ) - elif retriever_type == "embedding_sbert": - retriever = EmbeddingRetriever( - document_store=document_store, - embedding_model="sentence-transformers/msmarco-distilbert-base-tas-b", - model_format="sentence_transformers", - use_gpu=False, - ) - elif retriever_type == "embedding_sbert_instructions": - retriever = EmbeddingRetriever( - document_store=document_store, - embedding_model="sentence-transformers/msmarco-distilbert-dot-v5", - model_format="sentence_transformers", - query_prompt="Embed this query for retrieval:", - passage_prompt="Embed this passage for retrieval:", - use_gpu=False, - ) - elif retriever_type == "retribert": - retriever = EmbeddingRetriever( - document_store=document_store, embedding_model="yjernite/retribert-base-uncased", use_gpu=False - ) - elif retriever_type == "openai": - retriever = EmbeddingRetriever( - document_store=document_store, - embedding_model="text-embedding-ada-002", - use_gpu=False, - api_key=os.getenv("OPENAI_API_KEY"), - ) - elif retriever_type == "azure": - retriever = EmbeddingRetriever( - document_store=document_store, - embedding_model="text-embedding-ada-002", - use_gpu=False, - api_key=os.getenv("AZURE_OPENAI_API_KEY"), - azure_base_url=os.getenv("AZURE_OPENAI_BASE_URL"), - azure_deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME_EMBED"), - ) - elif retriever_type == "cohere": - retriever = EmbeddingRetriever( - document_store=document_store, - embedding_model="small", - use_gpu=False, - api_key=os.environ.get("COHERE_API_KEY", ""), - ) - elif retriever_type == "dpr_lfqa": - retriever = DensePassageRetriever( - document_store=document_store, - query_embedding_model="vblagoje/dpr-question_encoder-single-lfqa-wiki", - passage_embedding_model="vblagoje/dpr-ctx_encoder-single-lfqa-wiki", - use_gpu=False, - embed_title=True, - ) - elif retriever_type == "bm25": - retriever = BM25Retriever(document_store=document_store) - elif retriever_type == "es_filter_only": - retriever = FilterRetriever(document_store=document_store) - elif retriever_type == "table_text_retriever": - retriever = TableTextRetriever( - document_store=document_store, - query_embedding_model="deepset/bert-small-mm_retrieval-question_encoder", - passage_embedding_model="deepset/bert-small-mm_retrieval-passage_encoder", - table_embedding_model="deepset/bert-small-mm_retrieval-table_encoder", - use_gpu=False, - ) - else: - raise Exception(f"No retriever fixture for '{retriever_type}'") - - return retriever - - -# FIXME Fix this in the docstore tests refactoring -from inspect import getmembers, isclass, isfunction - - -def mock_pinecone(monkeypatch): - for fname, function in getmembers(pinecone_mock, isfunction): - monkeypatch.setattr(f"pinecone.{fname}", function, raising=False) - for cname, class_ in getmembers(pinecone_mock, isclass): - monkeypatch.setattr(f"pinecone.{cname}", class_, raising=False) - - -@pytest.fixture(params=["elasticsearch", "faiss", "memory", "weaviate", "pinecone"]) -def document_store_with_docs(request, docs, tmp_path, monkeypatch): - if request.param == "pinecone": - mock_pinecone(monkeypatch) - - embedding_dim = request.node.get_closest_marker("embedding_dim", pytest.mark.embedding_dim(768)) - document_store = get_document_store( - document_store_type=request.param, embedding_dim=embedding_dim.args[0], tmp_path=tmp_path - ) - document_store.write_documents(docs) - yield document_store - document_store.delete_index(document_store.index) - - -@pytest.fixture -def document_store(request, tmp_path, monkeypatch: pytest.MonkeyPatch): - if request.param == "pinecone": - mock_pinecone(monkeypatch) - - embedding_dim = request.node.get_closest_marker("embedding_dim", pytest.mark.embedding_dim(768)) - document_store = get_document_store( - document_store_type=request.param, embedding_dim=embedding_dim.args[0], tmp_path=tmp_path - ) - yield document_store - document_store.delete_index(document_store.index) - - -def get_sql_url(tmp_path): - if SQL_TYPE == "postgres": - return "postgresql://postgres:postgres@127.0.0.1/postgres" - else: - return f"sqlite:///{tmp_path}/haystack_test.db" - - -# TODO: Verify this is still necessary as it's called by no one -def setup_postgres(): - # status = subprocess.run(["docker run --name postgres_test -d -e POSTGRES_HOST_AUTH_METHOD=trust -p 5432:5432 postgres"], shell=True) - # if status.returncode: - # logging.warning("Tried to start PostgreSQL through Docker but this failed. It is likely that there is already an existing instance running.") - # else: - # sleep(5) - from sqlalchemy import create_engine, text - - engine = create_engine("postgresql://postgres:postgres@127.0.0.1/postgres", isolation_level="AUTOCOMMIT") - - with engine.connect() as connection: - try: - connection.execute(text("DROP SCHEMA IF EXISTS public CASCADE")) - except Exception as e: - logging.error(e) - connection.execute(text("CREATE SCHEMA public;")) - connection.execute(text('SET SESSION idle_in_transaction_session_timeout = "1s";')) - - -# TODO: Verify this is still necessary as it's called by no one -def teardown_postgres(): - from sqlalchemy import create_engine, text - - engine = create_engine("postgresql://postgres:postgres@127.0.0.1/postgres", isolation_level="AUTOCOMMIT") - with engine.connect() as connection: - connection.execute(text("DROP SCHEMA public CASCADE")) - connection.close() - - -def get_document_store( - document_store_type, - tmp_path, - embedding_dim=768, - embedding_field="embedding", - index="haystack_test", - similarity: str = "cosine", - recreate_index: bool = True, -): # cosine is default similarity as dot product is not supported by Weaviate - document_store: BaseDocumentStore - if document_store_type == "memory": - document_store = InMemoryDocumentStore( - return_embedding=True, - embedding_dim=embedding_dim, - embedding_field=embedding_field, - index=index, - similarity=similarity, - use_bm25=True, - bm25_parameters={"k1": 1.2, "b": 0.75}, # parameters similar to those of Elasticsearch - ) - - elif document_store_type == "elasticsearch": - # make sure we start from a fresh index - document_store = ElasticsearchDocumentStore( - index=index, - return_embedding=True, - embedding_dim=embedding_dim, - embedding_field=embedding_field, - similarity=similarity, - recreate_index=recreate_index, - ) - - elif document_store_type == "faiss": - document_store = FAISSDocumentStore( - embedding_dim=embedding_dim, - sql_url=get_sql_url(tmp_path), - return_embedding=True, - embedding_field=embedding_field, - index=index, - similarity=similarity, - isolation_level="AUTOCOMMIT", - ) - - elif document_store_type == "weaviate": - document_store = WeaviateDocumentStore( - index=index, similarity=similarity, embedding_dim=embedding_dim, recreate_index=recreate_index - ) - - elif document_store_type == "pinecone": - document_store = PineconeDocumentStore( - api_key=os.environ.get("PINECONE_API_KEY") or "fake-haystack-test-key", - embedding_dim=embedding_dim, - embedding_field=embedding_field, - index=index, - similarity=similarity, - recreate_index=recreate_index, - metadata_config={"indexed": META_FIELDS}, - ) - - elif document_store_type == "opensearch_faiss": - document_store = OpenSearchDocumentStore( - index=index, - return_embedding=True, - embedding_dim=embedding_dim, - embedding_field=embedding_field, - similarity=similarity, - recreate_index=recreate_index, - port=9201, - knn_engine="faiss", - ) - - else: - raise Exception(f"No document store fixture for '{document_store_type}'") - - return document_store - - -@pytest.fixture -def haystack_azure_conf(): - api_key = os.environ.get("AZURE_OPENAI_API_KEY", None) - azure_base_url = os.environ.get("AZURE_OPENAI_BASE_URL", None) - azure_deployment_name = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", None) - if api_key and azure_base_url and azure_deployment_name: - return {"api_key": api_key, "azure_base_url": azure_base_url, "azure_deployment_name": azure_deployment_name} - else: - return {} - - -@pytest.fixture -def haystack_openai_config(request, haystack_azure_conf): - if request.param == "openai": - api_key = os.environ.get("OPENAI_API_KEY", None) - if not api_key: - return {} - else: - return {"api_key": api_key, "embedding_model": "text-embedding-ada-002"} - elif request.param == "azure": - return haystack_azure_conf - - return {} - - -@pytest.fixture -def samples_path(): - return Path(__file__).parent / "samples" - - -@pytest.fixture -def sample_txt_file_paths_list(samples_path): - return list((samples_path / "docs").glob("*.txt")) - - -@pytest.fixture -def preview_samples_path(): - return Path(__file__).parent / "preview" / "test_files" - - -@pytest.fixture(autouse=True) -def request_blocker(request: pytest.FixtureRequest, monkeypatch): - """ - This fixture is applied automatically to all tests. - Those that are marked as unit will have the requests module - monkeypatched to avoid making HTTP requests by mistake. - """ - marker = request.node.get_closest_marker("unit") - if marker is None: - return - - def urlopen_mock(self, method, url, *args, **kwargs): - raise RuntimeError(f"The test was about to {method} {self.scheme}://{self.host}{url}") - - monkeypatch.setattr("urllib3.connectionpool.HTTPConnectionPool.urlopen", urlopen_mock) + tokenizer = Mock() + tokenizer.encode = lambda text: text.split() + tokenizer.decode = lambda tokens: " ".join(tokens) + return tokenizer -@pytest.fixture -def mock_auto_tokenizer(): - with patch("transformers.AutoTokenizer.from_pretrained", autospec=True) as mock_from_pretrained: - yield mock_from_pretrained +@pytest.fixture() +def test_files_path(): + return Path(__file__).parent / "test_files" diff --git a/test/preview/dataclasses/test_byte_stream.py b/test/dataclasses/test_byte_stream.py similarity index 100% rename from test/preview/dataclasses/test_byte_stream.py rename to test/dataclasses/test_byte_stream.py diff --git a/test/preview/dataclasses/test_chat_message.py b/test/dataclasses/test_chat_message.py similarity index 100% rename from test/preview/dataclasses/test_chat_message.py rename to test/dataclasses/test_chat_message.py diff --git a/test/preview/dataclasses/test_document.py b/test/dataclasses/test_document.py similarity index 100% rename from test/preview/dataclasses/test_document.py rename to test/dataclasses/test_document.py diff --git a/test/preview/dataclasses/test_streaming_chunk.py b/test/dataclasses/test_streaming_chunk.py similarity index 100% rename from test/preview/dataclasses/test_streaming_chunk.py rename to test/dataclasses/test_streaming_chunk.py diff --git a/test/preview/document_stores/test_in_memory.py b/test/document_stores/test_in_memory.py similarity index 100% rename from test/preview/document_stores/test_in_memory.py rename to test/document_stores/test_in_memory.py diff --git a/test/preview/conftest.py b/test/preview/conftest.py deleted file mode 100644 index 3a2f166120..0000000000 --- a/test/preview/conftest.py +++ /dev/null @@ -1,23 +0,0 @@ -from pathlib import Path -from unittest.mock import Mock -import pytest - -from haystack.preview.testing.test_utils import set_all_seeds - -set_all_seeds(0) - - -@pytest.fixture() -def mock_tokenizer(): - """ - Tokenizes the string by splitting on spaces. - """ - tokenizer = Mock() - tokenizer.encode = lambda text: text.split() - tokenizer.decode = lambda tokens: " ".join(tokens) - return tokenizer - - -@pytest.fixture() -def test_files_path(): - return Path(__file__).parent / "test_files" diff --git a/test/preview/test_files/audio/answer.wav b/test/test_files/audio/answer.wav similarity index 100% rename from test/preview/test_files/audio/answer.wav rename to test/test_files/audio/answer.wav diff --git a/test/preview/test_files/audio/the context for this answer is here.wav b/test/test_files/audio/the context for this answer is here.wav similarity index 100% rename from test/preview/test_files/audio/the context for this answer is here.wav rename to test/test_files/audio/the context for this answer is here.wav diff --git a/test/preview/test_files/audio/this is the content of the document.wav b/test/test_files/audio/this is the content of the document.wav similarity index 100% rename from test/preview/test_files/audio/this is the content of the document.wav rename to test/test_files/audio/this is the content of the document.wav diff --git a/test/preview/test_files/docx/sample_docx.docx b/test/test_files/docx/sample_docx.docx similarity index 100% rename from test/preview/test_files/docx/sample_docx.docx rename to test/test_files/docx/sample_docx.docx diff --git a/test/preview/test_files/html/what_is_haystack.html b/test/test_files/html/what_is_haystack.html similarity index 100% rename from test/preview/test_files/html/what_is_haystack.html rename to test/test_files/html/what_is_haystack.html diff --git a/test/preview/test_files/images/apple.jpg b/test/test_files/images/apple.jpg similarity index 100% rename from test/preview/test_files/images/apple.jpg rename to test/test_files/images/apple.jpg diff --git a/test/preview/test_files/images/haystack-logo.png b/test/test_files/images/haystack-logo.png similarity index 100% rename from test/preview/test_files/images/haystack-logo.png rename to test/test_files/images/haystack-logo.png diff --git a/test/preview/test_files/markdown/sample.md b/test/test_files/markdown/sample.md similarity index 100% rename from test/preview/test_files/markdown/sample.md rename to test/test_files/markdown/sample.md diff --git a/test/preview/test_files/pdf/react_paper.pdf b/test/test_files/pdf/react_paper.pdf similarity index 100% rename from test/preview/test_files/pdf/react_paper.pdf rename to test/test_files/pdf/react_paper.pdf diff --git a/test/preview/test_files/pdf/sample_pdf_1.pdf b/test/test_files/pdf/sample_pdf_1.pdf similarity index 100% rename from test/preview/test_files/pdf/sample_pdf_1.pdf rename to test/test_files/pdf/sample_pdf_1.pdf diff --git a/test/preview/test_files/pdf/sample_pdf_2.pdf b/test/test_files/pdf/sample_pdf_2.pdf similarity index 100% rename from test/preview/test_files/pdf/sample_pdf_2.pdf rename to test/test_files/pdf/sample_pdf_2.pdf diff --git a/test/preview/test_files/txt/doc_1.txt b/test/test_files/txt/doc_1.txt similarity index 100% rename from test/preview/test_files/txt/doc_1.txt rename to test/test_files/txt/doc_1.txt diff --git a/test/preview/test_files/txt/doc_2.txt b/test/test_files/txt/doc_2.txt similarity index 100% rename from test/preview/test_files/txt/doc_2.txt rename to test/test_files/txt/doc_2.txt diff --git a/test/preview/test_files/txt/doc_3.txt b/test/test_files/txt/doc_3.txt similarity index 100% rename from test/preview/test_files/txt/doc_3.txt rename to test/test_files/txt/doc_3.txt diff --git a/test/preview/test_files/yaml/test_pipeline.yaml b/test/test_files/yaml/test_pipeline.yaml similarity index 100% rename from test/preview/test_files/yaml/test_pipeline.yaml rename to test/test_files/yaml/test_pipeline.yaml diff --git a/test/preview/test_pipeline.py b/test/test_pipeline.py similarity index 100% rename from test/preview/test_pipeline.py rename to test/test_pipeline.py diff --git a/test/preview/test_telemetry.py b/test/test_telemetry.py similarity index 100% rename from test/preview/test_telemetry.py rename to test/test_telemetry.py diff --git a/test/preview/testing/test_factory.py b/test/testing/test_factory.py similarity index 100% rename from test/preview/testing/test_factory.py rename to test/testing/test_factory.py diff --git a/test/preview/utils/test_filters.py b/test/utils/test_filters.py similarity index 100% rename from test/preview/utils/test_filters.py rename to test/utils/test_filters.py From ea1e3f588b8e7dad8f009609a5e834dfee6cebd9 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 24 Nov 2023 12:09:47 +0100 Subject: [PATCH 004/397] Update dependencies list --------- Co-authored-by: Silvano Cerza --- pyproject.toml | 170 ++----------------------------------------------- 1 file changed, 7 insertions(+), 163 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8def0a45c3..74c63ba61b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,162 +46,21 @@ classifiers = [ "Topic :: Scientific/Engineering :: Artificial Intelligence", ] dependencies = [ - "requests", - "httpx", - "pydantic<2", - "transformers==4.35.2", - "pandas", - "rank_bm25", - "scikit-learn>=1.3.0", # TF-IDF and metrics - "lazy-imports==0.3.1", # Optional imports - "prompthub-py==4.0.0", - "platformdirs", - - # Utils - "tqdm", # progress bars in model download and training scripts - "networkx", # graphs library - "quantulum3", # quantities extraction from text - "posthog", # telemetry - "tenacity", # retry decorator - "sseclient-py", # server side events for OpenAI streaming - "more_itertools", # utilities - - # Web Retriever - "boilerpy3", - - # Multimodal Embedder haystack/nodes/retriever/multimodal/embedder.py - "Pillow", - - # OpenAI tokenizer - "tiktoken>=0.5.1", - - # Schema validation - "jsonschema", - - # Agent events - "events", - - "requests-cache<1.0.0", -] - -[project.optional-dependencies] -preview = [ - "canals==0.10.1", - "requests", + "canals==0.11.0", + "requests", # needed by canals "pandas", "rank_bm25", "tqdm", "tenacity", "lazy-imports", - "posthog", # telemetry - - "Jinja2", "openai<1.0.0", + "Jinja2", + "posthog", # telemetry "pyyaml", - "more-itertools", # DocumentSplitter -] -inference = [ - "transformers[torch,sentencepiece]==4.35.2", - "sentence-transformers>=2.2.0", # See haystack/nodes/retriever/_embedding_encoder.py, _SentenceTransformersEmbeddingEncoder - "huggingface-hub>=0.5.0", -] -elasticsearch = [ - "farm-haystack[elasticsearch7]", -] -elasticsearch7 = [ - "elasticsearch>=7.17,<8", - "elastic_transport<8" -] -elasticsearch8 = [ - "elasticsearch>=8,<9", - "elastic_transport>=8,<9" -] -sql = [ - "sqlalchemy>=1.4.2,<2", - "sqlalchemy_utils", - "psycopg2-binary; platform_system != 'Windows'", -] -only-faiss = [ - "faiss-cpu>=1.6.3,<=1.7.2", -] -faiss = [ - "farm-haystack[sql,only-faiss]", -] -only-faiss-gpu = [ - "faiss-gpu>=1.6.3,<2", -] -faiss-gpu = [ - "farm-haystack[sql,only-faiss-gpu]", -] -weaviate = [ - "weaviate-client>2", -] -only-pinecone = [ - "pinecone-client>=2.0.11,<3", -] -pinecone = [ - "farm-haystack[sql,only-pinecone]", -] -opensearch = [ - "opensearch-py>=2", -] -docstores = [ - "farm-haystack[elasticsearch,faiss,weaviate,pinecone,opensearch]", -] -docstores-gpu = [ - "farm-haystack[elasticsearch,faiss-gpu,weaviate,pinecone,opensearch]", -] -aws = [ - # first version to support Amazon Bedrock - "boto3>=1.28.57", -] -crawler = [ - "selenium>=4.11.0" -] -preprocessing = [ - "nltk", - "langdetect", # for language classification -] -file-conversion = [ - "azure-ai-formrecognizer>=3.2.0b2", # Microsoft Azure's Form Recognizer service (text and table exctrator) - "python-docx", - "python-pptx", - "tika", # Apache Tika (text & metadata extractor) - "beautifulsoup4", - "markdown", - "python-frontmatter", - "python-magic; platform_system != 'Windows'", # Depends on libmagic: https://pypi.org/project/python-magic/ - "python-magic-bin; platform_system == 'Windows'", # Needs to be installed without python-magic, otherwise Windows CI gets stuck. -] -pdf = [ - "PyMuPDF>=1.18.16" , # PDF text extraction alternative to xpdf; please check AGPLv3 license -] -ocr = [ - "pytesseract>0.3.7", - "pdf2image>1.14", -] -onnx = [ - "onnxruntime", - "onnxruntime_tools", -] -onnx-gpu = [ - "onnxruntime-gpu", - "onnxruntime_tools", -] -metrics = [ # for metrics - "scipy>=1.3.2", - "rapidfuzz>=2.0.15,<2.8.0", # FIXME https://github.com/deepset-ai/haystack/pull/3199 - "seqeval", - "mlflow", -] -ray = [ - "ray[serve]>=1.9.1,<2; platform_system != 'Windows'", - "ray[serve]>=1.9.1,<2,!=1.12.0; platform_system == 'Windows'", # Avoid 1.12.0 due to https://github.com/ray-project/ray/issues/24169 (fails on windows) - "aiorwlock>=1.3.0,<2", -] -colab = [ - "pillow<=9.0.0", + "more-itertools", # TextDocumentSplitter ] + +[project.optional-dependencies] dev = [ "pre-commit", # Type check @@ -218,7 +77,6 @@ dev = [ "psutil", # Linting "pylint", - "farm-haystack[formatting]", # Documentation "toml", "reno", @@ -226,9 +84,6 @@ dev = [ # We pin it here to avoid taking too much time. # https://opendev.org/openstack/reno/src/branch/master/requirements.txt#L7 "dulwich>=0.21.0,<1.0.0", -] - -formatting = [ # Version specified following Black stability policy: # https://black.readthedocs.io/en/stable/the_black_code_style/index.html#stability-policy "black[jupyter]~=23.0", @@ -238,17 +93,6 @@ audio = [ "openai-whisper>=20231106" ] -all = [ - "farm-haystack[inference,docstores,crawler,preprocessing,file-conversion,pdf,ocr,metrics,aws,preview,audio]", -] -all-gpu = [ - # beir is incompatible with faiss-gpu: https://github.com/beir-cellar/beir/issues/71 - "farm-haystack[inference,docstores-gpu,crawler,preprocessing,file-conversion,pdf,ocr,metrics,aws,preview,audio]", -] - -[project.scripts] -haystack = "haystack.cli.entry_point:main" - [project.urls] "CI: GitHub" = "https://github.com/deepset-ai/haystack/actions" "Docs: RTD" = "https://haystack.deepset.ai/overview/intro" From bbb6025e8991909dea2dd065baf7e9d17f387d1d Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 24 Nov 2023 12:14:43 +0100 Subject: [PATCH 005/397] update package name --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 74c63ba61b..053f449bac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = [ build-backend = "hatchling.build" [project] -name = "farm-haystack" +name = "haystack-ai" dynamic = [ "version", ] From e6637f5ec248183155c253255eb54688b89b8767 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Fri, 24 Nov 2023 14:48:43 +0100 Subject: [PATCH 006/397] Fix all tests --- e2e/conftest.py | 152 +- e2e/models_to_cache.txt | 1 - .../pipelines/test_dense_doc_search.py | 19 +- .../pipelines/test_extractive_qa_pipeline.py | 8 +- .../test_hybrid_doc_search_pipeline.py | 12 +- .../pipelines/test_preprocessing_pipeline.py | 16 +- .../pipelines/test_rag_pipelines.py | 16 +- e2e/preview/conftest.py | 11 - e2e/{preview => }/samples/doc_1.txt | 0 e2e/samples/pipelines/async_test_pipeline.yml | 60 - e2e/samples/pipelines/sample_pdf_1.pdf | Bin 44524 -> 0 bytes .../pipelines/test.haystack-pipeline.yml | 43 - e2e/{preview => }/samples/sample_pdf_1.pdf | Bin .../in_memory_bm25_documentsearch.py | 8 +- .../preview/retrievers/in_memory_bm25_rag.py | 14 +- haystack/__init__.py | 4 +- haystack/components/audio/__init__.py | 4 +- haystack/components/audio/whisper_local.py | 4 +- haystack/components/audio/whisper_remote.py | 4 +- haystack/components/builders/__init__.py | 6 +- .../components/builders/answer_builder.py | 2 +- .../builders/dynamic_prompt_builder.py | 22 +- .../components/builders/prompt_builder.py | 4 +- haystack/components/caching/__init__.py | 2 +- .../components/caching/url_cache_checker.py | 4 +- haystack/components/classifiers/__init__.py | 2 +- .../document_language_classifier.py | 4 +- haystack/components/converters/__init__.py | 12 +- haystack/components/converters/azure.py | 4 +- haystack/components/converters/html.py | 8 +- haystack/components/converters/markdown.py | 8 +- haystack/components/converters/pypdf.py | 6 +- haystack/components/converters/tika.py | 4 +- haystack/components/converters/txt.py | 4 +- haystack/components/embedders/__init__.py | 10 +- .../backends/sentence_transformers_backend.py | 2 +- .../embedders/openai_document_embedder.py | 6 +- .../embedders/openai_text_embedder.py | 4 +- ...sentence_transformers_document_embedder.py | 8 +- .../sentence_transformers_text_embedder.py | 6 +- haystack/components/fetchers/__init__.py | 2 +- haystack/components/fetchers/link_content.py | 6 +- haystack/components/generators/__init__.py | 8 +- .../components/generators/chat/__init__.py | 4 +- .../generators/chat/hugging_face_tgi.py | 18 +- haystack/components/generators/chat/openai.py | 10 +- haystack/components/generators/cohere.py | 6 +- haystack/components/generators/hf_utils.py | 2 +- .../generators/hugging_face_local.py | 6 +- .../components/generators/hugging_face_tgi.py | 14 +- haystack/components/generators/openai.py | 8 +- haystack/components/generators/utils.py | 4 +- haystack/components/preprocessors/__init__.py | 4 +- .../preprocessors/document_cleaner.py | 2 +- .../preprocessors/document_splitter.py | 2 +- haystack/components/rankers/__init__.py | 4 +- haystack/components/rankers/meta_field.py | 6 +- .../rankers/transformers_similarity.py | 8 +- haystack/components/readers/__init__.py | 2 +- haystack/components/readers/extractive.py | 4 +- haystack/components/retrievers/__init__.py | 4 +- .../retrievers/in_memory_bm25_retriever.py | 4 +- .../in_memory_embedding_retriever.py | 4 +- haystack/components/routers/__init__.py | 10 +- .../components/routers/conditional_router.py | 8 +- .../components/routers/document_joiner.py | 2 +- .../components/routers/file_type_router.py | 4 +- .../components/routers/metadata_router.py | 4 +- .../routers/text_language_router.py | 4 +- haystack/components/samplers/__init__.py | 2 +- haystack/components/samplers/top_p.py | 8 +- haystack/components/websearch/__init__.py | 4 +- haystack/components/websearch/searchapi.py | 2 +- haystack/components/websearch/serper_dev.py | 2 +- haystack/components/writers/__init__.py | 2 +- .../components/writers/document_writer.py | 4 +- haystack/dataclasses/__init__.py | 12 +- haystack/dataclasses/answer.py | 2 +- haystack/dataclasses/document.py | 2 +- haystack/document_stores/__init__.py | 8 +- .../document_stores/in_memory/__init__.py | 2 +- .../in_memory/document_store.py | 14 +- haystack/document_stores/protocols.py | 2 +- haystack/marshal/__init__.py | 4 +- haystack/pipeline.py | 4 +- haystack/telemetry/__init__.py | 2 +- haystack/telemetry/_environment.py | 2 +- haystack/telemetry/_telemetry.py | 4 +- haystack/testing/document_store.py | 8 +- haystack/testing/factory.py | 6 +- haystack/utils/__init__.py | 6 +- haystack/utils/filters.py | 4 +- haystack/version.py | 6 +- proposals/text/5794-evaluation-haystack-2.py | 12 +- test/components/audio/test_whisper_local.py | 24 +- test/components/audio/test_whisper_remote.py | 46 +- .../builders/test_answer_builder.py | 4 +- .../builders/test_dynamic_prompt_builder.py | 6 +- .../builders/test_prompt_builder.py | 4 +- .../caching/test_url_cache_checker.py | 35 +- .../test_document_language_classifier.py | 4 +- .../test_azure_ocr_doc_converter.py | 22 +- .../converters/test_html_to_document.py | 40 +- .../converters/test_markdown_to_document.py | 24 +- .../converters/test_pypdf_to_document.py | 22 +- .../converters/test_textfile_to_document.py | 28 +- .../converters/test_tika_doc_converter.py | 22 +- .../test_openai_document_embedder.py | 20 +- .../embedders/test_openai_text_embedder.py | 10 +- ...sentence_transformers_document_embedder.py | 14 +- ...sentence_transformers_embedding_backend.py | 8 +- ...est_sentence_transformers_text_embedder.py | 12 +- .../fetchers/test_link_content_fetcher.py | 14 +- test/components/generators/chat/conftest.py | 2 +- .../generators/chat/test_hugging_face_tgi.py | 6 +- .../components/generators/chat/test_openai.py | 22 +- .../generators/test_cohere_generators.py | 10 +- test/components/generators/test_hf_utils.py | 2 +- .../test_hugging_face_local_generator.py | 24 +- .../generators/test_hugging_face_tgi.py | 6 +- test/components/generators/test_openai.py | 22 +- test/components/generators/test_utils.py | 6 +- .../preprocessors/test_document_cleaner.py | 4 +- .../preprocessors/test_document_splitter.py | 4 +- test/components/rankers/test_metafield.py | 8 +- .../rankers/test_transformers_similarity.py | 8 +- test/components/readers/test_extractive.py | 20 +- .../test_in_memory_bm25_retriever.py | 20 +- .../test_in_memory_embedding_retriever.py | 24 +- .../routers/test_conditional_router.py | 27 +- .../routers/test_document_joiner.py | 4 +- test/components/routers/test_file_router.py | 50 +- .../routers/test_metadata_router.py | 4 +- .../routers/test_text_language_router.py | 4 +- test/components/samplers/test_top_p.py | 4 +- test/components/websearch/test_searchapi.py | 8 +- test/components/websearch/test_serperdev.py | 8 +- .../writers/test_document_writer.py | 31 +- test/conftest.py | 2 +- test/dataclasses/test_byte_stream.py | 2 +- test/dataclasses/test_chat_message.py | 2 +- test/dataclasses/test_document.py | 4 +- test/dataclasses/test_streaming_chunk.py | 2 +- test/document_stores/test_in_memory.py | 14 +- test/samples/audio/answer.wav | Bin 29228 -> 0 bytes .../the context for this answer is here.wav | Bin 99884 -> 0 bytes .../this is the content of the document.wav | Bin 89644 -> 0 bytes test/samples/crawler/index.html | 11 - test/samples/crawler/page1.html | 13 - test/samples/crawler/page1_subpage1.html | 9 - test/samples/crawler/page1_subpage2.html | 9 - test/samples/crawler/page2.html | 12 - test/samples/crawler/page2_subpage1.html | 9 - test/samples/crawler/page_dynamic.html | 33 - test/samples/crawler/page_dynamic_result.txt | 29 - test/samples/crawler/page_w_hidden_text.html | 10 - ..._limit_of_the_default_naming_function.html | 1 - test/samples/dc/documents-stream.response | 157 - test/samples/dc/matching_test_1.csv | 2 - test/samples/dc/pipeline_config.json | 81 - test/samples/dc/query_winterfell.response | 26 - test/samples/docs/doc_1.txt | 2 - test/samples/docs/doc_2.txt | 2 - test/samples/docx/sample_docx.docx | Bin 13232 -> 0 bytes test/samples/dpr/sample.json | 1 - test/samples/embeddings/embedding_1.txt | 769 -- test/samples/embeddings/embedding_2.txt | 769 -- test/samples/extensionless_files/docx_file | Bin 11899 -> 0 bytes test/samples/extensionless_files/gif_file | Bin 64 -> 0 bytes test/samples/extensionless_files/html_file | 2 - test/samples/extensionless_files/jpg_file | Bin 6427 -> 0 bytes test/samples/extensionless_files/mp3_file | Bin 2342 -> 0 bytes test/samples/extensionless_files/odt_file | Bin 8277 -> 0 bytes test/samples/extensionless_files/pdf_file | Bin 1117 -> 0 bytes test/samples/extensionless_files/png_file | Bin 4747 -> 0 bytes test/samples/extensionless_files/pptx_file | Bin 32936 -> 0 bytes test/samples/extensionless_files/txt_file | 1 - test/samples/extensionless_files/wav_file | Bin 17718 -> 0 bytes test/samples/extensionless_files/zip_file | Bin 238 -> 0 bytes test/samples/glove/tiny.txt | 10 - test/samples/images/apple.jpg | Bin 69286 -> 0 bytes test/samples/images/car.jpg | Bin 2194280 -> 0 bytes test/samples/images/cat.jpg | Bin 634756 -> 0 bytes test/samples/images/galaxy.jpg | Bin 1788822 -> 0 bytes test/samples/images/paris.jpg | Bin 8498942 -> 0 bytes test/samples/markdown/sample.md | 65 - test/samples/mmr/sample.json | 1014 -- ...mple pdf file with spaces on file name.pdf | Bin 26093 -> 0 bytes test/samples/pdf/sample_pdf_1.pdf | Bin 44524 -> 0 bytes test/samples/pdf/sample_pdf_2.pdf | Bin 26093 -> 0 bytes test/samples/pdf/sample_pdf_3.pdf | Bin 8164 -> 0 bytes test/samples/pdf/sample_pdf_4.pdf | Bin 142786 -> 0 bytes test/samples/pdf/sample_pdf_5.pdf | Bin 2745 -> 0 bytes test/samples/pdf/sample_pdf_6.pdf | Bin 20141 -> 0 bytes .../ray.advanced.haystack-pipeline.yml | 73 - .../pipeline/ray.simple.haystack-pipeline.yml | 52 - .../pipeline/test.haystack-pipeline.yml | 90 - test/samples/pptx/sample_pptx.pptx | Bin 33983 -> 0 bytes .../preprocessor/nltk_models/pt.pickle | Bin 19415 -> 0 bytes .../preprocessor/nltk_models/wrong/en.pickle | 2 - test/samples/qa/answer-offset-wrong.json | 21 - test/samples/qa/answer-wrong.json | 21 - test/samples/qa/dev-sample.json | 1 - test/samples/qa/eval-sample.json | 43 - test/samples/qa/noanswer.json | 21 - test/samples/qa/train-sample.json | 1 - test/samples/qa/vanilla.json | 21 - test/samples/schema/table_answer.json | 35 - test/samples/schema/table_doc.json | 36 - test/samples/schema/table_doc_emb.json | 41 - test/samples/schema/table_label.json | 66 - test/samples/schema/text_answer.json | 22 - test/samples/schema/text_doc.json | 11 - test/samples/schema/text_doc_emb.json | 16 - test/samples/schema/text_label.json | 40 - test/samples/squad/small.json | 10021 ---------------- test/samples/squad/tiny.json | 58 - test/samples/squad/tiny_augmented.json | 1 - test/samples/squad/tiny_passages.json | 33 - test/test_files/yaml/test_pipeline.yaml | 4 +- test/test_pipeline.py | 2 +- test/test_telemetry.py | 10 +- test/testing/test_factory.py | 12 +- test/utils/test_filters.py | 6 +- 224 files changed, 613 insertions(+), 14689 deletions(-) delete mode 100644 e2e/models_to_cache.txt rename e2e/{preview => }/pipelines/test_dense_doc_search.py (84%) rename e2e/{preview => }/pipelines/test_extractive_qa_pipeline.py (90%) rename e2e/{preview => }/pipelines/test_hybrid_doc_search_pipeline.py (83%) rename e2e/{preview => }/pipelines/test_preprocessing_pipeline.py (86%) rename e2e/{preview => }/pipelines/test_rag_pipelines.py (91%) delete mode 100644 e2e/preview/conftest.py rename e2e/{preview => }/samples/doc_1.txt (100%) delete mode 100644 e2e/samples/pipelines/async_test_pipeline.yml delete mode 100644 e2e/samples/pipelines/sample_pdf_1.pdf delete mode 100644 e2e/samples/pipelines/test.haystack-pipeline.yml rename e2e/{preview => }/samples/sample_pdf_1.pdf (100%) delete mode 100644 test/samples/audio/answer.wav delete mode 100644 test/samples/audio/the context for this answer is here.wav delete mode 100644 test/samples/audio/this is the content of the document.wav delete mode 100644 test/samples/crawler/index.html delete mode 100644 test/samples/crawler/page1.html delete mode 100644 test/samples/crawler/page1_subpage1.html delete mode 100644 test/samples/crawler/page1_subpage2.html delete mode 100644 test/samples/crawler/page2.html delete mode 100644 test/samples/crawler/page2_subpage1.html delete mode 100644 test/samples/crawler/page_dynamic.html delete mode 100644 test/samples/crawler/page_dynamic_result.txt delete mode 100644 test/samples/crawler/page_w_hidden_text.html delete mode 100644 test/samples/crawler/page_with_a_very_long_name_to_do_some_tests_Now_let's_add_some_text_just_to_pass_the_129_chars_mark_and_trigger_the_chars_limit_of_the_default_naming_function.html delete mode 100644 test/samples/dc/documents-stream.response delete mode 100644 test/samples/dc/matching_test_1.csv delete mode 100644 test/samples/dc/pipeline_config.json delete mode 100644 test/samples/dc/query_winterfell.response delete mode 100644 test/samples/docs/doc_1.txt delete mode 100644 test/samples/docs/doc_2.txt delete mode 100644 test/samples/docx/sample_docx.docx delete mode 100644 test/samples/dpr/sample.json delete mode 100644 test/samples/embeddings/embedding_1.txt delete mode 100644 test/samples/embeddings/embedding_2.txt delete mode 100644 test/samples/extensionless_files/docx_file delete mode 100644 test/samples/extensionless_files/gif_file delete mode 100644 test/samples/extensionless_files/html_file delete mode 100644 test/samples/extensionless_files/jpg_file delete mode 100644 test/samples/extensionless_files/mp3_file delete mode 100644 test/samples/extensionless_files/odt_file delete mode 100644 test/samples/extensionless_files/pdf_file delete mode 100644 test/samples/extensionless_files/png_file delete mode 100644 test/samples/extensionless_files/pptx_file delete mode 100644 test/samples/extensionless_files/txt_file delete mode 100644 test/samples/extensionless_files/wav_file delete mode 100644 test/samples/extensionless_files/zip_file delete mode 100644 test/samples/glove/tiny.txt delete mode 100644 test/samples/images/apple.jpg delete mode 100644 test/samples/images/car.jpg delete mode 100644 test/samples/images/cat.jpg delete mode 100644 test/samples/images/galaxy.jpg delete mode 100644 test/samples/images/paris.jpg delete mode 100644 test/samples/markdown/sample.md delete mode 100644 test/samples/mmr/sample.json delete mode 100644 test/samples/pdf/sample pdf file with spaces on file name.pdf delete mode 100644 test/samples/pdf/sample_pdf_1.pdf delete mode 100644 test/samples/pdf/sample_pdf_2.pdf delete mode 100644 test/samples/pdf/sample_pdf_3.pdf delete mode 100644 test/samples/pdf/sample_pdf_4.pdf delete mode 100644 test/samples/pdf/sample_pdf_5.pdf delete mode 100644 test/samples/pdf/sample_pdf_6.pdf delete mode 100644 test/samples/pipeline/ray.advanced.haystack-pipeline.yml delete mode 100644 test/samples/pipeline/ray.simple.haystack-pipeline.yml delete mode 100644 test/samples/pipeline/test.haystack-pipeline.yml delete mode 100644 test/samples/pptx/sample_pptx.pptx delete mode 100644 test/samples/preprocessor/nltk_models/pt.pickle delete mode 100644 test/samples/preprocessor/nltk_models/wrong/en.pickle delete mode 100644 test/samples/qa/answer-offset-wrong.json delete mode 100644 test/samples/qa/answer-wrong.json delete mode 100644 test/samples/qa/dev-sample.json delete mode 100644 test/samples/qa/eval-sample.json delete mode 100644 test/samples/qa/noanswer.json delete mode 100644 test/samples/qa/train-sample.json delete mode 100755 test/samples/qa/vanilla.json delete mode 100644 test/samples/schema/table_answer.json delete mode 100644 test/samples/schema/table_doc.json delete mode 100644 test/samples/schema/table_doc_emb.json delete mode 100644 test/samples/schema/table_label.json delete mode 100644 test/samples/schema/text_answer.json delete mode 100644 test/samples/schema/text_doc.json delete mode 100644 test/samples/schema/text_doc_emb.json delete mode 100644 test/samples/schema/text_label.json delete mode 100644 test/samples/squad/small.json delete mode 100644 test/samples/squad/tiny.json delete mode 100644 test/samples/squad/tiny_augmented.json delete mode 100644 test/samples/squad/tiny_passages.json diff --git a/e2e/conftest.py b/e2e/conftest.py index 41d02927e2..c5b7bb08e2 100644 --- a/e2e/conftest.py +++ b/e2e/conftest.py @@ -1,21 +1,7 @@ -import os -import uuid -from contextlib import contextmanager from pathlib import Path import pytest - -from haystack.schema import Document -from haystack.modeling.utils import set_all_seeds -from haystack.document_stores import ( - InMemoryDocumentStore, - ElasticsearchDocumentStore, - WeaviateDocumentStore, - PineconeDocumentStore, - OpenSearchDocumentStore, - FAISSDocumentStore, -) - +from haystack.testing.test_utils import set_all_seeds set_all_seeds(0) @@ -23,139 +9,3 @@ @pytest.fixture def samples_path(): return Path(__file__).parent / "samples" - - -@pytest.fixture -def preview_samples_path(): - return Path(__file__).parent / "preview" / "test_files" - - -@pytest.fixture -def docs_all_formats(): - return [ - # metafield at the top level for backward compatibility - { - "content": "My name is Paul and I live in New York", - "meta_field": "test2", - "name": "filename2", - "date_field": "2019-10-01", - "numeric_field": 5.0, - }, - # "dict" format - { - "content": "My name is Carla and I live in Berlin", - "meta": {"meta_field": "test1", "name": "filename1", "date_field": "2020-03-01", "numeric_field": 5.5}, - }, - # Document object - Document( - content="My name is Christelle and I live in Paris", - meta={"meta_field": "test3", "name": "filename3", "date_field": "2018-10-01", "numeric_field": 4.5}, - ), - Document( - content="My name is Camila and I live in Madrid", - meta={"meta_field": "test4", "name": "filename4", "date_field": "2021-02-01", "numeric_field": 3.0}, - ), - Document( - content="My name is Matteo and I live in Rome", - meta={"meta_field": "test5", "name": "filename5", "date_field": "2019-01-01", "numeric_field": 0.0}, - ), - ] - - -@pytest.fixture -def docs(docs_all_formats): - return [Document.from_dict(doc) if isinstance(doc, dict) else doc for doc in docs_all_formats] - - -@contextmanager -def document_store( - name, - docs, - tmp_path, - embedding_dim=768, - embedding_field="embedding", - index="haystack_test", - similarity="cosine", # cosine is default similarity as dot product is not supported by Weaviate - recreate_index=True, -): - if name == "memory": - document_store = InMemoryDocumentStore( - return_embedding=True, - embedding_dim=embedding_dim, - embedding_field=embedding_field, - index=index, - similarity=similarity, - use_bm25=True, - ) - - elif name == "elasticsearch": - # make sure we start from a fresh index - document_store = ElasticsearchDocumentStore( - index=index, - return_embedding=True, - embedding_dim=embedding_dim, - embedding_field=embedding_field, - similarity=similarity, - recreate_index=recreate_index, - ) - - elif name == "faiss": - document_store = FAISSDocumentStore( - embedding_dim=embedding_dim, - sql_url=f"sqlite:///{tmp_path}/haystack_test.db", - return_embedding=True, - embedding_field=embedding_field, - index=index, - similarity=similarity, - isolation_level="AUTOCOMMIT", - ) - - elif name == "weaviate": - document_store = WeaviateDocumentStore( - index=index, similarity=similarity, embedding_dim=embedding_dim, recreate_index=recreate_index - ) - for d in docs: - d.id = str(uuid.uuid4()) - - elif name == "pinecone": - document_store = PineconeDocumentStore( - api_key=os.environ.get("PINECONE_API_KEY") or "fake-haystack-test-key", - embedding_dim=embedding_dim, - embedding_field=embedding_field, - index=index, - similarity=similarity, - recreate_index=recreate_index, - metadata_config={ - "indexed": [ - "meta_field", - "name", - "date_field", - "numeric_field", - "f1", - "f3", - "meta_id", - "meta_field_for_count", - "meta_key_1", - "meta_key_2", - ] - }, - ) - - elif name == "opensearch_faiss": - document_store = OpenSearchDocumentStore( - index=index, - return_embedding=True, - embedding_dim=embedding_dim, - embedding_field=embedding_field, - similarity=similarity, - recreate_index=recreate_index, - port=9201, - knn_engine="faiss", - ) - - else: - raise Exception(f"No document store fixture for '{name}'") - - document_store.write_documents(docs) - yield document_store - document_store.delete_index(document_store.index) diff --git a/e2e/models_to_cache.txt b/e2e/models_to_cache.txt deleted file mode 100644 index e16bb03169..0000000000 --- a/e2e/models_to_cache.txt +++ /dev/null @@ -1 +0,0 @@ -sentence-transformers/paraphrase-MiniLM-L3-v2 diff --git a/e2e/preview/pipelines/test_dense_doc_search.py b/e2e/pipelines/test_dense_doc_search.py similarity index 84% rename from e2e/preview/pipelines/test_dense_doc_search.py rename to e2e/pipelines/test_dense_doc_search.py index ae2612893d..02f77cd04a 100644 --- a/e2e/preview/pipelines/test_dense_doc_search.py +++ b/e2e/pipelines/test_dense_doc_search.py @@ -1,14 +1,13 @@ import json -from pathlib import Path -from haystack.preview import Pipeline -from haystack.preview.components.embedders import SentenceTransformersDocumentEmbedder, SentenceTransformersTextEmbedder -from haystack.preview.components.converters import PyPDFToDocument, TextFileToDocument -from haystack.preview.components.preprocessors import DocumentCleaner, DocumentSplitter -from haystack.preview.components.routers import FileTypeRouter, DocumentJoiner -from haystack.preview.components.writers import DocumentWriter -from haystack.preview.document_stores import InMemoryDocumentStore -from haystack.preview.components.retrievers import InMemoryEmbeddingRetriever +from haystack import Pipeline +from haystack.components.embedders import SentenceTransformersDocumentEmbedder, SentenceTransformersTextEmbedder +from haystack.components.converters import PyPDFToDocument, TextFileToDocument +from haystack.components.preprocessors import DocumentCleaner, DocumentSplitter +from haystack.components.routers import FileTypeRouter, DocumentJoiner +from haystack.components.writers import DocumentWriter +from haystack.document_stores import InMemoryDocumentStore +from haystack.components.retrievers import InMemoryEmbeddingRetriever def test_dense_doc_search_pipeline(tmp_path, samples_path): @@ -51,7 +50,7 @@ def test_dense_doc_search_pipeline(tmp_path, samples_path): with open(tmp_path / "test_dense_doc_search_indexing_pipeline.json", "r") as f: indexing_pipeline = Pipeline.from_dict(json.load(f)) - indexing_result = indexing_pipeline.run({"file_type_router": {"sources": samples_path.iterdir()}}) + indexing_result = indexing_pipeline.run({"file_type_router": {"sources": list(samples_path.iterdir())}}) filled_document_store = indexing_pipeline.get_component("writer").document_store assert indexing_result["writer"]["documents_written"] == 2 diff --git a/e2e/preview/pipelines/test_extractive_qa_pipeline.py b/e2e/pipelines/test_extractive_qa_pipeline.py similarity index 90% rename from e2e/preview/pipelines/test_extractive_qa_pipeline.py rename to e2e/pipelines/test_extractive_qa_pipeline.py index 5af133dd40..298859d12f 100644 --- a/e2e/preview/pipelines/test_extractive_qa_pipeline.py +++ b/e2e/pipelines/test_extractive_qa_pipeline.py @@ -1,9 +1,9 @@ import json -from haystack.preview import Pipeline, Document -from haystack.preview.document_stores import InMemoryDocumentStore -from haystack.preview.components.retrievers import InMemoryBM25Retriever -from haystack.preview.components.readers import ExtractiveReader +from haystack import Pipeline, Document +from haystack.document_stores import InMemoryDocumentStore +from haystack.components.retrievers import InMemoryBM25Retriever +from haystack.components.readers import ExtractiveReader def test_extractive_qa_pipeline(tmp_path): diff --git a/e2e/preview/pipelines/test_hybrid_doc_search_pipeline.py b/e2e/pipelines/test_hybrid_doc_search_pipeline.py similarity index 83% rename from e2e/preview/pipelines/test_hybrid_doc_search_pipeline.py rename to e2e/pipelines/test_hybrid_doc_search_pipeline.py index e85db341d8..a9ead31b1d 100644 --- a/e2e/preview/pipelines/test_hybrid_doc_search_pipeline.py +++ b/e2e/pipelines/test_hybrid_doc_search_pipeline.py @@ -1,11 +1,11 @@ import json -from haystack.preview import Pipeline, Document -from haystack.preview.components.embedders import SentenceTransformersTextEmbedder -from haystack.preview.components.rankers import TransformersSimilarityRanker -from haystack.preview.components.routers.document_joiner import DocumentJoiner -from haystack.preview.document_stores import InMemoryDocumentStore -from haystack.preview.components.retrievers import InMemoryBM25Retriever, InMemoryEmbeddingRetriever +from haystack import Pipeline, Document +from haystack.components.embedders import SentenceTransformersTextEmbedder +from haystack.components.rankers import TransformersSimilarityRanker +from haystack.components.routers.document_joiner import DocumentJoiner +from haystack.document_stores import InMemoryDocumentStore +from haystack.components.retrievers import InMemoryBM25Retriever, InMemoryEmbeddingRetriever def test_hybrid_doc_search_pipeline(tmp_path): diff --git a/e2e/preview/pipelines/test_preprocessing_pipeline.py b/e2e/pipelines/test_preprocessing_pipeline.py similarity index 86% rename from e2e/preview/pipelines/test_preprocessing_pipeline.py rename to e2e/pipelines/test_preprocessing_pipeline.py index 2f16f1d993..ae56324ea8 100644 --- a/e2e/preview/pipelines/test_preprocessing_pipeline.py +++ b/e2e/pipelines/test_preprocessing_pipeline.py @@ -1,13 +1,13 @@ import json -from haystack.preview import Pipeline -from haystack.preview.components.embedders import SentenceTransformersDocumentEmbedder -from haystack.preview.components.converters import TextFileToDocument -from haystack.preview.components.preprocessors import DocumentSplitter, DocumentCleaner -from haystack.preview.components.classifiers import DocumentLanguageClassifier -from haystack.preview.components.routers import FileTypeRouter, MetadataRouter -from haystack.preview.components.writers import DocumentWriter -from haystack.preview.document_stores import InMemoryDocumentStore +from haystack import Pipeline +from haystack.components.embedders import SentenceTransformersDocumentEmbedder +from haystack.components.converters import TextFileToDocument +from haystack.components.preprocessors import DocumentSplitter, DocumentCleaner +from haystack.components.classifiers import DocumentLanguageClassifier +from haystack.components.routers import FileTypeRouter, MetadataRouter +from haystack.components.writers import DocumentWriter +from haystack.document_stores import InMemoryDocumentStore def test_preprocessing_pipeline(tmp_path): diff --git a/e2e/preview/pipelines/test_rag_pipelines.py b/e2e/pipelines/test_rag_pipelines.py similarity index 91% rename from e2e/preview/pipelines/test_rag_pipelines.py rename to e2e/pipelines/test_rag_pipelines.py index d05c0fabea..9ab11af962 100644 --- a/e2e/preview/pipelines/test_rag_pipelines.py +++ b/e2e/pipelines/test_rag_pipelines.py @@ -2,14 +2,14 @@ import json import pytest -from haystack.preview import Pipeline, Document -from haystack.preview.document_stores import InMemoryDocumentStore -from haystack.preview.components.writers import DocumentWriter -from haystack.preview.components.retrievers import InMemoryBM25Retriever, InMemoryEmbeddingRetriever -from haystack.preview.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder -from haystack.preview.components.generators import GPTGenerator -from haystack.preview.components.builders.answer_builder import AnswerBuilder -from haystack.preview.components.builders.prompt_builder import PromptBuilder +from haystack import Pipeline, Document +from haystack.document_stores import InMemoryDocumentStore +from haystack.components.writers import DocumentWriter +from haystack.components.retrievers import InMemoryBM25Retriever, InMemoryEmbeddingRetriever +from haystack.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder +from haystack.components.generators import GPTGenerator +from haystack.components.builders.answer_builder import AnswerBuilder +from haystack.components.builders.prompt_builder import PromptBuilder @pytest.mark.skipif( diff --git a/e2e/preview/conftest.py b/e2e/preview/conftest.py deleted file mode 100644 index 3ad8d8a746..0000000000 --- a/e2e/preview/conftest.py +++ /dev/null @@ -1,11 +0,0 @@ -from pathlib import Path - -import pytest -from haystack.preview.testing.test_utils import set_all_seeds - -set_all_seeds(0) - - -@pytest.fixture -def samples_path(): - return Path(__file__).parent / "samples" diff --git a/e2e/preview/samples/doc_1.txt b/e2e/samples/doc_1.txt similarity index 100% rename from e2e/preview/samples/doc_1.txt rename to e2e/samples/doc_1.txt diff --git a/e2e/samples/pipelines/async_test_pipeline.yml b/e2e/samples/pipelines/async_test_pipeline.yml deleted file mode 100644 index 3763730087..0000000000 --- a/e2e/samples/pipelines/async_test_pipeline.yml +++ /dev/null @@ -1,60 +0,0 @@ -# This pipeline has been automatically migrated to conform to Haystack 1.15.1. -# Please check that the pipeline is still working as expected. -# In this version: split by paragraphs, new prompt (simplified, opinions rather than facts) - -version: "1.15.1" - -components: - - name: DocumentStore - type: ElasticsearchDocumentStore - - name: BM25Retriever - type: BM25Retriever - params: - document_store: DocumentStore - top_k: 30 - - name: JoinDocuments - type: JoinDocuments - params: - top_k_join: 30 - join_mode: reciprocal_rank_fusion - - name: Reranker - type: SentenceTransformersRanker - params: - model_name_or_path: svalabs/cross-electra-ms-marco-german-uncased - top_k: 8 - - name: QueryClassifier - type: TransformersQueryClassifier - params: - model_name_or_path: deepset/deberta-v3-base-injection - labels: ["LEGIT", "INJECTION"] - - name: qa_template - params: - output_parser: - type: AnswerParser - prompt: "Given this context answer the question:{new_line}\ - '''{join(documents, delimiter=new_line, pattern='Rede[$idx], Datum: $date, Dies ist die Rede von: $politician_name (Partei: $faction): <$content>')}'''{new_line}\ - Question: {query}{new_line}\ - Answer: {new_line}" - type: PromptTemplate - - name: PromptNode - type: Sleeper - - name: FileTypeClassifier - type: FileTypeClassifier - - name: TextConverter - type: TextConverter - - name: PDFConverter - type: PDFToTextConverter - -pipelines: - - name: query - nodes: - - name: QueryClassifier - inputs: [Query] - - name: BM25Retriever - inputs: [QueryClassifier.output_1] - - name: JoinDocuments - inputs: [BM25Retriever] - - name: Reranker - inputs: [JoinDocuments] - - name: PromptNode - inputs: [Reranker] diff --git a/e2e/samples/pipelines/sample_pdf_1.pdf b/e2e/samples/pipelines/sample_pdf_1.pdf deleted file mode 100644 index 87259b897f83b462f521276bf32d210ea008bcd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44524 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

1p2->@_y0X+Ac~V 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 LF=KrFr&;|4#k|z* diff --git a/e2e/samples/pipelines/test.haystack-pipeline.yml b/e2e/samples/pipelines/test.haystack-pipeline.yml deleted file mode 100644 index 42149765bb..0000000000 --- a/e2e/samples/pipelines/test.haystack-pipeline.yml +++ /dev/null @@ -1,43 +0,0 @@ -version: ignore - -components: - - name: Reader - type: FARMReader - params: - no_ans_boost: -10 - model_name_or_path: deepset/bert-medium-squad2-distilled - num_processes: 0 - - name: Retriever - type: BM25Retriever - params: - top_k: 2 - document_store: DocumentStore - - name: DocumentStore - type: ElasticsearchDocumentStore - - name: PDFConverter - type: PDFToTextConverter - params: - remove_numeric_tables: false - - name: Preprocessor - type: PreProcessor - params: - clean_whitespace: true - -pipelines: - - name: query_pipeline - nodes: - - name: Retriever - inputs: [Query] - - name: Reader - inputs: [Retriever] - - - name: indexing_pipeline - nodes: - - name: PDFConverter - inputs: [File] - - name: Preprocessor - inputs: [PDFConverter] - - name: Retriever - inputs: [Preprocessor] - - name: DocumentStore - inputs: [Retriever] diff --git a/e2e/preview/samples/sample_pdf_1.pdf b/e2e/samples/sample_pdf_1.pdf similarity index 100% rename from e2e/preview/samples/sample_pdf_1.pdf rename to e2e/samples/sample_pdf_1.pdf diff --git a/examples/preview/retrievers/in_memory_bm25_documentsearch.py b/examples/preview/retrievers/in_memory_bm25_documentsearch.py index e153bbefa6..734e8bde30 100644 --- a/examples/preview/retrievers/in_memory_bm25_documentsearch.py +++ b/examples/preview/retrievers/in_memory_bm25_documentsearch.py @@ -1,7 +1,7 @@ -from haystack.preview import Document -from haystack.preview.components.retrievers import InMemoryBM25Retriever -from haystack.preview.document_stores import InMemoryDocumentStore -from haystack.preview.pipeline import Pipeline +from haystack import Document +from haystack.components.retrievers import InMemoryBM25Retriever +from haystack.document_stores import InMemoryDocumentStore +from haystack.pipeline import Pipeline # Create components and a query pipeline document_store = InMemoryDocumentStore() diff --git a/examples/preview/retrievers/in_memory_bm25_rag.py b/examples/preview/retrievers/in_memory_bm25_rag.py index ebb9ec5b00..b0a0b33a5d 100644 --- a/examples/preview/retrievers/in_memory_bm25_rag.py +++ b/examples/preview/retrievers/in_memory_bm25_rag.py @@ -1,12 +1,12 @@ import os -from haystack.preview import Document -from haystack.preview import Pipeline -from haystack.preview.components.builders.answer_builder import AnswerBuilder -from haystack.preview.components.builders.prompt_builder import PromptBuilder -from haystack.preview.components.generators import GPTGenerator -from haystack.preview.components.retrievers import InMemoryBM25Retriever -from haystack.preview.document_stores import InMemoryDocumentStore +from haystack import Document +from haystack import Pipeline +from haystack.components.builders.answer_builder import AnswerBuilder +from haystack.components.builders.prompt_builder import PromptBuilder +from haystack.components.generators import GPTGenerator +from haystack.components.retrievers import InMemoryBM25Retriever +from haystack.document_stores import InMemoryDocumentStore # Create a RAG query pipeline prompt_template = """ diff --git a/haystack/__init__.py b/haystack/__init__.py index 4d467a8e0a..618bd0f81e 100644 --- a/haystack/__init__.py +++ b/haystack/__init__.py @@ -1,8 +1,8 @@ from canals import component from canals.serialization import default_from_dict, default_to_dict from canals.errors import DeserializationError, ComponentError -from haystack.preview.pipeline import Pipeline -from haystack.preview.dataclasses import Document, Answer, GeneratedAnswer, ExtractedAnswer +from haystack.pipeline import Pipeline +from haystack.dataclasses import Document, Answer, GeneratedAnswer, ExtractedAnswer __all__ = [ diff --git a/haystack/components/audio/__init__.py b/haystack/components/audio/__init__.py index 3d3b07cd82..ae0d6bfd38 100644 --- a/haystack/components/audio/__init__.py +++ b/haystack/components/audio/__init__.py @@ -1,4 +1,4 @@ -from haystack.preview.components.audio.whisper_local import LocalWhisperTranscriber -from haystack.preview.components.audio.whisper_remote import RemoteWhisperTranscriber +from haystack.components.audio.whisper_local import LocalWhisperTranscriber +from haystack.components.audio.whisper_remote import RemoteWhisperTranscriber __all__ = ["LocalWhisperTranscriber", "RemoteWhisperTranscriber"] diff --git a/haystack/components/audio/whisper_local.py b/haystack/components/audio/whisper_local.py index f45f652df2..516152d003 100644 --- a/haystack/components/audio/whisper_local.py +++ b/haystack/components/audio/whisper_local.py @@ -3,8 +3,8 @@ import logging from pathlib import Path -from haystack.preview import component, Document, default_to_dict, ComponentError -from haystack.preview.lazy_imports import LazyImport +from haystack import component, Document, default_to_dict, ComponentError +from haystack.lazy_imports import LazyImport with LazyImport( "Run 'pip install transformers[torch]' to install torch and " diff --git a/haystack/components/audio/whisper_remote.py b/haystack/components/audio/whisper_remote.py index 848a7c170f..02384e2d43 100644 --- a/haystack/components/audio/whisper_remote.py +++ b/haystack/components/audio/whisper_remote.py @@ -6,8 +6,8 @@ import openai -from haystack.preview import Document, component, default_from_dict, default_to_dict -from haystack.preview.dataclasses import ByteStream +from haystack import Document, component, default_from_dict, default_to_dict +from haystack.dataclasses import ByteStream logger = logging.getLogger(__name__) diff --git a/haystack/components/builders/__init__.py b/haystack/components/builders/__init__.py index 6f47bce0d7..25254d7242 100644 --- a/haystack/components/builders/__init__.py +++ b/haystack/components/builders/__init__.py @@ -1,5 +1,5 @@ -from haystack.preview.components.builders.answer_builder import AnswerBuilder -from haystack.preview.components.builders.prompt_builder import PromptBuilder -from haystack.preview.components.builders.dynamic_prompt_builder import DynamicPromptBuilder +from haystack.components.builders.answer_builder import AnswerBuilder +from haystack.components.builders.prompt_builder import PromptBuilder +from haystack.components.builders.dynamic_prompt_builder import DynamicPromptBuilder __all__ = ["AnswerBuilder", "PromptBuilder", "DynamicPromptBuilder"] diff --git a/haystack/components/builders/answer_builder.py b/haystack/components/builders/answer_builder.py index 0f44a33bc3..1da053511f 100644 --- a/haystack/components/builders/answer_builder.py +++ b/haystack/components/builders/answer_builder.py @@ -2,7 +2,7 @@ import re from typing import List, Dict, Any, Optional -from haystack.preview import component, GeneratedAnswer, Document +from haystack import component, GeneratedAnswer, Document logger = logging.getLogger(__name__) diff --git a/haystack/components/builders/dynamic_prompt_builder.py b/haystack/components/builders/dynamic_prompt_builder.py index 36ba15f804..c8ca6c2ba1 100644 --- a/haystack/components/builders/dynamic_prompt_builder.py +++ b/haystack/components/builders/dynamic_prompt_builder.py @@ -3,9 +3,9 @@ from jinja2 import Template, meta -from haystack.preview import component -from haystack.preview import default_to_dict -from haystack.preview.dataclasses.chat_message import ChatMessage, ChatRole +from haystack import component +from haystack import default_to_dict +from haystack.dataclasses.chat_message import ChatMessage, ChatRole logger = logging.getLogger(__name__) @@ -29,10 +29,10 @@ class DynamicPromptBuilder: The following example demonstrates how to use DynamicPromptBuilder to generate a chat prompt: ```python - from haystack.preview.components.builders import DynamicPromptBuilder - from haystack.preview.components.generators.chat import GPTChatGenerator - from haystack.preview.dataclasses import ChatMessage - from haystack.preview import Pipeline + from haystack.components.builders import DynamicPromptBuilder + from haystack.components.generators.chat import GPTChatGenerator + from haystack.dataclasses import ChatMessage + from haystack import Pipeline # no parameter init, we don't use any runtime template variables prompt_builder = DynamicPromptBuilder() @@ -64,10 +64,10 @@ class DynamicPromptBuilder: of pipeline runtime variables (such as documents): ```python - from haystack.preview.components.builders import DynamicPromptBuilder - from haystack.preview.components.generators.chat import GPTChatGenerator - from haystack.preview.dataclasses import ChatMessage, Document - from haystack.preview import Pipeline, component + from haystack.components.builders import DynamicPromptBuilder + from haystack.components.generators.chat import GPTChatGenerator + from haystack.dataclasses import ChatMessage, Document + from haystack import Pipeline, component from typing import List # we'll use documents runtime variable in our template, so we need to specify it in the init diff --git a/haystack/components/builders/prompt_builder.py b/haystack/components/builders/prompt_builder.py index b6e0da6fb4..b504ba3c38 100644 --- a/haystack/components/builders/prompt_builder.py +++ b/haystack/components/builders/prompt_builder.py @@ -2,8 +2,8 @@ from jinja2 import Template, meta -from haystack.preview import component -from haystack.preview import default_to_dict +from haystack import component +from haystack import default_to_dict @component diff --git a/haystack/components/caching/__init__.py b/haystack/components/caching/__init__.py index d2e8a69c1f..74343a8661 100644 --- a/haystack/components/caching/__init__.py +++ b/haystack/components/caching/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.components.caching.url_cache_checker import UrlCacheChecker +from haystack.components.caching.url_cache_checker import UrlCacheChecker __all__ = ["UrlCacheChecker"] diff --git a/haystack/components/caching/url_cache_checker.py b/haystack/components/caching/url_cache_checker.py index c3d87bcfcc..c4c178f91f 100644 --- a/haystack/components/caching/url_cache_checker.py +++ b/haystack/components/caching/url_cache_checker.py @@ -1,7 +1,7 @@ from typing import List, Dict, Any -from haystack.preview import component, Document, default_from_dict, default_to_dict, DeserializationError -from haystack.preview.document_stores import DocumentStore, document_store +from haystack import component, Document, default_from_dict, default_to_dict, DeserializationError +from haystack.document_stores import DocumentStore, document_store @component diff --git a/haystack/components/classifiers/__init__.py b/haystack/components/classifiers/__init__.py index 6a4cfaee8d..a6173dc3cb 100644 --- a/haystack/components/classifiers/__init__.py +++ b/haystack/components/classifiers/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.components.classifiers.document_language_classifier import DocumentLanguageClassifier +from haystack.components.classifiers.document_language_classifier import DocumentLanguageClassifier __all__ = ["DocumentLanguageClassifier"] diff --git a/haystack/components/classifiers/document_language_classifier.py b/haystack/components/classifiers/document_language_classifier.py index 5a04b4675b..a66aff9439 100644 --- a/haystack/components/classifiers/document_language_classifier.py +++ b/haystack/components/classifiers/document_language_classifier.py @@ -1,8 +1,8 @@ import logging from typing import List, Dict, Optional -from haystack.preview import component, Document -from haystack.preview.lazy_imports import LazyImport +from haystack import component, Document +from haystack.lazy_imports import LazyImport logger = logging.getLogger(__name__) diff --git a/haystack/components/converters/__init__.py b/haystack/components/converters/__init__.py index 62367b2222..0bc40cc05b 100644 --- a/haystack/components/converters/__init__.py +++ b/haystack/components/converters/__init__.py @@ -1,9 +1,9 @@ -from haystack.preview.components.converters.txt import TextFileToDocument -from haystack.preview.components.converters.tika import TikaDocumentConverter -from haystack.preview.components.converters.azure import AzureOCRDocumentConverter -from haystack.preview.components.converters.pypdf import PyPDFToDocument -from haystack.preview.components.converters.html import HTMLToDocument -from haystack.preview.components.converters.markdown import MarkdownToDocument +from haystack.components.converters.txt import TextFileToDocument +from haystack.components.converters.tika import TikaDocumentConverter +from haystack.components.converters.azure import AzureOCRDocumentConverter +from haystack.components.converters.pypdf import PyPDFToDocument +from haystack.components.converters.html import HTMLToDocument +from haystack.components.converters.markdown import MarkdownToDocument __all__ = [ "TextFileToDocument", diff --git a/haystack/components/converters/azure.py b/haystack/components/converters/azure.py index 304078d7d2..da07f51a5d 100644 --- a/haystack/components/converters/azure.py +++ b/haystack/components/converters/azure.py @@ -2,8 +2,8 @@ from typing import List, Union, Dict, Any, Optional import os -from haystack.preview.lazy_imports import LazyImport -from haystack.preview import component, Document, default_to_dict +from haystack.lazy_imports import LazyImport +from haystack import component, Document, default_to_dict with LazyImport(message="Run 'pip install \"azure-ai-formrecognizer>=3.2.0b2\"'") as azure_import: diff --git a/haystack/components/converters/html.py b/haystack/components/converters/html.py index 8b68119b38..e3219aa9fd 100644 --- a/haystack/components/converters/html.py +++ b/haystack/components/converters/html.py @@ -2,9 +2,9 @@ from pathlib import Path from typing import Any, Dict, List, Optional, Union -from haystack.preview import Document, component -from haystack.preview.dataclasses import ByteStream -from haystack.preview.lazy_imports import LazyImport +from haystack import Document, component +from haystack.dataclasses import ByteStream +from haystack.lazy_imports import LazyImport logger = logging.getLogger(__name__) @@ -19,7 +19,7 @@ class HTMLToDocument: Usage example: ```python - from haystack.preview.components.converters.html import HTMLToDocument + from haystack.components.converters.html import HTMLToDocument converter = HTMLToDocument() results = converter.run(sources=["sample.html"]) diff --git a/haystack/components/converters/markdown.py b/haystack/components/converters/markdown.py index 145b78a910..2639010df7 100644 --- a/haystack/components/converters/markdown.py +++ b/haystack/components/converters/markdown.py @@ -4,9 +4,9 @@ from tqdm import tqdm -from haystack.preview import Document, component -from haystack.preview.dataclasses import ByteStream -from haystack.preview.lazy_imports import LazyImport +from haystack import Document, component +from haystack.dataclasses import ByteStream +from haystack.lazy_imports import LazyImport with LazyImport("Run 'pip install markdown-it-py mdit_plain'") as markdown_conversion_imports: from markdown_it import MarkdownIt @@ -23,7 +23,7 @@ class MarkdownToDocument: Usage example: ```python - from haystack.preview.components.converters.markdown import MarkdownToDocument + from haystack.components.converters.markdown import MarkdownToDocument converter = MarkdownToDocument() results = converter.run(sources=["sample.md"]) diff --git a/haystack/components/converters/pypdf.py b/haystack/components/converters/pypdf.py index ede7da3816..9c046374f6 100644 --- a/haystack/components/converters/pypdf.py +++ b/haystack/components/converters/pypdf.py @@ -3,9 +3,9 @@ from typing import List, Union, Protocol, Dict from pathlib import Path -from haystack.preview.dataclasses import ByteStream -from haystack.preview.lazy_imports import LazyImport -from haystack.preview import Document, component, default_to_dict +from haystack.dataclasses import ByteStream +from haystack.lazy_imports import LazyImport +from haystack import Document, component, default_to_dict with LazyImport("Run 'pip install pypdf'") as pypdf_import: from pypdf import PdfReader diff --git a/haystack/components/converters/tika.py b/haystack/components/converters/tika.py index 89f7c217eb..e1047cd72c 100644 --- a/haystack/components/converters/tika.py +++ b/haystack/components/converters/tika.py @@ -2,8 +2,8 @@ from pathlib import Path from typing import List, Union -from haystack.preview.lazy_imports import LazyImport -from haystack.preview import component, Document +from haystack.lazy_imports import LazyImport +from haystack import component, Document with LazyImport("Run 'pip install tika'") as tika_import: diff --git a/haystack/components/converters/txt.py b/haystack/components/converters/txt.py index 2e63f72861..21e93f5bc7 100644 --- a/haystack/components/converters/txt.py +++ b/haystack/components/converters/txt.py @@ -2,8 +2,8 @@ from pathlib import Path from typing import List, Union -from haystack.preview import Document, component -from haystack.preview.dataclasses import ByteStream +from haystack import Document, component +from haystack.dataclasses import ByteStream logger = logging.getLogger(__name__) diff --git a/haystack/components/embedders/__init__.py b/haystack/components/embedders/__init__.py index a0840d7e0a..538da678af 100644 --- a/haystack/components/embedders/__init__.py +++ b/haystack/components/embedders/__init__.py @@ -1,9 +1,7 @@ -from haystack.preview.components.embedders.sentence_transformers_text_embedder import SentenceTransformersTextEmbedder -from haystack.preview.components.embedders.sentence_transformers_document_embedder import ( - SentenceTransformersDocumentEmbedder, -) -from haystack.preview.components.embedders.openai_document_embedder import OpenAIDocumentEmbedder -from haystack.preview.components.embedders.openai_text_embedder import OpenAITextEmbedder +from haystack.components.embedders.sentence_transformers_text_embedder import SentenceTransformersTextEmbedder +from haystack.components.embedders.sentence_transformers_document_embedder import SentenceTransformersDocumentEmbedder +from haystack.components.embedders.openai_document_embedder import OpenAIDocumentEmbedder +from haystack.components.embedders.openai_text_embedder import OpenAITextEmbedder __all__ = [ "SentenceTransformersTextEmbedder", diff --git a/haystack/components/embedders/backends/sentence_transformers_backend.py b/haystack/components/embedders/backends/sentence_transformers_backend.py index 8883c235a4..b9d80a1570 100644 --- a/haystack/components/embedders/backends/sentence_transformers_backend.py +++ b/haystack/components/embedders/backends/sentence_transformers_backend.py @@ -1,6 +1,6 @@ from typing import List, Optional, Union, Dict -from haystack.preview.lazy_imports import LazyImport +from haystack.lazy_imports import LazyImport with LazyImport(message="Run 'pip install \"sentence-transformers>=2.2.0\"'") as sentence_transformers_import: from sentence_transformers import SentenceTransformer diff --git a/haystack/components/embedders/openai_document_embedder.py b/haystack/components/embedders/openai_document_embedder.py index 1a2f1e1f18..6f9afafb5d 100644 --- a/haystack/components/embedders/openai_document_embedder.py +++ b/haystack/components/embedders/openai_document_embedder.py @@ -5,7 +5,7 @@ from tqdm import tqdm -from haystack.preview import component, Document, default_to_dict +from haystack import component, Document, default_to_dict @component @@ -16,8 +16,8 @@ class OpenAIDocumentEmbedder: Usage example: ```python - from haystack.preview import Document - from haystack.preview.components.embedders import OpenAIDocumentEmbedder + from haystack import Document + from haystack.components.embedders import OpenAIDocumentEmbedder doc = Document(text="I love pizza!") diff --git a/haystack/components/embedders/openai_text_embedder.py b/haystack/components/embedders/openai_text_embedder.py index 7be6065a83..599a4a0c4f 100644 --- a/haystack/components/embedders/openai_text_embedder.py +++ b/haystack/components/embedders/openai_text_embedder.py @@ -3,7 +3,7 @@ import openai -from haystack.preview import component, default_to_dict +from haystack import component, default_to_dict @component @@ -13,7 +13,7 @@ class OpenAITextEmbedder: Usage example: ```python - from haystack.preview.components.embedders import OpenAITextEmbedder + from haystack.components.embedders import OpenAITextEmbedder text_to_embed = "I love pizza!" diff --git a/haystack/components/embedders/sentence_transformers_document_embedder.py b/haystack/components/embedders/sentence_transformers_document_embedder.py index 7b7a5ca183..60f2afd042 100644 --- a/haystack/components/embedders/sentence_transformers_document_embedder.py +++ b/haystack/components/embedders/sentence_transformers_document_embedder.py @@ -1,7 +1,7 @@ from typing import List, Optional, Union, Dict, Any -from haystack.preview import component, Document, default_to_dict -from haystack.preview.components.embedders.backends.sentence_transformers_backend import ( +from haystack import component, Document, default_to_dict +from haystack.components.embedders.backends.sentence_transformers_backend import ( _SentenceTransformersEmbeddingBackendFactory, ) @@ -14,8 +14,8 @@ class SentenceTransformersDocumentEmbedder: Usage example: ```python - from haystack.preview import Document - from haystack.preview.components.embedders import SentenceTransformersDocumentEmbedder + from haystack import Document + from haystack.components.embedders import SentenceTransformersDocumentEmbedder doc = Document(text="I love pizza!") doc_embedder = SentenceTransformersDocumentEmbedder() doc_embedder.warm_up() diff --git a/haystack/components/embedders/sentence_transformers_text_embedder.py b/haystack/components/embedders/sentence_transformers_text_embedder.py index badb3997ee..f54331449f 100644 --- a/haystack/components/embedders/sentence_transformers_text_embedder.py +++ b/haystack/components/embedders/sentence_transformers_text_embedder.py @@ -1,7 +1,7 @@ from typing import List, Optional, Union, Dict, Any -from haystack.preview import component, default_to_dict -from haystack.preview.components.embedders.backends.sentence_transformers_backend import ( +from haystack import component, default_to_dict +from haystack.components.embedders.backends.sentence_transformers_backend import ( _SentenceTransformersEmbeddingBackendFactory, ) @@ -13,7 +13,7 @@ class SentenceTransformersTextEmbedder: Usage example: ```python - from haystack.preview.components.embedders import SentenceTransformersTextEmbedder + from haystack.components.embedders import SentenceTransformersTextEmbedder text_to_embed = "I love pizza!" diff --git a/haystack/components/fetchers/__init__.py b/haystack/components/fetchers/__init__.py index f0580d369a..9478884d24 100644 --- a/haystack/components/fetchers/__init__.py +++ b/haystack/components/fetchers/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.components.fetchers.link_content import LinkContentFetcher +from haystack.components.fetchers.link_content import LinkContentFetcher __all__ = ["LinkContentFetcher"] diff --git a/haystack/components/fetchers/link_content.py b/haystack/components/fetchers/link_content.py index 664f716291..e1fee5f718 100644 --- a/haystack/components/fetchers/link_content.py +++ b/haystack/components/fetchers/link_content.py @@ -8,9 +8,9 @@ from requests.exceptions import HTTPError from tenacity import RetryCallState, retry, retry_if_exception_type, stop_after_attempt, wait_exponential -from haystack.preview import component -from haystack.preview.dataclasses import ByteStream -from haystack.preview.version import __version__ +from haystack import component +from haystack.dataclasses import ByteStream +from haystack.version import __version__ logger = logging.getLogger(__name__) diff --git a/haystack/components/generators/__init__.py b/haystack/components/generators/__init__.py index 037ca7b7a5..5466bce2c1 100644 --- a/haystack/components/generators/__init__.py +++ b/haystack/components/generators/__init__.py @@ -1,6 +1,6 @@ -from haystack.preview.components.generators.cohere import CohereGenerator -from haystack.preview.components.generators.hugging_face_local import HuggingFaceLocalGenerator -from haystack.preview.components.generators.hugging_face_tgi import HuggingFaceTGIGenerator -from haystack.preview.components.generators.openai import GPTGenerator +from haystack.components.generators.cohere import CohereGenerator +from haystack.components.generators.hugging_face_local import HuggingFaceLocalGenerator +from haystack.components.generators.hugging_face_tgi import HuggingFaceTGIGenerator +from haystack.components.generators.openai import GPTGenerator __all__ = ["HuggingFaceLocalGenerator", "HuggingFaceTGIGenerator", "GPTGenerator", "CohereGenerator"] diff --git a/haystack/components/generators/chat/__init__.py b/haystack/components/generators/chat/__init__.py index 2126529d83..b28648b5ca 100644 --- a/haystack/components/generators/chat/__init__.py +++ b/haystack/components/generators/chat/__init__.py @@ -1,4 +1,4 @@ -from haystack.preview.components.generators.chat.hugging_face_tgi import HuggingFaceTGIChatGenerator -from haystack.preview.components.generators.chat.openai import GPTChatGenerator +from haystack.components.generators.chat.hugging_face_tgi import HuggingFaceTGIChatGenerator +from haystack.components.generators.chat.openai import GPTChatGenerator __all__ = ["HuggingFaceTGIChatGenerator", "GPTChatGenerator"] diff --git a/haystack/components/generators/chat/hugging_face_tgi.py b/haystack/components/generators/chat/hugging_face_tgi.py index 4d4062ef24..33c28b2403 100644 --- a/haystack/components/generators/chat/hugging_face_tgi.py +++ b/haystack/components/generators/chat/hugging_face_tgi.py @@ -3,11 +3,11 @@ from typing import Any, Dict, List, Optional, Iterable, Callable from urllib.parse import urlparse -from haystack.preview import component, default_to_dict, default_from_dict -from haystack.preview.components.generators.utils import serialize_callback_handler, deserialize_callback_handler -from haystack.preview.dataclasses import ChatMessage, StreamingChunk -from haystack.preview.components.generators.hf_utils import check_valid_model, check_generation_params -from haystack.preview.lazy_imports import LazyImport +from haystack import component, default_to_dict, default_from_dict +from haystack.components.generators.utils import serialize_callback_handler, deserialize_callback_handler +from haystack.dataclasses import ChatMessage, StreamingChunk +from haystack.components.generators.hf_utils import check_valid_model, check_generation_params +from haystack.lazy_imports import LazyImport with LazyImport(message="Run 'pip install transformers'") as transformers_import: from huggingface_hub import InferenceClient @@ -26,8 +26,8 @@ class HuggingFaceTGIChatGenerator: Inference API tier: ```python - from haystack.preview.components.generators.chat import HuggingFaceTGIChatGenerator - from haystack.preview.dataclasses import ChatMessage + from haystack.components.generators.chat import HuggingFaceTGIChatGenerator + from haystack.dataclasses import ChatMessage messages = [ChatMessage.from_system("\nYou are a helpful, respectful and honest assistant"), ChatMessage.from_user("What's Natural Language Processing?")] @@ -43,8 +43,8 @@ class HuggingFaceTGIChatGenerator: endpoint, you'll need to provide the URL of the endpoint as well as a valid token: ```python - from haystack.preview.components.generators.chat import HuggingFaceTGIChatGenerator - from haystack.preview.dataclasses import ChatMessage + from haystack.components.generators.chat import HuggingFaceTGIChatGenerator + from haystack.dataclasses import ChatMessage messages = [ChatMessage.from_system("\nYou are a helpful, respectful and honest assistant"), ChatMessage.from_user("What's Natural Language Processing?")] diff --git a/haystack/components/generators/chat/openai.py b/haystack/components/generators/chat/openai.py index 0b219378ee..1ec2b541e2 100644 --- a/haystack/components/generators/chat/openai.py +++ b/haystack/components/generators/chat/openai.py @@ -6,9 +6,9 @@ import openai from openai.openai_object import OpenAIObject -from haystack.preview import component, default_from_dict, default_to_dict -from haystack.preview.components.generators.utils import serialize_callback_handler, deserialize_callback_handler -from haystack.preview.dataclasses import StreamingChunk, ChatMessage +from haystack import component, default_from_dict, default_to_dict +from haystack.components.generators.utils import serialize_callback_handler, deserialize_callback_handler +from haystack.dataclasses import StreamingChunk, ChatMessage logger = logging.getLogger(__name__) @@ -30,8 +30,8 @@ class GPTChatGenerator: [documentation](https://platform.openai.com/docs/api-reference/chat). ```python - from haystack.preview.components.generators.chat import GPTChatGenerator - from haystack.preview.dataclasses import ChatMessage + from haystack.components.generators.chat import GPTChatGenerator + from haystack.dataclasses import ChatMessage messages = [ChatMessage.from_user("What's Natural Language Processing?")] diff --git a/haystack/components/generators/cohere.py b/haystack/components/generators/cohere.py index ee7106a5b1..36c8fb1379 100644 --- a/haystack/components/generators/cohere.py +++ b/haystack/components/generators/cohere.py @@ -3,8 +3,8 @@ import sys from typing import Any, Callable, Dict, List, Optional -from haystack.preview.lazy_imports import LazyImport -from haystack.preview import DeserializationError, component, default_from_dict, default_to_dict +from haystack.lazy_imports import LazyImport +from haystack import DeserializationError, component, default_from_dict, default_to_dict with LazyImport(message="Run 'pip install cohere'") as cohere_import: from cohere import Client, COHERE_API_URL @@ -22,7 +22,7 @@ class CohereGenerator: Example usage: ```python - from haystack.preview.generators import CohereGenerator + from haystack.generators import CohereGenerator generator = CohereGenerator(api_key="test-api-key") generator.run(prompt="What's the capital of France?") ``` diff --git a/haystack/components/generators/hf_utils.py b/haystack/components/generators/hf_utils.py index 9eca92ae5a..832a996281 100644 --- a/haystack/components/generators/hf_utils.py +++ b/haystack/components/generators/hf_utils.py @@ -1,7 +1,7 @@ import inspect from typing import Any, Dict, List, Optional -from haystack.preview.lazy_imports import LazyImport +from haystack.lazy_imports import LazyImport with LazyImport(message="Run 'pip install transformers'") as transformers_import: from huggingface_hub import InferenceClient, HfApi diff --git a/haystack/components/generators/hugging_face_local.py b/haystack/components/generators/hugging_face_local.py index 91dc639588..e165d80a3a 100644 --- a/haystack/components/generators/hugging_face_local.py +++ b/haystack/components/generators/hugging_face_local.py @@ -2,8 +2,8 @@ from typing import Any, Dict, List, Literal, Optional, Union from copy import deepcopy -from haystack.preview import component, default_to_dict -from haystack.preview.lazy_imports import LazyImport +from haystack import component, default_to_dict +from haystack.lazy_imports import LazyImport logger = logging.getLogger(__name__) @@ -65,7 +65,7 @@ class HuggingFaceLocalGenerator: Usage example: ```python - from haystack.preview.components.generators import HuggingFaceLocalGenerator + from haystack.components.generators import HuggingFaceLocalGenerator generator = HuggingFaceLocalGenerator(model="google/flan-t5-large", task="text2text-generation", diff --git a/haystack/components/generators/hugging_face_tgi.py b/haystack/components/generators/hugging_face_tgi.py index 71dc64acd7..9f23598141 100644 --- a/haystack/components/generators/hugging_face_tgi.py +++ b/haystack/components/generators/hugging_face_tgi.py @@ -3,11 +3,11 @@ from typing import Any, Dict, List, Optional, Iterable, Callable from urllib.parse import urlparse -from haystack.preview import component, default_to_dict, default_from_dict -from haystack.preview.components.generators.utils import serialize_callback_handler, deserialize_callback_handler -from haystack.preview.dataclasses import StreamingChunk -from haystack.preview.components.generators.hf_utils import check_generation_params, check_valid_model -from haystack.preview.lazy_imports import LazyImport +from haystack import component, default_to_dict, default_from_dict +from haystack.components.generators.utils import serialize_callback_handler, deserialize_callback_handler +from haystack.dataclasses import StreamingChunk +from haystack.components.generators.hf_utils import check_generation_params, check_valid_model +from haystack.lazy_imports import LazyImport with LazyImport(message="Run 'pip install transformers'") as transformers_import: from huggingface_hub import InferenceClient @@ -28,7 +28,7 @@ class HuggingFaceTGIGenerator: Inference API tier: ```python - from haystack.preview.components.generators import HuggingFaceTGIGenerator + from haystack.components.generators import HuggingFaceTGIGenerator client = HuggingFaceTGIGenerator(model="mistralai/Mistral-7B-v0.1", token="") client.warm_up() response = client.run("What's Natural Language Processing?", max_new_tokens=120) @@ -39,7 +39,7 @@ class HuggingFaceTGIGenerator: In these two cases, you'll need to provide the URL of the endpoint as well as a valid token: ```python - from haystack.preview.components.generators import HuggingFaceTGIGenerator + from haystack.components.generators import HuggingFaceTGIGenerator client = HuggingFaceTGIGenerator(model="mistralai/Mistral-7B-v0.1", url="", token="") diff --git a/haystack/components/generators/openai.py b/haystack/components/generators/openai.py index 34316637c1..bb4f807bf1 100644 --- a/haystack/components/generators/openai.py +++ b/haystack/components/generators/openai.py @@ -6,9 +6,9 @@ import openai from openai.openai_object import OpenAIObject -from haystack.preview import component, default_from_dict, default_to_dict -from haystack.preview.components.generators.utils import serialize_callback_handler, deserialize_callback_handler -from haystack.preview.dataclasses import StreamingChunk, ChatMessage +from haystack import component, default_from_dict, default_to_dict +from haystack.components.generators.utils import serialize_callback_handler, deserialize_callback_handler +from haystack.dataclasses import StreamingChunk, ChatMessage logger = logging.getLogger(__name__) @@ -30,7 +30,7 @@ class GPTGenerator: [documentation](https://platform.openai.com/docs/api-reference/chat). ```python - from haystack.preview.components.generators import GPTGenerator + from haystack.components.generators import GPTGenerator client = GPTGenerator() response = client.run("What's Natural Language Processing? Be brief.") print(response) diff --git a/haystack/components/generators/utils.py b/haystack/components/generators/utils.py index 397009e4e0..a8113d8676 100644 --- a/haystack/components/generators/utils.py +++ b/haystack/components/generators/utils.py @@ -2,8 +2,8 @@ import sys from typing import Optional, Callable -from haystack.preview import DeserializationError -from haystack.preview.dataclasses import StreamingChunk +from haystack import DeserializationError +from haystack.dataclasses import StreamingChunk def default_streaming_callback(chunk: StreamingChunk) -> None: diff --git a/haystack/components/preprocessors/__init__.py b/haystack/components/preprocessors/__init__.py index 2045621e22..d1ed7a96ec 100644 --- a/haystack/components/preprocessors/__init__.py +++ b/haystack/components/preprocessors/__init__.py @@ -1,4 +1,4 @@ -from haystack.preview.components.preprocessors.document_cleaner import DocumentCleaner -from haystack.preview.components.preprocessors.document_splitter import DocumentSplitter +from haystack.components.preprocessors.document_cleaner import DocumentCleaner +from haystack.components.preprocessors.document_splitter import DocumentSplitter __all__ = ["DocumentSplitter", "DocumentCleaner"] diff --git a/haystack/components/preprocessors/document_cleaner.py b/haystack/components/preprocessors/document_cleaner.py index 370173baca..7a4f0ffd32 100644 --- a/haystack/components/preprocessors/document_cleaner.py +++ b/haystack/components/preprocessors/document_cleaner.py @@ -5,7 +5,7 @@ from itertools import chain from typing import Generator, List, Optional, Set -from haystack.preview import Document, component +from haystack import Document, component logger = logging.getLogger(__name__) diff --git a/haystack/components/preprocessors/document_splitter.py b/haystack/components/preprocessors/document_splitter.py index ecb8a3f11f..8696f3d160 100644 --- a/haystack/components/preprocessors/document_splitter.py +++ b/haystack/components/preprocessors/document_splitter.py @@ -3,7 +3,7 @@ from more_itertools import windowed -from haystack.preview import component, Document +from haystack import component, Document @component diff --git a/haystack/components/rankers/__init__.py b/haystack/components/rankers/__init__.py index f188f01225..d4aeab1d16 100644 --- a/haystack/components/rankers/__init__.py +++ b/haystack/components/rankers/__init__.py @@ -1,4 +1,4 @@ -from haystack.preview.components.rankers.meta_field import MetaFieldRanker -from haystack.preview.components.rankers.transformers_similarity import TransformersSimilarityRanker +from haystack.components.rankers.meta_field import MetaFieldRanker +from haystack.components.rankers.transformers_similarity import TransformersSimilarityRanker __all__ = ["MetaFieldRanker", "TransformersSimilarityRanker"] diff --git a/haystack/components/rankers/meta_field.py b/haystack/components/rankers/meta_field.py index 7c7e4a73cc..b22c1e1b6e 100644 --- a/haystack/components/rankers/meta_field.py +++ b/haystack/components/rankers/meta_field.py @@ -3,7 +3,7 @@ from collections import defaultdict from typing import List, Dict, Any, Optional, Literal -from haystack.preview import ComponentError, Document, component, default_to_dict +from haystack import ComponentError, Document, component, default_to_dict logger = logging.getLogger(__name__) @@ -15,8 +15,8 @@ class MetaFieldRanker: Usage example: ``` - from haystack.preview import Document - from haystack.preview.components.rankers import MetaFieldRanker + from haystack import Document + from haystack.components.rankers import MetaFieldRanker ranker = MetaFieldRanker(metadata_field="rating") docs = [ diff --git a/haystack/components/rankers/transformers_similarity.py b/haystack/components/rankers/transformers_similarity.py index 0c4176a7a1..ce77d2324c 100644 --- a/haystack/components/rankers/transformers_similarity.py +++ b/haystack/components/rankers/transformers_similarity.py @@ -2,8 +2,8 @@ from pathlib import Path from typing import List, Union, Dict, Any, Optional -from haystack.preview import ComponentError, Document, component, default_to_dict -from haystack.preview.lazy_imports import LazyImport +from haystack import ComponentError, Document, component, default_to_dict +from haystack.lazy_imports import LazyImport logger = logging.getLogger(__name__) @@ -21,8 +21,8 @@ class TransformersSimilarityRanker: Usage example: ``` - from haystack.preview import Document - from haystack.preview.components.rankers import TransformersSimilarityRanker + from haystack import Document + from haystack.components.rankers import TransformersSimilarityRanker ranker = TransformersSimilarityRanker() docs = [Document(content="Paris"), Document(content="Berlin")] diff --git a/haystack/components/readers/__init__.py b/haystack/components/readers/__init__.py index e48da38979..3a25921b18 100644 --- a/haystack/components/readers/__init__.py +++ b/haystack/components/readers/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.components.readers.extractive import ExtractiveReader +from haystack.components.readers.extractive import ExtractiveReader __all__ = ["ExtractiveReader"] diff --git a/haystack/components/readers/extractive.py b/haystack/components/readers/extractive.py index 5c763eef94..6cbda5f9f8 100644 --- a/haystack/components/readers/extractive.py +++ b/haystack/components/readers/extractive.py @@ -5,8 +5,8 @@ import logging import os -from haystack.preview import component, default_to_dict, ComponentError, Document, ExtractedAnswer -from haystack.preview.lazy_imports import LazyImport +from haystack import component, default_to_dict, ComponentError, Document, ExtractedAnswer +from haystack.lazy_imports import LazyImport with LazyImport("Run 'pip install transformers[torch,sentencepiece]'") as torch_and_transformers_import: from transformers import AutoModelForQuestionAnswering, AutoTokenizer diff --git a/haystack/components/retrievers/__init__.py b/haystack/components/retrievers/__init__.py index 92e534d58b..b65de67a36 100644 --- a/haystack/components/retrievers/__init__.py +++ b/haystack/components/retrievers/__init__.py @@ -1,4 +1,4 @@ -from haystack.preview.components.retrievers.in_memory_bm25_retriever import InMemoryBM25Retriever -from haystack.preview.components.retrievers.in_memory_embedding_retriever import InMemoryEmbeddingRetriever +from haystack.components.retrievers.in_memory_bm25_retriever import InMemoryBM25Retriever +from haystack.components.retrievers.in_memory_embedding_retriever import InMemoryEmbeddingRetriever __all__ = ["InMemoryBM25Retriever", "InMemoryEmbeddingRetriever"] diff --git a/haystack/components/retrievers/in_memory_bm25_retriever.py b/haystack/components/retrievers/in_memory_bm25_retriever.py index a3f7826123..bf34c0ebfa 100644 --- a/haystack/components/retrievers/in_memory_bm25_retriever.py +++ b/haystack/components/retrievers/in_memory_bm25_retriever.py @@ -1,7 +1,7 @@ from typing import Dict, List, Any, Optional -from haystack.preview import component, Document, default_to_dict, default_from_dict, DeserializationError -from haystack.preview.document_stores import InMemoryDocumentStore, document_store +from haystack import component, Document, default_to_dict, default_from_dict, DeserializationError +from haystack.document_stores import InMemoryDocumentStore, document_store @component diff --git a/haystack/components/retrievers/in_memory_embedding_retriever.py b/haystack/components/retrievers/in_memory_embedding_retriever.py index dad86fdc58..b7332a53a5 100644 --- a/haystack/components/retrievers/in_memory_embedding_retriever.py +++ b/haystack/components/retrievers/in_memory_embedding_retriever.py @@ -1,7 +1,7 @@ from typing import Dict, List, Any, Optional -from haystack.preview import component, Document, default_to_dict, default_from_dict, DeserializationError -from haystack.preview.document_stores import InMemoryDocumentStore, document_store +from haystack import component, Document, default_to_dict, default_from_dict, DeserializationError +from haystack.document_stores import InMemoryDocumentStore, document_store @component diff --git a/haystack/components/routers/__init__.py b/haystack/components/routers/__init__.py index 2da95625fc..65f8b9cb87 100644 --- a/haystack/components/routers/__init__.py +++ b/haystack/components/routers/__init__.py @@ -1,7 +1,7 @@ -from haystack.preview.components.routers.document_joiner import DocumentJoiner -from haystack.preview.components.routers.file_type_router import FileTypeRouter -from haystack.preview.components.routers.metadata_router import MetadataRouter -from haystack.preview.components.routers.conditional_router import ConditionalRouter -from haystack.preview.components.routers.text_language_router import TextLanguageRouter +from haystack.components.routers.document_joiner import DocumentJoiner +from haystack.components.routers.file_type_router import FileTypeRouter +from haystack.components.routers.metadata_router import MetadataRouter +from haystack.components.routers.conditional_router import ConditionalRouter +from haystack.components.routers.text_language_router import TextLanguageRouter __all__ = ["DocumentJoiner", "FileTypeRouter", "MetadataRouter", "TextLanguageRouter", "ConditionalRouter"] diff --git a/haystack/components/routers/conditional_router.py b/haystack/components/routers/conditional_router.py index af96d96ff3..a080dcb346 100644 --- a/haystack/components/routers/conditional_router.py +++ b/haystack/components/routers/conditional_router.py @@ -7,7 +7,7 @@ from jinja2 import meta, Environment, TemplateSyntaxError from jinja2.nativetypes import NativeEnvironment -from haystack.preview import component, default_from_dict, default_to_dict, DeserializationError +from haystack import component, default_from_dict, default_to_dict, DeserializationError logger = logging.getLogger(__name__) @@ -148,7 +148,7 @@ class ConditionalRouter: Here's an example: ```python - from haystack.preview.components.routers import ConditionalRouter + from haystack.components.routers import ConditionalRouter routes = [ { @@ -185,8 +185,8 @@ class ConditionalRouter: ``` from typing import List from haystack import Pipeline - from haystack.preview.dataclasses import ByteStream - from haystack.preview.components.routers import ConditionalRouter + from haystack.dataclasses import ByteStream + from haystack.components.routers import ConditionalRouter routes = [ { diff --git a/haystack/components/routers/document_joiner.py b/haystack/components/routers/document_joiner.py index 96b9b989b2..17c026271e 100644 --- a/haystack/components/routers/document_joiner.py +++ b/haystack/components/routers/document_joiner.py @@ -5,7 +5,7 @@ from typing import List, Optional from canals.component.types import Variadic -from haystack.preview import component, Document +from haystack import component, Document logger = logging.getLogger(__name__) diff --git a/haystack/components/routers/file_type_router.py b/haystack/components/routers/file_type_router.py index e644129706..c9a12d2723 100644 --- a/haystack/components/routers/file_type_router.py +++ b/haystack/components/routers/file_type_router.py @@ -4,8 +4,8 @@ from pathlib import Path from typing import List, Union, Optional, Dict -from haystack.preview import component -from haystack.preview.dataclasses import ByteStream +from haystack import component +from haystack.dataclasses import ByteStream logger = logging.getLogger(__name__) diff --git a/haystack/components/routers/metadata_router.py b/haystack/components/routers/metadata_router.py index f83b1e5542..7f32ea6330 100644 --- a/haystack/components/routers/metadata_router.py +++ b/haystack/components/routers/metadata_router.py @@ -1,7 +1,7 @@ from typing import Dict, List -from haystack.preview import component, Document -from haystack.preview.utils.filters import document_matches_filter, convert +from haystack import component, Document +from haystack.utils.filters import document_matches_filter, convert @component diff --git a/haystack/components/routers/text_language_router.py b/haystack/components/routers/text_language_router.py index 4e8ffd0167..664f342fd4 100644 --- a/haystack/components/routers/text_language_router.py +++ b/haystack/components/routers/text_language_router.py @@ -1,8 +1,8 @@ import logging from typing import List, Dict, Optional -from haystack.preview import component -from haystack.preview.lazy_imports import LazyImport +from haystack import component +from haystack.lazy_imports import LazyImport logger = logging.getLogger(__name__) diff --git a/haystack/components/samplers/__init__.py b/haystack/components/samplers/__init__.py index cab0e878e8..533a404839 100644 --- a/haystack/components/samplers/__init__.py +++ b/haystack/components/samplers/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.components.samplers.top_p import TopPSampler +from haystack.components.samplers.top_p import TopPSampler __all__ = ["TopPSampler"] diff --git a/haystack/components/samplers/top_p.py b/haystack/components/samplers/top_p.py index c3740cbbaa..0eda0aff99 100644 --- a/haystack/components/samplers/top_p.py +++ b/haystack/components/samplers/top_p.py @@ -1,8 +1,8 @@ import logging from typing import List, Optional -from haystack.preview import ComponentError, Document, component -from haystack.preview.lazy_imports import LazyImport +from haystack import ComponentError, Document, component +from haystack.lazy_imports import LazyImport logger = logging.getLogger(__name__) @@ -19,8 +19,8 @@ class TopPSampler: Usage example: ```python - from haystack.preview import Document - from haystack.preview.components.samplers import TopPSampler + from haystack import Document + from haystack.components.samplers import TopPSampler sampler = TopPSampler(top_p=0.95) docs = [ diff --git a/haystack/components/websearch/__init__.py b/haystack/components/websearch/__init__.py index ce20e77857..6d0e930bab 100644 --- a/haystack/components/websearch/__init__.py +++ b/haystack/components/websearch/__init__.py @@ -1,4 +1,4 @@ -from haystack.preview.components.websearch.serper_dev import SerperDevWebSearch -from haystack.preview.components.websearch.searchapi import SearchApiWebSearch +from haystack.components.websearch.serper_dev import SerperDevWebSearch +from haystack.components.websearch.searchapi import SearchApiWebSearch __all__ = ["SerperDevWebSearch", "SearchApiWebSearch"] diff --git a/haystack/components/websearch/searchapi.py b/haystack/components/websearch/searchapi.py index fafe8bd95a..2650502bc1 100644 --- a/haystack/components/websearch/searchapi.py +++ b/haystack/components/websearch/searchapi.py @@ -5,7 +5,7 @@ import requests -from haystack.preview import Document, component, default_to_dict, ComponentError +from haystack import Document, component, default_to_dict, ComponentError logger = logging.getLogger(__name__) diff --git a/haystack/components/websearch/serper_dev.py b/haystack/components/websearch/serper_dev.py index 8b98d3ebc9..288c17d78f 100644 --- a/haystack/components/websearch/serper_dev.py +++ b/haystack/components/websearch/serper_dev.py @@ -5,7 +5,7 @@ import requests -from haystack.preview import Document, component, default_to_dict, ComponentError +from haystack import Document, component, default_to_dict, ComponentError logger = logging.getLogger(__name__) diff --git a/haystack/components/writers/__init__.py b/haystack/components/writers/__init__.py index 8328148352..6a024029c7 100644 --- a/haystack/components/writers/__init__.py +++ b/haystack/components/writers/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.components.writers.document_writer import DocumentWriter +from haystack.components.writers.document_writer import DocumentWriter __all__ = ["DocumentWriter"] diff --git a/haystack/components/writers/document_writer.py b/haystack/components/writers/document_writer.py index 2ce45afde5..297aeb1c48 100644 --- a/haystack/components/writers/document_writer.py +++ b/haystack/components/writers/document_writer.py @@ -1,7 +1,7 @@ from typing import List, Optional, Dict, Any -from haystack.preview import component, Document, default_from_dict, default_to_dict, DeserializationError -from haystack.preview.document_stores import DocumentStore, DuplicatePolicy, document_store +from haystack import component, Document, default_from_dict, default_to_dict, DeserializationError +from haystack.document_stores import DocumentStore, DuplicatePolicy, document_store @component diff --git a/haystack/dataclasses/__init__.py b/haystack/dataclasses/__init__.py index f27204bc4f..ddf491fd3d 100644 --- a/haystack/dataclasses/__init__.py +++ b/haystack/dataclasses/__init__.py @@ -1,9 +1,9 @@ -from haystack.preview.dataclasses.document import Document -from haystack.preview.dataclasses.answer import ExtractedAnswer, GeneratedAnswer, Answer -from haystack.preview.dataclasses.byte_stream import ByteStream -from haystack.preview.dataclasses.chat_message import ChatMessage -from haystack.preview.dataclasses.chat_message import ChatRole -from haystack.preview.dataclasses.streaming_chunk import StreamingChunk +from haystack.dataclasses.document import Document +from haystack.dataclasses.answer import ExtractedAnswer, GeneratedAnswer, Answer +from haystack.dataclasses.byte_stream import ByteStream +from haystack.dataclasses.chat_message import ChatMessage +from haystack.dataclasses.chat_message import ChatRole +from haystack.dataclasses.streaming_chunk import StreamingChunk __all__ = [ "Document", diff --git a/haystack/dataclasses/answer.py b/haystack/dataclasses/answer.py index ed3c1ae0c1..eaa30316ce 100644 --- a/haystack/dataclasses/answer.py +++ b/haystack/dataclasses/answer.py @@ -1,6 +1,6 @@ from typing import Any, Dict, List, Optional from dataclasses import dataclass -from haystack.preview.dataclasses.document import Document +from haystack.dataclasses.document import Document @dataclass(frozen=True) diff --git a/haystack/dataclasses/document.py b/haystack/dataclasses/document.py index 168951edc0..e6cad22a4e 100644 --- a/haystack/dataclasses/document.py +++ b/haystack/dataclasses/document.py @@ -7,7 +7,7 @@ import numpy import pandas -from haystack.preview.dataclasses.byte_stream import ByteStream +from haystack.dataclasses.byte_stream import ByteStream logger = logging.getLogger(__name__) diff --git a/haystack/document_stores/__init__.py b/haystack/document_stores/__init__.py index 632c1f448f..0b7bb80874 100644 --- a/haystack/document_stores/__init__.py +++ b/haystack/document_stores/__init__.py @@ -1,7 +1,7 @@ -from haystack.preview.document_stores.protocols import DocumentStore, DuplicatePolicy -from haystack.preview.document_stores.in_memory.document_store import InMemoryDocumentStore -from haystack.preview.document_stores.errors import DocumentStoreError, DuplicateDocumentError, MissingDocumentError -from haystack.preview.document_stores.decorator import document_store +from haystack.document_stores.protocols import DocumentStore, DuplicatePolicy +from haystack.document_stores.in_memory.document_store import InMemoryDocumentStore +from haystack.document_stores.errors import DocumentStoreError, DuplicateDocumentError, MissingDocumentError +from haystack.document_stores.decorator import document_store __all__ = [ "DocumentStore", diff --git a/haystack/document_stores/in_memory/__init__.py b/haystack/document_stores/in_memory/__init__.py index 5b3644431a..aa576f553b 100644 --- a/haystack/document_stores/in_memory/__init__.py +++ b/haystack/document_stores/in_memory/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.document_stores.in_memory.document_store import InMemoryDocumentStore +from haystack.document_stores.in_memory.document_store import InMemoryDocumentStore __all__ = ["InMemoryDocumentStore"] diff --git a/haystack/document_stores/in_memory/document_store.py b/haystack/document_stores/in_memory/document_store.py index f00c4199bd..2600b35d08 100644 --- a/haystack/document_stores/in_memory/document_store.py +++ b/haystack/document_stores/in_memory/document_store.py @@ -7,13 +7,13 @@ import rank_bm25 from tqdm.auto import tqdm -from haystack.preview import default_from_dict, default_to_dict -from haystack.preview.document_stores.decorator import document_store -from haystack.preview.dataclasses import Document -from haystack.preview.document_stores.protocols import DuplicatePolicy -from haystack.preview.utils.filters import document_matches_filter, convert -from haystack.preview.document_stores.errors import DuplicateDocumentError, DocumentStoreError -from haystack.preview.utils import expit +from haystack import default_from_dict, default_to_dict +from haystack.document_stores.decorator import document_store +from haystack.dataclasses import Document +from haystack.document_stores.protocols import DuplicatePolicy +from haystack.utils.filters import document_matches_filter, convert +from haystack.document_stores.errors import DuplicateDocumentError, DocumentStoreError +from haystack.utils import expit logger = logging.getLogger(__name__) diff --git a/haystack/document_stores/protocols.py b/haystack/document_stores/protocols.py index 6a27f19551..a7e0920c20 100644 --- a/haystack/document_stores/protocols.py +++ b/haystack/document_stores/protocols.py @@ -2,7 +2,7 @@ import logging from enum import Enum -from haystack.preview.dataclasses import Document +from haystack.dataclasses import Document # Ellipsis are needed for the type checker, it's safe to disable module-wide diff --git a/haystack/marshal/__init__.py b/haystack/marshal/__init__.py index f737be0574..53e5955de4 100644 --- a/haystack/marshal/__init__.py +++ b/haystack/marshal/__init__.py @@ -1,4 +1,4 @@ -from haystack.preview.marshal.protocol import Marshaller -from haystack.preview.marshal.yaml import YamlMarshaller +from haystack.marshal.protocol import Marshaller +from haystack.marshal.yaml import YamlMarshaller __all__ = ["Marshaller", "YamlMarshaller"] diff --git a/haystack/pipeline.py b/haystack/pipeline.py index 275277295e..4d9b25bce4 100644 --- a/haystack/pipeline.py +++ b/haystack/pipeline.py @@ -4,8 +4,8 @@ import logging import canals -from haystack.preview.telemetry import pipeline_running -from haystack.preview.marshal import Marshaller, YamlMarshaller +from haystack.telemetry import pipeline_running +from haystack.marshal import Marshaller, YamlMarshaller DEFAULT_MARSHALLER = YamlMarshaller() diff --git a/haystack/telemetry/__init__.py b/haystack/telemetry/__init__.py index be32ab8102..31aeadde14 100644 --- a/haystack/telemetry/__init__.py +++ b/haystack/telemetry/__init__.py @@ -1 +1 @@ -from haystack.preview.telemetry._telemetry import pipeline_running, tutorial_running +from haystack.telemetry._telemetry import pipeline_running, tutorial_running diff --git a/haystack/telemetry/_environment.py b/haystack/telemetry/_environment.py index c450c19320..0b15a9ab60 100644 --- a/haystack/telemetry/_environment.py +++ b/haystack/telemetry/_environment.py @@ -5,7 +5,7 @@ import sys from typing import Optional, Dict, Any -from haystack.preview.version import __version__ +from haystack.version import __version__ logger = logging.getLogger(__name__) diff --git a/haystack/telemetry/_telemetry.py b/haystack/telemetry/_telemetry.py index 24a0e9d9db..9b5d843482 100644 --- a/haystack/telemetry/_telemetry.py +++ b/haystack/telemetry/_telemetry.py @@ -8,10 +8,10 @@ import yaml import posthog -from haystack.preview.telemetry._environment import collect_system_specs +from haystack.telemetry._environment import collect_system_specs if TYPE_CHECKING: - from haystack.preview.pipeline import Pipeline + from haystack.pipeline import Pipeline HAYSTACK_TELEMETRY_ENABLED = "HAYSTACK_TELEMETRY_ENABLED" diff --git a/haystack/testing/document_store.py b/haystack/testing/document_store.py index bb8c1f15fb..9b034f99d5 100644 --- a/haystack/testing/document_store.py +++ b/haystack/testing/document_store.py @@ -5,10 +5,10 @@ import pytest import pandas as pd -from haystack.preview.dataclasses import Document -from haystack.preview.document_stores import DocumentStore, DuplicatePolicy -from haystack.preview.document_stores.errors import DuplicateDocumentError -from haystack.preview.errors import FilterError +from haystack.dataclasses import Document +from haystack.document_stores import DocumentStore, DuplicatePolicy +from haystack.document_stores.errors import DuplicateDocumentError +from haystack.errors import FilterError def _random_embeddings(n): diff --git a/haystack/testing/factory.py b/haystack/testing/factory.py index d36392bfa0..38c14e75b2 100644 --- a/haystack/testing/factory.py +++ b/haystack/testing/factory.py @@ -1,8 +1,8 @@ from typing import Any, Dict, Optional, Tuple, Type, List, Union -from haystack.preview import default_to_dict, default_from_dict -from haystack.preview.dataclasses import Document -from haystack.preview.document_stores import document_store, DocumentStore, DuplicatePolicy +from haystack import default_to_dict, default_from_dict +from haystack.dataclasses import Document +from haystack.document_stores import document_store, DocumentStore, DuplicatePolicy def document_store_class( diff --git a/haystack/utils/__init__.py b/haystack/utils/__init__.py index a84ea468e2..2fcc7c8393 100644 --- a/haystack/utils/__init__.py +++ b/haystack/utils/__init__.py @@ -1,3 +1,3 @@ -from haystack.preview.utils.expit import expit -from haystack.preview.utils.requests_utils import request_with_retry -from haystack.preview.utils.filters import document_matches_filter +from haystack.utils.expit import expit +from haystack.utils.requests_utils import request_with_retry +from haystack.utils.filters import document_matches_filter diff --git a/haystack/utils/filters.py b/haystack/utils/filters.py index 35475c15db..7551594e11 100644 --- a/haystack/utils/filters.py +++ b/haystack/utils/filters.py @@ -4,8 +4,8 @@ import pandas as pd -from haystack.preview.dataclasses import Document -from haystack.preview.errors import FilterError +from haystack.dataclasses import Document +from haystack.errors import FilterError def document_matches_filter(filters: Dict[str, Any], document: Document) -> bool: diff --git a/haystack/version.py b/haystack/version.py index 23a3060671..5d9e899fa2 100644 --- a/haystack/version.py +++ b/haystack/version.py @@ -1,9 +1,9 @@ from importlib import metadata -# haystack.preview is distributed as a separate package called `haystack-ai`. +# haystack is distributed as a separate package called `haystack-ai`. # We want to keep all preview dependencies separate from the current Haystack version, -# so imports in haystack.preview must only import from haystack.preview. -# Since we need to access __version__ in haystack.preview without importing from +# so imports in haystack must only import from haystack. +# Since we need to access __version__ in haystack without importing from # haystack we must set it here too. # When installing `haystack-ai` we want to use that package version though # as `farm-haystack` might not be installed and cause this to fail. diff --git a/proposals/text/5794-evaluation-haystack-2.py b/proposals/text/5794-evaluation-haystack-2.py index c482130207..6997cd5d04 100644 --- a/proposals/text/5794-evaluation-haystack-2.py +++ b/proposals/text/5794-evaluation-haystack-2.py @@ -7,12 +7,12 @@ import os -from haystack.preview import Pipeline -from haystack.preview.dataclasses.document import Document -from haystack.preview.components.retrievers.memory import MemoryBM25Retriever -from haystack.preview.document_stores.memory import MemoryDocumentStore -from haystack.preview.components.generators.openai.gpt35 import GPT35Generator -from haystack.preview.components.builders.prompt_builder import PromptBuilder +from haystack import Pipeline +from haystack.dataclasses.document import Document +from haystack.components.retrievers.memory import MemoryBM25Retriever +from haystack.document_stores.memory import MemoryDocumentStore +from haystack.components.generators.openai.gpt35 import GPT35Generator +from haystack.components.builders.prompt_builder import PromptBuilder docstore = MemoryDocumentStore() diff --git a/test/components/audio/test_whisper_local.py b/test/components/audio/test_whisper_local.py index df23b12018..8b40021a36 100644 --- a/test/components/audio/test_whisper_local.py +++ b/test/components/audio/test_whisper_local.py @@ -5,8 +5,8 @@ import pytest import torch -from haystack.preview.dataclasses import Document -from haystack.preview.components.audio import LocalWhisperTranscriber +from haystack.dataclasses import Document +from haystack.components.audio import LocalWhisperTranscriber SAMPLES_PATH = Path(__file__).parent.parent.parent / "test_files" @@ -32,7 +32,7 @@ def test_to_dict(self): transcriber = LocalWhisperTranscriber() data = transcriber.to_dict() assert data == { - "type": "haystack.preview.components.audio.whisper_local.LocalWhisperTranscriber", + "type": "haystack.components.audio.whisper_local.LocalWhisperTranscriber", "init_parameters": {"model_name_or_path": "large", "device": "cpu", "whisper_params": {}}, } @@ -45,7 +45,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = transcriber.to_dict() assert data == { - "type": "haystack.preview.components.audio.whisper_local.LocalWhisperTranscriber", + "type": "haystack.components.audio.whisper_local.LocalWhisperTranscriber", "init_parameters": { "model_name_or_path": "tiny", "device": "cuda", @@ -55,7 +55,7 @@ def test_to_dict_with_custom_init_parameters(self): @pytest.mark.unit def test_warmup(self): - with patch("haystack.preview.components.audio.whisper_local.whisper") as mocked_whisper: + with patch("haystack.components.audio.whisper_local.whisper") as mocked_whisper: transcriber = LocalWhisperTranscriber(model_name_or_path="large-v2") mocked_whisper.load_model.assert_not_called() transcriber.warm_up() @@ -63,7 +63,7 @@ def test_warmup(self): @pytest.mark.unit def test_warmup_doesnt_reload(self): - with patch("haystack.preview.components.audio.whisper_local.whisper") as mocked_whisper: + with patch("haystack.components.audio.whisper_local.whisper") as mocked_whisper: transcriber = LocalWhisperTranscriber(model_name_or_path="large-v2") transcriber.warm_up() transcriber.warm_up() @@ -144,25 +144,25 @@ def test_transcribe_stream(self): @pytest.mark.integration @pytest.mark.skipif(sys.platform in ["win32", "cygwin"], reason="ffmpeg not installed on Windows CI") - def test_whisper_local_transcriber(self, preview_samples_path): + def test_whisper_local_transcriber(self, test_files_path): comp = LocalWhisperTranscriber(model_name_or_path="medium", whisper_params={"language": "english"}) comp.warm_up() output = comp.run( audio_files=[ - preview_samples_path / "audio" / "this is the content of the document.wav", - str((preview_samples_path / "audio" / "the context for this answer is here.wav").absolute()), - open(preview_samples_path / "audio" / "answer.wav", "rb"), + test_files_path / "audio" / "this is the content of the document.wav", + str((test_files_path / "audio" / "the context for this answer is here.wav").absolute()), + open(test_files_path / "audio" / "answer.wav", "rb"), ] ) docs = output["documents"] assert len(docs) == 3 assert docs[0].content.strip().lower() == "this is the content of the document." - assert preview_samples_path / "audio" / "this is the content of the document.wav" == docs[0].meta["audio_file"] + assert test_files_path / "audio" / "this is the content of the document.wav" == docs[0].meta["audio_file"] assert docs[1].content.strip().lower() == "the context for this answer is here." assert ( - str((preview_samples_path / "audio" / "the context for this answer is here.wav").absolute()) + str((test_files_path / "audio" / "the context for this answer is here.wav").absolute()) == docs[1].meta["audio_file"] ) diff --git a/test/components/audio/test_whisper_remote.py b/test/components/audio/test_whisper_remote.py index df6b8067f5..64f06ee978 100644 --- a/test/components/audio/test_whisper_remote.py +++ b/test/components/audio/test_whisper_remote.py @@ -6,8 +6,8 @@ import pytest from openai.util import convert_to_openai_object -from haystack.preview.components.audio.whisper_remote import RemoteWhisperTranscriber -from haystack.preview.dataclasses import ByteStream +from haystack.components.audio.whisper_remote import RemoteWhisperTranscriber +from haystack.dataclasses import ByteStream def mock_openai_response(response_format="json", **kwargs) -> openai.openai_object.OpenAIObject: @@ -81,7 +81,7 @@ def test_to_dict_default_parameters(self): transcriber = RemoteWhisperTranscriber(api_key="test_api_key") data = transcriber.to_dict() assert data == { - "type": "haystack.preview.components.audio.whisper_remote.RemoteWhisperTranscriber", + "type": "haystack.components.audio.whisper_remote.RemoteWhisperTranscriber", "init_parameters": { "model_name": "whisper-1", "api_base_url": "https://api.openai.com/v1", @@ -104,7 +104,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = transcriber.to_dict() assert data == { - "type": "haystack.preview.components.audio.whisper_remote.RemoteWhisperTranscriber", + "type": "haystack.components.audio.whisper_remote.RemoteWhisperTranscriber", "init_parameters": { "model_name": "whisper-1", "organization": "test-org", @@ -120,7 +120,7 @@ def test_from_dict_with_defualt_parameters(self, monkeypatch): monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") data = { - "type": "haystack.preview.components.audio.whisper_remote.RemoteWhisperTranscriber", + "type": "haystack.components.audio.whisper_remote.RemoteWhisperTranscriber", "init_parameters": { "model_name": "whisper-1", "api_base_url": "https://api.openai.com/v1", @@ -141,7 +141,7 @@ def test_from_dict_with_custom_init_parameters(self, monkeypatch): monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") data = { - "type": "haystack.preview.components.audio.whisper_remote.RemoteWhisperTranscriber", + "type": "haystack.components.audio.whisper_remote.RemoteWhisperTranscriber", "init_parameters": { "model_name": "whisper-1", "organization": "test-org", @@ -170,7 +170,7 @@ def test_from_dict_with_defualt_parameters_no_env_var(self, monkeypatch): monkeypatch.delenv("OPENAI_API_KEY", raising=False) data = { - "type": "haystack.preview.components.audio.whisper_remote.RemoteWhisperTranscriber", + "type": "haystack.components.audio.whisper_remote.RemoteWhisperTranscriber", "init_parameters": { "model_name": "whisper-1", "api_base_url": "https://api.openai.com/v1", @@ -183,10 +183,10 @@ def test_from_dict_with_defualt_parameters_no_env_var(self, monkeypatch): RemoteWhisperTranscriber.from_dict(data) @pytest.mark.unit - def test_run_str(self, preview_samples_path): - with patch("haystack.preview.components.audio.whisper_remote.openai.Audio") as openai_audio_patch: + def test_run_str(self, test_files_path): + with patch("haystack.components.audio.whisper_remote.openai.Audio") as openai_audio_patch: model = "whisper-1" - file_path = str(preview_samples_path / "audio" / "this is the content of the document.wav") + file_path = str(test_files_path / "audio" / "this is the content of the document.wav") openai_audio_patch.transcribe.side_effect = mock_openai_response transcriber = RemoteWhisperTranscriber(api_key="test_api_key", model_name=model, response_format="json") @@ -196,10 +196,10 @@ def test_run_str(self, preview_samples_path): assert result["documents"][0].meta["file_path"] == file_path @pytest.mark.unit - def test_run_path(self, preview_samples_path): - with patch("haystack.preview.components.audio.whisper_remote.openai.Audio") as openai_audio_patch: + def test_run_path(self, test_files_path): + with patch("haystack.components.audio.whisper_remote.openai.Audio") as openai_audio_patch: model = "whisper-1" - file_path = preview_samples_path / "audio" / "this is the content of the document.wav" + file_path = test_files_path / "audio" / "this is the content of the document.wav" openai_audio_patch.transcribe.side_effect = mock_openai_response transcriber = RemoteWhisperTranscriber(api_key="test_api_key", model_name=model, response_format="json") @@ -209,10 +209,10 @@ def test_run_path(self, preview_samples_path): assert result["documents"][0].meta["file_path"] == file_path @pytest.mark.unit - def test_run_bytestream(self, preview_samples_path): - with patch("haystack.preview.components.audio.whisper_remote.openai.Audio") as openai_audio_patch: + def test_run_bytestream(self, test_files_path): + with patch("haystack.components.audio.whisper_remote.openai.Audio") as openai_audio_patch: model = "whisper-1" - file_path = preview_samples_path / "audio" / "this is the content of the document.wav" + file_path = test_files_path / "audio" / "this is the content of the document.wav" openai_audio_patch.transcribe.side_effect = mock_openai_response transcriber = RemoteWhisperTranscriber(api_key="test_api_key", model_name=model, response_format="json") @@ -230,13 +230,13 @@ def test_run_bytestream(self, preview_samples_path): reason="Export an env var called OPENAI_API_KEY containing the OpenAI API key to run this test.", ) @pytest.mark.integration - def test_whisper_remote_transcriber(self, preview_samples_path): + def test_whisper_remote_transcriber(self, test_files_path): transcriber = RemoteWhisperTranscriber(api_key=os.environ.get("OPENAI_API_KEY")) paths = [ - preview_samples_path / "audio" / "this is the content of the document.wav", - str(preview_samples_path / "audio" / "the context for this answer is here.wav"), - ByteStream.from_file_path(preview_samples_path / "audio" / "answer.wav"), + test_files_path / "audio" / "this is the content of the document.wav", + str(test_files_path / "audio" / "the context for this answer is here.wav"), + ByteStream.from_file_path(test_files_path / "audio" / "answer.wav"), ] output = transcriber.run(sources=paths) @@ -244,11 +244,9 @@ def test_whisper_remote_transcriber(self, preview_samples_path): docs = output["documents"] assert len(docs) == 3 assert docs[0].content.strip().lower() == "this is the content of the document." - assert preview_samples_path / "audio" / "this is the content of the document.wav" == docs[0].meta["file_path"] + assert test_files_path / "audio" / "this is the content of the document.wav" == docs[0].meta["file_path"] assert docs[1].content.strip().lower() == "the context for this answer is here." - assert ( - str(preview_samples_path / "audio" / "the context for this answer is here.wav") == docs[1].meta["file_path"] - ) + assert str(test_files_path / "audio" / "the context for this answer is here.wav") == docs[1].meta["file_path"] assert docs[2].content.strip().lower() == "answer." diff --git a/test/components/builders/test_answer_builder.py b/test/components/builders/test_answer_builder.py index 7ce6d56e7b..80f24d7c5b 100644 --- a/test/components/builders/test_answer_builder.py +++ b/test/components/builders/test_answer_builder.py @@ -2,8 +2,8 @@ import pytest -from haystack.preview import GeneratedAnswer, Document -from haystack.preview.components.builders.answer_builder import AnswerBuilder +from haystack import GeneratedAnswer, Document +from haystack.components.builders.answer_builder import AnswerBuilder class TestAnswerBuilder: diff --git a/test/components/builders/test_dynamic_prompt_builder.py b/test/components/builders/test_dynamic_prompt_builder.py index 007040da1e..9fee6b9699 100644 --- a/test/components/builders/test_dynamic_prompt_builder.py +++ b/test/components/builders/test_dynamic_prompt_builder.py @@ -3,8 +3,8 @@ import pytest from jinja2 import TemplateSyntaxError -from haystack.preview.components.builders.dynamic_prompt_builder import DynamicPromptBuilder -from haystack.preview.dataclasses import ChatMessage +from haystack.components.builders.dynamic_prompt_builder import DynamicPromptBuilder +from haystack.dataclasses import ChatMessage class TestDynamicPromptBuilder: @@ -53,7 +53,7 @@ def test_to_dict_method_returns_expected_dictionary(self): chat_mode = True builder = DynamicPromptBuilder(runtime_variables, chat_mode) expected_dict = { - "type": "haystack.preview.components.builders.dynamic_prompt_builder.DynamicPromptBuilder", + "type": "haystack.components.builders.dynamic_prompt_builder.DynamicPromptBuilder", "init_parameters": {"runtime_variables": runtime_variables, "chat_mode": chat_mode}, } assert builder.to_dict() == expected_dict diff --git a/test/components/builders/test_prompt_builder.py b/test/components/builders/test_prompt_builder.py index e43e99bb92..cd98339577 100644 --- a/test/components/builders/test_prompt_builder.py +++ b/test/components/builders/test_prompt_builder.py @@ -1,6 +1,6 @@ import pytest -from haystack.preview.components.builders.prompt_builder import PromptBuilder +from haystack.components.builders.prompt_builder import PromptBuilder @pytest.mark.unit @@ -14,7 +14,7 @@ def test_to_dict(): builder = PromptBuilder(template="This is a {{ variable }}") res = builder.to_dict() assert res == { - "type": "haystack.preview.components.builders.prompt_builder.PromptBuilder", + "type": "haystack.components.builders.prompt_builder.PromptBuilder", "init_parameters": {"template": "This is a {{ variable }}"}, } diff --git a/test/components/caching/test_url_cache_checker.py b/test/components/caching/test_url_cache_checker.py index 1a9487f045..7f58ac9166 100644 --- a/test/components/caching/test_url_cache_checker.py +++ b/test/components/caching/test_url_cache_checker.py @@ -1,9 +1,9 @@ import pytest -from haystack.preview import Document, DeserializationError -from haystack.preview.testing.factory import document_store_class -from haystack.preview.document_stores.in_memory import InMemoryDocumentStore -from haystack.preview.components.caching.url_cache_checker import UrlCacheChecker +from haystack import Document, DeserializationError +from haystack.testing.factory import document_store_class +from haystack.document_stores.in_memory import InMemoryDocumentStore +from haystack.components.caching.url_cache_checker import UrlCacheChecker class TestUrlCacheChecker: @@ -13,12 +13,9 @@ def test_to_dict(self): component = UrlCacheChecker(document_store=mocked_docstore_class()) data = component.to_dict() assert data == { - "type": "haystack.preview.components.caching.url_cache_checker.UrlCacheChecker", + "type": "haystack.components.caching.url_cache_checker.UrlCacheChecker", "init_parameters": { - "document_store": { - "type": "haystack.preview.testing.factory.MockedDocumentStore", - "init_parameters": {}, - }, + "document_store": {"type": "haystack.testing.factory.MockedDocumentStore", "init_parameters": {}}, "url_field": "url", }, } @@ -29,12 +26,9 @@ def test_to_dict_with_custom_init_parameters(self): component = UrlCacheChecker(document_store=mocked_docstore_class(), url_field="my_url_field") data = component.to_dict() assert data == { - "type": "haystack.preview.components.caching.url_cache_checker.UrlCacheChecker", + "type": "haystack.components.caching.url_cache_checker.UrlCacheChecker", "init_parameters": { - "document_store": { - "type": "haystack.preview.testing.factory.MockedDocumentStore", - "init_parameters": {}, - }, + "document_store": {"type": "haystack.testing.factory.MockedDocumentStore", "init_parameters": {}}, "url_field": "my_url_field", }, } @@ -43,12 +37,9 @@ def test_to_dict_with_custom_init_parameters(self): def test_from_dict(self): mocked_docstore_class = document_store_class("MockedDocumentStore") data = { - "type": "haystack.preview.components.caching.url_cache_checker.UrlCacheChecker", + "type": "haystack.components.caching.url_cache_checker.UrlCacheChecker", "init_parameters": { - "document_store": { - "type": "haystack.preview.testing.factory.MockedDocumentStore", - "init_parameters": {}, - }, + "document_store": {"type": "haystack.testing.factory.MockedDocumentStore", "init_parameters": {}}, "url_field": "my_url_field", }, } @@ -58,14 +49,14 @@ def test_from_dict(self): @pytest.mark.unit def test_from_dict_without_docstore(self): - data = {"type": "haystack.preview.components.caching.url_cache_checker.UrlCacheChecker", "init_parameters": {}} + data = {"type": "haystack.components.caching.url_cache_checker.UrlCacheChecker", "init_parameters": {}} with pytest.raises(DeserializationError, match="Missing 'document_store' in serialization data"): UrlCacheChecker.from_dict(data) @pytest.mark.unit def test_from_dict_without_docstore_type(self): data = { - "type": "haystack.preview.components.caching.url_cache_checker.UrlCacheChecker", + "type": "haystack.components.caching.url_cache_checker.UrlCacheChecker", "init_parameters": {"document_store": {"init_parameters": {}}}, } with pytest.raises(DeserializationError, match="Missing 'type' in document store's serialization data"): @@ -74,7 +65,7 @@ def test_from_dict_without_docstore_type(self): @pytest.mark.unit def test_from_dict_nonexisting_docstore(self): data = { - "type": "haystack.preview.components.caching.url_cache_checker.UrlCacheChecker", + "type": "haystack.components.caching.url_cache_checker.UrlCacheChecker", "init_parameters": {"document_store": {"type": "NonexistingDocumentStore", "init_parameters": {}}}, } with pytest.raises(DeserializationError, match="DocumentStore of type 'NonexistingDocumentStore' not found."): diff --git a/test/components/classifiers/test_document_language_classifier.py b/test/components/classifiers/test_document_language_classifier.py index 53214b3633..ac06cdbe2e 100644 --- a/test/components/classifiers/test_document_language_classifier.py +++ b/test/components/classifiers/test_document_language_classifier.py @@ -1,8 +1,8 @@ import logging import pytest -from haystack.preview import Document -from haystack.preview.components.classifiers import DocumentLanguageClassifier +from haystack import Document +from haystack.components.classifiers import DocumentLanguageClassifier class TestDocumentLanguageClassifier: diff --git a/test/components/converters/test_azure_ocr_doc_converter.py b/test/components/converters/test_azure_ocr_doc_converter.py index 83c5075c4b..be7b6fe3c8 100644 --- a/test/components/converters/test_azure_ocr_doc_converter.py +++ b/test/components/converters/test_azure_ocr_doc_converter.py @@ -3,7 +3,7 @@ import pytest -from haystack.preview.components.converters.azure import AzureOCRDocumentConverter +from haystack.components.converters.azure import AzureOCRDocumentConverter class TestAzureOCRDocumentConverter: @@ -18,13 +18,13 @@ def test_to_dict(self): component = AzureOCRDocumentConverter(endpoint="test_endpoint", api_key="test_credential_key") data = component.to_dict() assert data == { - "type": "haystack.preview.components.converters.azure.AzureOCRDocumentConverter", + "type": "haystack.components.converters.azure.AzureOCRDocumentConverter", "init_parameters": {"endpoint": "test_endpoint", "model_id": "prebuilt-read"}, } @pytest.mark.unit - def test_run(self, preview_samples_path): - with patch("haystack.preview.components.converters.azure.DocumentAnalysisClient") as mock_azure_client: + def test_run(self, test_files_path): + with patch("haystack.components.converters.azure.DocumentAnalysisClient") as mock_azure_client: mock_result = Mock(pages=[Mock(lines=[Mock(content="mocked line 1"), Mock(content="mocked line 2")])]) mock_result.to_dict.return_value = { "api_version": "2023-02-28-preview", @@ -35,7 +35,7 @@ def test_run(self, preview_samples_path): mock_azure_client.return_value.begin_analyze_document.return_value.result.return_value = mock_result component = AzureOCRDocumentConverter(endpoint="test_endpoint", api_key="test_credential_key") - output = component.run(paths=[preview_samples_path / "pdf" / "sample_pdf_1.pdf"]) + output = component.run(paths=[test_files_path / "pdf" / "sample_pdf_1.pdf"]) document = output["documents"][0] assert document.content == "mocked line 1\nmocked line 2\n\f" assert "raw_azure_response" in output @@ -49,11 +49,11 @@ def test_run(self, preview_samples_path): @pytest.mark.integration @pytest.mark.skipif(not os.environ.get("CORE_AZURE_CS_ENDPOINT", None), reason="Azure credentials not available") @pytest.mark.skipif(not os.environ.get("CORE_AZURE_CS_API_KEY", None), reason="Azure credentials not available") - def test_run_with_pdf_file(self, preview_samples_path): + def test_run_with_pdf_file(self, test_files_path): component = AzureOCRDocumentConverter( endpoint=os.environ["CORE_AZURE_CS_ENDPOINT"], api_key=os.environ["CORE_AZURE_CS_API_KEY"] ) - output = component.run(paths=[preview_samples_path / "pdf" / "sample_pdf_1.pdf"]) + output = component.run(paths=[test_files_path / "pdf" / "sample_pdf_1.pdf"]) documents = output["documents"] assert len(documents) == 1 assert "A sample PDF file" in documents[0].content @@ -63,11 +63,11 @@ def test_run_with_pdf_file(self, preview_samples_path): @pytest.mark.integration @pytest.mark.skipif(not os.environ.get("CORE_AZURE_CS_ENDPOINT", None), reason="Azure credentials not available") @pytest.mark.skipif(not os.environ.get("CORE_AZURE_CS_API_KEY", None), reason="Azure credentials not available") - def test_with_image_file(self, preview_samples_path): + def test_with_image_file(self, test_files_path): component = AzureOCRDocumentConverter( endpoint=os.environ["CORE_AZURE_CS_ENDPOINT"], api_key=os.environ["CORE_AZURE_CS_API_KEY"] ) - output = component.run(paths=[preview_samples_path / "images" / "haystack-logo.png"]) + output = component.run(paths=[test_files_path / "images" / "haystack-logo.png"]) documents = output["documents"] assert len(documents) == 1 assert "haystack" in documents[0].content @@ -76,11 +76,11 @@ def test_with_image_file(self, preview_samples_path): @pytest.mark.integration @pytest.mark.skipif(not os.environ.get("CORE_AZURE_CS_ENDPOINT", None), reason="Azure credentials not available") @pytest.mark.skipif(not os.environ.get("CORE_AZURE_CS_API_KEY", None), reason="Azure credentials not available") - def test_run_with_docx_file(self, preview_samples_path): + def test_run_with_docx_file(self, test_files_path): component = AzureOCRDocumentConverter( endpoint=os.environ["CORE_AZURE_CS_ENDPOINT"], api_key=os.environ["CORE_AZURE_CS_API_KEY"] ) - output = component.run(paths=[preview_samples_path / "docx" / "sample_docx.docx"]) + output = component.run(paths=[test_files_path / "docx" / "sample_docx.docx"]) documents = output["documents"] assert len(documents) == 1 assert "Sample Docx File" in documents[0].content diff --git a/test/components/converters/test_html_to_document.py b/test/components/converters/test_html_to_document.py index 4e182b279b..4aae469a1e 100644 --- a/test/components/converters/test_html_to_document.py +++ b/test/components/converters/test_html_to_document.py @@ -2,17 +2,17 @@ import pytest -from haystack.preview.components.converters import HTMLToDocument -from haystack.preview.dataclasses import ByteStream +from haystack.components.converters import HTMLToDocument +from haystack.dataclasses import ByteStream class TestHTMLToDocument: @pytest.mark.unit - def test_run(self, preview_samples_path): + def test_run(self, test_files_path): """ Test if the component runs correctly. """ - sources = [preview_samples_path / "html" / "what_is_haystack.html"] + sources = [test_files_path / "html" / "what_is_haystack.html"] converter = HTMLToDocument() results = converter.run(sources=sources) docs = results["documents"] @@ -20,12 +20,12 @@ def test_run(self, preview_samples_path): assert "Haystack" in docs[0].content @pytest.mark.unit - def test_run_doc_metadata(self, preview_samples_path): + def test_run_doc_metadata(self, test_files_path): """ Test if the component runs correctly when metadata is supplied by the user. """ converter = HTMLToDocument() - sources = [preview_samples_path / "html" / "what_is_haystack.html"] + sources = [test_files_path / "html" / "what_is_haystack.html"] metadata = [{"file_name": "what_is_haystack.html"}] results = converter.run(sources=sources, meta=metadata) docs = results["documents"] @@ -35,23 +35,23 @@ def test_run_doc_metadata(self, preview_samples_path): assert docs[0].meta == {"file_name": "what_is_haystack.html"} @pytest.mark.unit - def test_incorrect_meta(self, preview_samples_path): + def test_incorrect_meta(self, test_files_path): """ Test if the component raises an error when incorrect metadata is supplied by the user. """ converter = HTMLToDocument() - sources = [preview_samples_path / "html" / "what_is_haystack.html"] + sources = [test_files_path / "html" / "what_is_haystack.html"] metadata = [{"file_name": "what_is_haystack.html"}, {"file_name": "haystack.html"}] with pytest.raises(ValueError, match="The length of the metadata list must match the number of sources."): converter.run(sources=sources, meta=metadata) @pytest.mark.unit - def test_run_bytestream_metadata(self, preview_samples_path): + def test_run_bytestream_metadata(self, test_files_path): """ Test if the component runs correctly when metadata is read from the ByteStream object. """ converter = HTMLToDocument() - with open(preview_samples_path / "html" / "what_is_haystack.html", "rb") as file: + with open(test_files_path / "html" / "what_is_haystack.html", "rb") as file: byte_stream = file.read() stream = ByteStream(byte_stream, metadata={"content_type": "text/html", "url": "test_url"}) @@ -63,14 +63,14 @@ def test_run_bytestream_metadata(self, preview_samples_path): assert docs[0].meta == {"content_type": "text/html", "url": "test_url"} @pytest.mark.unit - def test_run_bytestream_and_doc_metadata(self, preview_samples_path): + def test_run_bytestream_and_doc_metadata(self, test_files_path): """ Test if the component runs correctly when metadata is read from the ByteStream object and supplied by the user. There is no overlap between the metadata received. """ converter = HTMLToDocument() - with open(preview_samples_path / "html" / "what_is_haystack.html", "rb") as file: + with open(test_files_path / "html" / "what_is_haystack.html", "rb") as file: byte_stream = file.read() stream = ByteStream(byte_stream, metadata={"content_type": "text/html", "url": "test_url"}) @@ -83,7 +83,7 @@ def test_run_bytestream_and_doc_metadata(self, preview_samples_path): assert docs[0].meta == {"file_name": "what_is_haystack.html", "content_type": "text/html", "url": "test_url"} @pytest.mark.unit - def test_run_bytestream_doc_overlapping_metadata(self, preview_samples_path): + def test_run_bytestream_doc_overlapping_metadata(self, test_files_path): """ Test if the component runs correctly when metadata is read from the ByteStream object and supplied by the user. @@ -92,7 +92,7 @@ def test_run_bytestream_doc_overlapping_metadata(self, preview_samples_path): The component should use the supplied metadata to overwrite the values if there is an overlap between the keys. """ converter = HTMLToDocument() - with open(preview_samples_path / "html" / "what_is_haystack.html", "rb") as file: + with open(test_files_path / "html" / "what_is_haystack.html", "rb") as file: byte_stream = file.read() # ByteStream has "url" present in metadata stream = ByteStream(byte_stream, metadata={"content_type": "text/html", "url": "test_url_correct"}) @@ -111,11 +111,11 @@ def test_run_bytestream_doc_overlapping_metadata(self, preview_samples_path): } @pytest.mark.unit - def test_run_wrong_file_type(self, preview_samples_path, caplog): + def test_run_wrong_file_type(self, test_files_path, caplog): """ Test if the component runs correctly when an input file is not of the expected type. """ - sources = [preview_samples_path / "audio" / "answer.wav"] + sources = [test_files_path / "audio" / "answer.wav"] converter = HTMLToDocument() with caplog.at_level(logging.WARNING): results = converter.run(sources=sources) @@ -136,15 +136,15 @@ def test_run_error_handling(self, caplog): assert results["documents"] == [] @pytest.mark.unit - def test_mixed_sources_run(self, preview_samples_path): + def test_mixed_sources_run(self, test_files_path): """ Test if the component runs correctly if the input is a mix of paths and ByteStreams. """ sources = [ - preview_samples_path / "html" / "what_is_haystack.html", - str((preview_samples_path / "html" / "what_is_haystack.html").absolute()), + test_files_path / "html" / "what_is_haystack.html", + str((test_files_path / "html" / "what_is_haystack.html").absolute()), ] - with open(preview_samples_path / "html" / "what_is_haystack.html", "rb") as f: + with open(test_files_path / "html" / "what_is_haystack.html", "rb") as f: byte_stream = f.read() sources.append(ByteStream(byte_stream)) diff --git a/test/components/converters/test_markdown_to_document.py b/test/components/converters/test_markdown_to_document.py index 3dc69429df..b4c669f08e 100644 --- a/test/components/converters/test_markdown_to_document.py +++ b/test/components/converters/test_markdown_to_document.py @@ -2,8 +2,8 @@ import pytest -from haystack.preview.components.converters.markdown import MarkdownToDocument -from haystack.preview.dataclasses import ByteStream +from haystack.components.converters.markdown import MarkdownToDocument +from haystack.dataclasses import ByteStream class TestMarkdownToDocument: @@ -20,9 +20,9 @@ def test_init_params_custom(self): assert converter.progress_bar is False @pytest.mark.integration - def test_run(self, preview_samples_path): + def test_run(self, test_files_path): converter = MarkdownToDocument() - sources = [preview_samples_path / "markdown" / "sample.md"] + sources = [test_files_path / "markdown" / "sample.md"] results = converter.run(sources=sources) docs = results["documents"] @@ -32,9 +32,9 @@ def test_run(self, preview_samples_path): assert "# git clone https://github.com/deepset-ai/haystack.git" in doc.content @pytest.mark.integration - def test_run_metadata(self, preview_samples_path): + def test_run_metadata(self, test_files_path): converter = MarkdownToDocument() - sources = [preview_samples_path / "markdown" / "sample.md"] + sources = [test_files_path / "markdown" / "sample.md"] metadata = [{"file_name": "sample.md"}] results = converter.run(sources=sources, meta=metadata) docs = results["documents"] @@ -46,11 +46,11 @@ def test_run_metadata(self, preview_samples_path): assert doc.meta == {"file_name": "sample.md"} @pytest.mark.integration - def test_run_wrong_file_type(self, preview_samples_path, caplog): + def test_run_wrong_file_type(self, test_files_path, caplog): """ Test if the component runs correctly when an input file is not of the expected type. """ - sources = [preview_samples_path / "audio" / "answer.wav"] + sources = [test_files_path / "audio" / "answer.wav"] converter = MarkdownToDocument() with caplog.at_level(logging.WARNING): output = converter.run(sources=sources) @@ -72,15 +72,15 @@ def test_run_error_handling(self, caplog): assert not result["documents"] @pytest.mark.unit - def test_mixed_sources_run(self, preview_samples_path): + def test_mixed_sources_run(self, test_files_path): """ Test if the component runs correctly if the input is a mix of strings, paths and ByteStreams. """ sources = [ - preview_samples_path / "markdown" / "sample.md", - str((preview_samples_path / "markdown" / "sample.md").absolute()), + test_files_path / "markdown" / "sample.md", + str((test_files_path / "markdown" / "sample.md").absolute()), ] - with open(preview_samples_path / "markdown" / "sample.md", "rb") as f: + with open(test_files_path / "markdown" / "sample.md", "rb") as f: byte_stream = f.read() sources.append(ByteStream(byte_stream)) diff --git a/test/components/converters/test_pypdf_to_document.py b/test/components/converters/test_pypdf_to_document.py index e7fb0202fb..4a0ce9e903 100644 --- a/test/components/converters/test_pypdf_to_document.py +++ b/test/components/converters/test_pypdf_to_document.py @@ -2,9 +2,9 @@ import pytest from pypdf import PdfReader -from haystack.preview import Document -from haystack.preview.components.converters.pypdf import PyPDFToDocument, CONVERTERS_REGISTRY -from haystack.preview.dataclasses import ByteStream +from haystack import Document +from haystack.components.converters.pypdf import PyPDFToDocument, CONVERTERS_REGISTRY +from haystack.dataclasses import ByteStream class TestPyPDFToDocument: @@ -18,11 +18,11 @@ def test_init_fail_nonexisting_converter(self): PyPDFToDocument(converter_name="non_existing_converter") @pytest.mark.unit - def test_run(self, preview_samples_path): + def test_run(self, test_files_path): """ Test if the component runs correctly. """ - paths = [preview_samples_path / "pdf" / "react_paper.pdf"] + paths = [test_files_path / "pdf" / "react_paper.pdf"] converter = PyPDFToDocument() output = converter.run(sources=paths) docs = output["documents"] @@ -30,7 +30,7 @@ def test_run(self, preview_samples_path): assert "ReAct" in docs[0].content @pytest.mark.unit - def test_run_error_handling(self, preview_samples_path, caplog): + def test_run_error_handling(self, test_files_path, caplog): """ Test if the component correctly handles errors. """ @@ -41,12 +41,12 @@ def test_run_error_handling(self, preview_samples_path, caplog): assert "Could not read non_existing_file.pdf" in caplog.text @pytest.mark.unit - def test_mixed_sources_run(self, preview_samples_path): + def test_mixed_sources_run(self, test_files_path): """ Test if the component runs correctly when mixed sources are provided. """ - paths = [preview_samples_path / "pdf" / "react_paper.pdf"] - with open(preview_samples_path / "pdf" / "react_paper.pdf", "rb") as f: + paths = [test_files_path / "pdf" / "react_paper.pdf"] + with open(test_files_path / "pdf" / "react_paper.pdf", "rb") as f: paths.append(ByteStream(f.read())) converter = PyPDFToDocument() @@ -57,11 +57,11 @@ def test_mixed_sources_run(self, preview_samples_path): assert "ReAct" in docs[1].content @pytest.mark.unit - def test_custom_converter(self, preview_samples_path): + def test_custom_converter(self, test_files_path): """ Test if the component correctly handles custom converters. """ - paths = [preview_samples_path / "pdf" / "react_paper.pdf"] + paths = [test_files_path / "pdf" / "react_paper.pdf"] class MyCustomConverter: def convert(self, reader: PdfReader) -> Document: diff --git a/test/components/converters/test_textfile_to_document.py b/test/components/converters/test_textfile_to_document.py index aafa77d1e2..415d897179 100644 --- a/test/components/converters/test_textfile_to_document.py +++ b/test/components/converters/test_textfile_to_document.py @@ -4,24 +4,20 @@ import pytest -from haystack.preview.dataclasses import ByteStream -from haystack.preview.components.converters.txt import TextFileToDocument +from haystack.dataclasses import ByteStream +from haystack.components.converters.txt import TextFileToDocument class TestTextfileToDocument: @pytest.mark.unit - def test_run(self, preview_samples_path): + def test_run(self, test_files_path): """ Test if the component runs correctly. """ - bytestream = ByteStream.from_file_path(preview_samples_path / "txt" / "doc_3.txt") - bytestream.metadata["file_path"] = str(preview_samples_path / "txt" / "doc_3.txt") + bytestream = ByteStream.from_file_path(test_files_path / "txt" / "doc_3.txt") + bytestream.metadata["file_path"] = str(test_files_path / "txt" / "doc_3.txt") bytestream.metadata["key"] = "value" - files = [ - str(preview_samples_path / "txt" / "doc_1.txt"), - preview_samples_path / "txt" / "doc_2.txt", - bytestream, - ] + files = [str(test_files_path / "txt" / "doc_1.txt"), test_files_path / "txt" / "doc_2.txt", bytestream] converter = TextFileToDocument() output = converter.run(sources=files) docs = output["documents"] @@ -34,15 +30,11 @@ def test_run(self, preview_samples_path): assert docs[2].meta == bytestream.metadata @pytest.mark.unit - def test_run_error_handling(self, preview_samples_path, caplog): + def test_run_error_handling(self, test_files_path, caplog): """ Test if the component correctly handles errors. """ - paths = [ - preview_samples_path / "txt" / "doc_1.txt", - "non_existing_file.txt", - preview_samples_path / "txt" / "doc_3.txt", - ] + paths = [test_files_path / "txt" / "doc_1.txt", "non_existing_file.txt", test_files_path / "txt" / "doc_3.txt"] converter = TextFileToDocument() with caplog.at_level(logging.WARNING): output = converter.run(sources=paths) @@ -53,11 +45,11 @@ def test_run_error_handling(self, preview_samples_path, caplog): assert docs[1].meta["file_path"] == str(paths[2]) @pytest.mark.unit - def test_encoding_override(self, preview_samples_path): + def test_encoding_override(self, test_files_path): """ Test if the encoding metadata field is used properly """ - bytestream = ByteStream.from_file_path(preview_samples_path / "txt" / "doc_1.txt") + bytestream = ByteStream.from_file_path(test_files_path / "txt" / "doc_1.txt") bytestream.metadata["key"] = "value" converter = TextFileToDocument(encoding="utf-16") diff --git a/test/components/converters/test_tika_doc_converter.py b/test/components/converters/test_tika_doc_converter.py index c346c4bf95..527e734e12 100644 --- a/test/components/converters/test_tika_doc_converter.py +++ b/test/components/converters/test_tika_doc_converter.py @@ -2,14 +2,14 @@ import pytest -from haystack.preview.components.converters.tika import TikaDocumentConverter +from haystack.components.converters.tika import TikaDocumentConverter class TestTikaDocumentConverter: @pytest.mark.unit def test_run(self): component = TikaDocumentConverter() - with patch("haystack.preview.components.converters.tika.tika_parser.from_file") as mock_tika_parser: + with patch("haystack.components.converters.tika.tika_parser.from_file") as mock_tika_parser: mock_tika_parser.return_value = {"content": "Content of mock_file.pdf"} documents = component.run(paths=["mock_file.pdf"])["documents"] @@ -19,7 +19,7 @@ def test_run(self): @pytest.mark.unit def test_run_logs_warning_if_content_empty(self, caplog): component = TikaDocumentConverter() - with patch("haystack.preview.components.converters.tika.tika_parser.from_file") as mock_tika_parser: + with patch("haystack.components.converters.tika.tika_parser.from_file") as mock_tika_parser: mock_tika_parser.return_value = {"content": ""} with caplog.at_level("WARNING"): component.run(paths=["mock_file.pdf"]) @@ -28,28 +28,26 @@ def test_run_logs_warning_if_content_empty(self, caplog): @pytest.mark.unit def test_run_logs_error(self, caplog): component = TikaDocumentConverter() - with patch("haystack.preview.components.converters.tika.tika_parser.from_file") as mock_tika_parser: + with patch("haystack.components.converters.tika.tika_parser.from_file") as mock_tika_parser: mock_tika_parser.side_effect = Exception("Some error") with caplog.at_level("ERROR"): component.run(paths=["mock_file.pdf"]) assert "Could not convert file at 'mock_file.pdf' to Document. Error: Some error" in caplog.text @pytest.mark.integration - def test_run_with_txt_files(self, preview_samples_path): + def test_run_with_txt_files(self, test_files_path): component = TikaDocumentConverter() - output = component.run( - paths=[preview_samples_path / "txt" / "doc_1.txt", preview_samples_path / "txt" / "doc_2.txt"] - ) + output = component.run(paths=[test_files_path / "txt" / "doc_1.txt", test_files_path / "txt" / "doc_2.txt"]) documents = output["documents"] assert len(documents) == 2 assert "Some text for testing.\nTwo lines in here." in documents[0].content assert "This is a test line.\n123 456 789\n987 654 321" in documents[1].content @pytest.mark.integration - def test_run_with_pdf_file(self, preview_samples_path): + def test_run_with_pdf_file(self, test_files_path): component = TikaDocumentConverter() output = component.run( - paths=[preview_samples_path / "pdf" / "sample_pdf_1.pdf", preview_samples_path / "pdf" / "sample_pdf_2.pdf"] + paths=[test_files_path / "pdf" / "sample_pdf_1.pdf", test_files_path / "pdf" / "sample_pdf_2.pdf"] ) documents = output["documents"] assert len(documents) == 2 @@ -65,9 +63,9 @@ def test_run_with_pdf_file(self, preview_samples_path): assert "This would make it easier for other users to find the article." in documents[1].content @pytest.mark.integration - def test_run_with_docx_file(self, preview_samples_path): + def test_run_with_docx_file(self, test_files_path): component = TikaDocumentConverter() - output = component.run(paths=[preview_samples_path / "docx" / "sample_docx.docx"]) + output = component.run(paths=[test_files_path / "docx" / "sample_docx.docx"]) documents = output["documents"] assert len(documents) == 1 assert "Sample Docx File" in documents[0].content diff --git a/test/components/embedders/test_openai_document_embedder.py b/test/components/embedders/test_openai_document_embedder.py index 954846c480..c98dd27653 100644 --- a/test/components/embedders/test_openai_document_embedder.py +++ b/test/components/embedders/test_openai_document_embedder.py @@ -7,8 +7,8 @@ from openai.util import convert_to_openai_object from openai.openai_object import OpenAIObject -from haystack.preview import Document -from haystack.preview.components.embedders.openai_document_embedder import OpenAIDocumentEmbedder +from haystack import Document +from haystack.components.embedders.openai_document_embedder import OpenAIDocumentEmbedder def mock_openai_response(input: List[str], model: str = "text-embedding-ada-002", **kwargs) -> OpenAIObject: @@ -79,7 +79,7 @@ def test_to_dict(self): component = OpenAIDocumentEmbedder(api_key="fake-api-key") data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.openai_document_embedder.OpenAIDocumentEmbedder", + "type": "haystack.components.embedders.openai_document_embedder.OpenAIDocumentEmbedder", "init_parameters": { "model_name": "text-embedding-ada-002", "organization": None, @@ -107,7 +107,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.openai_document_embedder.OpenAIDocumentEmbedder", + "type": "haystack.components.embedders.openai_document_embedder.OpenAIDocumentEmbedder", "init_parameters": { "model_name": "model", "organization": "my-org", @@ -161,9 +161,7 @@ def test_prepare_texts_to_embed_w_suffix(self): def test_embed_batch(self): texts = ["text 1", "text 2", "text 3", "text 4", "text 5"] - with patch( - "haystack.preview.components.embedders.openai_document_embedder.openai.Embedding" - ) as openai_embedding_patch: + with patch("haystack.components.embedders.openai_document_embedder.openai.Embedding") as openai_embedding_patch: openai_embedding_patch.create.side_effect = mock_openai_response embedder = OpenAIDocumentEmbedder(api_key="fake-api-key", model_name="model") @@ -189,9 +187,7 @@ def test_run(self): ] model = "text-similarity-ada-001" - with patch( - "haystack.preview.components.embedders.openai_document_embedder.openai.Embedding" - ) as openai_embedding_patch: + with patch("haystack.components.embedders.openai_document_embedder.openai.Embedding") as openai_embedding_patch: openai_embedding_patch.create.side_effect = mock_openai_response embedder = OpenAIDocumentEmbedder( api_key="fake-api-key", @@ -231,9 +227,7 @@ def test_run_custom_batch_size(self): ] model = "text-similarity-ada-001" - with patch( - "haystack.preview.components.embedders.openai_document_embedder.openai.Embedding" - ) as openai_embedding_patch: + with patch("haystack.components.embedders.openai_document_embedder.openai.Embedding") as openai_embedding_patch: openai_embedding_patch.create.side_effect = mock_openai_response embedder = OpenAIDocumentEmbedder( api_key="fake-api-key", diff --git a/test/components/embedders/test_openai_text_embedder.py b/test/components/embedders/test_openai_text_embedder.py index 50be49ac5d..bbe4c8b31f 100644 --- a/test/components/embedders/test_openai_text_embedder.py +++ b/test/components/embedders/test_openai_text_embedder.py @@ -4,7 +4,7 @@ from openai.util import convert_to_openai_object import numpy as np -from haystack.preview.components.embedders.openai_text_embedder import OpenAITextEmbedder +from haystack.components.embedders.openai_text_embedder import OpenAITextEmbedder def mock_openai_response(model: str = "text-embedding-ada-002", **kwargs) -> openai.openai_object.OpenAIObject: @@ -59,7 +59,7 @@ def test_to_dict(self): component = OpenAITextEmbedder(api_key="fake-api-key") data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.openai_text_embedder.OpenAITextEmbedder", + "type": "haystack.components.embedders.openai_text_embedder.OpenAITextEmbedder", "init_parameters": { "model_name": "text-embedding-ada-002", "organization": None, @@ -79,7 +79,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.openai_text_embedder.OpenAITextEmbedder", + "type": "haystack.components.embedders.openai_text_embedder.OpenAITextEmbedder", "init_parameters": { "model_name": "model", "organization": "fake-organization", @@ -92,9 +92,7 @@ def test_to_dict_with_custom_init_parameters(self): def test_run(self): model = "text-similarity-ada-001" - with patch( - "haystack.preview.components.embedders.openai_text_embedder.openai.Embedding" - ) as openai_embedding_patch: + with patch("haystack.components.embedders.openai_text_embedder.openai.Embedding") as openai_embedding_patch: openai_embedding_patch.create.side_effect = mock_openai_response embedder = OpenAITextEmbedder(api_key="fake-api-key", model_name=model, prefix="prefix ", suffix=" suffix") diff --git a/test/components/embedders/test_sentence_transformers_document_embedder.py b/test/components/embedders/test_sentence_transformers_document_embedder.py index 2f5e5e667f..44aba64560 100644 --- a/test/components/embedders/test_sentence_transformers_document_embedder.py +++ b/test/components/embedders/test_sentence_transformers_document_embedder.py @@ -2,10 +2,8 @@ import pytest import numpy as np -from haystack.preview import Document -from haystack.preview.components.embedders.sentence_transformers_document_embedder import ( - SentenceTransformersDocumentEmbedder, -) +from haystack import Document +from haystack.components.embedders.sentence_transformers_document_embedder import SentenceTransformersDocumentEmbedder class TestSentenceTransformersDocumentEmbedder: @@ -53,7 +51,7 @@ def test_to_dict(self): component = SentenceTransformersDocumentEmbedder(model_name_or_path="model") data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.sentence_transformers_document_embedder.SentenceTransformersDocumentEmbedder", + "type": "haystack.components.embedders.sentence_transformers_document_embedder.SentenceTransformersDocumentEmbedder", "init_parameters": { "model_name_or_path": "model", "device": "cpu", @@ -85,7 +83,7 @@ def test_to_dict_with_custom_init_parameters(self): data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.sentence_transformers_document_embedder.SentenceTransformersDocumentEmbedder", + "type": "haystack.components.embedders.sentence_transformers_document_embedder.SentenceTransformersDocumentEmbedder", "init_parameters": { "model_name_or_path": "model", "device": "cuda", @@ -102,7 +100,7 @@ def test_to_dict_with_custom_init_parameters(self): @pytest.mark.unit @patch( - "haystack.preview.components.embedders.sentence_transformers_document_embedder._SentenceTransformersEmbeddingBackendFactory" + "haystack.components.embedders.sentence_transformers_document_embedder._SentenceTransformersEmbeddingBackendFactory" ) def test_warmup(self, mocked_factory): embedder = SentenceTransformersDocumentEmbedder(model_name_or_path="model") @@ -114,7 +112,7 @@ def test_warmup(self, mocked_factory): @pytest.mark.unit @patch( - "haystack.preview.components.embedders.sentence_transformers_document_embedder._SentenceTransformersEmbeddingBackendFactory" + "haystack.components.embedders.sentence_transformers_document_embedder._SentenceTransformersEmbeddingBackendFactory" ) def test_warmup_doesnt_reload(self, mocked_factory): embedder = SentenceTransformersDocumentEmbedder(model_name_or_path="model") diff --git a/test/components/embedders/test_sentence_transformers_embedding_backend.py b/test/components/embedders/test_sentence_transformers_embedding_backend.py index 4ac8c55869..9aec7954b3 100644 --- a/test/components/embedders/test_sentence_transformers_embedding_backend.py +++ b/test/components/embedders/test_sentence_transformers_embedding_backend.py @@ -1,12 +1,12 @@ from unittest.mock import patch import pytest -from haystack.preview.components.embedders.backends.sentence_transformers_backend import ( +from haystack.components.embedders.backends.sentence_transformers_backend import ( _SentenceTransformersEmbeddingBackendFactory, ) @pytest.mark.unit -@patch("haystack.preview.components.embedders.backends.sentence_transformers_backend.SentenceTransformer") +@patch("haystack.components.embedders.backends.sentence_transformers_backend.SentenceTransformer") def test_factory_behavior(mock_sentence_transformer): embedding_backend = _SentenceTransformersEmbeddingBackendFactory.get_embedding_backend( model_name_or_path="my_model", device="cpu" @@ -21,7 +21,7 @@ def test_factory_behavior(mock_sentence_transformer): @pytest.mark.unit -@patch("haystack.preview.components.embedders.backends.sentence_transformers_backend.SentenceTransformer") +@patch("haystack.components.embedders.backends.sentence_transformers_backend.SentenceTransformer") def test_model_initialization(mock_sentence_transformer): _SentenceTransformersEmbeddingBackendFactory.get_embedding_backend( model_name_or_path="model", device="cpu", use_auth_token="my_token" @@ -32,7 +32,7 @@ def test_model_initialization(mock_sentence_transformer): @pytest.mark.unit -@patch("haystack.preview.components.embedders.backends.sentence_transformers_backend.SentenceTransformer") +@patch("haystack.components.embedders.backends.sentence_transformers_backend.SentenceTransformer") def test_embedding_function_with_kwargs(mock_sentence_transformer): embedding_backend = _SentenceTransformersEmbeddingBackendFactory.get_embedding_backend(model_name_or_path="model") diff --git a/test/components/embedders/test_sentence_transformers_text_embedder.py b/test/components/embedders/test_sentence_transformers_text_embedder.py index d93e576ac8..cc0f96e830 100644 --- a/test/components/embedders/test_sentence_transformers_text_embedder.py +++ b/test/components/embedders/test_sentence_transformers_text_embedder.py @@ -3,7 +3,7 @@ import numpy as np -from haystack.preview.components.embedders.sentence_transformers_text_embedder import SentenceTransformersTextEmbedder +from haystack.components.embedders.sentence_transformers_text_embedder import SentenceTransformersTextEmbedder class TestSentenceTransformersTextEmbedder: @@ -45,7 +45,7 @@ def test_to_dict(self): component = SentenceTransformersTextEmbedder(model_name_or_path="model") data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder", + "type": "haystack.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder", "init_parameters": { "model_name_or_path": "model", "device": "cpu", @@ -72,7 +72,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder", + "type": "haystack.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder", "init_parameters": { "model_name_or_path": "model", "device": "cuda", @@ -90,7 +90,7 @@ def test_to_dict_not_serialize_token(self): component = SentenceTransformersTextEmbedder(model_name_or_path="model", token="awesome-token") data = component.to_dict() assert data == { - "type": "haystack.preview.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder", + "type": "haystack.components.embedders.sentence_transformers_text_embedder.SentenceTransformersTextEmbedder", "init_parameters": { "model_name_or_path": "model", "device": "cpu", @@ -105,7 +105,7 @@ def test_to_dict_not_serialize_token(self): @pytest.mark.unit @patch( - "haystack.preview.components.embedders.sentence_transformers_text_embedder._SentenceTransformersEmbeddingBackendFactory" + "haystack.components.embedders.sentence_transformers_text_embedder._SentenceTransformersEmbeddingBackendFactory" ) def test_warmup(self, mocked_factory): embedder = SentenceTransformersTextEmbedder(model_name_or_path="model") @@ -117,7 +117,7 @@ def test_warmup(self, mocked_factory): @pytest.mark.unit @patch( - "haystack.preview.components.embedders.sentence_transformers_text_embedder._SentenceTransformersEmbeddingBackendFactory" + "haystack.components.embedders.sentence_transformers_text_embedder._SentenceTransformersEmbeddingBackendFactory" ) def test_warmup_doesnt_reload(self, mocked_factory): embedder = SentenceTransformersTextEmbedder(model_name_or_path="model") diff --git a/test/components/fetchers/test_link_content_fetcher.py b/test/components/fetchers/test_link_content_fetcher.py index 7d7d4f904d..bb8505f4a5 100644 --- a/test/components/fetchers/test_link_content_fetcher.py +++ b/test/components/fetchers/test_link_content_fetcher.py @@ -3,7 +3,7 @@ import pytest import requests -from haystack.preview.components.fetchers.link_content import ( +from haystack.components.fetchers.link_content import ( LinkContentFetcher, text_content_handler, binary_content_handler, @@ -17,7 +17,7 @@ @pytest.fixture def mock_get_link_text_content(): - with patch("haystack.preview.components.fetchers.link_content.requests") as mock_run: + with patch("haystack.components.fetchers.link_content.requests") as mock_run: mock_run.get.return_value = Mock( status_code=200, text="Example test response", headers={"Content-Type": "text/plain"} ) @@ -26,7 +26,7 @@ def mock_get_link_text_content(): @pytest.fixture def mock_get_link_content(test_files_path): - with patch("haystack.preview.components.fetchers.link_content.requests") as mock_run: + with patch("haystack.components.fetchers.link_content.requests") as mock_run: mock_run.get.return_value = Mock( status_code=200, content=open(test_files_path / "pdf" / "sample_pdf_1.pdf", "rb").read(), @@ -62,7 +62,7 @@ def test_init_with_params(self): @pytest.mark.unit def test_run_text(self): correct_response = b"Example test response" - with patch("haystack.preview.components.fetchers.link_content.requests") as mock_run: + with patch("haystack.components.fetchers.link_content.requests") as mock_run: mock_run.get.return_value = Mock( status_code=200, text="Example test response", headers={"Content-Type": "text/plain"} ) @@ -75,7 +75,7 @@ def test_run_text(self): @pytest.mark.unit def test_run_html(self): correct_response = b"

Example test response

" - with patch("haystack.preview.components.fetchers.link_content.requests") as mock_run: + with patch("haystack.components.fetchers.link_content.requests") as mock_run: mock_run.get.return_value = Mock( status_code=200, text="

Example test response

", headers={"Content-Type": "text/html"} ) @@ -88,7 +88,7 @@ def test_run_html(self): @pytest.mark.unit def test_run_binary(self, test_files_path): file_bytes = open(test_files_path / "pdf" / "sample_pdf_1.pdf", "rb").read() - with patch("haystack.preview.components.fetchers.link_content.requests") as mock_run: + with patch("haystack.components.fetchers.link_content.requests") as mock_run: mock_run.get.return_value = Mock( status_code=200, content=file_bytes, headers={"Content-Type": "application/pdf"} ) @@ -103,7 +103,7 @@ def test_run_bad_status_code(self): empty_byte_stream = b"" fetcher = LinkContentFetcher(raise_on_failure=False) mock_response = Mock(status_code=403) - with patch("haystack.preview.components.fetchers.link_content.requests") as mock_run: + with patch("haystack.components.fetchers.link_content.requests") as mock_run: mock_run.get.return_value = mock_response streams = fetcher.run(urls=["https://www.example.com"])["streams"] diff --git a/test/components/generators/chat/conftest.py b/test/components/generators/chat/conftest.py index 7a6e7a0fba..1e4e241e4a 100644 --- a/test/components/generators/chat/conftest.py +++ b/test/components/generators/chat/conftest.py @@ -1,6 +1,6 @@ import pytest -from haystack.preview.dataclasses import ChatMessage +from haystack.dataclasses import ChatMessage @pytest.fixture diff --git a/test/components/generators/chat/test_hugging_face_tgi.py b/test/components/generators/chat/test_hugging_face_tgi.py index 35de294176..9c6c065831 100644 --- a/test/components/generators/chat/test_hugging_face_tgi.py +++ b/test/components/generators/chat/test_hugging_face_tgi.py @@ -4,15 +4,15 @@ from huggingface_hub.inference._text_generation import TextGenerationStreamResponse, Token, StreamDetails, FinishReason from huggingface_hub.utils import RepositoryNotFoundError -from haystack.preview.components.generators.chat import HuggingFaceTGIChatGenerator +from haystack.components.generators.chat import HuggingFaceTGIChatGenerator -from haystack.preview.dataclasses import StreamingChunk, ChatMessage +from haystack.dataclasses import StreamingChunk, ChatMessage @pytest.fixture def mock_check_valid_model(): with patch( - "haystack.preview.components.generators.chat.hugging_face_tgi.check_valid_model", MagicMock(return_value=None) + "haystack.components.generators.chat.hugging_face_tgi.check_valid_model", MagicMock(return_value=None) ) as mock: yield mock diff --git a/test/components/generators/chat/test_openai.py b/test/components/generators/chat/test_openai.py index 9535bc14d7..8823644207 100644 --- a/test/components/generators/chat/test_openai.py +++ b/test/components/generators/chat/test_openai.py @@ -4,9 +4,9 @@ import openai import pytest -from haystack.preview.components.generators.chat import GPTChatGenerator -from haystack.preview.components.generators.utils import default_streaming_callback -from haystack.preview.dataclasses import ChatMessage, StreamingChunk +from haystack.components.generators.chat import GPTChatGenerator +from haystack.components.generators.utils import default_streaming_callback +from haystack.dataclasses import ChatMessage, StreamingChunk @pytest.fixture @@ -104,7 +104,7 @@ def test_to_dict_default(self): component = GPTChatGenerator(api_key="test-api-key") data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.chat.openai.GPTChatGenerator", + "type": "haystack.components.generators.chat.openai.GPTChatGenerator", "init_parameters": { "model_name": "gpt-3.5-turbo", "streaming_callback": None, @@ -124,11 +124,11 @@ def test_to_dict_with_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.chat.openai.GPTChatGenerator", + "type": "haystack.components.generators.chat.openai.GPTChatGenerator", "init_parameters": { "model_name": "gpt-4", "api_base_url": "test-base-url", - "streaming_callback": "haystack.preview.components.generators.utils.default_streaming_callback", + "streaming_callback": "haystack.components.generators.utils.default_streaming_callback", "generation_kwargs": {"max_tokens": 10, "some_test_param": "test-params"}, }, } @@ -144,7 +144,7 @@ def test_to_dict_with_lambda_streaming_callback(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.chat.openai.GPTChatGenerator", + "type": "haystack.components.generators.chat.openai.GPTChatGenerator", "init_parameters": { "model_name": "gpt-4", "api_base_url": "test-base-url", @@ -157,11 +157,11 @@ def test_to_dict_with_lambda_streaming_callback(self): def test_from_dict(self, monkeypatch): monkeypatch.setenv("OPENAI_API_KEY", "fake-api-key") data = { - "type": "haystack.preview.components.generators.chat.openai.GPTChatGenerator", + "type": "haystack.components.generators.chat.openai.GPTChatGenerator", "init_parameters": { "model_name": "gpt-4", "api_base_url": "test-base-url", - "streaming_callback": "haystack.preview.components.generators.utils.default_streaming_callback", + "streaming_callback": "haystack.components.generators.utils.default_streaming_callback", "generation_kwargs": {"max_tokens": 10, "some_test_param": "test-params"}, }, } @@ -176,11 +176,11 @@ def test_from_dict_fail_wo_env_var(self, monkeypatch): openai.api_key = None monkeypatch.delenv("OPENAI_API_KEY", raising=False) data = { - "type": "haystack.preview.components.generators.chat.openai.GPTChatGenerator", + "type": "haystack.components.generators.chat.openai.GPTChatGenerator", "init_parameters": { "model_name": "gpt-4", "api_base_url": "test-base-url", - "streaming_callback": "haystack.preview.components.generators.utils.default_streaming_callback", + "streaming_callback": "haystack.components.generators.utils.default_streaming_callback", "generation_kwargs": {"max_tokens": 10, "some_test_param": "test-params"}, }, } diff --git a/test/components/generators/test_cohere_generators.py b/test/components/generators/test_cohere_generators.py index cd1f9cb2a4..34cff2af98 100644 --- a/test/components/generators/test_cohere_generators.py +++ b/test/components/generators/test_cohere_generators.py @@ -3,7 +3,7 @@ import pytest import cohere -from haystack.preview.components.generators import CohereGenerator +from haystack.components.generators import CohereGenerator def default_streaming_callback(chunk): @@ -43,7 +43,7 @@ def test_to_dict_default(self): component = CohereGenerator(api_key="test-api-key") data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.cohere.CohereGenerator", + "type": "haystack.components.generators.cohere.CohereGenerator", "init_parameters": { "model_name": "command", "streaming_callback": None, @@ -62,7 +62,7 @@ def test_to_dict_with_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.cohere.CohereGenerator", + "type": "haystack.components.generators.cohere.CohereGenerator", "init_parameters": { "model_name": "command-light", "max_tokens": 10, @@ -83,7 +83,7 @@ def test_to_dict_with_lambda_streaming_callback(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.cohere.CohereGenerator", + "type": "haystack.components.generators.cohere.CohereGenerator", "init_parameters": { "model_name": "command", "streaming_callback": "test_cohere_generators.", @@ -96,7 +96,7 @@ def test_to_dict_with_lambda_streaming_callback(self): def test_from_dict(self, monkeypatch): monkeypatch.setenv("COHERE_API_KEY", "test-key") data = { - "type": "haystack.preview.components.generators.cohere.CohereGenerator", + "type": "haystack.components.generators.cohere.CohereGenerator", "init_parameters": { "model_name": "command", "max_tokens": 10, diff --git a/test/components/generators/test_hf_utils.py b/test/components/generators/test_hf_utils.py index f69a099743..96a4ba122e 100644 --- a/test/components/generators/test_hf_utils.py +++ b/test/components/generators/test_hf_utils.py @@ -1,6 +1,6 @@ import pytest -from haystack.preview.components.generators.hf_utils import check_generation_params +from haystack.components.generators.hf_utils import check_generation_params @pytest.mark.unit diff --git a/test/components/generators/test_hugging_face_local_generator.py b/test/components/generators/test_hugging_face_local_generator.py index 367a54c640..c7dd0ef490 100644 --- a/test/components/generators/test_hugging_face_local_generator.py +++ b/test/components/generators/test_hugging_face_local_generator.py @@ -4,12 +4,12 @@ import pytest import torch -from haystack.preview.components.generators.hugging_face_local import HuggingFaceLocalGenerator, StopWordsCriteria +from haystack.components.generators.hugging_face_local import HuggingFaceLocalGenerator, StopWordsCriteria class TestHuggingFaceLocalGenerator: @pytest.mark.unit - @patch("haystack.preview.components.generators.hugging_face_local.model_info") + @patch("haystack.components.generators.hugging_face_local.model_info") def test_init_default(self, model_info_mock): model_info_mock.return_value.pipeline_tag = "text2text-generation" generator = HuggingFaceLocalGenerator() @@ -68,7 +68,7 @@ def test_init_task_in_huggingface_pipeline_kwargs(self): } @pytest.mark.unit - @patch("haystack.preview.components.generators.hugging_face_local.model_info") + @patch("haystack.components.generators.hugging_face_local.model_info") def test_init_task_inferred_from_model_name(self, model_info_mock): model_info_mock.return_value.pipeline_tag = "text2text-generation" generator = HuggingFaceLocalGenerator(model_name_or_path="google/flan-t5-base") @@ -137,7 +137,7 @@ def test_init_fails_with_both_stopwords_and_stoppingcriteria(self): ) @pytest.mark.unit - @patch("haystack.preview.components.generators.hugging_face_local.model_info") + @patch("haystack.components.generators.hugging_face_local.model_info") def test_to_dict_default(self, model_info_mock): model_info_mock.return_value.pipeline_tag = "text2text-generation" @@ -145,7 +145,7 @@ def test_to_dict_default(self, model_info_mock): data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.hugging_face_local.HuggingFaceLocalGenerator", + "type": "haystack.components.generators.hugging_face_local.HuggingFaceLocalGenerator", "init_parameters": { "huggingface_pipeline_kwargs": { "model": "google/flan-t5-base", @@ -170,7 +170,7 @@ def test_to_dict_with_parameters(self): data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.hugging_face_local.HuggingFaceLocalGenerator", + "type": "haystack.components.generators.hugging_face_local.HuggingFaceLocalGenerator", "init_parameters": { "huggingface_pipeline_kwargs": { "model": "gpt2", @@ -184,7 +184,7 @@ def test_to_dict_with_parameters(self): } @pytest.mark.unit - @patch("haystack.preview.components.generators.hugging_face_local.pipeline") + @patch("haystack.components.generators.hugging_face_local.pipeline") def test_warm_up(self, pipeline_mock): generator = HuggingFaceLocalGenerator( model_name_or_path="google/flan-t5-base", task="text2text-generation", token="test-token" @@ -198,7 +198,7 @@ def test_warm_up(self, pipeline_mock): ) @pytest.mark.unit - @patch("haystack.preview.components.generators.hugging_face_local.pipeline") + @patch("haystack.components.generators.hugging_face_local.pipeline") def test_warm_up_doesn_reload(self, pipeline_mock): generator = HuggingFaceLocalGenerator( model_name_or_path="google/flan-t5-base", task="text2text-generation", token="test-token" @@ -230,7 +230,7 @@ def test_run(self): assert results == {"replies": ["Rome"]} @pytest.mark.unit - @patch("haystack.preview.components.generators.hugging_face_local.pipeline") + @patch("haystack.components.generators.hugging_face_local.pipeline") def test_run_empty_prompt(self, pipeline_mock): generator = HuggingFaceLocalGenerator( model_name_or_path="google/flan-t5-base", @@ -310,9 +310,9 @@ def test_stop_words_criteria(self): assert present_and_continuous @pytest.mark.unit - @patch("haystack.preview.components.generators.hugging_face_local.pipeline") - @patch("haystack.preview.components.generators.hugging_face_local.StopWordsCriteria") - @patch("haystack.preview.components.generators.hugging_face_local.StoppingCriteriaList") + @patch("haystack.components.generators.hugging_face_local.pipeline") + @patch("haystack.components.generators.hugging_face_local.StopWordsCriteria") + @patch("haystack.components.generators.hugging_face_local.StoppingCriteriaList") def test_warm_up_set_stopping_criteria_list( self, pipeline_mock, stop_words_criteria_mock, stopping_criteria_list_mock ): diff --git a/test/components/generators/test_hugging_face_tgi.py b/test/components/generators/test_hugging_face_tgi.py index 5fcbb304b1..bcad88ef5c 100644 --- a/test/components/generators/test_hugging_face_tgi.py +++ b/test/components/generators/test_hugging_face_tgi.py @@ -4,14 +4,14 @@ from huggingface_hub.inference._text_generation import TextGenerationStreamResponse, Token, StreamDetails, FinishReason from huggingface_hub.utils import RepositoryNotFoundError -from haystack.preview.components.generators import HuggingFaceTGIGenerator -from haystack.preview.dataclasses import StreamingChunk +from haystack.components.generators import HuggingFaceTGIGenerator +from haystack.dataclasses import StreamingChunk @pytest.fixture def mock_check_valid_model(): with patch( - "haystack.preview.components.generators.hugging_face_tgi.check_valid_model", MagicMock(return_value=None) + "haystack.components.generators.hugging_face_tgi.check_valid_model", MagicMock(return_value=None) ) as mock: yield mock diff --git a/test/components/generators/test_openai.py b/test/components/generators/test_openai.py index 94a862654d..cde89a5d77 100644 --- a/test/components/generators/test_openai.py +++ b/test/components/generators/test_openai.py @@ -5,9 +5,9 @@ import openai import pytest -from haystack.preview.components.generators import GPTGenerator -from haystack.preview.components.generators.utils import default_streaming_callback -from haystack.preview.dataclasses import StreamingChunk, ChatMessage +from haystack.components.generators import GPTGenerator +from haystack.components.generators.utils import default_streaming_callback +from haystack.dataclasses import StreamingChunk, ChatMessage @pytest.fixture @@ -97,7 +97,7 @@ def test_to_dict_default(self): component = GPTGenerator(api_key="test-api-key") data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.openai.GPTGenerator", + "type": "haystack.components.generators.openai.GPTGenerator", "init_parameters": { "model_name": "gpt-3.5-turbo", "streaming_callback": None, @@ -118,12 +118,12 @@ def test_to_dict_with_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.openai.GPTGenerator", + "type": "haystack.components.generators.openai.GPTGenerator", "init_parameters": { "model_name": "gpt-4", "system_prompt": None, "api_base_url": "test-base-url", - "streaming_callback": "haystack.preview.components.generators.utils.default_streaming_callback", + "streaming_callback": "haystack.components.generators.utils.default_streaming_callback", "generation_kwargs": {"max_tokens": 10, "some_test_param": "test-params"}, }, } @@ -139,7 +139,7 @@ def test_to_dict_with_lambda_streaming_callback(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.generators.openai.GPTGenerator", + "type": "haystack.components.generators.openai.GPTGenerator", "init_parameters": { "model_name": "gpt-4", "system_prompt": None, @@ -153,12 +153,12 @@ def test_to_dict_with_lambda_streaming_callback(self): def test_from_dict(self, monkeypatch): monkeypatch.setenv("OPENAI_API_KEY", "fake-api-key") data = { - "type": "haystack.preview.components.generators.openai.GPTGenerator", + "type": "haystack.components.generators.openai.GPTGenerator", "init_parameters": { "model_name": "gpt-4", "system_prompt": None, "api_base_url": "test-base-url", - "streaming_callback": "haystack.preview.components.generators.utils.default_streaming_callback", + "streaming_callback": "haystack.components.generators.utils.default_streaming_callback", "generation_kwargs": {"max_tokens": 10, "some_test_param": "test-params"}, }, } @@ -173,11 +173,11 @@ def test_from_dict_fail_wo_env_var(self, monkeypatch): openai.api_key = None monkeypatch.delenv("OPENAI_API_KEY", raising=False) data = { - "type": "haystack.preview.components.generators.openai.GPTGenerator", + "type": "haystack.components.generators.openai.GPTGenerator", "init_parameters": { "model_name": "gpt-4", "api_base_url": "test-base-url", - "streaming_callback": "haystack.preview.components.generators.utils.default_streaming_callback", + "streaming_callback": "haystack.components.generators.utils.default_streaming_callback", "generation_kwargs": {"max_tokens": 10, "some_test_param": "test-params"}, }, } diff --git a/test/components/generators/test_utils.py b/test/components/generators/test_utils.py index 9339502990..fbb3bab1ae 100644 --- a/test/components/generators/test_utils.py +++ b/test/components/generators/test_utils.py @@ -1,7 +1,7 @@ import pytest -from haystack.preview.components.generators.utils import default_streaming_callback -from haystack.preview.components.generators.utils import serialize_callback_handler, deserialize_callback_handler +from haystack.components.generators.utils import default_streaming_callback +from haystack.components.generators.utils import serialize_callback_handler, deserialize_callback_handler # streaming callback needs to be on module level @@ -18,7 +18,7 @@ def test_callback_handler_serialization(): @pytest.mark.unit def test_callback_handler_serialization_non_local(): result = serialize_callback_handler(default_streaming_callback) - assert result == "haystack.preview.components.generators.utils.default_streaming_callback" + assert result == "haystack.components.generators.utils.default_streaming_callback" @pytest.mark.unit diff --git a/test/components/preprocessors/test_document_cleaner.py b/test/components/preprocessors/test_document_cleaner.py index 71f412f3f1..a4b4bad8af 100644 --- a/test/components/preprocessors/test_document_cleaner.py +++ b/test/components/preprocessors/test_document_cleaner.py @@ -2,8 +2,8 @@ import pytest -from haystack.preview import Document -from haystack.preview.components.preprocessors import DocumentCleaner +from haystack import Document +from haystack.components.preprocessors import DocumentCleaner class TestDocumentCleaner: diff --git a/test/components/preprocessors/test_document_splitter.py b/test/components/preprocessors/test_document_splitter.py index 4e28d1b135..20f163df72 100644 --- a/test/components/preprocessors/test_document_splitter.py +++ b/test/components/preprocessors/test_document_splitter.py @@ -1,7 +1,7 @@ import pytest -from haystack.preview import Document -from haystack.preview.components.preprocessors import DocumentSplitter +from haystack import Document +from haystack.components.preprocessors import DocumentSplitter class TestDocumentSplitter: diff --git a/test/components/rankers/test_metafield.py b/test/components/rankers/test_metafield.py index b6e762c6f8..36d4511d26 100644 --- a/test/components/rankers/test_metafield.py +++ b/test/components/rankers/test_metafield.py @@ -1,7 +1,7 @@ import pytest -from haystack.preview import Document, ComponentError -from haystack.preview.components.rankers.meta_field import MetaFieldRanker +from haystack import Document, ComponentError +from haystack.components.rankers.meta_field import MetaFieldRanker class TestMetaFieldRanker: @@ -10,7 +10,7 @@ def test_to_dict(self): component = MetaFieldRanker(metadata_field="rating") data = component.to_dict() assert data == { - "type": "haystack.preview.components.rankers.meta_field.MetaFieldRanker", + "type": "haystack.components.rankers.meta_field.MetaFieldRanker", "init_parameters": { "metadata_field": "rating", "weight": 1.0, @@ -24,7 +24,7 @@ def test_to_dict_with_custom_init_parameters(self): component = MetaFieldRanker(metadata_field="rating", weight=0.5, top_k=5, ranking_mode="linear_score") data = component.to_dict() assert data == { - "type": "haystack.preview.components.rankers.meta_field.MetaFieldRanker", + "type": "haystack.components.rankers.meta_field.MetaFieldRanker", "init_parameters": {"metadata_field": "rating", "weight": 0.5, "top_k": 5, "ranking_mode": "linear_score"}, } diff --git a/test/components/rankers/test_transformers_similarity.py b/test/components/rankers/test_transformers_similarity.py index 95c1d1aea7..f726bb38d5 100644 --- a/test/components/rankers/test_transformers_similarity.py +++ b/test/components/rankers/test_transformers_similarity.py @@ -1,7 +1,7 @@ import pytest -from haystack.preview import Document, ComponentError -from haystack.preview.components.rankers.transformers_similarity import TransformersSimilarityRanker +from haystack import Document, ComponentError +from haystack.components.rankers.transformers_similarity import TransformersSimilarityRanker class TestSimilarityRanker: @@ -10,7 +10,7 @@ def test_to_dict(self): component = TransformersSimilarityRanker() data = component.to_dict() assert data == { - "type": "haystack.preview.components.rankers.transformers_similarity.TransformersSimilarityRanker", + "type": "haystack.components.rankers.transformers_similarity.TransformersSimilarityRanker", "init_parameters": { "device": "cpu", "top_k": 10, @@ -26,7 +26,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.rankers.transformers_similarity.TransformersSimilarityRanker", + "type": "haystack.components.rankers.transformers_similarity.TransformersSimilarityRanker", "init_parameters": { "device": "cuda", "model_name_or_path": "my_model", diff --git a/test/components/readers/test_extractive.py b/test/components/readers/test_extractive.py index 438922ae8d..b62f219db9 100644 --- a/test/components/readers/test_extractive.py +++ b/test/components/readers/test_extractive.py @@ -6,8 +6,8 @@ import torch from transformers import pipeline -from haystack.preview.components.readers import ExtractiveReader -from haystack.preview import Document +from haystack.components.readers import ExtractiveReader +from haystack import Document @pytest.fixture @@ -43,7 +43,7 @@ def mock_tokenize( tokens.attention_mask = attention_mask return tokens - with patch("haystack.preview.components.readers.extractive.AutoTokenizer.from_pretrained") as tokenizer: + with patch("haystack.components.readers.extractive.AutoTokenizer.from_pretrained") as tokenizer: tokenizer.return_value = mock_tokenize yield tokenizer @@ -70,7 +70,7 @@ def forward(self, input_ids, attention_mask, *args, **kwargs): prediction.end_logits = end return prediction - with patch("haystack.preview.components.readers.extractive.AutoModelForQuestionAnswering.from_pretrained") as model: + with patch("haystack.components.readers.extractive.AutoModelForQuestionAnswering.from_pretrained") as model: model.return_value = MockModel() reader = ExtractiveReader(model_name_or_path="mock-model", device="cpu:0") reader.warm_up() @@ -93,7 +93,7 @@ def test_to_dict(): data = component.to_dict() assert data == { - "type": "haystack.preview.components.readers.extractive.ExtractiveReader", + "type": "haystack.components.readers.extractive.ExtractiveReader", "init_parameters": { "model_name_or_path": "my-model", "device": None, @@ -117,7 +117,7 @@ def test_to_dict_empty_model_kwargs(): data = component.to_dict() assert data == { - "type": "haystack.preview.components.readers.extractive.ExtractiveReader", + "type": "haystack.components.readers.extractive.ExtractiveReader", "init_parameters": { "model_name_or_path": "my-model", "device": None, @@ -259,8 +259,8 @@ def test_nest_answers(mock_reader: ExtractiveReader): @pytest.mark.unit -@patch("haystack.preview.components.readers.extractive.AutoTokenizer.from_pretrained") -@patch("haystack.preview.components.readers.extractive.AutoModelForQuestionAnswering.from_pretrained") +@patch("haystack.components.readers.extractive.AutoTokenizer.from_pretrained") +@patch("haystack.components.readers.extractive.AutoModelForQuestionAnswering.from_pretrained") def test_warm_up_use_hf_token(mocked_automodel, mocked_autotokenizer): reader = ExtractiveReader("deepset/roberta-base-squad2", token="fake-token") reader.warm_up() @@ -324,8 +324,8 @@ def forward(self, input_ids, attention_mask, *args, **kwargs): prediction.end_logits = end return prediction - with patch("haystack.preview.components.readers.extractive.AutoTokenizer.from_pretrained") as tokenizer, patch( - "haystack.preview.components.readers.extractive.AutoModelForQuestionAnswering.from_pretrained" + with patch("haystack.components.readers.extractive.AutoTokenizer.from_pretrained") as tokenizer, patch( + "haystack.components.readers.extractive.AutoModelForQuestionAnswering.from_pretrained" ) as model: tokenizer.return_value = mock_tokenize model.return_value = MockModel() diff --git a/test/components/retrievers/test_in_memory_bm25_retriever.py b/test/components/retrievers/test_in_memory_bm25_retriever.py index 2a84f3bace..8a80c59649 100644 --- a/test/components/retrievers/test_in_memory_bm25_retriever.py +++ b/test/components/retrievers/test_in_memory_bm25_retriever.py @@ -2,11 +2,11 @@ import pytest -from haystack.preview import Pipeline, DeserializationError -from haystack.preview.testing.factory import document_store_class -from haystack.preview.components.retrievers.in_memory_bm25_retriever import InMemoryBM25Retriever -from haystack.preview.dataclasses import Document -from haystack.preview.document_stores import InMemoryDocumentStore +from haystack import Pipeline, DeserializationError +from haystack.testing.factory import document_store_class +from haystack.components.retrievers.in_memory_bm25_retriever import InMemoryBM25Retriever +from haystack.dataclasses import Document +from haystack.document_stores import InMemoryDocumentStore @pytest.fixture() @@ -51,7 +51,7 @@ def test_to_dict(self): data = component.to_dict() assert data == { - "type": "haystack.preview.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", + "type": "haystack.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", "init_parameters": { "document_store": {"type": "MyFakeStore", "init_parameters": {}}, "filters": None, @@ -70,7 +70,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", + "type": "haystack.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", "init_parameters": { "document_store": {"type": "MyFakeStore", "init_parameters": {}}, "filters": {"name": "test.txt"}, @@ -83,9 +83,9 @@ def test_to_dict_with_custom_init_parameters(self): def test_from_dict(self): document_store_class("MyFakeStore", bases=(InMemoryDocumentStore,)) data = { - "type": "haystack.preview.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", + "type": "haystack.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", "init_parameters": { - "document_store": {"type": "haystack.preview.testing.factory.MyFakeStore", "init_parameters": {}}, + "document_store": {"type": "haystack.testing.factory.MyFakeStore", "init_parameters": {}}, "filters": {"name": "test.txt"}, "top_k": 5, }, @@ -111,7 +111,7 @@ def test_from_dict_without_docstore_type(self): @pytest.mark.unit def test_from_dict_nonexisting_docstore(self): data = { - "type": "haystack.preview.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", + "type": "haystack.components.retrievers.in_memory_bm25_retriever.InMemoryBM25Retriever", "init_parameters": {"document_store": {"type": "NonexistingDocstore", "init_parameters": {}}}, } with pytest.raises(DeserializationError, match="DocumentStore type 'NonexistingDocstore' not found"): diff --git a/test/components/retrievers/test_in_memory_embedding_retriever.py b/test/components/retrievers/test_in_memory_embedding_retriever.py index 6c03e6d621..b0688af125 100644 --- a/test/components/retrievers/test_in_memory_embedding_retriever.py +++ b/test/components/retrievers/test_in_memory_embedding_retriever.py @@ -3,11 +3,11 @@ import pytest import numpy as np -from haystack.preview import Pipeline, DeserializationError -from haystack.preview.testing.factory import document_store_class -from haystack.preview.components.retrievers.in_memory_embedding_retriever import InMemoryEmbeddingRetriever -from haystack.preview.dataclasses import Document -from haystack.preview.document_stores import InMemoryDocumentStore +from haystack import Pipeline, DeserializationError +from haystack.testing.factory import document_store_class +from haystack.components.retrievers.in_memory_embedding_retriever import InMemoryEmbeddingRetriever +from haystack.dataclasses import Document +from haystack.document_stores import InMemoryDocumentStore class TestMemoryEmbeddingRetriever: @@ -41,7 +41,7 @@ def test_to_dict(self): data = component.to_dict() assert data == { - "type": "haystack.preview.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", + "type": "haystack.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", "init_parameters": { "document_store": {"type": "test_module.MyFakeStore", "init_parameters": {}}, "filters": None, @@ -65,7 +65,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", + "type": "haystack.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", "init_parameters": { "document_store": {"type": "test_module.MyFakeStore", "init_parameters": {}}, "filters": {"name": "test.txt"}, @@ -79,9 +79,9 @@ def test_to_dict_with_custom_init_parameters(self): def test_from_dict(self): document_store_class("MyFakeStore", bases=(InMemoryDocumentStore,)) data = { - "type": "haystack.preview.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", + "type": "haystack.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", "init_parameters": { - "document_store": {"type": "haystack.preview.testing.factory.MyFakeStore", "init_parameters": {}}, + "document_store": {"type": "haystack.testing.factory.MyFakeStore", "init_parameters": {}}, "filters": {"name": "test.txt"}, "top_k": 5, }, @@ -95,7 +95,7 @@ def test_from_dict(self): @pytest.mark.unit def test_from_dict_without_docstore(self): data = { - "type": "haystack.preview.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", + "type": "haystack.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", "init_parameters": {}, } with pytest.raises(DeserializationError, match="Missing 'document_store' in serialization data"): @@ -104,7 +104,7 @@ def test_from_dict_without_docstore(self): @pytest.mark.unit def test_from_dict_without_docstore_type(self): data = { - "type": "haystack.preview.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", + "type": "haystack.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", "init_parameters": {"document_store": {"init_parameters": {}}}, } with pytest.raises(DeserializationError, match="Missing 'type' in document store's serialization data"): @@ -113,7 +113,7 @@ def test_from_dict_without_docstore_type(self): @pytest.mark.unit def test_from_dict_nonexisting_docstore(self): data = { - "type": "haystack.preview.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", + "type": "haystack.components.retrievers.in_memory_embedding_retriever.InMemoryEmbeddingRetriever", "init_parameters": {"document_store": {"type": "NonexistingDocstore", "init_parameters": {}}}, } with pytest.raises(DeserializationError, match="DocumentStore type 'NonexistingDocstore' not found"): diff --git a/test/components/routers/test_conditional_router.py b/test/components/routers/test_conditional_router.py index 501fb530d1..177322eeac 100644 --- a/test/components/routers/test_conditional_router.py +++ b/test/components/routers/test_conditional_router.py @@ -5,13 +5,9 @@ import pytest -from haystack.preview.components.routers import ConditionalRouter -from haystack.preview.components.routers.conditional_router import ( - NoRouteSelectedException, - serialize_type, - deserialize_type, -) -from haystack.preview.dataclasses import ChatMessage +from haystack.components.routers import ConditionalRouter +from haystack.components.routers.conditional_router import NoRouteSelectedException, serialize_type, deserialize_type +from haystack.dataclasses import ChatMessage class TestRouter: @@ -198,15 +194,15 @@ def test_output_type_serialization(self): assert serialize_type(str) == "str" assert serialize_type(List[int]) == "typing.List[int]" assert serialize_type(List[Dict[str, int]]) == "typing.List[typing.Dict[str, int]]" - assert serialize_type(ChatMessage) == "haystack.preview.dataclasses.chat_message.ChatMessage" + assert serialize_type(ChatMessage) == "haystack.dataclasses.chat_message.ChatMessage" assert serialize_type(typing.List[Dict[str, int]]) == "typing.List[typing.Dict[str, int]]" - assert serialize_type(List[ChatMessage]) == "typing.List[haystack.preview.dataclasses.chat_message.ChatMessage]" + assert serialize_type(List[ChatMessage]) == "typing.List[haystack.dataclasses.chat_message.ChatMessage]" assert ( serialize_type(typing.Dict[int, ChatMessage]) - == "typing.Dict[int, haystack.preview.dataclasses.chat_message.ChatMessage]" + == "typing.Dict[int, haystack.dataclasses.chat_message.ChatMessage]" ) assert serialize_type(int) == "int" - assert serialize_type(ChatMessage.from_user("ciao")) == "haystack.preview.dataclasses.chat_message.ChatMessage" + assert serialize_type(ChatMessage.from_user("ciao")) == "haystack.dataclasses.chat_message.ChatMessage" def test_output_type_deserialization(self): assert deserialize_type("str") == str @@ -216,14 +212,13 @@ def test_output_type_deserialization(self): assert deserialize_type("typing.Dict[str, typing.List[int]]") == Dict[str, List[int]] assert deserialize_type("typing.List[typing.Dict[str, typing.List[int]]]") == List[Dict[str, List[int]]] assert ( - deserialize_type("typing.List[haystack.preview.dataclasses.chat_message.ChatMessage]") - == typing.List[ChatMessage] + deserialize_type("typing.List[haystack.dataclasses.chat_message.ChatMessage]") == typing.List[ChatMessage] ) assert ( - deserialize_type("typing.Dict[int, haystack.preview.dataclasses.chat_message.ChatMessage]") + deserialize_type("typing.Dict[int, haystack.dataclasses.chat_message.ChatMessage]") == typing.Dict[int, ChatMessage] ) - assert deserialize_type("haystack.preview.dataclasses.chat_message.ChatMessage") == ChatMessage + assert deserialize_type("haystack.dataclasses.chat_message.ChatMessage") == ChatMessage assert deserialize_type("int") == int def test_router_de_serialization(self): @@ -283,7 +278,7 @@ def test_router_de_serialization_user_type(self): # check that the output_type is a string and a proper class name assert ( router_dict["init_parameters"]["routes"][0]["output_type"] - == "haystack.preview.dataclasses.chat_message.ChatMessage" + == "haystack.dataclasses.chat_message.ChatMessage" ) # deserialize the router diff --git a/test/components/routers/test_document_joiner.py b/test/components/routers/test_document_joiner.py index 9b4ab7bf2a..217175bca8 100644 --- a/test/components/routers/test_document_joiner.py +++ b/test/components/routers/test_document_joiner.py @@ -2,8 +2,8 @@ import pytest -from haystack.preview import Document -from haystack.preview.components.routers.document_joiner import DocumentJoiner +from haystack import Document +from haystack.components.routers.document_joiner import DocumentJoiner class TestDocumentJoiner: diff --git a/test/components/routers/test_file_router.py b/test/components/routers/test_file_router.py index b513d95830..c4e6a12b90 100644 --- a/test/components/routers/test_file_router.py +++ b/test/components/routers/test_file_router.py @@ -2,8 +2,8 @@ import pytest -from haystack.preview.components.routers.file_type_router import FileTypeRouter -from haystack.preview.dataclasses import ByteStream +from haystack.components.routers.file_type_router import FileTypeRouter +from haystack.dataclasses import ByteStream @pytest.mark.skipif( @@ -12,15 +12,15 @@ ) class TestFileTypeRouter: @pytest.mark.unit - def test_run(self, preview_samples_path): + def test_run(self, test_files_path): """ Test if the component runs correctly in the simplest happy path. """ file_paths = [ - preview_samples_path / "txt" / "doc_1.txt", - preview_samples_path / "txt" / "doc_2.txt", - preview_samples_path / "audio" / "the context for this answer is here.wav", - preview_samples_path / "images" / "apple.jpg", + test_files_path / "txt" / "doc_1.txt", + test_files_path / "txt" / "doc_2.txt", + test_files_path / "audio" / "the context for this answer is here.wav", + test_files_path / "images" / "apple.jpg", ] router = FileTypeRouter(mime_types=["text/plain", "audio/x-wav", "image/jpeg"]) @@ -32,15 +32,15 @@ def test_run(self, preview_samples_path): assert not output["unclassified"] @pytest.mark.unit - def test_run_with_bytestreams(self, preview_samples_path): + def test_run_with_bytestreams(self, test_files_path): """ Test if the component runs correctly with ByteStream inputs. """ file_paths = [ - preview_samples_path / "txt" / "doc_1.txt", - preview_samples_path / "txt" / "doc_2.txt", - preview_samples_path / "audio" / "the context for this answer is here.wav", - preview_samples_path / "images" / "apple.jpg", + test_files_path / "txt" / "doc_1.txt", + test_files_path / "txt" / "doc_2.txt", + test_files_path / "audio" / "the context for this answer is here.wav", + test_files_path / "images" / "apple.jpg", ] mime_types = ["text/plain", "text/plain", "audio/x-wav", "image/jpeg"] # Convert file paths to ByteStream objects and set metadata @@ -66,12 +66,12 @@ def test_run_with_bytestreams(self, preview_samples_path): assert len(output.get("unclassified")) == 1 @pytest.mark.unit - def test_run_with_bytestreams_and_file_paths(self, preview_samples_path): + def test_run_with_bytestreams_and_file_paths(self, test_files_path): file_paths = [ - preview_samples_path / "txt" / "doc_1.txt", - preview_samples_path / "audio" / "the context for this answer is here.wav", - preview_samples_path / "txt" / "doc_2.txt", - preview_samples_path / "images" / "apple.jpg", + test_files_path / "txt" / "doc_1.txt", + test_files_path / "audio" / "the context for this answer is here.wav", + test_files_path / "txt" / "doc_2.txt", + test_files_path / "images" / "apple.jpg", ] mime_types = ["text/plain", "audio/x-wav", "text/plain", "image/jpeg"] byte_stream_sources = [] @@ -98,14 +98,14 @@ def test_no_files(self): assert not output @pytest.mark.unit - def test_unlisted_extensions(self, preview_samples_path): + def test_unlisted_extensions(self, test_files_path): """ Test that the component correctly handles files with non specified mime types. """ file_paths = [ - preview_samples_path / "txt" / "doc_1.txt", - preview_samples_path / "audio" / "ignored.mp3", - preview_samples_path / "audio" / "this is the content of the document.wav", + test_files_path / "txt" / "doc_1.txt", + test_files_path / "audio" / "ignored.mp3", + test_files_path / "audio" / "this is the content of the document.wav", ] router = FileTypeRouter(mime_types=["text/plain"]) output = router.run(sources=file_paths) @@ -116,14 +116,14 @@ def test_unlisted_extensions(self, preview_samples_path): assert str(output["unclassified"][1]).endswith("this is the content of the document.wav") @pytest.mark.unit - def test_no_extension(self, preview_samples_path): + def test_no_extension(self, test_files_path): """ Test that the component ignores files with no extension. """ file_paths = [ - preview_samples_path / "txt" / "doc_1.txt", - preview_samples_path / "txt" / "doc_2", - preview_samples_path / "txt" / "doc_2.txt", + test_files_path / "txt" / "doc_1.txt", + test_files_path / "txt" / "doc_2", + test_files_path / "txt" / "doc_2.txt", ] router = FileTypeRouter(mime_types=["text/plain"]) output = router.run(sources=file_paths) diff --git a/test/components/routers/test_metadata_router.py b/test/components/routers/test_metadata_router.py index 5109f8db6c..615f1cfa3d 100644 --- a/test/components/routers/test_metadata_router.py +++ b/test/components/routers/test_metadata_router.py @@ -1,7 +1,7 @@ import pytest -from haystack.preview import Document -from haystack.preview.components.routers.metadata_router import MetadataRouter +from haystack import Document +from haystack.components.routers.metadata_router import MetadataRouter class TestMetadataRouter: diff --git a/test/components/routers/test_text_language_router.py b/test/components/routers/test_text_language_router.py index c3e333ec2b..eca8ccf82d 100644 --- a/test/components/routers/test_text_language_router.py +++ b/test/components/routers/test_text_language_router.py @@ -1,8 +1,8 @@ import logging import pytest -from haystack.preview import Document -from haystack.preview.components.routers import TextLanguageRouter +from haystack import Document +from haystack.components.routers import TextLanguageRouter class TestTextLanguageRouter: diff --git a/test/components/samplers/test_top_p.py b/test/components/samplers/test_top_p.py index 74d0e269db..a264c1b750 100644 --- a/test/components/samplers/test_top_p.py +++ b/test/components/samplers/test_top_p.py @@ -2,8 +2,8 @@ import pytest -from haystack.preview import Document, ComponentError -from haystack.preview.components.samplers.top_p import TopPSampler +from haystack import Document, ComponentError +from haystack.components.samplers.top_p import TopPSampler class TestTopPSampler: diff --git a/test/components/websearch/test_searchapi.py b/test/components/websearch/test_searchapi.py index c1aef566b1..0747c54f53 100644 --- a/test/components/websearch/test_searchapi.py +++ b/test/components/websearch/test_searchapi.py @@ -4,8 +4,8 @@ import pytest from requests import Timeout, RequestException, HTTPError -from haystack.preview import Document -from haystack.preview.components.websearch.searchapi import SearchApiError, SearchApiWebSearch +from haystack import Document +from haystack.components.websearch.searchapi import SearchApiError, SearchApiWebSearch EXAMPLE_SEARCHAPI_RESPONSE = { @@ -361,7 +361,7 @@ @pytest.fixture def mock_searchapi_search_result(): - with patch("haystack.preview.components.websearch.searchapi.requests.get") as mock_get: + with patch("haystack.components.websearch.searchapi.requests.get") as mock_get: mock_get.return_value = Mock(status_code=200, json=lambda: EXAMPLE_SEARCHAPI_RESPONSE) yield mock_get @@ -380,7 +380,7 @@ def test_to_dict(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.websearch.searchapi.SearchApiWebSearch", + "type": "haystack.components.websearch.searchapi.SearchApiWebSearch", "init_parameters": { "top_k": 10, "allowed_domains": ["testdomain.com"], diff --git a/test/components/websearch/test_serperdev.py b/test/components/websearch/test_serperdev.py index 48d8619d21..16a8750573 100644 --- a/test/components/websearch/test_serperdev.py +++ b/test/components/websearch/test_serperdev.py @@ -4,8 +4,8 @@ import pytest from requests import Timeout, RequestException, HTTPError -from haystack.preview import Document -from haystack.preview.components.websearch.serper_dev import SerperDevWebSearch, SerperDevError +from haystack import Document +from haystack.components.websearch.serper_dev import SerperDevWebSearch, SerperDevError EXAMPLE_SERPERDEV_RESPONSE = { @@ -102,7 +102,7 @@ @pytest.fixture def mock_serper_dev_search_result(): - with patch("haystack.preview.components.websearch.serper_dev.requests") as mock_run: + with patch("haystack.components.websearch.serper_dev.requests") as mock_run: mock_run.post.return_value = Mock(status_code=200, json=lambda: EXAMPLE_SERPERDEV_RESPONSE) yield mock_run @@ -121,7 +121,7 @@ def test_to_dict(self): ) data = component.to_dict() assert data == { - "type": "haystack.preview.components.websearch.serper_dev.SerperDevWebSearch", + "type": "haystack.components.websearch.serper_dev.SerperDevWebSearch", "init_parameters": {"top_k": 10, "allowed_domains": ["test.com"], "search_params": {"param": "test"}}, } diff --git a/test/components/writers/test_document_writer.py b/test/components/writers/test_document_writer.py index ed5b9a4119..a35361f6b3 100644 --- a/test/components/writers/test_document_writer.py +++ b/test/components/writers/test_document_writer.py @@ -1,10 +1,10 @@ import pytest -from haystack.preview import Document, DeserializationError -from haystack.preview.testing.factory import document_store_class -from haystack.preview.components.writers.document_writer import DocumentWriter -from haystack.preview.document_stores import DuplicatePolicy -from haystack.preview.document_stores.in_memory import InMemoryDocumentStore +from haystack import Document, DeserializationError +from haystack.testing.factory import document_store_class +from haystack.components.writers.document_writer import DocumentWriter +from haystack.document_stores import DuplicatePolicy +from haystack.document_stores.in_memory import InMemoryDocumentStore class TestDocumentWriter: @@ -14,12 +14,9 @@ def test_to_dict(self): component = DocumentWriter(document_store=mocked_docstore_class()) data = component.to_dict() assert data == { - "type": "haystack.preview.components.writers.document_writer.DocumentWriter", + "type": "haystack.components.writers.document_writer.DocumentWriter", "init_parameters": { - "document_store": { - "type": "haystack.preview.testing.factory.MockedDocumentStore", - "init_parameters": {}, - }, + "document_store": {"type": "haystack.testing.factory.MockedDocumentStore", "init_parameters": {}}, "policy": "FAIL", }, } @@ -30,12 +27,9 @@ def test_to_dict_with_custom_init_parameters(self): component = DocumentWriter(document_store=mocked_docstore_class(), policy=DuplicatePolicy.SKIP) data = component.to_dict() assert data == { - "type": "haystack.preview.components.writers.document_writer.DocumentWriter", + "type": "haystack.components.writers.document_writer.DocumentWriter", "init_parameters": { - "document_store": { - "type": "haystack.preview.testing.factory.MockedDocumentStore", - "init_parameters": {}, - }, + "document_store": {"type": "haystack.testing.factory.MockedDocumentStore", "init_parameters": {}}, "policy": "SKIP", }, } @@ -44,12 +38,9 @@ def test_to_dict_with_custom_init_parameters(self): def test_from_dict(self): mocked_docstore_class = document_store_class("MockedDocumentStore") data = { - "type": "haystack.preview.components.writers.document_writer.DocumentWriter", + "type": "haystack.components.writers.document_writer.DocumentWriter", "init_parameters": { - "document_store": { - "type": "haystack.preview.testing.factory.MockedDocumentStore", - "init_parameters": {}, - }, + "document_store": {"type": "haystack.testing.factory.MockedDocumentStore", "init_parameters": {}}, "policy": "SKIP", }, } diff --git a/test/conftest.py b/test/conftest.py index 3a2f166120..4887fa777f 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -2,7 +2,7 @@ from unittest.mock import Mock import pytest -from haystack.preview.testing.test_utils import set_all_seeds +from haystack.testing.test_utils import set_all_seeds set_all_seeds(0) diff --git a/test/dataclasses/test_byte_stream.py b/test/dataclasses/test_byte_stream.py index 4c3f0e154c..1bcbbc3da3 100644 --- a/test/dataclasses/test_byte_stream.py +++ b/test/dataclasses/test_byte_stream.py @@ -1,6 +1,6 @@ import io -from haystack.preview.dataclasses import ByteStream +from haystack.dataclasses import ByteStream import pytest diff --git a/test/dataclasses/test_chat_message.py b/test/dataclasses/test_chat_message.py index 1c0ec71cf3..d1489a90cc 100644 --- a/test/dataclasses/test_chat_message.py +++ b/test/dataclasses/test_chat_message.py @@ -1,7 +1,7 @@ import pytest from transformers import AutoTokenizer -from haystack.preview.dataclasses import ChatMessage, ChatRole +from haystack.dataclasses import ChatMessage, ChatRole @pytest.mark.unit diff --git a/test/dataclasses/test_document.py b/test/dataclasses/test_document.py index 593a3f449e..549fa67090 100644 --- a/test/dataclasses/test_document.py +++ b/test/dataclasses/test_document.py @@ -3,8 +3,8 @@ import pandas as pd import pytest -from haystack.preview import Document -from haystack.preview.dataclasses.byte_stream import ByteStream +from haystack import Document +from haystack.dataclasses.byte_stream import ByteStream @pytest.mark.unit diff --git a/test/dataclasses/test_streaming_chunk.py b/test/dataclasses/test_streaming_chunk.py index 1a4c99ccc3..df061ea2ba 100644 --- a/test/dataclasses/test_streaming_chunk.py +++ b/test/dataclasses/test_streaming_chunk.py @@ -1,6 +1,6 @@ import pytest -from haystack.preview.dataclasses import StreamingChunk +from haystack.dataclasses import StreamingChunk @pytest.mark.unit diff --git a/test/document_stores/test_in_memory.py b/test/document_stores/test_in_memory.py index ce37754338..91c5f5fa45 100644 --- a/test/document_stores/test_in_memory.py +++ b/test/document_stores/test_in_memory.py @@ -4,11 +4,11 @@ import pandas as pd import pytest -from haystack.preview import Document -from haystack.preview.document_stores import InMemoryDocumentStore, DocumentStoreError, DuplicatePolicy +from haystack import Document +from haystack.document_stores import InMemoryDocumentStore, DocumentStoreError, DuplicatePolicy -from haystack.preview.testing.document_store import DocumentStoreBaseTests +from haystack.testing.document_store import DocumentStoreBaseTests class TestMemoryDocumentStore(DocumentStoreBaseTests): # pylint: disable=R0904 @@ -25,7 +25,7 @@ def test_to_dict(self): store = InMemoryDocumentStore() data = store.to_dict() assert data == { - "type": "haystack.preview.document_stores.in_memory.document_store.InMemoryDocumentStore", + "type": "haystack.document_stores.in_memory.document_store.InMemoryDocumentStore", "init_parameters": { "bm25_tokenization_regex": r"(?u)\b\w\w+\b", "bm25_algorithm": "BM25Okapi", @@ -44,7 +44,7 @@ def test_to_dict_with_custom_init_parameters(self): ) data = store.to_dict() assert data == { - "type": "haystack.preview.document_stores.in_memory.document_store.InMemoryDocumentStore", + "type": "haystack.document_stores.in_memory.document_store.InMemoryDocumentStore", "init_parameters": { "bm25_tokenization_regex": "custom_regex", "bm25_algorithm": "BM25Plus", @@ -54,10 +54,10 @@ def test_to_dict_with_custom_init_parameters(self): } @pytest.mark.unit - @patch("haystack.preview.document_stores.in_memory.document_store.re") + @patch("haystack.document_stores.in_memory.document_store.re") def test_from_dict(self, mock_regex): data = { - "type": "haystack.preview.document_stores.in_memory.document_store.InMemoryDocumentStore", + "type": "haystack.document_stores.in_memory.document_store.InMemoryDocumentStore", "init_parameters": { "bm25_tokenization_regex": "custom_regex", "bm25_algorithm": "BM25Plus", diff --git a/test/samples/audio/answer.wav b/test/samples/audio/answer.wav deleted file mode 100644 index 874eab01fede4e6b7fe24270d70ff85a87f5caa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29228 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 diff --git a/test/samples/audio/the context for this answer is here.wav b/test/samples/audio/the context for this answer is here.wav deleted file mode 100644 index b6515a85dbda357af854a4df5f7e390702333963..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99884 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 KjOa?vll?zJxZF_y diff --git a/test/samples/audio/this is the content of the document.wav b/test/samples/audio/this is the content of the document.wav deleted file mode 100644 index 37d651fa9dd0755ab3aa9d6c71d19958c7d18719..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89644 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

-&{zMv1^W?Xr?>wlI!cm-L192gLef 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 diff --git a/test/samples/crawler/index.html b/test/samples/crawler/index.html deleted file mode 100644 index 34d01cf7d6..0000000000 --- a/test/samples/crawler/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Test Home Page for Crawler - - -

home page content

- link to page 1 - link to page 2 - - diff --git a/test/samples/crawler/page1.html b/test/samples/crawler/page1.html deleted file mode 100644 index b2481e9e2f..0000000000 --- a/test/samples/crawler/page1.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Test Page 1 for Crawler - - -

page 1 content

- link to home - link to page 2 - link to subpage 1 - link to subpage 2 - - diff --git a/test/samples/crawler/page1_subpage1.html b/test/samples/crawler/page1_subpage1.html deleted file mode 100644 index 4c50a1e924..0000000000 --- a/test/samples/crawler/page1_subpage1.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Test Subpage 1 of Page 1 for Crawler - - -

subpage 1 of page 1 content

- - diff --git a/test/samples/crawler/page1_subpage2.html b/test/samples/crawler/page1_subpage2.html deleted file mode 100644 index 50ac48e5c1..0000000000 --- a/test/samples/crawler/page1_subpage2.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Test Subpage 2 of Page 1 for Crawler - - -

subpage 2 of page 1 content

- - diff --git a/test/samples/crawler/page2.html b/test/samples/crawler/page2.html deleted file mode 100644 index 7494b01859..0000000000 --- a/test/samples/crawler/page2.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - Test Page 2 for Crawler - - -

page 2 content

- link to home - link to page 1 - link to subpage - - diff --git a/test/samples/crawler/page2_subpage1.html b/test/samples/crawler/page2_subpage1.html deleted file mode 100644 index b5539e3517..0000000000 --- a/test/samples/crawler/page2_subpage1.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Test Subpage 1 of Page 2 for Crawler - - -

subpage 1 of page 2 content

- - diff --git a/test/samples/crawler/page_dynamic.html b/test/samples/crawler/page_dynamic.html deleted file mode 100644 index bccca8cc57..0000000000 --- a/test/samples/crawler/page_dynamic.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - Test Dynamic Page - - -

home page content

- - - - diff --git a/test/samples/crawler/page_dynamic_result.txt b/test/samples/crawler/page_dynamic_result.txt deleted file mode 100644 index 920342fcfa..0000000000 --- a/test/samples/crawler/page_dynamic_result.txt +++ /dev/null @@ -1,29 +0,0 @@ - - home page content - - link to index - - link to page 1 - - - const updateTimeout = setTimeout(myUpdateFunction, 150); - - function myUpdateFunction() { - const remElem = document.querySelector('#a2'); - if (remElem) - remElem.parentNode.removeChild(remElem); - - if (!document.querySelector('#a4')) { - const newElem = document.createElement('a'); - newElem.href = 'page2.html'; - newElem.id = 'a4'; - newElem.innerText = 'link to page 2'; - document.body.appendChild(newElem); - } - - clearTimeout(updateTimeout); - } - - - -link to page 2 diff --git a/test/samples/crawler/page_w_hidden_text.html b/test/samples/crawler/page_w_hidden_text.html deleted file mode 100644 index 2497f6d754..0000000000 --- a/test/samples/crawler/page_w_hidden_text.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - Test Page - - -

visible text

-

hidden text

- - diff --git a/test/samples/crawler/page_with_a_very_long_name_to_do_some_tests_Now_let's_add_some_text_just_to_pass_the_129_chars_mark_and_trigger_the_chars_limit_of_the_default_naming_function.html b/test/samples/crawler/page_with_a_very_long_name_to_do_some_tests_Now_let's_add_some_text_just_to_pass_the_129_chars_mark_and_trigger_the_chars_limit_of_the_default_naming_function.html deleted file mode 100644 index bfd77840f7..0000000000 --- a/test/samples/crawler/page_with_a_very_long_name_to_do_some_tests_Now_let's_add_some_text_just_to_pass_the_129_chars_mark_and_trigger_the_chars_limit_of_the_default_naming_function.html +++ /dev/null @@ -1 +0,0 @@ -This is a page with a very long name to do some tests. diff --git a/test/samples/dc/documents-stream.response b/test/samples/dc/documents-stream.response deleted file mode 100644 index 94d77adeb4..0000000000 --- a/test/samples/dc/documents-stream.response +++ /dev/null @@ -1,157 +0,0 @@ -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9e30ff59-bb4a-4bfe-985d-ec7957dd6d36", "_split_id": 0}, "embedding": null, "id": "f75637c3165fdb74d53dc1ce640b2ab5"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9e30ff59-bb4a-4bfe-985d-ec7957dd6d36", "_split_id": 1}, "embedding": null, "id": "ad4955b31d30255e13c996c89a3b522d"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9b9eb589-7717-46c7-9f45-c8d59870ab41", "_split_id": 0}, "embedding": null, "id": "a6011cd04fa7a59fef9ade057b3f2231"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0116ab5b-3435-4255-ab5f-94e8660053bb", "_split_id": 4}, "embedding": null, "id": "f825879c0ff3182ec02f9377f28f5f4b"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0ca62c2f-b937-4fd1-abbc-1af3f9bcdd0e", "_split_id": 2}, "embedding": null, "id": "6409361f09eef3fc25d808456fa90999"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "485fdf30-5969-432c-9e72-2553f3f827e7", "_split_id": 5}, "embedding": null, "id": "6627d6bf95771aa8559d0e7280ea86e9"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "e136b82b-57c2-46ea-b6bd-bcfa01a3abe8", "_split_id": 0}, "embedding": null, "id": "c6c4b261c36d54b6ef079a211fd48602"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "97608f5f-5b7a-4422-b241-566ffcbf8cc5", "_split_id": 5}, "embedding": null, "id": "e68c3ca4fcf7287d5bfa6f56d4cf6e59"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "e136b82b-57c2-46ea-b6bd-bcfa01a3abe8", "_split_id": 2}, "embedding": null, "id": "b9a063a886d5701b171d598a4f5e2205"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "070b0cc4-a20e-4451-b3ab-0a26f032fb5d", "_split_id": 0}, "embedding": null, "id": "e1b07dd19b98e0fcb316f1a0e77b5363"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "e136b82b-57c2-46ea-b6bd-bcfa01a3abe8", "_split_id": 3}, "embedding": null, "id": "146c441ffbb5f8ea8557aea31ee7eeb9"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "070b0cc4-a20e-4451-b3ab-0a26f032fb5d", "_split_id": 1}, "embedding": null, "id": "d6e50bfd4f4f5756c04ccf618421ec96"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "97608f5f-5b7a-4422-b241-566ffcbf8cc5", "_split_id": 0}, "embedding": null, "id": "1dab72ffb8e992523c348943cf74282b"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0ca62c2f-b937-4fd1-abbc-1af3f9bcdd0e", "_split_id": 0}, "embedding": null, "id": "67daa603546af9ab779bfdc156eef3b5"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0e3576c8-dc4f-441e-985e-0e5d287a31bc", "_split_id": 0}, "embedding": null, "id": "a5938e3fcd9730ee19ad39a45a965a99"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "070b0cc4-a20e-4451-b3ab-0a26f032fb5d", "_split_id": 5}, "embedding": null, "id": "aa2fcdf84c5b5e0ff8bc5fdebf7140fa"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "97608f5f-5b7a-4422-b241-566ffcbf8cc5", "_split_id": 4}, "embedding": null, "id": "d64489260bf4284d0458d6403fdfd9bf"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0ca62c2f-b937-4fd1-abbc-1af3f9bcdd0e", "_split_id": 1}, "embedding": null, "id": "ca7f99264952d42cfb3025657f058386"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0e3576c8-dc4f-441e-985e-0e5d287a31bc", "_split_id": 1}, "embedding": null, "id": "1576b46bd52061b9d65b4198823dc8fa"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "6caad09d-0740-41d9-aa14-364f00bba648", "_split_id": 2}, "embedding": null, "id": "3c2392cb0922fb379d799a6cb1e375f0"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "10e79a98-51c8-44bf-b193-132458cfac70", "_split_id": 2}, "embedding": null, "id": "705a3624d286946fefb3f05e4d203078"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0ca62c2f-b937-4fd1-abbc-1af3f9bcdd0e", "_split_id": 3}, "embedding": null, "id": "884c36948e9dc3f64c70cf128fddb8a1"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0e3576c8-dc4f-441e-985e-0e5d287a31bc", "_split_id": 2}, "embedding": null, "id": "26daf3db8a5667fa6eb2acc5e022f1cd"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "6caad09d-0740-41d9-aa14-364f00bba648", "_split_id": 3}, "embedding": null, "id": "5456e3c558c6408c684720f722611d2b"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "10e79a98-51c8-44bf-b193-132458cfac70", "_split_id": 5}, "embedding": null, "id": "9555becfc50429a1decd35d92638406"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0ca62c2f-b937-4fd1-abbc-1af3f9bcdd0e", "_split_id": 4}, "embedding": null, "id": "cf7c81ecf1e32cb9c19a569259dc7bf7"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0e3576c8-dc4f-441e-985e-0e5d287a31bc", "_split_id": 3}, "embedding": null, "id": "f91f136bbd4a233d20fa813ddbb3351a"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "6caad09d-0740-41d9-aa14-364f00bba648", "_split_id": 5}, "embedding": null, "id": "31253e3c0984916e4013635f57b356d6"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "485fdf30-5969-432c-9e72-2553f3f827e7", "_split_id": 4}, "embedding": null, "id": "40b317f0ac0dc55297ab5d9376054d50"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "c713ff80-6464-4d17-81a3-c7451fac11c5", "_split_id": 0}, "embedding": null, "id": "81635c0e2dd455b0b4f86b829cc51a9b"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0e3576c8-dc4f-441e-985e-0e5d287a31bc", "_split_id": 4}, "embedding": null, "id": "35136e9ac9f154e10f9178fe29f5f30c"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "1d1d692d-3a11-4b4a-b376-2bbd4a7a92ff", "_split_id": 0}, "embedding": null, "id": "f955858e1d9a6ab8564f47ec15fb57dc"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9e30ff59-bb4a-4bfe-985d-ec7957dd6d36", "_split_id": 2}, "embedding": null, "id": "40f288df332ab5f463b624e9a5ac69e3"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "c713ff80-6464-4d17-81a3-c7451fac11c5", "_split_id": 2}, "embedding": null, "id": "778f791ebd5e7e7939c0d07092029e6d"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "10e79a98-51c8-44bf-b193-132458cfac70", "_split_id": 0}, "embedding": null, "id": "6501ac6fabdd0dd4951d2f24aadcc8a9"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "1d1d692d-3a11-4b4a-b376-2bbd4a7a92ff", "_split_id": 1}, "embedding": null, "id": "bf7b927572cdb4d552f89cc4675bd5a0"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0e3576c8-dc4f-441e-985e-0e5d287a31bc", "_split_id": 5}, "embedding": null, "id": "1dc8685072d31460c94ed89f88c9b391"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "c713ff80-6464-4d17-81a3-c7451fac11c5", "_split_id": 5}, "embedding": null, "id": "9bd4b4bad63b3cb1dd6573b856ab16dd"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "10e79a98-51c8-44bf-b193-132458cfac70", "_split_id": 1}, "embedding": null, "id": "5302591c4d92a24cfc4c1f2246e78b02"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "1d1d692d-3a11-4b4a-b376-2bbd4a7a92ff", "_split_id": 3}, "embedding": null, "id": "2cfc84f0dc7c85f8b6cfafc03ce09812"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0ca62c2f-b937-4fd1-abbc-1af3f9bcdd0e", "_split_id": 5}, "embedding": null, "id": "1dc263e00b6cbe680334a005e6d0353b"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0116ab5b-3435-4255-ab5f-94e8660053bb", "_split_id": 0}, "embedding": null, "id": "e9e63270e334ec0041ce0dafc05243c0"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "c713ff80-6464-4d17-81a3-c7451fac11c5", "_split_id": 1}, "embedding": null, "id": "26bde1b9edee014f664480044056c091"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "3f86e0db-a515-4948-aa24-70f8eba83237", "_split_id": 0}, "embedding": null, "id": "a0f3d8012a4838798acd323a2a541126"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "61ca8758-045c-4d16-9a1a-e7cb35f41f37", "_split_id": 1}, "embedding": null, "id": "14d9d8d5a07011e436c244783249df3f"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0116ab5b-3435-4255-ab5f-94e8660053bb", "_split_id": 2}, "embedding": null, "id": "99ffd03e406bf1fa513dff015219bc30"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "c713ff80-6464-4d17-81a3-c7451fac11c5", "_split_id": 3}, "embedding": null, "id": "7d4e0b515bc89dd52d13aa4bbf72e956"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "3f86e0db-a515-4948-aa24-70f8eba83237", "_split_id": 4}, "embedding": null, "id": "a64adb19bc82119c8c65aa19de6b30ea"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "61ca8758-045c-4d16-9a1a-e7cb35f41f37", "_split_id": 2}, "embedding": null, "id": "69733c5d8e11d5b11d034e0f0da1503a"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "10e79a98-51c8-44bf-b193-132458cfac70", "_split_id": 3}, "embedding": null, "id": "c18981cb92b56f58cf8b9428bdfdd2f3"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "e136b82b-57c2-46ea-b6bd-bcfa01a3abe8", "_split_id": 4}, "embedding": null, "id": "34aa666352f2f9a00f9e75d2e7c1c36d"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "ba94ac9a-e1b8-413d-a4bb-360384c3518a", "_split_id": 4}, "embedding": null, "id": "792becc5868394d119dea485e3db1427"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "61ca8758-045c-4d16-9a1a-e7cb35f41f37", "_split_id": 5}, "embedding": null, "id": "745beb9c3b99d589d1e8e19d48fd6d79"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "10e79a98-51c8-44bf-b193-132458cfac70", "_split_id": 4}, "embedding": null, "id": "f64fd840961ff94de2eabf4413363a1e"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "e136b82b-57c2-46ea-b6bd-bcfa01a3abe8", "_split_id": 5}, "embedding": null, "id": "642d59d63f8e3b031cefd239e1c18281"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "ba94ac9a-e1b8-413d-a4bb-360384c3518a", "_split_id": 5}, "embedding": null, "id": "dd8a709b15654a2cc9d2ea5fee147310"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "6caad09d-0740-41d9-aa14-364f00bba648", "_split_id": 0}, "embedding": null, "id": "18520fa7a244f6ed99607d5743e7f4fb"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "e136b82b-57c2-46ea-b6bd-bcfa01a3abe8", "_split_id": 1}, "embedding": null, "id": "8f56e5aa14fb56c434442a0c02bfb01"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0116ab5b-3435-4255-ab5f-94e8660053bb", "_split_id": 3}, "embedding": null, "id": "61a4cdd9ab0c79fd7a0a071a73e4a317"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "cc308b3e-6f82-4e15-ad87-6bcd80fe10b6", "_split_id": 4}, "embedding": null, "id": "80ee0337f6c9ece55c785f404d5c56c8"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "6caad09d-0740-41d9-aa14-364f00bba648", "_split_id": 4}, "embedding": null, "id": "c232cf6ad3369337504eb451366a139"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "485fdf30-5969-432c-9e72-2553f3f827e7", "_split_id": 1}, "embedding": null, "id": "b8174be8e798669f7985c45d7d68f157"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0116ab5b-3435-4255-ab5f-94e8660053bb", "_split_id": 5}, "embedding": null, "id": "eeca5fdff97dabc64a9f686e5aa0e322"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "d7191635-03e8-4709-934e-5dfd95dcb2ef", "_split_id": 4}, "embedding": null, "id": "12de7ada1add46c898f98b6577390d1c"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "512bdbe6-56a5-48f1-8e09-6283a788102b", "_split_id": 3}, "embedding": null, "id": "6f3848f7fb0d8b9bde1f219acde84877"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "97608f5f-5b7a-4422-b241-566ffcbf8cc5", "_split_id": 1}, "embedding": null, "id": "92415a4d4b56c7d7c43e8d7c6643db69"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "485fdf30-5969-432c-9e72-2553f3f827e7", "_split_id": 2}, "embedding": null, "id": "fe2e2b6af8a2844e59a054d25b0918a0"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "2af4c6e4-34a4-4941-b0b9-48e9ea2681ab", "_split_id": 1}, "embedding": null, "id": "2644cbcd0c6761359e3c248bf3ab1357"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "512bdbe6-56a5-48f1-8e09-6283a788102b", "_split_id": 4}, "embedding": null, "id": "687c158b5b609a81482eacf9538e4a60"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9e30ff59-bb4a-4bfe-985d-ec7957dd6d36", "_split_id": 5}, "embedding": null, "id": "364f8ea7efd1906c54985984b502f74b"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "2af4c6e4-34a4-4941-b0b9-48e9ea2681ab", "_split_id": 0}, "embedding": null, "id": "424c7b045a65fb28dfb2d2d8e3f79fb"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "512bdbe6-56a5-48f1-8e09-6283a788102b", "_split_id": 1}, "embedding": null, "id": "59ee0e8d608b1973de4f2647a9dd0a35"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "ba94ac9a-e1b8-413d-a4bb-360384c3518a", "_split_id": 0}, "embedding": null, "id": "88294aa3f4498c393b8645e5c0b21753"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "71281e3f-6f7c-4f76-a831-94cd40735ada", "_split_id": 3}, "embedding": null, "id": "d90275fa100797d880b8d0f33794494f"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "2af4c6e4-34a4-4941-b0b9-48e9ea2681ab", "_split_id": 4}, "embedding": null, "id": "dd4e06eed4fdcca2d91ecac0e4b1ad5d"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "62455269-7e9d-4d8e-8630-5127bd4bb434", "_split_id": 5}, "embedding": null, "id": "483dcead2143d78bd3a83f40ea565283"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "ba94ac9a-e1b8-413d-a4bb-360384c3518a", "_split_id": 2}, "embedding": null, "id": "3b7cec16a2139f2720fe3c083c1368da"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "71281e3f-6f7c-4f76-a831-94cd40735ada", "_split_id": 4}, "embedding": null, "id": "8d5bd71e6284b077303f42d53abb3a4a"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "71281e3f-6f7c-4f76-a831-94cd40735ada", "_split_id": 0}, "embedding": null, "id": "6eda74e9f40b44fba9ee7563bbd684a2"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "80dca679-78c3-4aa0-975c-655ecb68e4c9", "_split_id": 5}, "embedding": null, "id": "1311b9940de66dc7dc0972af7113762d"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9b9eb589-7717-46c7-9f45-c8d59870ab41", "_split_id": 3}, "embedding": null, "id": "9b72d21ab34c8be348d9569c5c8bf358"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "3f86e0db-a515-4948-aa24-70f8eba83237", "_split_id": 2}, "embedding": null, "id": "efc8b111a70d759b331c0ff3f0dc8944"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "71281e3f-6f7c-4f76-a831-94cd40735ada", "_split_id": 5}, "embedding": null, "id": "e977a2185c6e972ee7cce9f3a05db612"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "61ca8758-045c-4d16-9a1a-e7cb35f41f37", "_split_id": 4}, "embedding": null, "id": "380ddb5d492caca27dd99082051c45b1"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9b9eb589-7717-46c7-9f45-c8d59870ab41", "_split_id": 4}, "embedding": null, "id": "2e3ad885fd7400c2e6f219b4ece8ca35"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "3f86e0db-a515-4948-aa24-70f8eba83237", "_split_id": 5}, "embedding": null, "id": "e7e0731826d6762a754cbd5d8963557b"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "1d1d692d-3a11-4b4a-b376-2bbd4a7a92ff", "_split_id": 4}, "embedding": null, "id": "a24c16ded4381475e3d14fe30649c6e4"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "752c9097-95ce-4601-8ac1-bb0b50067304", "_split_id": 1}, "embedding": null, "id": "47f5846190dfdd28e96dbd05b6feb27f"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "beccebad-30ff-4798-b8c7-f400539995df", "_split_id": 0}, "embedding": null, "id": "85641b7c7add0bc7f37d26a6bd964d18"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "ba94ac9a-e1b8-413d-a4bb-360384c3518a", "_split_id": 3}, "embedding": null, "id": "308468b87aa53ac1d04a1d8aa1dd5383"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "1d1d692d-3a11-4b4a-b376-2bbd4a7a92ff", "_split_id": 5}, "embedding": null, "id": "736112bf727be893008c3253521d278f"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9bf5912e-9ad5-40bb-96d7-3dfa98e9b98e", "_split_id": 1}, "embedding": null, "id": "d44c637484fd79ffe3b3eaafff21068b"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "beccebad-30ff-4798-b8c7-f400539995df", "_split_id": 5}, "embedding": null, "id": "af9023ac0de9fb04fbff73254d3df21e"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "2af4c6e4-34a4-4941-b0b9-48e9ea2681ab", "_split_id": 3}, "embedding": null, "id": "b295318e8d17298777520f5804423bb7"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "cc308b3e-6f82-4e15-ad87-6bcd80fe10b6", "_split_id": 0}, "embedding": null, "id": "3d9d3f310f3f866fce02b64832f98bea"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "2af4c6e4-34a4-4941-b0b9-48e9ea2681ab", "_split_id": 2}, "embedding": null, "id": "48c4896276f83a084c43c3633b8fab07"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9b9eb589-7717-46c7-9f45-c8d59870ab41", "_split_id": 1}, "embedding": null, "id": "b52678990c9fc6bcf1df25dae58c6271"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "ba94ac9a-e1b8-413d-a4bb-360384c3518a", "_split_id": 1}, "embedding": null, "id": "7a9a6d0a9ccd8f3f088e22f5d72c9f8f"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "2af4c6e4-34a4-4941-b0b9-48e9ea2681ab", "_split_id": 5}, "embedding": null, "id": "d35d59087dfd30e436fe092f36f5755e"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "1d1d692d-3a11-4b4a-b376-2bbd4a7a92ff", "_split_id": 2}, "embedding": null, "id": "3e7fad376980eb8492bf0f2d1eb1fb56"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9b9eb589-7717-46c7-9f45-c8d59870ab41", "_split_id": 2}, "embedding": null, "id": "6ef0c7a4240bada8f1505875c5c3ca02"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "62455269-7e9d-4d8e-8630-5127bd4bb434", "_split_id": 0}, "embedding": null, "id": "f1c65e35452f07437e328e161dca0ee8"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "cc308b3e-6f82-4e15-ad87-6bcd80fe10b6", "_split_id": 2}, "embedding": null, "id": "ba8bc53df8f31ba0ea8b4660678da5cb"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "beccebad-30ff-4798-b8c7-f400539995df", "_split_id": 3}, "embedding": null, "id": "f4b86ebd3f79478dcf90b4f3af6b0405"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "71281e3f-6f7c-4f76-a831-94cd40735ada", "_split_id": 2}, "embedding": null, "id": "bfa86c3c26988f6eb5b06d32eb7c7ae3"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "80dca679-78c3-4aa0-975c-655ecb68e4c9", "_split_id": 0}, "embedding": null, "id": "f671ab6ed326cb2384462739cd1be3be"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "beccebad-30ff-4798-b8c7-f400539995df", "_split_id": 4}, "embedding": null, "id": "db5f82cb89d5fb2181131d8d0f78334f"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "cc308b3e-6f82-4e15-ad87-6bcd80fe10b6", "_split_id": 5}, "embedding": null, "id": "8a2cbc4cc018e2b26ba5565a82dd1949"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "80dca679-78c3-4aa0-975c-655ecb68e4c9", "_split_id": 1}, "embedding": null, "id": "dbd271fe770e8f2aa713567747de4f35"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "62455269-7e9d-4d8e-8630-5127bd4bb434", "_split_id": 1}, "embedding": null, "id": "812c8fbf638f046dce02c8f91b35b219"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "752c9097-95ce-4601-8ac1-bb0b50067304", "_split_id": 0}, "embedding": null, "id": "5d83c0592539aa706fdfec970653f51a"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "80dca679-78c3-4aa0-975c-655ecb68e4c9", "_split_id": 3}, "embedding": null, "id": "62f3e479aaf83f20a7aae1cc2a023a7c"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "62455269-7e9d-4d8e-8630-5127bd4bb434", "_split_id": 3}, "embedding": null, "id": "98a36bcbba1f2754a1415f3f2d5f5fab"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "485fdf30-5969-432c-9e72-2553f3f827e7", "_split_id": 0}, "embedding": null, "id": "bf152449a08aa816e5640ecde4c02ff9"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "80dca679-78c3-4aa0-975c-655ecb68e4c9", "_split_id": 2}, "embedding": null, "id": "51e849f9d79e363f72767380e6cce61d"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "80dca679-78c3-4aa0-975c-655ecb68e4c9", "_split_id": 4}, "embedding": null, "id": "8020e9bff64ffcd0e84d6844624d3107"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9bf5912e-9ad5-40bb-96d7-3dfa98e9b98e", "_split_id": 2}, "embedding": null, "id": "a332e90c7f513ce4aff3187e7f8d43cb"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "485fdf30-5969-432c-9e72-2553f3f827e7", "_split_id": 3}, "embedding": null, "id": "e4015a8668c01910ef00c67d32971664"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "070b0cc4-a20e-4451-b3ab-0a26f032fb5d", "_split_id": 2}, "embedding": null, "id": "eaf926d8eaaa6112ce103ded1e2a5a8a"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "61ca8758-045c-4d16-9a1a-e7cb35f41f37", "_split_id": 0}, "embedding": null, "id": "1b79409d27711e2ab60a1cc8d78b70e2"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9bf5912e-9ad5-40bb-96d7-3dfa98e9b98e", "_split_id": 3}, "embedding": null, "id": "1f763f056400ed45f314cff34b1bdc95"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9e30ff59-bb4a-4bfe-985d-ec7957dd6d36", "_split_id": 3}, "embedding": null, "id": "c7e82cf9ce9efe6057ceb9829bcdff75"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "61ca8758-045c-4d16-9a1a-e7cb35f41f37", "_split_id": 3}, "embedding": null, "id": "b44d31f2ef9b4d9259de34e7daa3953e"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "070b0cc4-a20e-4451-b3ab-0a26f032fb5d", "_split_id": 4}, "embedding": null, "id": "7ffddbb3683bb1ce1e3c9e348a21b65a"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9e30ff59-bb4a-4bfe-985d-ec7957dd6d36", "_split_id": 4}, "embedding": null, "id": "306237dd7b15bdf8bc9bf6c639852e90"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "752c9097-95ce-4601-8ac1-bb0b50067304", "_split_id": 2}, "embedding": null, "id": "13dc8a97ec67cc20c7bfce40cd0c0255"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "752c9097-95ce-4601-8ac1-bb0b50067304", "_split_id": 3}, "embedding": null, "id": "70cef6ad0ee2c4d4d6011d13e2810c24"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "97608f5f-5b7a-4422-b241-566ffcbf8cc5", "_split_id": 2}, "embedding": null, "id": "2271c9be977bf58d8e985707db9a4369"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "752c9097-95ce-4601-8ac1-bb0b50067304", "_split_id": 4}, "embedding": null, "id": "a3a54f7623b6fa47a078d0a2bb6dc3b1"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "d7191635-03e8-4709-934e-5dfd95dcb2ef", "_split_id": 1}, "embedding": null, "id": "841bdbd441fbc3f333ded9a1af06f55c"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "97608f5f-5b7a-4422-b241-566ffcbf8cc5", "_split_id": 3}, "embedding": null, "id": "f144e7610e734e29eff30c01bb20fdca"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "d7191635-03e8-4709-934e-5dfd95dcb2ef", "_split_id": 0}, "embedding": null, "id": "88b151179d3d321d3f7c031c13041c68"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "512bdbe6-56a5-48f1-8e09-6283a788102b", "_split_id": 2}, "embedding": null, "id": "1eaa267bec349caf7b7afefa2b733db3"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "c713ff80-6464-4d17-81a3-c7451fac11c5", "_split_id": 4}, "embedding": null, "id": "921835a14f52d71a481f5dc59527be76"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "d7191635-03e8-4709-934e-5dfd95dcb2ef", "_split_id": 5}, "embedding": null, "id": "b278156afa817539585744a7fd0d5b47"} -{"content": "getative Merkmale\n\nBl\u00fctenknospe von Adansonia digitata\n\nBl\u00fcte von Adansonia digitata (Sektion Adansonia)\n\nBl\u00fcte von Adansonia rubrostipa (Sektion Longitubae)\nDie Adansonia-Arten sind in der Trockenzeit laubabwerfende Laubb\u00e4ume, die Wuchsh\u00f6hen von etwa 5 bis 30 Metern erreichen. Die gewaltigen, unbewehrten St\u00e4mme sind zylindrisch, konisch oder flaschenf\u00f6rmig. Sie tragen f\u00fcr gew\u00f6hnlich kompakte Baumkronen. Die unbewehrten (selten mit konischen Dornen besetzten, z. B. bei Adansonia rubrostipa) Haupt\u00e4ste sind waagerecht oder aufsteigend. Die r\u00f6tlichbraune bis gr\u00fcnliche Borke ist glatt oder bl\u00e4tterig und hat h\u00e4ufig eine gelbe oder gr\u00fcne Photosyntheseschicht nahe der Oberfl\u00e4che. Die Innenschichten bestehen aus z\u00e4hen L\u00e4ngsfasern. Das Holz ist fasrig und weich. Es sondert aus Verletzungen ein geruchloses, klebriges Harz ab. Juvenile Pflanzen sind schlank, mit verj\u00fcngten St\u00e4mmen, die am Grund oft geschwollen sind. Die Internodien an der Spitze der Wachstumszone sind sehr kurz, aber an den Jungtrieben l\u00e4nger. Die spiralig an den Zweigen angeordneten, handf\u00f6rmig gefiederten Laubbl\u00e4tter sind h\u00e4utig bis ledrig. Der Blattstiel ist mit zwei Gelenken versehen (bipulvinat). Die f\u00fcnf bis elf sitzenden oder gestielten Bl\u00e4ttchen sind elliptisch, lanzettlich oder verkehrt lanzettlich, wobei die seitlichen Teilbl\u00e4tter kleiner als die mittleren sind. Die Teilbl\u00e4tter sind kahl bis filzig mit einfachen oder in Gruppen angeordneten Haaren. Die Bl\u00e4ttchen sind meist spitz bis zu einer Spitze zulaufend (apiculat), selten stumpf. Der Blattrand ist ganzrandig oder gez\u00e4hnt. Die Laubbl\u00e4tter werden w\u00e4hrend der Trockenzeit abgeworfen. Die bis 2 Millimeter langen Nebenbl\u00e4tter fallen bald ab; selten sind sie 1 bis 1,5 Zentimeter lang und dauerhaft. Bl\u00fctenst\u00e4nde und Bl\u00fcten\nDie aufrechten und nur bei Adansonia digitata h\u00e4ngenden Bl\u00fcten sitzen einzeln oder selten zu zweit in achselst\u00e4ndigen Bl\u00fctenst\u00e4nden. Diese stehen in Gruppen bis zu f\u00fcnf an den Zweigenden. Bl\u00fctenstiel und Bl\u00fctenstandsstiel sind mehr oder weniger getrennt, Letzterer hat drei fr\u00fch abfallende (caducose) Tragbl\u00e4tter. Die Knospen sind fast kugelf\u00f6rmig, eif\u00f6rmig oder zylindrisch. Die zwittrigen, f\u00fcnfz\u00e4hligen Bl\u00fcten sind radi\u00e4rsymmetrisch bis leicht zygomorph gebaut. Der Bl\u00fctenbecher ist au\u00dfen geschuppt, gr\u00fcn oder braun und im Inneren seidenartig, cremefarben, rosarot oder rot. Am Grund befindet sich ein schmaler Gewebestreifen, der Nektar absondert. Er kann auch eine ringf\u00f6rmige Vertiefung bilden, die durch den Boden der Kelchr\u00f6hre gebildet wird. Die f\u00fcnf Kelchbl\u00e4tter sind mehr oder weniger miteinander verwachsen und ihre Zipfel sind am Bl\u00fctenboden zur\u00fcckgebogen oder gekr\u00fcmmt. Die f\u00fcnf freien, gebogenen Kronbl\u00e4tter sind cremewei\u00df, gelb oder rot. Es sind zahlreiche (100 bis 1100) Staubbl\u00e4tter vorhanden, die gew\u00f6hnlich kahl und wei\u00df oder gelblich sind. Die untere H\u00e4lfte der Staubf\u00e4den ist zu einer R\u00f6hre verwachsen, die zylindrisch oder leicht verj\u00fcngt ist. Die obere H\u00e4lfte der Staubf\u00e4den ist frei. Die Staubbeutel sind frei und gekr\u00fcmmt. [1] Sie sind monothekisch und \u00f6ffnen sich mit einem L\u00e4ngsriss. F\u00fcnf Fruchtbl\u00e4tter sind zu einem oberst\u00e4ndigen (hypogynen) Fruchtknoten verwachsen; er ist konisch bis l\u00e4nglich, braun oder gelblich und filzig mit aufw\u00e4rts zeigenden Haaren. Die zahlreichen anatropen Samenanlagen werden von langen, dichotomischen Nabelstr\u00e4ngen (Funiculi) getragen, die aus sieben bis neun tief eingebetteten Plazenten entstehen. Der Griffel ist einfach, d\u00fcnn, wei\u00df oder dunkelrot und an der Basis dicht filzig. Die Narbe besteht gew\u00f6hnlich aus f\u00fcnf bis zehn gelblichen oder dunkelroten, kurzen Lappen. Fr\u00fcchte und Samen\n\u2192 Hauptartikel: Baobab-Frucht\n\nFr\u00fcchte einer Adansonia digitata aus Burkina Faso\n\nSamen von Adansonia digitata\nDie kugelf\u00f6rmige, eif\u00f6rmige oder eif\u00f6rmig-zylindrische Frucht ist eine trockene, gro\u00dfe, vielsamige Beere, die gew\u00f6hnlich nicht aufp", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "16910b9c-2942-4fd6-8729-e5676975b5ac", "_split_id": 0}, "embedding": null, "id": "7a9c2244bca423d04b7ff4314ceafc4d"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "0116ab5b-3435-4255-ab5f-94e8660053bb", "_split_id": 1}, "embedding": null, "id": "9bbff11a33318cb6680a221287e877df"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "512bdbe6-56a5-48f1-8e09-6283a788102b", "_split_id": 0}, "embedding": null, "id": "e61a0b3a23847acf1cf05630a3750ed6"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9b9eb589-7717-46c7-9f45-c8d59870ab41", "_split_id": 5}, "embedding": null, "id": "70393fa829c62d578505c06c4ccc903e"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9bf5912e-9ad5-40bb-96d7-3dfa98e9b98e", "_split_id": 4}, "embedding": null, "id": "c0a4d58ba1d1d252a9ada44ded7b37e8"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "3f86e0db-a515-4948-aa24-70f8eba83237", "_split_id": 1}, "embedding": null, "id": "503b083688114e1997fac60feba57af9"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "070b0cc4-a20e-4451-b3ab-0a26f032fb5d", "_split_id": 3}, "embedding": null, "id": "503a002fe7e5cfc19f85631163f6fe4d"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "3f86e0db-a515-4948-aa24-70f8eba83237", "_split_id": 3}, "embedding": null, "id": "1976f06bad817bcc7faf1cb1e8499e62"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "62455269-7e9d-4d8e-8630-5127bd4bb434", "_split_id": 2}, "embedding": null, "id": "c3de8639066bed3a6b52a5064d1e1052"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "cc308b3e-6f82-4e15-ad87-6bcd80fe10b6", "_split_id": 1}, "embedding": null, "id": "6decc484a7ba882ea7c745840a07daf7"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "beccebad-30ff-4798-b8c7-f400539995df", "_split_id": 2}, "embedding": null, "id": "7d037c42140d50899bfda640680fba4f"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "cc308b3e-6f82-4e15-ad87-6bcd80fe10b6", "_split_id": 3}, "embedding": null, "id": "fbe20894c6e7c2d615e0fd68c8d9d1cf"} -{"content": "I picked up the phone, and instantly, I knew it was coming. It was David Benioff and Dan Weiss, the two creators of the show, and they stated the facts. But they did it really nice. I couldn't have asked for a better way to have that news broken to me. Them telling me beforehand really helped me out, otherwise I would have been in a state when I read it in the scripts. I probably would have cried.\" Actress Natalie Dormer, who was cast to play Queen Margaery Tyrell in the show's second season, also made her final appearance as a main cast member for the series. In contrast to Chapman, Dormer found out about her character's impending death approximately six months before the rest of the cast, saying \"I requested while making season 5 that showrunners David Benioff and Dan Weiss release me from working on the show earlier than usual so I could do another project, and they ended up phoning me \u2014 and that was The Call. But I got it six months ahead of normal. They were like, 'We weren't going to tell you this for a few more months, but we're not going to release you now, so you can't do that job you really want to do and we're really sorry about that. But on the bright side, we are going to release you proper in the not-so-distant future.' It was good news, bad news \u2014 no you can't do this, but don't worry, you're going to have lots more opportunities very soon.\" Dormer also stated about her departure, \"It's the longest time I've ever spent playing a character. I'll always have a little yellow rose after my heart, and I think it was just the right length of time, to be honest. It's time for the Westeros story to move on and it's a perfect time for her to exit.\" After appearing as a recurring guest actor in the fifth season, actor Jonathan Pryce was promoted to regular cast member for the sixth season. Prior to being cast as the High Sparrow, Pryce was approached to play another role in one of the previous seasons and refused the part. After being approached with the role of the High Sparrow, Pryce stated that he accepted the role because \"If the role hadn't been what it turned out to be for High Sparrow, I probably would not have been involved. I remember starting out and my agent said 'does the character change the situation or is he just a functionary' and this character changes the situation.\" Pryce added, \"Once I started work on ''Games of Thrones'' I was incredibly impressed with the organization, the crew and they're really good at their job and story telling so I have become a fan of the show.\" Recurring guest actors for the series Eugene Simon, Julian Glover, Roger Ashton-Griffiths, Finn Jones, and Ian Gelder, who portrayed Lancel Lannister, Pycelle, Mace Tyrell, Loras Tyrell, and Kevan Lannister, respectively, also made their final appearance in the series. Finn Jones, who was cast concurrently in the leading role for the upcoming television series Marvel's ''Iron Fist'', spoke about his departure saying, \"I had been on ''Thrones'' for six years. It was yearly employment. Now I was at a crossroads and I had to think of what the future is. I was very blessed that something like this has come along at the right moment,\" referring to ''Iron Fist''. Eugene Simon also spoke about his learning of his departure, saying that the showrunners promised a \"huge scene\" for his character in the season finale, with Simon responding, \"for everything that you've done for the last six years, thank you. This is a wonderful way to go. I really, really appreciate it, and I look forward to doing it for you.\" For the scene at the Tower of Joy, Lyanna Stark was portrayed by actress Aisling Franciosi. The Danish comedian Frank Hvam portrayed the clerk at the Citadel, although his lines may have been dubbed as he was not a confident English speaker. ===Filming===\nMiguel Sapochnik served as director for the episode, his fourth episode for the series. Cathedral of Saint Mary in Girona, Spain stood in for the exterior shots of the Great Sept, with special effects altering parts of the building. \"The Winds of Winter\" was directed by Miguel Sapochnik. He previously directed the fifth season episodes \"The Gift\" and \"Hardhome\", and the sixth season episode \"Battle of the Bastards\". In an interview, Sapochnik spoke about the scenes at the beginning of the episode, which mostly lacked any dialogue, saying \"Don't get me wrong, I am a huge fan of smart and witty dialogue. This is something that ''Game of Thrones'' is probably quite famous for and rightly so, but I love non-verbal film making more than anything probably.\" He continued by drawing a comparison to the film ''Heat'' starring Robert DeNiro, noting \"To me, this is truly wonderful filmmaking. And so any opportunity I can get to try my hand at that I welcome. From that perspective, I really hit the jackpot this year and I'm very grateful.\" In another interview, Sapochnik revealed that the wildfire explosion at the Sept of Baelor was originally going to only be seen from the outside, but after storyboarding the sequence with shots of the High Sparrow also being engulfed, Sapochnik was able to convince Benioff and Weiss to make the change for the sequence. Sapochnik also stated about the sequence, \"The main chunk of the sequence was essentially a courtroom drama and then lots of little scenes surrounding it shot in many different sets and locations and even countries so it took a long time to get all the pieces into the editing system and start actually editing.\"", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "d7191635-03e8-4709-934e-5dfd95dcb2ef", "_split_id": 2}, "embedding": null, "id": "b1752550e8c83e6bf9ccb9a281a902e6"} -{"content": "He also said that the main goal of the scene was to \"bring all these intersecting storylines surrounding King's Landing together and end them,\" and that the music in the scene played an important role in reflecting how the scenes played out on screen tonally, praising Ramin Djawadi's opening score. The Girona Cathedral in Girona, Spain stood in for the exterior shots of the Sept of Baelor. Dean-Charles Chapman, who portrayed King Tommen Baratheon, spoke about filming his death scene, saying \"I was jumping onto a crash mat. Height-wise, I think if I was standing on the floor, it was up to my chest. But the crash mat was pretty thick. I must have done that about 50 times. My face was pretty bruised up. My face took it a little bit.\" Eugene Simon, who portrayed Lancel Lannister, also spoke about his death scene revealing about his discussions with Sapochnik, \"the note was when Lancel was dragging his body, there was a sense of someone who is trying to put aside their pain of being stabbed and being paralyzed as much as possible in order to try to defend what little hope there is left of trying to save the sept and also to save their life. It really only comes down to the very last few nanoseconds of footage that you realize the cause is lost.\" Simon also stated about the filming of Jonathan Pryce's, who portrays the High Sparrow, final scene, \"we had a very big nice round of applause when that took place. I remember that scene very well; we had 200 or so supporting actors in there, all of whom were so committed. They stayed there all day and did wonderful reactions to all the really intense bits. When the first part of the bomb goes off, all of them really, really performed that there was a full-on nuclear explosion going on underneath them.\" He continued, \"We had a big round of applause and celebration after that scene was done because I think we all knew it was going to be pretty monumentous. We said goodbye to countless Tyrells, Kevan Lannister my father, the High Sparrow and dozens of other. It was a pretty extraordinary day.\" In regards to the non-verbal exchange between Jaime and Cersei Lannister when she is sitting on the Iron Throne, Sapochnik stated \"I thought that non-verbal exchange was a very interesting moment but it wasn't clear from the script what exactly Benioff and Weiss wanted. So we just tried a few things, following our noses, drawing from what we knew about these characters and what you see was one of the versions we shot. Interestingly in the edit I still couldn't find a version I felt worked so I actually dropped the moment entirely out of my cut but David and Dan reinstated and to great effect. In fact, I can't really remember the sequence without it anymore. I think he's saying 'don't' and she's saying 'too late.'\" He continued \"The wonderful thing about filmmaking is you make and remake your film or episode a number of times over the duration of its existence. Firstly in the script stage, second is in prep when you plan how you're going to execute it. Third is in production when you actually get there and have to change everything and finally, in the edit, when you realize what you thought something meant means something totally different when put before or after another juxtaposing or complimentary image.\" In the same interview, Sapochnik was also asked about how he went about creating a sense of emotion in the 'King in the North' scene, saying \"It wasn't hard. I think as fans we'd been waiting for it for so long. That said, it was a very difficult scene to shoot. Mainly because it was unusually hot over the two days we shot it, everyone was wearing heavy furs and armor, Kit was actually pretty ill and everyone was crammed into this space full of plates of sheep's tongues and chicken carcasses so it got quite smelly and sticky. It's also quite a long scene and yet Bella did it probably more than a hundred times, only forgetting a line once in the entire time. When we finished the scene she got a standing ovation from all the cast and crew.\" Sapochnik was asked in an interview what the most difficult shot was to direct, responding \"The final sequence of seeing the armada on its way to Westeros was complicated because it involved so many different ships, and we only had one that we had to redress and shoot again and again. It was also raining and freezing when we shot it, and it was meant to be a Mediterranean climate. Emilia Clarke got so cold, her jaw started shaking uncontrollably and she totally lost her thread as far as what she was meant to be thinking in that moment, the cold will do that. She asked me to help, so I suggested that she just hum the theme to ''Game of Thrones'' in her head while we were rolling the cameras, and apparently that worked because it's the take we used in the final cut!\" ===Costuming===\nCostume designer Michele Clapton returned to the series to design Cersei Lannister's gown and crown, among other costumes. Costume designer Michele Clapton designed most of the newly introduced costumes and jewelry in \"The Winds of Winter\". Clapton had initially left the series, but returned for the final two episodes of the season to design four different costumes. In an interview, Michele Clapton spoke about the process and meaning behind Cersei Lannister's gown and crown in the season finale. Clapton stated that she had four to five weeks to create the gown, but once she received the script for the episode, she was \"immediately sure\" of how the dress should look. She stated in the interview, \"I knew it had to be leather and I knew it had to be linked to Tywin.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "d7191635-03e8-4709-934e-5dfd95dcb2ef", "_split_id": 3}, "embedding": null, "id": "d9cfe753a8c8b5db1f91c10784440c90"} -{"content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9bf5912e-9ad5-40bb-96d7-3dfa98e9b98e", "_split_id": 0}, "embedding": null, "id": "18738329b964f952ae10234b17e29540"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "9bf5912e-9ad5-40bb-96d7-3dfa98e9b98e", "_split_id": 5}, "embedding": null, "id": "3f9acff36e2a654836138641a719fcba"} -{"content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet\u2014again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand\u2014the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted \u2014 its mane represents the Iron Throne, her desire. She has made it her own \u2014 she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately \u2014 the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18\u201349 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "62455269-7e9d-4d8e-8630-5127bd4bb434", "_split_id": 4}, "embedding": null, "id": "9161a9da203caf552ed26085b94cb757"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "beccebad-30ff-4798-b8c7-f400539995df", "_split_id": 1}, "embedding": null, "id": "fc766222ad65737f3e9afd0e9afafea"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "71281e3f-6f7c-4f76-a831-94cd40735ada", "_split_id": 1}, "embedding": null, "id": "148e1086363892fe59f0661bf8ef545c"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "512bdbe6-56a5-48f1-8e09-6283a788102b", "_split_id": 5}, "embedding": null, "id": "d69f2b9533a10c1267422e53f0415ad4"} -{"content": "Elsewhere, there were big reveals and revenge kills that helped everything add up to a very surprising and satisfying season finale.\" He continued by praising how the trial sequence played out on screen, writing \"The actual staging and pacing of the trial and violent reckoning was really cool, with everyone getting dressed and little puzzle pieces falling into place, little birds leading men to their deaths, and Ramin Djawadi's excellent score.\" He gave the episode a 9.5 out of 10. Michael Calia of ''The Wall Street Journal'' similarly gave praise to the episode, writing \"It's a good thing\u00a0... that the season finale was full of massive developments, tying up several plot threads while leaving some others dangling in the most tantalizing way. This was the most complete episode of ''Game of Thrones'' yet, and possibly the best.\" He also wrote, \"Dany and her fleet are finally sailing to Westeros, her great dragons casting shadows over the waves. It's on.\" Jeremy Egner of ''The New York Times'' also praised the direction of the King's Landing story, and Lena Headey's portrayal of Cersei, saying in his review \"Ms. Headey's performance was but one element in a sequence that, technically, ranks among the show's best. Miguel Sapochnik, who directed last week's battle-heavy episode, brought a different kind of precision and urgency to Sunday's installment. Cersei's scheme unspooled amid insistent strings and a series of shots \u2014 those vicious little birds taking out Pycelle, Lancel and the dwindling candle-fuse, Margaery's growing concern and rising tension in the Sept \u2014 that built inexorably to the High Sparrow's realization that he wasn't as smart as he thought.\" James Hibberd of ''Entertainment Weekly'' stated he felt the episode introduced new conflicts to look forward to in the next season, saying \"Though the finale shifted from the battlefield, the events were, if anything, far more seismic, with game-changing revelations and huge moves from every corner of the realm that established some very clear new conflicts going into season 7.\" Sarah Larson of ''The New Yorker'' wrote in her review, \"It's a beautiful image. Boats, clouds, sun, dragons, and two female ship captains, pointing their armada toward a Westeros ruled by a queen.\" James Hunt of WhatCulture wrote in his review, \"What a way to go out. Season 6 has already proved to be a great season of TV, but it saved its best for last.\" Tim Surette of TV.com called the episode, \"the best episode ever.\" Brian Lowry of CNN wrote in his review for the episode, \"At this point it's hard to second-guess producers David Benioff and D.B. Weiss, who, working with Martin, have created a series for the ages.\" Willa Paskin of ''Slate'' wrote in his review, \"Revenge, a dish ''Game of Thrones'' has almost always made taste awful, served hot or cold, became, in the finale, a delicacy. \" ===Accolades===\n\nYear\n\nAward\n\nCategory\n\nNominee(s)\n\nResult\n\n2016\n\n68th Primetime Emmy Awards\n\nOutstanding Costumes for a Period/Fantasy Series, Limited Series, or Movie\n\nChloe Aubry Michele Clapton Sheena Wichary\n\nOutstanding Supporting Actress in a Drama Series\n\nLena Headey\n\nGold Derby TV Awards 2016\n\nBest Drama Episode\n\nBritish Society of Cinematographers\n\nBest Cinematography in a Television Drama\n\nFabian Wagner\n\nInternational Film Music Critics Association\n\nFilm Music Composition Of The Year\n\nRamin Djawadi for \"Light of the Seven\"\n\n2017\n\nIGN Awards\n\nBest TV Episode\n\nIGN People's Choice Award\n\nBest TV Episode\n\n69th Writers Guild of America Awards\n\nEpisodic Drama\n\nDavid Benioff D. B. Weiss\n\nVisual Effects Society Awards 2016\n\nOutstanding Created Environment in an Episode, Commercial or Real-Time Project\n\nEdmond Engelbrecht, Tomoka Matsumura, Edwin Holdsworth, and Cheri Fojtik \u2013 Citadel\n\nUSC Scripter Award\n\nBest Adapted Screenplay\n\nDavid Benioff D. B. Weiss\n\n==References==\n\n==External links==\n\n* at HBO.com\n*\n*", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "752c9097-95ce-4601-8ac1-bb0b50067304", "_split_id": 5}, "embedding": null, "id": "94f414af5e4b3262659d7eb76d2e8fca"} -{"content": "Daario is reluctant, admitting his love for her, but complies. Daenerys proclaims Tyrion the Hand of the Queen, and the two of them, along with their extensive forces from Essos and their new alliances of the Ironborn, Dorne, and Highgarden, finally depart for Westeros in a massive armada, with her dragons flying above. ==Production==\n\n===Writing===\nThe episode was written by series co-creators David Benioff and D. B. Weiss. \"The Winds of Winter\" was written by the series' creators David Benioff and D. B. Weiss. The episode was the longest in the show's history, to that point, with a run time of 68 minutes. In the \"Inside the Episode\" segment published by HBO shortly after the airing of the episode, Benioff spoke about the relationship between Sansa Stark and Jon Snow at this point in the season, saying \"Over the course of this season they've come to really rely upon each other, but she doesn't really trust him completely. She didn't tell him about the meeting with Littlefinger, she didn't tell him that she summoned the Knights of the Vale, there's definitely a little hint of conflict there. So I think there's a little bit of anger about that and a little bit of jealousy, and that relationship will be crucial to watch.\" Benioff continued by referencing the declaration of Jon Snow as King of the North, noting \"We see the second 'King in the North!' scene with Jon and I think it was important to us that it evoked in that first 'King in the North!' scene. Very different circumstances, different environment. In some ways, the evocation of the first one is meant to be a little worrisome because it was a very triumphant moment when Robb is named King in the North but it didn't go so well for the previous King in the North. So I think we have to be a little worried for Jon and at the same time it's a pretty big reversal and, you know, for a character who was dead at the beginning of the season to be declared king at the end of it. He's done well. He's done well in ten short episodes.\" Weiss also noted about the death of King Tommen Baratheon, \"Meanwhile, while the explosion is happening, Tommen is alone. This fragile, malleable, devastated child, basically, is sitting there without anybody to comfort him, and if she had been there, he wouldn't have gone out that window. She failed him, and she alone failed him here.\" Benioff continued about portraying the mindset of Cersei Lannister, saying \"I think the idea of Cersei without her children is a pretty terrifying prospect. It was the one thing that really humanized her, you know, her love for her kids. And as much of a monster as she could sometimes be, she was a mother who truly really did love her children, and now those children are gone, and all she's got is power.\" In a subsequent interview after the episode airing, Weiss stated that Cersei's mindset following the ramifications of this episode will play an important role in the story for the next season. In an interview with Isaac Hempstead-Wright, who portrays Bran Stark in the series, Wright was asked about the significance of Bran witnessing the scene at the Tower of Joy, saying \"I don't think Bran knows why this is significant, but he knows that it is significant because he wouldn't have seen it if it wasn't earth-shattering, because everything we've learned so far during his visions has been pretty big and important, from the creation of the first White Walker to the origins of Hodor. This is clearly another important milestone in the history of Westeros. For Bran, he sat there thinking, 'This isn't my brother. This is my cousin somehow, but who's the dad? And why have I been shown this? If I find out who the dad is and why I need to know who the dad is, then let Jon know quick.'\" The scene reveals neither Lyanna Stark's son's name nor his father's, with the transition between the newborn's face and Jon Snow's visually conveying the identity. HBO released an infographic shortly after the episode aired, confirming Ned Stark as Jon's guardian, and Lyanna Stark and Rhaegar Targaryen as his parents. In regards to Arya Stark's transformation following her time as a disciple of the Many-Faced God, Weiss noted in the \"Inside the Episode\" featurette, \"We all see where she's coming from, she's seen so many atrocities. It's a worrisome narrative; she started as this tough and plucky girl and turned into someone who's capable of slitting a man's throat and smiling as she watches him as he bleeds out.\" For the final shot of the season, Benioff felt that the shot of Daenerys making her way to Westeros was a monumental part in the series's history, saying \"That shot of Dany's fleet making its way out of the Slaver's Bay towards the Narrow Sea and home is probably the biggest thing to happen on the show thus far, that's the thing we've been waiting for since the pilot episode of the first season.\" He continued, \"It hasn't been a smooth road. That's the shot we're going to leave everyone with; it was a real thrill to see her, with Tyrion by her side, heading west.\" ===Casting===\n\n\"The Winds of Winter\" saw the departure of several cast members and recurring guest actors from the series. Notables included Dean-Charles Chapman, whose character, King Tommen Baratheon, committed suicide in the episode. Before appearing in the role of Tommen, which was originally portrayed by actor Callum Wharry, Chapman appeared in the third season of the series as Martyn Lannister, a minor character who was also killed off. Chapman stated that he found out about his character's death the night before the initial table read for the season, saying \"I was in my hotel, minding my own business, and I got a phone call.", "content_type": "text", "score": null, "meta": {"pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", "file_id": "6caad09d-0740-41d9-aa14-364f00bba648", "_split_id": 1}, "embedding": null, "id": "feaba5d57f8360e9f2538c3e5c8890d2"} diff --git a/test/samples/dc/matching_test_1.csv b/test/samples/dc/matching_test_1.csv deleted file mode 100644 index 0627e1ce64..0000000000 --- a/test/samples/dc/matching_test_1.csv +++ /dev/null @@ -1,2 +0,0 @@ -query,text,context,file_name,answer_start,answer_end -"What are Primitives?","These are classes that carry data through the system.","# Primitives\n\nIn Haystack, there are a handful of core classes that are regularly used in many different places.\nThese are classes that carry data through the system.\nUsers will likely interact with these as either the input or output of their pipeline.\n\n## Document\n\nThe Document class contains all the information regarding the contents of a document,\nincluding its id and metadata.\nIt may also contain information created in the pipeline including the confidence ","sample_pdf_1.pdf",113,166 diff --git a/test/samples/dc/pipeline_config.json b/test/samples/dc/pipeline_config.json deleted file mode 100644 index f10fd32190..0000000000 --- a/test/samples/dc/pipeline_config.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "version": "ignore", - "components": [ - { - "name": "DocumentStore", - "type": "DeepsetCloudDocumentStore", - "params": { - "similarity": "cosine" - } - }, - { - "name": "Retriever", - "type": "BM25Retriever", - "params": { - "document_store": "DocumentStore", - "top_k": 5 - } - }, - { - "name": "Reader", - "type": "FARMReader", - "params": { - "model_name_or_path": "deepset/minilm-uncased-squad2" - } - }, - { - "name": "TextFileConverter", - "type": "TextConverter" - }, - { - "name": "Preprocessor", - "type": "PreProcessor", - "params": { - "split_by": "word", - "split_length": 1000 - } - } - ], - "pipelines": [ - { - "name": "query", - "nodes": [ - { - "name": "Retriever", - "inputs": [ - "Query" - ] - } - ] - }, - { - "name": "indexing", - "nodes": [ - { - "name": "TextFileConverter", - "inputs": [ - "File" - ] - }, - { - "name": "Preprocessor", - "inputs": [ - "TextFileConverter" - ] - }, - { - "name": "Retriever", - "inputs": [ - "Preprocessor" - ] - }, - { - "name": "DocumentStore", - "inputs": [ - "Retriever" - ] - } - ] - } - ] -} diff --git a/test/samples/dc/query_winterfell.response b/test/samples/dc/query_winterfell.response deleted file mode 100644 index a91314e358..0000000000 --- a/test/samples/dc/query_winterfell.response +++ /dev/null @@ -1,26 +0,0 @@ -[{ - "id": "a6011cd04fa7a59fef9ade057b3f2231", - "content": "\n\n\"'''The Winds of Winter'''\" is the tenth and final episode of the sixth season of HBO's fantasy television series ''Game of Thrones'', and the sixtieth overall. It was written by series co-creators David Benioff and D. B. Weiss, and directed by Miguel Sapochnik. Cersei Lannister plots to destroy all her immediate enemies with one swift stroke; Arya Stark gets revenge; Jon Snow is declared King in the North by the lords of the Northern houses; Bran Stark learns that Jon is actually the son of Lyanna Stark; Samwell Tarly arrives at the Citadel; and Daenerys Targaryen begins heading to Westeros alongside Tyrion Lannister, her entire army, the Ironborn loyal to Yara Greyjoy, the Tyrells, the Sand Snakes, and her three dragons. \"The Winds of Winter\" received universal acclaim from critics, listing it as one of the series' best episodes as well as one of the best television episodes of all time. Critics praised the Great Sept explosion, Lena Headey's performance, Arya's revenge on the Freys, the resolution to the Tower of Joy flashback, and Daenerys going to Westeros as highlights of the episode. In the United States, the episode achieved a viewership of 8.89 million in its initial broadcast, making it the highest rated episode in the series' history at that time. It was nominated for several awards, including Headey for the Emmy for Outstanding Supporting Actress, and won the Emmy for Outstanding Costumes. This episode marks the final appearance for Natalie Dormer (Queen Margaery Tyrell), Dean-Charles Chapman (King Tommen Baratheon), Finn Jones (Ser Loras Tyrell), Eugene Simon (Lancel Lannister), Ian Gelder (Kevan Lannister), Jonathan Pryce (The High Sparrow), Roger Ashton-Griffiths (Mace Tyrell), Julian Glover (Grand Maester Pycelle), and Michiel Huisman (Daario Naharis). ==Plot==\n\n===At the Twins===\nWalder Frey celebrates the recapture of Riverrun with the Lannisters. Some time later, Walder eats dinner alone, wondering why his sons have yet to arrive. His servant reveals that she baked them into the meat pie he has been eating, and then removes her face to reveal that she is actually Arya Stark, before cutting Walder's throat. ===In King's Landing===\nOn the day of Cersei's and Loras' trials, the High Sparrow, the Faith and the court gather in the Great Sept. However Cersei remains in her chambers, while Ser Gregor prevents Tommen from leaving his quarters. Meanwhile, Qyburn summons Grand Maester Pycelle to his laboratory, where his child spies stab Pycelle to death. Loras confesses to his crimes and atones by giving up his name and title, and joins the Faith Militant. After Cersei fails to appear, Lancel is sent to retrieve her. Lancel follows one of Cersei's spies beneath the Sept, and finds a wildfire cache about to explode, but is stabbed before he can disarm the cache. Inside the Sept, Margaery, realizing that Cersei has set a trap, warns the crowd to leave, but the High Sparrow prevents anyone from leaving. The wildfire ignites and destroys the Great Sept, killing everyone inside. The sole survivor of the Faith Militant's destruction is Septa Unella, whom Cersei leaves with Gregor to be tortured. Tommen witnesses the explosion from the Red Keep; after being informed of Margaery's death, he takes his own life by jumping out of a window. Cersei orders Qyburn to cremate his remains and scatter the ashes at the ruins of the Great Sept, where Joffrey, Myrcella, and Tywin were interred. As Jaime and Bronn return from the Riverlands, they view the burning ruins of the Great Sept. Jaime subsequently arrives at the Red Keep to witness Cersei being crowned Queen of the Seven Kingdoms. ===At Oldtown===\nAs Samwell and Gilly arrive at Oldtown, they witness the Citadel releasing countless white ravens to announce the arrival of winter. They report to the Citadel, and Sam is scheduled to meet the Archmaester. In the meantime, Sam is granted access to the library. ===At Winterfell===\nDavos confronts Melisandre about Shireen's death. Melisandre admits to burning Shireen alive, but points out that she did it for the Lord of Light. Davos rebuts by saying that Stannis was defeated anyway and that Melisandre's actions were all for naught, forcing her to admit that she was wrong. Davos requests permission from Jon to execute Melisandre, but she counters that she will be useful in the coming war against the White Walkers. Jon exiles Melisandre from the North and he and Davos threaten to execute her if she ever returns. Later, Jon and Sansa discuss who will lead the united Stark forces, with each deferring to the other. Littlefinger privately meets with Sansa in the godswood. He reveals that his ultimate goal is to sit on the Iron Throne with Sansa at his side. Sansa rejects his offer and leaves. Later, Jon gathers the various Northern lords, the Knights of the Vale, and the Free Folk to plan for the fight against the White Walkers. Lyanna Mormont shames the Northern lords that did not come to Jon's aid. All lords present (except, to Sansa's concern, Littlefinger) declare a reluctant Jon the new King in the North. ===In Dorne===\nA grieving Olenna meets with Ellaria and the Sand Snakes concerning the possibility of an alliance against Cersei. To Olenna's surprise, Ellaria presents Varys, who offers Olenna vengeance by allying with Daenerys. ===Beyond the Wall===\nBran, Meera, and Benjen arrive near the Wall. Benjen takes his leave, as the Wall's magical protection also prevents him from being able to pass. Meera assists Bran to a weirwood tree and he re-enters the vision of Ned Stark at the Tower of Joy. Ned finds his sister Lyanna covered in blood from childbirth. With her dying breath, Lyanna pleads with Ned to protect her son, particularly from Robert Baratheon, whom she insists will kill her son if he were to know his true parentage. Ned is given the infant, who is revealed to be Jon Snow. ===In Meereen===\nDaenerys informs Daario that he will not accompany her to Westeros, as she needs him to keep order in Meereen while she invades Westeros.", - "embedding": null, - "content_type": "text", - "meta": { - "pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", - "file_id": "9b9eb589-7717-46c7-9f45-c8d59870ab41", - "_split_id": 0 - }, - "score": null, - "id_hash_keys": null -}, -{ - "id": "f825879c0ff3182ec02f9377f28f5f4b", - "content": "I wanted a distinct, strong silhouette, so I squared her shoulders. I also wanted the dress to skim her ankles, so that you could see her feet—again, strength. The silver shoulders are decorated in a similar manner to Jaime's gold hand—the one person that she still has something with.\" Clapton also noted that every part of the dress represents something, saying, \"There is no 'decoration' to Cersei.\" She stated that she additionally chose to make the dress black in order to represent mourning, as well as a \"deadness inside her.\" Clapton, in a separate interview, was also asked about the meaning and representation of Cersei's crown, saying \"I chose to make it in silver with just wisps of gold to try to show her isolation, her mental disentangling from her family. There is no reference to Baratheon; there is no need anymore. She doesn't have to try and prove a link. The center of the crown is the lion sigil abstracted — its mane represents the Iron Throne, her desire. She has made it her own — she is reborn.\" Clapton revealed as well that King Tommen Baratheon's costume was intended to show how heavily his responsibilities weigh on him, as he is weighted down with jeweled finery, with Clapton saying \"He was a nice boy. Too nice for this.\" ===Musical score===\nComposer Ramin Djawadi created the episode's musical score. The musical score for \"The Winds of Winter\" was composed by Ramin Djawadi. Djawadi has worked on the series since its inception, and additionally composed the show's main theme. In an interview, Djawadi spoke about the score he created for the beginning of the episode, titled \"Light of the Seven\", which largely consisted of piano, something unusual for the series. Djawadi stated, \"The interesting thing to me was the use of the piano. When we started the season, showrunners David Benioff and Dan Weiss, and Miguel Sapochnik, the director of the episode, reached out to me and said, 'There's something coming up in episode 10.' We talked about 'The Light of the Seven', and how it needed to be a new piece of music. Any kind of character theme could tip it, and we didn't want to tip the audience. Miguel brought it up: 'What about the piano?' We discussed it. The piano is not really in the language of the ''Game of Thrones'' score.\" He continued, \"It all felt like a perfect fit. What's great about the scene, too, is there's hardly any dialogue. It's nine minutes long. I knew I had to start minimal and give it space. Let notes ring, then give it space, and build up the anticipation from there, without tipping in either direction.\" Djawadi stated that he refrained from using the typical Lannister theme, \"The Rains of Castamere\", in order to create more of a mystery. The piece also featured vocals by two young boys singing in unison, with Djawadi describing how he pieced all of the separate pieces of the music together by saying \"The boys I recorded completely separate. The strings I recorded all together. Even the solo instruments, I recorded them separately — the solo violins and solo cellists were recorded separately. The piano, I played. And the organ as well.\" Asked in a separate interview about the overall process of composing the music and how it is used in the episode, Djawadi revealed \"I sit with David and Dan and we do what's called a spotting session where we watch the entire episode and then discuss when music should start and stop. Everybody's very involved with that. And it constantly gets played with. What I love about ''Game of Thrones'' is that the positioning of the music is so well done, because it's not overdone. When the music cuts in, it really has something to say.\" \"Light of the Seven\" reached No. 1 on Billboard's Spotify Viral 50 chart on its release. The episode also featured the show's main theme during the \"King in the North\" scene with Jon Snow at Winterfell. Critical praise was directed towards the musical score for the episode, with Lili Loofbourow of ''The Week'' calling it the \"real winner\" of the season finale. ==Reception==\n\n===Ratings===\n\"The Winds of Winter\" was viewed by 8.89 million American households on its initial viewing on HBO, significantly higher than the previous week's rating of 7.66 million viewers for the season's penultimate episode \"Battle of the Bastards\", making it the most watched episode in the series' history, until surpassed by the seventh-season premiere, \"Dragonstone\". The episode also acquired a 4.35 rating in the 18–49 demographic, making it the highest rated show on cable television of the night, and topping its previous best of 4.0, set twice earlier in the season. In the United Kingdom, the episode was viewed by 2.498 million viewers on Sky Atlantic, making it the highest-rated broadcast that week on its channel. It also received 0.153 million timeshift viewers. ===Critical reception===\n\n\"The Winds of Winter\" received acclaim from both critics and viewers, praising it as one of the series' best episodes. It has received a 99% rating on the review aggregator website Rotten Tomatoes from 58 reviews with an average score of 9.7 out of 10. The site's consensus reads \"'The Winds of Winter' makes the most of its extended run time, and is potentially the best season finale in the series' history.\" The episode had received a perfect 10 out of 10 score on IMDb for several weeks after its release. It now holds a rating of 9.9/10, being one of the few episodes ever to get a 9.9 or higher on the website. Matt Fowler of IGN wrote in his review for the episode \"The stories in the North and Meereen stayed a bit quiet as all their action got taken care of last week, leaving Cersei's big plot to destroy the Sept and everyone in it as this finale's big suspenseful and explosive set piece.", - "embedding": null, - "content_type": "text", - "meta": { - "pipeline_id": "d8db6228-3997-4596-9501-2ffeeccb6881", - "file_id": "0116ab5b-3435-4255-ab5f-94e8660053bb", - "_split_id": 4 - }, - "score": null, - "id_hash_keys": null -}] diff --git a/test/samples/docs/doc_1.txt b/test/samples/docs/doc_1.txt deleted file mode 100644 index 4121890801..0000000000 --- a/test/samples/docs/doc_1.txt +++ /dev/null @@ -1,2 +0,0 @@ -Some text for testing. -Two lines in here. diff --git a/test/samples/docs/doc_2.txt b/test/samples/docs/doc_2.txt deleted file mode 100644 index e0298997eb..0000000000 --- a/test/samples/docs/doc_2.txt +++ /dev/null @@ -1,2 +0,0 @@ -A Doc specifically talking about haystack. -Haystack can be used to scale QA models to large document collections. diff --git a/test/samples/docx/sample_docx.docx b/test/samples/docx/sample_docx.docx deleted file mode 100644 index 3a740ac96876f71e624fbc80fd2cb2408024e34f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13232 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�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 diff --git a/test/samples/dpr/sample.json b/test/samples/dpr/sample.json deleted file mode 100644 index df15f33334..0000000000 --- a/test/samples/dpr/sample.json +++ /dev/null @@ -1 +0,0 @@ -[{"dataset": "nq_dev_psgs_w100", "question": "who sings does he love me with reba", "answers": ["Linda Davis"], "positive_ctxs": [{"title": "Does He Love You", "text": "Does He Love You \"Does He Love You\" is a song written by Sandy Knox and Billy Stritch, and recorded as a duet by American country music artists Reba McEntire and Linda Davis. It was released in August 1993 as the first single from Reba's album \"Greatest Hits Volume Two\". It is one of country music's several songs about a love triangle. \"Does He Love You\" was written in 1982 by Billy Stritch. He recorded it with a trio in which he performed at the time, because he wanted a song that could be sung by the other two members", "score": 1000, "title_score": 1, "passage_id": "11828866"}, {"title": "Does He Love You", "text": "Does He Love You \"Does He Love You\" is a song written by Sandy Knox and Billy Stritch, and recorded as a duet by American country music artists Reba McEntire and Linda Davis. It was released in August 1993 as the first single from Reba's album \"Greatest Hits Volume Two\". It is one of country music's several songs about a love triangle. \"Does He Love You\" was written in 1982 by Billy Stritch. He recorded it with a trio in which he performed at the time, because he wanted a song that could be sung by the other two members", "score": 13.394315, "title_score": 0, "passage_id": "11828866"}, {"title": "Red Sandy Spika dress of Reba McEntire", "text": "Red Sandy Spika dress of Reba McEntire American recording artist Reba McEntire wore a sheer red dress to the 1993 Country Music Association Awards ceremony on September 29, 1993. The sheer fabric was covered with sequins, and cut with a low neckline. The garment was designed by stylist Sandy Spika, and McEntire wore it during a duet performance of \"Does He Love You\" with Linda Davis. McEntire later said, \"I got more press off that dress than if I'd won entertainer of the year.\" According to McEntire, when her little sister, Susie, saw her on stage she leaned over and", "score": 12.924647, "title_score": 0, "passage_id": "15632586"}, {"title": "Greatest Hits Volume Two (Reba McEntire album)", "text": "(then a background singer in McEntire's road band), was the first single and turned out to be a smash. It reached number 1 on the country charts. The song also earned them a Grammy award for Best Country Vocal Collaboration as well as the CMA Award for \"Vocal Event of the Year\". CMT ranked the song at No. 9 on their list of 100 Greatest Duets. \"Does He Love You\" is the first of three duets featuring Reba and Linda Davis. The album's other new track was \"They Asked About You\", which peaked at No. 7 on the country chart.", "score": 11.614756, "title_score": 0, "passage_id": "8870096"}, {"title": "Shoot for the Moon (album)", "text": "Shoot for the Moon (album) Shoot for the Moon is the third album by country music artist Linda Davis, It was her first to achieve placement on the Billboard Music Charts. It was the first album released following a win at the 1993 Grammy Awards for Best Country Vocal Collaboration (with country superstar Reba McEntire) for their hit \"Does He Love You.\" The album rose to the number 28 position on the Country Albums chart, and two of its tracks were relatively minor hits on the singles charts: \"Company Time\" at number 43, and \"Love Didn't Do It\" at number", "score": 11.0992, "title_score": 0, "passage_id": "7626265"}], "negative_ctxs": [{"title": "Cormac McCarthy", "text": "chores of the house, Lee was asked by Cormac to also get a day job so he could focus on his novel writing. Dismayed with the situation, she moved to Wyoming, where she filed for divorce and landed her first job teaching. Cormac McCarthy is fluent in Spanish and lived in Ibiza, Spain, in the 1960s and later settled in El Paso, Texas, where he lived for nearly 20 years. In an interview with Richard B. Woodward from \"The New York Times\", \"McCarthy doesn't drink anymore \u2013 he quit 16 years ago in El Paso, with one of his young", "score": 0, "title_score": 0, "passage_id": "2145653"}, {"title": "Pragmatic Sanction of 1549", "text": "one heir, Charles effectively united the Netherlands as one entity. After Charles' abdication in 1555, the Seventeen Provinces passed to his son, Philip II of Spain. The Pragmatic Sanction is said to be one example of the Habsburg contest with particularism that contributed to the Dutch Revolt. Each of the provinces had its own laws, customs and political practices. The new policy, imposed from the outside, angered many inhabitants, who viewed their provinces as distinct entities. It and other monarchical acts, such as the creation of bishoprics and promulgation of laws against heresy, stoked resentments, which fired the eruption of", "score": 0, "title_score": 0, "passage_id": "2271902"}, {"title": "Hall Airport", "text": "Hall Airport Hall Airport is a privately owned, public use airport located six nautical miles (11 km) northwest of the central business district of Kaufman, a city in Kaufman County, Texas, United States. Hall Airport covers an area of 27 acres (11 ha) at an elevation of 440 feet (134 m) above mean sea level. It has one runway designated 17/35 with a turf surface measuring 2,585 by 40 feet (788 x 12 m). For the 12-month period ending May 23, 2007, the airport had 201 general aviation aircraft operations, an average of 16 per month. At that time there", "score": 0, "title_score": 0, "passage_id": "17333840"}, {"title": "St Columba's College, Largs", "text": "early 1960s) who was followed by Brother Germanus (who later became David Germanus) then Brother Nicholas (who later left the Brothers to get married) who is mentioned as part of a 'holy fourball' of golfers (given his golfing skills) on pages 9 and 15 of \"Sam\" the autiobiography of Sam Torrance, the famous golfer and team captain for Europe in the Ryder Cup in 2002. Sam was a member, as was his father the Club Professional, of Routenburn Golf Club, situated above and adjacent to the school. The various headmasters kept up the wonderful traditions of devotion to the Marist", "score": 0, "title_score": 0, "passage_id": "13284527"}, {"title": "August De Schryver", "text": "August De Schryver August Edmond De Schryver (Ghent, 16 May 1898 \u2013 5 March 1991) was a Belgian politician. During the course of his political career, between 1935 and 1960, he held a number of ministerial portfolios within several successive governments including the Belgian government in exile during World War II. He was also President of the Christian Social Party between 1945 and 1949. As Minister of the Colonies until 1960, he presided over the independence of the Belgian Congo. De Schryver belongs to a catholic Family, son of August-Octaaf De Schryver (1848-1915). He studied at the St-Barbaracollege in Ghent.", "score": 0, "title_score": 0, "passage_id": "18167556"}, {"title": "Dablot Prejjesne", "text": "orthogonal grid). The Sami Prince is placed on the sixth rank, on the intersection of diagonals to that player's farthest right. The Sami King is placed on the seventh rank, at the right edge of the board (please refer to the image above and the first external link below for a visual description of the initial setup for both Sami tribe and landowner party). Similarly, the Landowner's Son and Landowner are placed on that player's farthest right on the sixth and seventh rank, respectively. 3. All pieces move alike. A piece moves one space along one of the gridlines to", "score": 0, "title_score": 0, "passage_id": "12336307"}, {"title": "Precision bombing", "text": "leave the canteen next to them standing. This development process, driven by the need to bomb in unsighted conditions, meant that by the end of World War II, unguided RAF bombs could be predictably delivered within 25 yards of a target from 15,000 feet height, and precisely on it from low level. For the U.S. Army Air Forces, daylight bombing was normal based upon box formations for defence from fighters. Bombing was coordinated through a lead aircraft but although still nominally precision bombing (as opposed to the area bombing carried out by RAF Bomber Command) the result of bombing from", "score": 0, "title_score": 0, "passage_id": "4545054"}, {"title": "Off-label use", "text": "\u00a7\u00a7301-97, manufacturers are prohibited from directly marketing a drug for a use other than the FDA-approved indication. However, in December 2012, the United States Second Circuit Court found that promotion of off-label uses by a company sales representative was considered to be protected speech per the First Amendment. In addition, The Food and Drug Administration Modernization Act of 1997 created an exception to the prohibition of off-label marketing, allowing manufacturers to provide medical practitioners with publications on off-label uses of a drug, in response to an unsolicited request. In 2004, the federal government and whistleblower David Franklin reached a $430", "score": 0, "title_score": 0, "passage_id": "4648233"}, {"title": "Schramm (film)", "text": "Schramm (film) Schramm is a 1993 German horror film directed by controversial taboo-breaking auteur J\u00f6rg Buttgereit. It is stylised and artfully shot on 16mm film. It tells the story of a man who has been known in the media as the 'Lipstick Killer'. Loosely based on true crime criminology profiles of Carl Panzram and similar serial killers. Lothar Schramm is a polite, neighborly cab driver who makes an honest living and invites callers in for cognac. Later on, he might slit their throats and assemble their bodies in suggestive poses. He lives next door to a young, beautiful prostitute named", "score": 0, "title_score": 0, "passage_id": "9107786"}, {"title": "Curtiss P-40 Warhawk variants", "text": "armor, but as there was a shortage of decent fighter aircraft after the Battle of Britain, the RAF pressed these into service into North Africa anyway.
Of the remaining 324 aircraft of the initial order, 131 were built as P-40Bs. Though strongly built, the first P-40 variant was poorly protected and lacked armor and self sealing tanks. This was partly rectified with the P-40B, which had additional armor behind the cockpit, but fuel system and control line vulnerability remained a problem to some extent with all Tomahawk types. The P-40B also had an additional .30 MG in each wing.", "score": 0, "title_score": 0, "passage_id": "7387972"}, {"title": "Acamarachi", "text": "Acamarachi's figurines are now exposed in the R. P. Gustavo Le Paige Archaeological Museum of San Pedro de Atacama. The region in which Acamarachi is located was a southern part of the Inca Empire. A major Inca road passed by the town of Toconao, not far from Acamarachi. Acamarachi Acamarachi (also known as \"Pili\") is a high volcano in northern Chile. In this part of Chile, it is the highest volcano. Its name means \"black moon\". It is a volcano in the Central Volcanic Zone of the Andes, a zone of strong volcanic activity during the last million years. Old", "score": 0, "title_score": 0, "passage_id": "19663641"}, {"title": "Serious Moonlight (2009 film)", "text": "sold their house and are moving away. They have had a baby as they had tried to in the past. They decide to have lunch one last time in town before they move. While walking to the restaurant, they walk past the same burglar who robbed their house, and the burglar nods at them in recognition. Louise looks away and walks away quickly, and Ian looks stunned (implying she organized the burglary). In 2006, a year prior to filming, the screenplay's writer, Adrienne Shelly, was murdered in New York City. Her widower, Andy Ostroy, acted as a producer for the", "score": 0, "title_score": 0, "passage_id": "11600779"}, {"title": "Hat Yai", "text": "in Satun (a gateway to the islands in the southern Andaman Sea), Langkawi, Penang, Kuala Lumpur, and Singapore. The minibus service has gained popularity in recent years as minibuses are considered a faster way to travel. Hat Yai International Airport is 9 km from downtown, serving destinations throughout Thailand and connecting the city to Kuala Lumpur and Singapore. It is also an important airport for Muslims on pilgrimage to Mecca. The airport is listed as Thailand's 5th busiest airport, serving 1,869,113 passengers in 2011. Demographically, Hat Yai is notable for a higher proportion of Malay-Muslim and Thai Chinese citizens than", "score": 0, "title_score": 0, "passage_id": "2682217"}, {"title": "Linear B", "text": "governed the selection of the vowel and therefore of the sign. The vowel had to be the same as the one of the first syllable following the cluster or if at the end of the word, preceding: \"ti-ri-po\" with \"ti-\" (instead of \"ta-\", \"te-\" and so on) to match \"-ri-\". A rare exception occurs in words formed from \"wa-na-ka\", \"wanax\" (\u03dd\u03ac\u03bd\u03b1\u03be, Homeric and Classical \u1f04\u03bd\u03b1\u03be): \"wa-na-ka-te\" for \"wanaktei\" (dative), and \"wa-na-ka-te-ro\" for \"wanakteros\", the adjectival form. Linear B also uses a large number of ideograms. They express: They are typically at the end of a line before a number and", "score": 0, "title_score": 0, "passage_id": "245647"}, {"title": "Franc\u0327ois Se\u0301bastien Charles Joseph de Croix, Count of Clerfayt", "text": "distinguished himself, earning rapid promotion, and received the Military Order of Maria Theresa decoration. At the conclusion of the peace (Treaty of Hubertusburg, 15 February 1763), though still under thirty, he had already become an Oberst (colonel). During the revolt in the Netherlands in 1787, Clerfayt, as a Walloon by birth, came under great pressure to abandon Emperor Joseph II. But he resisted all overtures, and in the following year went to fight in the Austro-Turkish War with the rank of Feldmarschal-Leutnant (lieutenant field marshal). In an independent command Clerfayt achieved great success, defeating the Turks at Mehadia and Calafat.", "score": 0, "title_score": 0, "passage_id": "1572057"}, {"title": "Counties of England", "text": "new areas for organising local government that it called administrative counties and county boroughs. These administrative areas adopted the names of, and closely resembled the areas of, the traditional counties. Later legislative changes to the new local government structure led to greater distinction between the traditional and the administrative counties. The Local Government Act 1972 abolished the 1888 act, its administrative counties and county boroughs. In their place, the 1972 Act created new areas for handling local government that were also called administrative counties. The 1972 administrative counties differed distinctly in area from the 1888 administrative counties, that had now", "score": 0, "title_score": 0, "passage_id": "2259868"}, {"title": "Guantanamo Bay Naval Base", "text": "War on Terror. Cases of torture of prisoners, and their alleged denial of protection under the Geneva Conventions, have been condemned internationally. Besides servicemen, the base houses a large number of civilian contractors working for the military. Many of these contractors are migrant workers from Jamaica and the Philippines, and are thought to constitute up to 40% of the base's population. Major contractors working at NSGB have included the following: Ocean Transportation is provided by Schuyler Line Navigation Company, a US Flag Ocean Carrier. Schuyler Line operates under government contract to supply sustainment and building supplies to the Base. The", "score": 0, "title_score": 0, "passage_id": "169246"}, {"title": "Kathleen Coleman", "text": "the Undergraduate Council of Harvard College, and in 2011 she served as President of the American Philological Association (now the Society for Classical Studies). Coleman is a member of the editorial boards of The American Journal of Philology, Eirene, Exemplaria Classica, Mnemosyne and Mnemosyne Supplements, and Rivista di Filologia e Istruzione Classica. Due to her extensive knowledge of gladiatorial combat and its history, she acted as Chief Academic Consultant on the script of Ridley Scott's \"Gladiator\". Professor Coleman purportedly found her work as a historical consultant to have had such little effect that she asked to be listed in the", "score": 0, "title_score": 0, "passage_id": "9157835"}, {"title": "Magical Girl Lyrical Nanoha (series)", "text": "against Precia, who is defeated and apparently dies. In \"Magical Girl Lyrical Nanoha A's\" (2005), Nanoha continues her magical training. Six months after the original series, she and Fate encounter the \"Wolkenritter\", four magic knights who steal others' magical abilities to save Hayate Yagami, a wheelchair-using Japanese girl. Since the Wolkenritter are skilled in Ancient Belkan combat magic far superior to theirs, Nanoha and Fate fail to stop them and the Book of Darkness, an ancient artifact bound to Hayate, is activated. A worldwide catastrophe is only prevented thanks to TSAB and most importantly, Hayate's intervention. In the following years,", "score": 0, "title_score": 0, "passage_id": "13703916"}, {"title": "Two Days Before the Day After Tomorrow", "text": "and the Houston mass evacuation during Hurricane Rita. For instance, when the people conclude that George Bush was the cause of the beaver dam being broken, someone says \"George Bush doesn't care about beavers!\" in a parody of Kanye West's quote, \"George Bush doesn't care about black people.\" In addition, during the evacuation, only white people are rescued, while a black man can be seen left stranded. This references the accusations of selectively racist rescue efforts and media coverage during the Hurricane Katrina crisis. \"Two Days Before the Day After Tomorrow\" also parodies the 2004 film \"The Day After Tomorrow\",", "score": 0, "title_score": 0, "passage_id": "6275842"}, {"title": "Siege of Leith", "text": "Broughty Castle and Leith. From 1548 onwards work began fortifying the port of Leith initially with a bulwark at the Kirkgate and at the chapel by the harbour, perhaps designed by the Italian Migliorino Ubaldini. The rest of the new fortifications were almost certainly designed by another Italian military engineer, Piero di Strozzi, and these represent the earliest use of the \"trace italienne\" style of artillery fortification in Britain. In August 1548 Strozzi directed the 300 Scottish workmen from a chair carried by four men because he had been shot in the leg at Haddington. In 1554, Mary of Guise,", "score": 0, "title_score": 0, "passage_id": "14386551"}, {"title": "Be\u0301la Nagy Abodi", "text": "forms, though it constitutes a distinct entity: Abodi's dominant artistic character can be immediately traced in his diverse and always renewing oeuvre. He is a daring experimentalist, a persistent seeker who never strains after visual artifices or unnatural stylistic unity for his own sake. Abodi is the archetype of a professional and intellectual creator who is in possession of a complete range of professional tools and who is endowed with superior knowledge. His abundant lifework is a mine of deeply sympathizing, socially committed, objective-realist or dramatic and shockingly expressive depictions, at other times pictorial satires deploying the weapons of irony", "score": 0, "title_score": 0, "passage_id": "16941665"}, {"title": "Metamorphic rock", "text": "the Earth's surface, subjected to high temperatures and the great pressure of the rock layers above it. They can form from tectonic processes such as continental collisions, which cause horizontal pressure, friction and distortion. They are also formed when rock is heated by the intrusion of hot molten rock called magma from the Earth's interior. The study of metamorphic rocks (now exposed at the Earth's surface following erosion and uplift) provides information about the temperatures and pressures that occur at great depths within the Earth's crust. Some examples of metamorphic rocks are gneiss, slate, marble, schist, and quartzite. Metamorphic minerals", "score": 0, "title_score": 0, "passage_id": "549063"}, {"title": "William James Rivers", "text": "the University of South Carolina began enrolling African Americans in 1873, Rivers resigned his position and accepted the presidency of Washington College in Chestertown, Maryland. He was president of Washington College for fourteen years, and retired to 23 Calvert Street in Baltimore, where he died on 22 June 1909. Students, faculty, and alumni met the train in Columbia bearing his body, and attended his burial in Elmwood Cemetery. Other writings of William James Rivers include, \"College Addresses, Et Cetera\". His \"Historical Sketch\" was long regarded as the definitive work on South Carolina history, and was famous among historiographers for the", "score": 0, "title_score": 0, "passage_id": "14641835"}, {"title": "Paul Sandlands", "text": "was appointed Recorder of Newark, one of the youngest recorders in the country. In 1928 he was made a Bencher, in 1932 became Recorder of Leicester, and in 1935 took silk. In 1944 he became Recorder of Birmingham and held the post until his retirement in 1959. Sandlands was appointed Officer of the Order of the British Empire (OBE) in the 1920 civilian war honours for his police service. Paul Sandlands Paul Ernest Sandlands OBE QC (25 May 1878\u20138 March 1962) was an English barrister and judge. Sandlands was the son of the Vicar of Brigstock, Northamptonshire. He was educated", "score": 0, "title_score": 0, "passage_id": "10665950"}, {"title": "Danville, Iowa", "text": "Danville, Iowa Danville is a city in Des Moines County, Iowa, United States. The population was 934 at the 2010 census. It is part of the Burlington, IA\u2013IL Micropolitan Statistical Area. Danville was founded in 1854. Danville is located at (40.863773, -91.315938). According to the United States Census Bureau, the city has a total area of , all of it land. Danville is about 4 miles northeast of Geode State Park. As of the census of 2010, there were 934 people, 362 households, and 262 families residing in the city. The population density was . There were 387 housing units", "score": 0, "title_score": 0, "passage_id": "1067334"}, {"title": "Salsa Big Band", "text": "Rican performers such as Tito Puente, Tito Rodr\u00edguez and Willie Rosario, and the Big band sound of the 1950s. \"Salsa Big Band\" received favorable reviews from music critics, with critics praising Blades' vision and willingness \"to try new sounds\"; one said that Blades was \"still at the top of the salsa world\". At the 18th Annual Latin Grammy Awards, the album won for Album of the Year and Best Salsa Album; and at the 60th Annual Grammy Awards the record won for Best Tropical Latin Album. Panamanian singer Rub\u00e9n Blades recorded \"Son de Panam\u00e1\" with Roberto Delgado & Orquesta in", "score": 0, "title_score": 0, "passage_id": "20445415"}, {"title": "Lembrassa", "text": "women including guidance on getting the right size bra when 80% of women have got it wrong. Lembrassa also follows its founder's belief in open marketplaces by having a single world-wide website and a single set of pricing. Customers from all over the world can purchase at the same sterling price. This approach is underlined by another of the founder\u2019s articles \"The world is you local shop\". Lembrassa has attracted media interest for the difficulties small businesses face in getting start-up support \"Lembrassa aims for perfect fit\" and for its attention to customer service \"Frustration at Shop Ranges\". Lembrassa Lembrassa", "score": 0, "title_score": 0, "passage_id": "14791209"}, {"title": "Srisitaramasuprabhatam", "text": "udastavapu\u1e25 sub\u0101ho\u1e25 viprendradevamunika\u1e63\u1e6dakale\u015bar\u0101ho\u1e25 \u015br\u012br\u0101ma r\u0101ghava hare tava suprabh\u0101tam \u0936\u093e\u092a\u093e\u0917\u094d\u0928\u093f\u0926\u0917\u094d\u0927\u092e\u0941\u0928\u093f\u0926\u093e\u0930\u0936\u093f\u0932\u094b\u0926\u094d\u0927\u0930\u093e\u0919\u094d\u0918\u094d\u0930\u0947\u0903 \u0938\u0940\u0930\u0927\u094d\u0935\u091c\u093e\u0915\u094d\u0937\u093f\u092e\u0927\u0941\u0932\u093f\u0921\u094d\u0935\u0928\u0930\u0941\u0921\u094d\u0935\u0930\u093e\u0919\u094d\u0918\u094d\u0930\u0947\u0903 \u0964 \u0915\u093e\u092e\u093e\u0930\u093f\u0935\u093f\u0937\u094d\u0923\u0941\u0935\u093f\u0927\u093f\u0935\u0928\u094d\u0926\u094d\u092f\u092e\u0928\u094b\u0939\u0930\u093e\u0919\u094d\u0918\u094d\u0930\u0947\u0903 \u0936\u094d\u0930\u0940\u0930\u093e\u092e \u0930\u093e\u0918\u0935 \u0939\u0930\u0947 \u0924\u0935 \u0938\u0941\u092a\u094d\u0930\u092d\u093e\u0924\u092e\u094d \u0965 \u015b\u0101p\u0101gnidagdhamunid\u0101ra\u015biloddhar\u0101\u1e45ghre\u1e25 s\u012bradhvaj\u0101k\u1e63imadhuli\u1e0dvanaru\u1e0dvar\u0101\u1e45ghre\u1e25 \u0964 k\u0101m\u0101rivi\u1e63\u1e47uvidhivandyamanohar\u0101\u1e45ghre\u1e25 \u015br\u012br\u0101ma r\u0101ghava hare tava suprabh\u0101tam \u0965 \u0915\u093e\u092e\u093e\u0930\u093f\u0915\u093e\u0930\u094d\u092e\u0941\u0915\u0915\u0926\u0930\u094d\u0925\u0928\u091a\u0941\u091e\u094d\u091a\u0941\u0926\u094b\u0937\u094d\u0923\u0903 \u092a\u0947\u092a\u0940\u092f\u092e\u093e\u0928\u092e\u0939\u093f\u091c\u093e\u0935\u0926\u0928\u0947\u0928\u094d\u0926\u0941\u092f\u0942\u0937\u094d\u0923\u0903 \u0964 \u092a\u093e\u0926\u093e\u092c\u094d\u091c\u0938\u0947\u0935\u0915\u092a\u092f\u094b\u0930\u0941\u0939\u092a\u0942\u0924\u092a\u0942\u0937\u094d\u0923\u0903 \u0936\u094d\u0930\u0940\u0930\u093e\u092e \u0930\u093e\u0918\u0935 \u0939\u0930\u0947 \u0924\u0935 \u0938\u0941\u092a\u094d\u0930\u092d\u093e\u0924\u092e\u094d \u0965 k\u0101m\u0101rik\u0101rmukakadarthanacu\u00f1cudo\u1e63\u1e47a\u1e25 pep\u012byam\u0101namahij\u0101vadanenduy\u016b\u1e63\u1e47a\u1e25 \u0964 p\u0101d\u0101bjasevakapayoruhap\u016btap\u016b\u1e63\u1e47a\u1e25 \u015br\u012br\u0101ma r\u0101ghava hare tava suprabh\u0101tam \u0965 \u0926\u0947\u0939\u092a\u094d\u0930\u092d\u093e\u0935\u093f\u091c\u093f\u0924\u092e\u0928\u094d\u092e\u0925\u0915\u094b\u091f\u093f\u0915\u093e\u0928\u094d\u0924\u0947\u0903 \u0915\u093e\u0928\u094d\u0924\u093e\u0932\u0915\u0938\u094d\u092f \u0926\u092f\u093f\u0924\u093e\u0926\u092f\u093f\u0924\u093e\u0930\u094d\u092f\u0926\u093e\u0928\u094d\u0924\u0947\u0903 \u0964 \u0935\u0928\u094d\u092f\u092a\u094d\u0930\u093f\u092f\u0938\u094d\u092f \u092e\u0941\u0928\u093f\u092e\u093e\u0928\u0938\u0938\u0943\u0937\u094d\u091f\u0936\u093e\u0928\u094d\u0924\u0947\u0903 \u0936\u094d\u0930\u0940\u0930\u093e\u092e \u0930\u093e\u0918\u0935 \u0939\u0930\u0947 \u0924\u0935 \u0938\u0941\u092a\u094d\u0930\u092d\u093e\u0924\u092e\u094d \u0965 dehaprabh\u0101vijitamanmathako\u1e6dik\u0101nte\u1e25 k\u0101nt\u0101lakasya dayit\u0101dayit\u0101ryad\u0101nte\u1e25 \u0964 vanyapriyasya munim\u0101nasas\u1e5b\u1e63\u1e6da\u015b\u0101nte\u1e25 \u015br\u012br\u0101ma r\u0101ghava hare tava suprabh\u0101tam \u0965 \u092e\u093e\u092f\u093e\u0939\u093f\u0930\u0923\u094d\u092e\u092f\u092e\u0943\u0917\u093e\u092d\u094d\u092f\u0928\u0941\u0927\u093e\u0935\u0928\u0938\u094d\u092f \u092a\u094d\u0930\u0924\u094d\u0924\u093e\u0924\u094d\u092e\u0932\u094b\u0915\u0936\u092c\u0930\u0940\u0916\u0917\u092a\u093e\u0935\u0928\u0938\u094d\u092f \u0964 \u092a\u094c\u0932\u0938\u094d\u0924\u094d\u092f\u0935\u0902\u0936\u092c\u0932\u0935\u093e\u0930\u094d\u0927\u093f\u0935\u0928\u093e\u0935\u0928\u0938\u094d\u092f \u0936\u094d\u0930\u0940\u0930\u093e\u092e \u0930\u093e\u0918\u0935 \u0939\u0930\u0947 \u0924\u0935 \u0938\u0941\u092a\u094d\u0930\u092d\u093e\u0924\u092e\u094d \u0965 m\u0101y\u0101hira\u1e47mayam\u1e5bg\u0101bhyanudh\u0101van\u0101sya pratt\u0101tmaloka\u015babar\u012bkhagap\u0101vanasya \u0964 paulastyava\u1e43\u015babalav\u0101rdhivan\u0101vanasya \u015br\u012br\u0101ma r\u0101ghava hare tava suprabh\u0101tam \u0965 \u0938\u093e\u0915\u0947\u0924\u0915\u0947\u0924 \u0915\u0943\u0924\u0938\u091c\u094d\u091c\u0928\u0939\u0943\u0928\u094d\u0928\u093f\u0915\u0947\u0924 \u0938\u0940\u0924\u093e\u0938\u092e\u0947\u0924 \u0938\u092e\u0926\u093f\u0935\u094d\u092f\u0917\u0941\u0923\u0948\u0930\u0941\u092a\u0947\u0924 \u0964 \u0936\u094d\u0930\u0940\u0930\u093e\u092e \u0915\u093e\u092e\u0930\u093f\u092a\u0941\u092a\u0942\u0924\u092e\u0928\u0903\u0938\u0941\u0915\u0947\u0924 \u0936\u094d\u0930\u0940\u0938\u093e\u0930\u094d\u0935\u092d\u094c\u092e\u092d\u0917\u0935\u0902\u0938\u094d\u0924\u0935", "score": 0, "title_score": 0, "passage_id": "15587181"}, {"title": "2015 NRL season", "text": "focus on Greg Inglis' trademark Goanna post-try celebration. The second Sunday afternoon match began at 4:10 pm instead of the traditional 3:10 pm. This change was to allow the Nine Network to show the match live into New South Wales and Queensland, and use it as a lead-in to their respective 6:00 pm news bulletins. The lineup of teams remained unchanged for the 9th consecutive year. The NRL's salary cap for the clubs' top 25 players will be $A6.3M for 2015. The 2015 pre-season featured the second Auckland Nines tournament, held over a weekend at Auckland's Eden Park in which", "score": 0, "title_score": 0, "passage_id": "18404394"}, {"title": "Bikeway safety", "text": "a cycle track than on the comparable reference road (the average being 0.72 the relative risk). They concluded that \"[c]ycle tracks lessen, or at least do not increase, crash and injury rates compared to bicycling in the street\" A final report from Cycling in Cities in 2012 found that cycling on segregated tracks had approximately one ninth the risk of cycling on major streets with parked cars and no cycle infrastructure, concluding that, \"Transportation infrastructure with lower bicycling injury risks merits public health support to reduce injuries and promote cycling.\" The New York City Department of Transportation implemented a bicycle", "score": 0, "title_score": 0, "passage_id": "18873517"}, {"title": "Kleinstaaterei", "text": "rival courts\u2014though usually politically insignificant\u2014often gained some renown through patronage. Today, the term \"Kleinstaaterei\" is sometimes used in the German media and elsewhere in a figurative sense to describe the German political system of federalism in a critical way, especially referring to its seeming inefficiency to decide on reforms in political fields that are the responsibility of the \"L\u00e4nder\" and thus are under the auspices of sixteen different administrations. As of 2010, \"Kleinstaaterei\" is most often invoked in matters of educational policy, such as the difficulties caused by the different school systems for children of families that move from one", "score": 0, "title_score": 0, "passage_id": "7065915"}, {"title": "Koothuparamba firing", "text": "the management.\", The police fired at the crowd for both the protection of the Minister and public and private property. Five DYFI activists were dead and six people were injured. Those who were facing criminal proceedings included the then sub-divisional magistrate Antony, DySP Abdul Hakkim Bathery, and constables P K Lukose, Sivadasan and Balachandran. They were charged with murder, attempted murder and conspiracy by a magistrate court based on a private complaint. The political party called C.P.I.(M)\u2013 The Communist Party of India (Marxist) was dominant in the Kannur District of the State of Kerala. One of its leaders called M.V.", "score": 0, "title_score": 0, "passage_id": "15678638"}, {"title": "Seattle Mountain Rescue", "text": "in 1948. Some of the early leaders of Seattle Mountain Rescue, notably Wolf Bauer, Ome Daiber, and Dr. Otto Trott, brought back extensive knowledge from Europe, designed new gear, and pioneered new procedures. A reporting party calls 911. (The reporting party may be the subject or his/her partner, or maybe someone in the city reporting an overdue hiker.) They tell the dispatcher that the subject is in the mountains and needs search and rescue. That will transfer the response to the appropriate people. In King County, a sheriff deputy will act as Incident Commander and dispatch appropriate units. Outside of", "score": 0, "title_score": 0, "passage_id": "13765151"}, {"title": "Marshall Strabala", "text": "partnership soured and litigation ensued, first in China where the partnership was centered, and then in Illinois.\" In February 2015, Strabala sued Zhang and Zhou in Illinois alleging \"Zhang and Zhou were secretly diverting money from 2DEFINE,\" though Zhang and Zhou denied \"any wrongdoing.\" There were also three lawsuits in China: \"(1) a lawsuit brought by Zhou against Strabala; (2) a lawsuit brought by Strabala against Zhang and Zhou; and (3) a lawsuit brought by Zhou\u2019s Chinese architecture firm, Tufan Architects Design Firm, against Strabala.\" In June 2011, Gensler, sued Strabala alleging in a complaint that after founding his own", "score": 0, "title_score": 0, "passage_id": "12963100"}, {"title": "Neil Mackay, 8th of Strathnaver", "text": "Strathnaver. In 1437, Neil Mackay having returned home led an expedition into Caithness at the head of his clansmen. This conflict became known as the Sandside Chase in which the Caithness men, believed to have been of the Clan Gunn, were defeated. Neil Mackay, 8th of Strahtnaver, married a daughter of George Munro, 10th Baron of Foulis, chief of Clan Munro, and his wife who was a daughter of Ross of Balnagown, chief of Clan Ross. They had the following children: Neil Mackay, 8th of Strathnaver Neil Mackay, 8th of Strathnaver, was the eighth chief of the ancient Clan Mackay,", "score": 0, "title_score": 0, "passage_id": "19702390"}, {"title": "Mir Gohram Khan Lashari", "text": "Mir Gohram Khan Lashari Mir Gwahram Khan Lashari also (Mir Gowahram Khan Lashari, Mir Gwaharam Khan Lashari or Mir Gohram Khan Lashari) was a Baloch chieftain in the 15th century. He was considered as a hero of the Lashari Baloch's, he also played a prominent part in Baloch history. Mir Gwahram and Mir Chakar Rind, head of the Rind Baloch tribe, went to war that resulted in thousands dead, including Mir Chakar's brother. The war and the gallantry of the two tribal leaders continues to be a part of the Baloch peoples' history. Under their pressure, the Lasharis and the", "score": 0, "title_score": 0, "passage_id": "17943470"}, {"title": "Sternum", "text": "21632 and # 21630, respectively). A bifid sternum is an extremely rare congenital abnormality caused by the fusion failure of the sternum. This condition results in sternal cleft which can be observed at birth without any symptom. The sternum, in vertebrate anatomy, is a flat bone that lies in the middle front part of the rib cage. It is endochondral in origin. It probably first evolved in early tetrapods as an extension of the pectoral girdle; it is not found in fish. In amphibians and reptiles it is typically a shield-shaped structure, often composed entirely of cartilage. It is absent", "score": 0, "title_score": 0, "passage_id": "15200163"}, {"title": "Patrick Creadon", "text": "feature documentary I.O.U.S.A. premiered in the U.S. Documentary Competition at Sundance in January 2008, one of only sixteen films selected from over 950 submissions. The film is a profile of former Comptroller General David M. Walker as he and others travel the country warning of financial challenges facing the country. Also featured prominently in the film is Robert Bixby, executive director of the non-partisan Concord Coalition. It was released by Roadside Attractions and opened theatrically on August 22, 2008. In an innovative event that took place the night before, \"I.O.U.S.A.\" was simulcast live by National CineMedia to an audience of", "score": 0, "title_score": 0, "passage_id": "12879287"}, {"title": "Operation Sharp Edge", "text": "Operation Sharp Edge Operation Sharp Edge was a non-combatant evacuation operation carried out by the 22nd Marine Expeditionary Unit (22nd MEU) and 26th MEU of the United States Marine Corps in Liberia in 1990 and 1991. The MEUs were supported by Amphibious Squadron FOUR (Task Force 61) composed of USS Saipan (LHA 2), USS Ponce (LPD 15), USS Sumter (LST 1181), USS Barnstable County (LST 1197), USS Peterson (DD 969), and Fleet Surgical Team TWO. The First Liberian Civil War broke out in December 1989. Increasing violence between political and ethnic factions, including in the capital of Monrovia, had made", "score": 0, "title_score": 0, "passage_id": "1397287"}, {"title": "Jhatka", "text": "detainees during the Akali movement and beyond had to resort to violence and agitations to secure this right. Among the terms in the settlement between the Akalis and the Muslim Unionist government in Punjab in 1942 was that jhatka meat be continued as a Sikh Martial Heritage. On religious Sikh festivals, including Hola Mohalla and Vaisakhi, at the Hazur Sahib Nanded, and many other Sikh Gurdwaras, jhatka meat is offered as \"mahaprasad\" to all visitors in a Gurdwara.Though, this practice is considered to be wrong and not acceptable by major sikhs as only lacto-vegetarian langar is supposed to be served", "score": 0, "title_score": 0, "passage_id": "9563583"}, {"title": "Tron: Legacy", "text": "as Sam and Kosinski returning to direct the sequel. Wilde was revealed in April to be returning as Quorra. Filming was expected to start in Vancouver in October 2015. However, in May 2015, \"The Hollywood Reporter\" stated that Walt Disney Studios had chosen not to continue with a third installment, which was confirmed by Wilde the following month. In the end of July, Boxleitner stated he frequently heard about the pre-production of \"Tron 3\" while shooting \"Cedar Cove\" in Vancouver, and was disappointed to hear about the cancellation. While expressing the opinion that Disney decided to \"play it safe\" and", "score": 0, "title_score": 0, "passage_id": "13295039"}, {"title": "John Stokes (Conservative politician)", "text": "by Shirley Williams. He was elected MP for Oldbury and Halesowen at the 1970 general election and for its successor seat, Halesowen and Stourbridge in February 1974, holding the latter until stepping down in 1992. He was a very active backbencher and described as an \"old-fashioned Conservative who trusted his constituents' instincts about what was right and wrong. He looked the part of the typical Conservative who graced the Commons benches in the years after (and before) the Second World War. His Conservatism seemed to belong to an earlier, simpler age. Yet the House, on the whole, loved him, and", "score": 0, "title_score": 0, "passage_id": "7021161"}, {"title": "Discharge coefficient", "text": "losses associated with a certain piece of equipment (constriction) in a fluid system, or the \"resistance\" that piece of equipment imposes upon the flow. This flow resistance, often expressed as a dimensionless parameter, formula_10, is related to the discharge coefficient through the equation: which may be obtained by substituting formula_9 in the aforementioned equation with the resistance, formula_10, multiplied by the dynamic pressure of the fluid, formula_14. Due to complex behavior of fluids around some of the structures such as orifices, gates, and weirs etc., some assumptions are made for the theoretical analysis of the stage-discharge relationship. For example, in", "score": 0, "title_score": 0, "passage_id": "14130934"}, {"title": "Essex Junction, Vermont", "text": "with approximately 3,000 employees. The village history was affected in a major way by the presence of IBM (now GlobalFoundries), which chose Essex Junction as the site for its facility in 1958. In 1958, IBM leased a facility in the southeast part of the village for its new Data Processing Division. By the end of the year, there were 500 workers. In 1969, the plant expanded to . In 1982, employment reached an all-time high of 8,000. In 2007, the town listers dropped the value of the plant from a high of $147.5 million to $104 million. The plant's workforce", "score": 0, "title_score": 0, "passage_id": "1240794"}, {"title": "Gjelbrim Taipi", "text": "his debut in a match against Chiasso after being named in the starting line-up and scored his side's the first goal during a 0\u20133 away win. On 16 January 2017. Taipi joined Swiss Challenge League side Schaffhausen. On 5 February 2017, he made his debut in a 2\u20132 away draw against Aarau after being named in the starting line-up. On 1 July 2017. Taipi joined Swiss Super League side St. Gallen. On 9 September 2017, he made his debut in a 3\u20133 away draw against Lausanne-Sport after coming on as a substitute at 63rd minute in place of Danijel Aleksi\u0107.", "score": 0, "title_score": 0, "passage_id": "17486180"}, {"title": "Selc\u0327uk Ayd\u0131n", "text": "victory. Following an eighth-round KO victory over Aaron Herrera two months earlier, Aydin then went on to face DeMarcus Corley on September 27, 2013. Aydin won by TKO in the fifth round when Corley was unable to continue and decided to quit in the process. Aydin fought against Ukrainian undefeated boxer Postol for title elimination in U.S and lost this match by KO in round 11. In the fifth round, Selcuk Aydin won by TKO against Nodar Robakidze. Sel\u00e7uk Ayd\u0131n Sel\u00e7uk Ayd\u0131n (born 4 September 1983) is a Turkish professional boxer. He held the European welterweight title from 2009 to", "score": 0, "title_score": 0, "passage_id": "5748031"}, {"title": "Peace of Basel", "text": "came at night to sign the peace treaty between France and Spain in which Spain was represented by Domingo d'Yriarte, who signed the treaty in the mansion of Ochs, the Holsteinerhof. These treaties with Prussia and Spain had the effect of breaking the alliance between the French Republic's two main opponents of the First Coalition. On 28 August 1795, the third treaty was completed, a peace between France and the Landgraviate of Hesse-Kassel, signed by Friedrich Sigismund Waitz von Eschen. There was also an agreement to exchange the Austrian troops who had been captured in Belgium. Peace of Basel The", "score": 0, "title_score": 0, "passage_id": "5632337"}, {"title": "Bumba Meu Boi", "text": "a focus on the death and resurrection of a bull. The principal figures include a bull, a white master (Cavalo Marinho, in Pernambuco), a black pregnant woman (Catirina), a Vaqueiro or cowboy (Mateus, Chico ou Pai Francisco), others vaqueiros (cowboys), \u00edndios, \u00edndias and caboclos (indigenous people), a priest, and a doctor (or indigenous healers). The audience is also a key component of the performance, as passionate responses from spectators provide a hectic atmosphere. Additionally, performers are known to become playfully physical with the audience, though with large consumptions of Cacha\u00e7a (a Brazilian national alcoholic drink), violence can occasionally occur. Today,", "score": 0, "title_score": 0, "passage_id": "4735651"}, {"title": "Associated Country Women of the World", "text": "Associated Country Women of the World The Associated Country Women of the World (ACWW) is the largest international organization for both rural and urban women, with a membership of nine million in over 70 countries. ACWW holds a triennial conference and publishes a magazine, \"The Countrywoman\", four times a year. Late 19th Century \u2013 rural women's groups were set up independently. Communication between groups enabled more country women to come together in friendship and work towards similar goals. London April 1929 \u2013 first International Conference of Rural Women \u2013 46 women from 24 countries attended four-day conference. Vienna 1930 \u2013", "score": 0, "title_score": 0, "passage_id": "5869585"}], "hard_negative_ctxs": [{"title": "Why Don't You Love Me (Beyonce\u0301 song)", "text": "song. According to the lyrics of \"Why Don't You Love Me\", Knowles impersonates a woman who questions her love interest about the reason for which he does not value her fabulousness, convincing him she's the best thing for him as she sings: \"Why don't you love me... when I make me so damn easy to love?... I got beauty... I got class... I got style and I got ass...\". The singer further tells her love interest that the decision not to choose her is \"entirely foolish\". Originally released as a pre-order bonus track on the deluxe edition of \"I Am...", "score": 14.678405, "title_score": 0, "passage_id": "14525568"}, {"title": "Does He Love You", "text": "singing the second chorus. Reba stays behind the wall the whole time, while Linda is in front of her. It then briefly goes back to the dressing room, where Reba continues to smash her lover's picture. The next scene shows Reba approaching Linda's house in the pouring rain at night, while Linda stands on her porch as they sing the bridge. The scene then shifts to the next day, where Reba watches from afar as Linda and the man are seen on a speedboat, where he hugs her, implying that Linda is who he truly loves. Reba finally smiles at", "score": 14.385411, "title_score": 0, "passage_id": "11828871"}, {"title": "Does He Love You", "text": "Linda as the boat leaves the dock. After the song is complete, the boat collapses and goes up in flames as the director (portrayed by actor Rob Reiner) yells \"cut\" and shows Reba and the crew the footage as the screen pans up to show the set and sky. The last day of shooting coincided with the last day of filming for the 1993 movie North (in which Reba stars and Reiner directed), and because of this, Reba's final outfit seen in the video was the same one she wore in the movie. Does He Love You \"Does He Love", "score": 14.2971, "title_score": 0, "passage_id": "11828872"}, {"title": "Does He Love You", "text": "on Patti LaBelle's album, \"Flame\". The song features a vocal battle between two female narrators who are in love with the same man. Both women know that the man is being unfaithful to them and are wondering who he truly loves. The big-budget, Jon Small-directed video was filmed over 3 days in mid-1993. It begins with Reba in her dressing room wearing a lilac feather gown, where she sees a picture of her lover, which she glances at. It then shows Linda as a professional actress at a movie premiere, then cuts back to Reba smashing the picture with a", "score": 14.29348, "title_score": 0, "passage_id": "11828869"}, {"title": "Violet Hill", "text": "prominent guitar riff, characterized by a jagged, fuzzbox distortion effect, enters. Martin sings about medieval imagery of carnivals, cathedrals, religion and war, culminating in a soaring chorus with an anthemic theme. The momentum of the song builds around guitarist Jonny Buckland, who plays a solo. The lyrics start off with Martin recalling: \"Was a long and dark December/From the rooftops I remember/There was snow\". Martin emphasizes towards the thoughts of a soldier going into battle. The line \"If you love me, why'd you let me go?\", talks about a man's love of a woman, who does not reciprocate his love.", "score": 13.823296, "title_score": 0, "passage_id": "11869749"}, {"title": "I Know You Don't Love Me", "text": "I Know You Don't Love Me \"I Know You Don't Love Me\" is the third and final single from Tony Yayo's debut album, \"Thoughts of a Predicate Felon\". The song features G-Unit. 50 Cent sings the chorus while Tony Yayo and Young Buck and Lloyd Banks rap on their own verses. The song tells the story of how the rappers are engaging in a relationship with the same woman, though she does not know they know, and how they know she does not love any of them because her obvious flirtatiousness and love for other rappers. Several other rappers and", "score": 13.810491, "title_score": 0, "passage_id": "9446572"}, {"title": "Chris Austin", "text": "Chris Austin Christopher Clay Austin (born February 24, 1964 in Boone, North Carolina \u2013 March 16, 1991 in San Diego, California) was a male country music singer. Austin was signed to Warner Bros. Records in 1988 and charted three singles on the \"Billboard\" Hot Country Songs chart. His highest-charting single, \"Blues Stay Away from Me,\" was included on the 1989 compilation album \"New Tradition Sings the Old Tradition\". Austin also co-wrote Ricky Skaggs' 1991 single \"Same Ol' Love.\" Austin was most known for playing guitar and fiddle for Ricky Skaggs's and Reba McEntire's road bands. Austin toured with McEntire until", "score": 13.790345, "title_score": 0, "passage_id": "12864394"}, {"title": "Angel in Your Arms", "text": "Don't Want to Be Right\", \"Angel in Your Arms\" reached #8 C&W. \"Angel in Your Arms\" has also been recorded by Lynn Anderson (\"I Love What Love Is Doing to Me\" 1977), Red Hurley (as \"The Angel in Your Arms\") (\"With Love\" 1978), Millie Jackson (\"Feelin' Bitchy\" 1977), Reba McEntire (\"Reba McEntire\" 1977), Billie Jo Spears (\"I Will Survive\" 1979). In the UK, where the Hot original had had an unsuccessful April 1977 release, \"Angel in the Morning\" was recorded in 1979 by veteran vocalist Carol Deene who had been inactive for some years: Deene's version, released on her own", "score": 13.503983, "title_score": 0, "passage_id": "14295833"}, {"title": "\"R\" Is for Ricochet", "text": "guilty because she was in love with Beckwith, a married man. While Reba was in prison, Beckwith slept with her replacement in the office. Kinsey has known Cheney for a couple of years; now she is smitten with him. For this arrest, he and the whole team of investigators want Reba to provide evidence of the money laundering, an inside witness for their case. They decide that Kinsey, now building a rapport with Reba, should ask her to take this on. Unwillingly, Kinsey does so. Kinsey's landlord, Henry, meets with Mattie Halstead, a woman he met on a cruise ship", "score": 13.183542, "title_score": 0, "passage_id": "11687923"}, {"title": "You Keep Me Hangin' On", "text": "bed as she sings the song and finds herself being \"threatened\" by a strange man who is breaking down the walls around her. Country music singer Reba McEntire covered the song in 1995 for her twenty-second studio album, \"Starting Over\". Released as the album's fourth single in 1996 on MCA Nashville Records, it was co-produced by Tony Brown and Michael Omartian. Although not released to country radio, McEntire's rendition was her only dance hit, reaching number two on Hot Dance Club Play. You Keep Me Hangin' On \"You Keep Me Hangin' On\" is a 1966 song written and composed by", "score": 13.09029, "title_score": 0, "passage_id": "4204938"}, {"title": "U + Me (Love Lesson)", "text": "(2016). Andy Kellman felt that it \"could not have been made at any other point in Blige's career\". Lyrics include: \"The lies you told to me make it easy for me to leave, You plus me wasn\u2019t the best thing\" and \"And I just can't deny the fact / we don't belong together / Guess it ain't the real thing.\" She also talks about a relationship that does not add up to a happy ending singing: \"You plus me was a love lesson / In too deep with our imperfections.\" Blige also sings about getting over a breakup with the", "score": 13.089972, "title_score": 0, "passage_id": "20005568"}, {"title": "The Banks of Green Willow", "text": "young sea-captain, becomes pregnant and runs away with him to sea, having first stolen money from her parents. When her child is born on board ship, the labour is especially difficult and there is no \"woman's help\" available. Knowing she will die, she asks her lover to \"bind a napkin round my head, then throw me overboard, both me and my baby\" Her lover does this and watches as she \"quivers\" - presumably in her death-throes - and he sings a lament to \"my true love, whom I once loved so dearly\" and who shall be buried on \"The Banks", "score": 13.060878, "title_score": 0, "passage_id": "12469362"}, {"title": "Kelly Clarkson", "text": "with NASCAR during their 2007 season, appearing in televised advertisements, performed at pre-race concerts, promoted NASCAR Day, and appeared at the Champions' Banquet in December. Clarkson collaborated with Reba McEntire for filming an hour-long \"CMT Crossroads\" special at Nashville's Ryman Auditorium on February 22, 2007. Introduced by Dolly Parton, Clarkson performed \"Why Haven't I Heard from You\" and \"Does He Love You\" with Martina McBride on the television special \"CMT Giants: Reba McEntire\". She also appeared on an episode of McEntire's sitcom \"Reba\", that aired on January 14, 2007. At the Academy of Country Music Awards on May 16, 2007,", "score": 12.924647, "title_score": 0, "passage_id": "2462308"}, {"title": "Does He Love You", "text": "metal object. Reba shows up in a limo with the same man. The two women are seen then in a photo shoot with Linda holding an award and the man in the background. The picture is taken, but it shows Reba losing focus for some reason. The next scene shows Linda and the man flirting in a hotel bar. Reba appears wearing a white shower cloak, standing behind a glass and wood wall, as if not to be noticed by Linda. She sees what is really going on, and Linda notices her, only to come over to her and begin", "score": 12.868059, "title_score": 0, "passage_id": "11828870"}, {"title": "Oliver! (film)", "text": "and employ Nancy to help them as Oliver trusts her more than he does the others. Nancy refuses as she wants Oliver to have a life free of thievery, but Sikes hits her. As Nancy reluctantly follows Sikes, she sings of her unwavering love for him despite his ways (\"As Long As He Needs Me\"). The next day, Brownlow entrusts Oliver with some books and money to be delivered to the bookshop. As he leaves, Brownlow notices a striking resemblance between Oliver and a portrait of his long-lost niece Emily, who ran away from home after being jilted by her", "score": 12.804581, "title_score": 0, "passage_id": "7635787"}, {"title": "Sorry (Halsey song)", "text": "I can be/ Cause I can sometimes treat the people/ That I love like jewelry\" sung by Halsey. During the chorus, she sings \"So I'm sorry to my unknown lover/ Sorry that I can't believe/ That anybody ever really/ Starts to fall in love with me\". Toward the ending, she sings \"Someone will love you/ But someone isn't me\". An accompanying music video for \"Sorry\" was directed by Sing J Lee and Halsey, who had also helmed the videos for the previous singles, \"Now or Never\" and \"Bad at Love\". It was uploaded on February 2, 2018, on Halsey's Vevo", "score": 12.671311, "title_score": 0, "passage_id": "20132108"}, {"title": "Reba Number 1's", "text": "Reba Number 1's Reba #1s is a double-disc compilation album released in 2005 celebrating Reba McEntire's thirty years in the music industry. It is the first compilation of her career to include tracks from her early Mercury Records years along with her MCA recordings. The album features all of McEntire's solo number one hits spanning her career. The thirty-five-track compilation features twenty-two \"Billboard\" number-one hits, eleven non-\"Billboard\" number ones and two new tracks, \"You're Gonna Be\" (re-titled \"You're Gonna Be (Always Loved by Me)\" when released as a single) and \"Love Needs a Holiday\", which respectively reached 33 and 60", "score": 12.64251, "title_score": 0, "passage_id": "8846861"}, {"title": "Song and Dance", "text": "to worse.\" However, he wrote that \"Miss Peters is an unimpeachable peach of a performer who does so much for the top half of this double bill as to warrant its immediate rechristening 'Song of Bernadette'. She not only sings, acts, and (in the bottom half) dances to perfection, she also, superlatively, 'is' \". Original London production Original Broadway production Song and Dance Song and Dance is a musical comprising two acts, one told entirely in \"Song\" and one entirely in \"Dance\", tied together by a unifying love story. The \"Song\" act is \"Tell Me on a Sunday\", with lyrics", "score": 12.505135, "title_score": 0, "passage_id": "2079190"}, {"title": "When You Tell Me That You Love Me", "text": "The Norwegian soprano Sissel Kyrkjeb\u00f8 recorded \"When You Tell Me That You Love Me\" as a duet with Spanish tenor Jose Carreras on her 2007 album, Northern Lights. Sissel sings in English and Carreras sings in Italian. On the album the song is called \"Quando Sento Che Mi Ami\" The 12 American Idol Finalists - Season 4 Finalists got together perform this Diana Ross hit. It was selected as the American Red Cross Disaster Relief Single in 2005 for the American Idol TV show. It also appears on the compilation album. When You Tell Me That You Love Me \"When", "score": 12.218677, "title_score": 0, "passage_id": "9533808"}, {"title": "Poison (Beyonce\u0301 song)", "text": "does seem album worthy. It's something most can relate to if you've ever been in a relationship. Beyonce sings about a failed relationship that's no good, but yet is so hard to walk away from and ends up being just like Poison. Recording artist Nicki Minaj discussed the song during an interview with \"Rap-Up\" magazine, saying \"When I tell you it gives me life, like, it gives me life. Her voice is effortless. It's badass, like, 'I know I'm the best.' I love the melody, I love the cadence. It's playful, but it's just so in-your-face. It's dope and it's", "score": 12.125429, "title_score": 0, "passage_id": "15404269"}, {"title": "Dragon Ball Z Hit Song Collection series", "text": "\"Ichido wa Kekkon Shitai Mambo\" features Kuririn singing cheerfully about how much he desires to get married. \"Vegeta-sama no Oryori Jigoku!!\" marks the only character song in the series, but not the last, by Vegeta. Here, he sings about cooking a special Okonomiyaki while giving \"battle commands\" to his ingredients who sing backup. \"Share 'reba Inochi no Izumi Waku-Waku!! 2\" is the follow-up to \"Share 'reba Inochi no Izumi Waku-Waku!!\" which is both performed by the northern Kaio-sama. Once again he continues to tell jokes that he only finds funny. By the end of the song he has succumbed to", "score": 12.102381, "title_score": 0, "passage_id": "8276698"}, {"title": "John Berry (singer)", "text": "on the \"Billboard\" country charts, followed by the No. 22 \"Kiss Me in the Car\". With his first major album in the stores, Berry went on the road with a major concert tour opening for the likes of Reba McEntire, Aaron Tippin, and The Mavericks. After this came \"Your Love Amazes Me\", which in 1994 became his only Number One hit on the \"Billboard\" charts. Following it were the No. 5 \"What's in It for Me\" (originally the b-side to \"Your Love Amazes Me\") and No. 4 \"You and Only You\", the latter of which was also a Number One", "score": 12.079264, "title_score": 0, "passage_id": "8600722"}, {"title": "La rondine", "text": "playfully mock him, while Lisette, Magda's maid, tells him he does not know what he is talking about. Prunier takes offence and Magda orders Lisette to leave. Prunier maintains that no one is immune to romantic love and sings the first verse of his latest song about Doretta, who rejected a king as her suitor because of the value she placed on true love. He does not know how to finish the song, so Magda takes over and provides the second verse: she recounts how Doretta falls in love with a student (Aria: \"Chi il bel sogno di Doretta\"). Magda's", "score": 12.05489, "title_score": 0, "passage_id": "5161064"}, {"title": "Papa, Can You Hear Me?", "text": "singing the song while Nelson is staying with the family, as an ode to Nelson's missing father. In an episode of the show \"Will & Grace\", Jack sings the song on separate occasions, as does Will in an earlier episode while visiting a therapist. In the \"Grilled Cheesus\" episode of \"Glee\", Rachel sings this song for Burt Hummel (who is in a coma as the song is being sung) and his son Kurt Hummel. Rachel sings the song outside as Yentl does in the movie, and later beside Burt's hospital bed, with Mercedes, Finn, Quinn and Finn's mother Carol with", "score": 12.002037, "title_score": 0, "passage_id": "8594464"}, {"title": "L'Orfeo", "text": "creeps in: \"Who will assure me that she is following?\". Perhaps, he thinks, Plutone, driven by envy, has imposed the condition through spite? Suddenly distracted by an off-stage commotion, Orfeo looks round; immediately, the image of Euridice begins to fade. She sings, despairingly: \"Losest thou me through too much love?\" and disappears. Orfeo attempts to follow her but is drawn away by an unseen force. The chorus of spirits sings that Orfeo, having overcome Hades, was in turn overcome by his passions. Back in the fields of Thrace, Orfeo has a long soliloquy in which he laments his loss, praises", "score": 11.971418, "title_score": 0, "passage_id": "2694208"}, {"title": "The Mountebanks", "text": "is in love with Teresa, the village beauty. He sings a ballad about her, but it is clear that she does not love him in return. She suggests that he marry Elvino's niece, Ultrice, who follows Alfredo everywhere, but Alfredo wants nothing to do with Ultrice. Elvino is concerned that he does not know the proper protocol for entertaining a Duke and Duchess. He suggests that Alfredo impersonate a Duke, so that he can practice his manners. Alfredo implores Teresa to impersonate the Duchess, but Teresa insists that Ultrice play the role. A troupe of strolling players arrives. Their leader,", "score": 11.941302, "title_score": 0, "passage_id": "7686257"}, {"title": "Um Anjo Veio Me Falar", "text": "responds and continues, \"that the dream has no end No matter how long it will take (I'll wait for you) And it's never been so strong, I heard an angel tell me.\" In the second part, Aline sings about dreaming of a kiss and a caring someone. Karin and Luciana sing that someday they will find love, and Luciana sings, \"In your arms is where I want to be.\" At the \"bridge\", Aline sings once more, \"All the love I've always sought, you've come to show me.\" Still on bridge, they claim to have found an \"angel\", \"the love they", "score": 11.936984, "title_score": 0, "passage_id": "20379033"}, {"title": "Drama Queen (Ivy Queen album)", "text": "Queen sings: \"Pure love does not fight, it does not hurt you, love that is pure does not cause you to fall\", and described the song as \"an honest statement of what love is\". \"I Do\" is a minor-key, mid-tempo pop and R&B power ballad built on a handclapped rhythm and piano. Lyrically, the song is a message to men and women; Queen sings: \"My ladies, if you know better, if he loves you, let him come back. My fellas, if you love her, don't let nothing hold you back, run out and look for her\". Queen recorded the song", "score": 11.935445, "title_score": 0, "passage_id": "14591524"}, {"title": "Milioner (song)", "text": "she doesn't want any money and love is that that actually she misses. She says that he could not buy her, because with money love is not buying. The song is continuing and Elena asks him why he is still on the top and says to him to come down to her world, he is just missing love. She sings about her eyes comparing with black diamonds, and says that with brilliants her lips are full. She just wants one thousand kisses. The chorus is continuing. Leroy Chambers sings in English the following sentences: \"\"Every time you call me, you", "score": 11.912751, "title_score": 0, "passage_id": "13476900"}, {"title": "You Must Love Me", "text": "and gradually fades out. \"You Must Love Me\" is set in common time, with a moderate tempo of 92 beats per minute. It is composed in the key of B major, with Madonna's vocals spanning from G to B. The song has a basic sequence of B\u2013E/B\u2013F/B\u2013B in the beginning and changes to B\u2013F when Madonna sings the opening verse \"Where do we go from here?\". \"You Must Love Me\" received generally positive reviews from critics. J. Randy Taraborrelli, author of \"\", wrote: \"Who can deny that her voice has remarkable and unmistakable presence when heard during 'You Must Love", "score": 11.91184, "title_score": 0, "passage_id": "5632209"}, {"title": "Nick Bottom", "text": "Bottom believes they are playing a prank on him, proclaiming, \"This is to make an ass of me, to fright me if they could.\" So he stays in the forest by himself and sings loudly to show them he isn't afraid. The Fairy Queen Titania is awakened by Bottom's song. She has been enchanted by a love potion, which will cause her to fall in love with the first living thing that she sees when she wakes (no matter who, or what it is), made from the juice of a rare flower, once hit by Cupid's arrow, that her husband,", "score": 11.909573, "title_score": 0, "passage_id": "4659470"}, {"title": "The Immaculate Collection", "text": "and percussion. Madonna begins singing \"I'm talking /I believe in the power of love /I'm singing /I believe that you can rescue me\" before engaging in the breathy, spoken word vocals, like on \"Justify My Love\". She sings \"Rescue me /It's hard to believe your love has given me hope /Rescue me /It's hard to believe I'm drowning, baby throw out your rope\" over the chorus. At one point of the song, Madonna sings the line \"And right while I am kneeling there I suddenly begin to care\", which was likened to oral sex. \"Justify My Love\" was released as", "score": 11.884291, "title_score": 0, "passage_id": "4701379"}, {"title": "Naughty Marietta (operetta)", "text": "I Were Anyone Else But Me\"). Adah feels that \u00c9tienne does not love her anymore and tries to see her future in cards (\"'Neath a Southern Moon\"). Marietta, disguised as Rudolfo's son, performs an \"Italian Street Song\" for the townsfolk. The Lieutenant Governor announces that a dispatch has come from the King of France offering 10,000 francs for the return of the Contessa d'Altena who exchanged places with her maid and traveled to the colonies as a casquette girl. The Contessa always sings a fragment of a certain tune, and the townspeople recognize it as the ghost's song. Sir Harry", "score": 11.840254, "title_score": 0, "passage_id": "6876386"}, {"title": "Aimee Mann", "text": "she sang on Rush's song \"Time Stand Still\" on the album \"Hold Your Fire\". The single is credited as \"Rush (featuring Aimee Mann)\". In 1995, she recorded a cover version of Harry Nilsson's \"One\" on the album \"For the Love of Harry: Everybody Sings Nilsson\" and in 1996, \"Baby Blue\" on the Badfinger tribute album \"Come and Get It\". In 1997, Mann recorded a cover of \"Nobody Does It Better\", the theme song of the James Bond film \"The Spy Who Loved Me\", on the album \"\". In 2001, Mann recorded covers of The Beatles' \"Two of Us\" with Michael", "score": 11.840254, "title_score": 0, "passage_id": "2006324"}, {"title": "Cabaret (musical)", "text": "song\u2014becoming the strident \"Tomorrow Belongs to Me\". He initially sings \"a cappella\", before the customers and the band join in. (In the 1998 and 2014 revivals, this is replaced by the Emcee playing a recording of a boy soprano). Months later, Cliff and Sally are still living together and have fallen in love. Cliff knows that he is in a \"dream,\" but he enjoys living with Sally too much to come to his senses (\"Why Should I Wake Up?\"). Sally reveals that she is pregnant, but she does not know the father and reluctantly decides to get an abortion. Cliff", "score": 11.834493, "title_score": 0, "passage_id": "2156040"}, {"title": "The One (Kylie Minogue song)", "text": "ballad and compared the song to her 2004 single \"I Believe in You\". Tom Ewing from Pitchfork Media said \"When that track ends and 'The One' shimmers gloriously in with New Order guitars and morse-code synths, the return to 4/4 dance-pop brings an almost tangible inrush of confidence. \"I'm the One-- love me love me love me,\" she sings, and for these four minutes she is and we do.\" Lyrically, the song deals with a female (Minogue) telling her lover that she is \"the one\", and wanting him to love her, chanting the lyric \"Love me/Love me/Love me/Love me\". Minogue", "score": 11.824989, "title_score": 0, "passage_id": "11775156"}, {"title": "Is There Life Out There?", "text": "a stranger. Lily's strength, love and perseverance are the only things that can help her now. Is There Life Out There? Is There Life Out There is a 1994 American television film starring Reba McEntire, who also sings the title song. Lily Marshall (McEntire) has a loving, supportive husband, two great kids and an unfulfilled dream: to return to college and get the degree she always wanted. \"Is there life beyond her family and home?\", Lily wonders. The hole in Lily's life is soon filled by too much. There's a confusing new social life on campus, schoolwork keeping her up", "score": 11.792831, "title_score": 0, "passage_id": "7660477"}, {"title": "Lucky Day (Nicola Roberts song)", "text": "described by Robert Copsey of Digital Spy as a \"60s-swing-meets-East-London vibe\". Roberts' voice has been described by Katherine St Asaph of Pop Dust as a \"springy\" vibrato, with breathy background vocals featuring sounds effect including repeated kissing noises. Roberts sings about falling in love with someone, as she sings: \"Aah, say that you love me, say that you need me too... best you ever had. It could be so easy, for you to please me, baby. So how come you tease me?\". Roberts discussed the track on her blog, commenting that its lyrical content alludes to a boy that initially", "score": 11.765256, "title_score": 0, "passage_id": "15818778"}, {"title": "Seduction: Sinatra Sings of Love", "text": "Seduction: Sinatra Sings of Love Seduction: Sinatra Sings of Love is a 2009 double disc compilation album by American singer Frank Sinatra. Released by Rhino just in time for Valentine's Day 2009, Seduction: Sinatra Sings of Love is a good collection of 22 highlights\u2014with an additional ten cuts on the two-disc \"deluxe\" edition\u2014from Sinatra's Reprise recordings. While there are surely some hits here -- \"Some Enchanted Evening,\" \"They Can't Take That Away from Me,\" \"I Get A Kick Out of You,\" \"I've Got You Under My Skin\"\u2014what's noteworthy about this collection is that it is not just a recycling of", "score": 11.732032, "title_score": 0, "passage_id": "14299948"}, {"title": "Off Key", "text": "In 1981, he released an album of tangos, \"Pl\u00e1cido Domingo Sings Tangos\", which included Carlos Gardel's classic, \"El d\u00eda que me quieres\", which Palacios sings in the film. Domingo, who also conducts, periodically accompanies himself on the piano while singing, as does Palacios with this song. The movie also features an original piece written by Bernardo Bonezzi, which acts as Dupres' son's composition during the party scene. The reviewer for \"Variety\" was unimpressed by the movie's screwball comedy script and likened it to a series of underwhelming English-language films made by Spanish moviemakers. He believed that the frenetic pace of", "score": 11.609625, "title_score": 0, "passage_id": "18080988"}, {"title": "Na\u0303o Da\u0301 pra Resistir", "text": "and hip-hop. The song talks about a love that is irresistible, where the protagonist tries to disguise, but ends up falling in love with the loved one. The song begins with Luciana on lead vocals, followed by Patricia, who changes versions with Luciana to the chorus. In the chorus, the girls sing, \"I can not resist your love, you look at me like this, baby, I go, your kisses just for me, and your taste, I can not resist I need your love.\" After the chorus, Karin sings the second full part, taking help from the girls in the backing", "score": 11.609015, "title_score": 0, "passage_id": "20369590"}, {"title": "Forever Love (Reba McEntire song)", "text": "in Pasadena, CA over one day, it shows footage from the movie, interspersed with scenes of Reba performing the song in a garden. Forever Love (Reba McEntire song) \"Forever Love\" is a song recorded by American country music artist Reba McEntire, and written by Liz Hengber, Deanna Bryant and Sunny Russ. It was released in July 1998 as the second single from her studio album, \"If You See Him\" (1998). The song reached number four on the US \"Billboard\" Hot Country Singles & Tracks chart in November 1998. It was also the title song to a made-for-television movie \"Forever Love\"", "score": 11.578635, "title_score": 0, "passage_id": "14605381"}, {"title": "If You See Him/If You See Her", "text": "giving McEntire her twenty-ninth number one single, and Brooks & Dunn their twelfth. On the Brooks & Dunn: The Last Rodeo special on (on CBS) May 23, 2010, Lady Antebellum sang this song with Reba McEntire and Brooks & Dunn coming in towards the end. The video starts off with Reba at a bar. Then, Kix Brooks comes to the bar. Then, Reba sings in an empty fancy theatre, along with Ronnie Dunn. A piano on the stage is seen in the background, and Kix is seen playing the piano. Before the end of the video, Kix and Ronnie are", "score": 11.534451, "title_score": 0, "passage_id": "11702569"}, {"title": "Dionne Warwick", "text": "Burt Bacharach accompanying her on the piano. In 2006, Warwick signed with Concord Records after a fifteen-year tenure at Arista, which had ended in 1994. Her first and only release for the label was \"My Friends and Me\", a duets album containing reworkings of her old hits, very similar to her 1998 CD \"Dionne Sings Dionne\". Among her singing partners were Gloria Estefan, Olivia Newton-John, Wynonna Judd and Reba McEntire. The album peaked at #66 on the Top R&B/Hip-Hop Albums chart. The album was produced by her son, Damon Elliott. A follow-up album featuring Warwick's old hits as duets with", "score": 11.527695, "title_score": 0, "passage_id": "1446309"}, {"title": "End of Time (song)", "text": "be your friend / I will love you so deeply / I will be the one to kiss you at night / I will love you till the end of time.\" She continues her appeal as she sings to her love interest, \"Take you away from here / There's nothing between us but space and time\". On the bridge, Knowles belts her vocal lines over a shooting horn sequence; with her multiple-layered vocals, she commands, \"Boy come to me\", and towards the end, she repeatedly sings, \"Say you\u2019ll never let me go\". Knowles \"finds the strength in two\" as she", "score": 11.509991, "title_score": 0, "passage_id": "15623733"}, {"title": "A Hard Day's Night (album)", "text": "as well as being the lead singer on these same nine tracks (although McCartney sings lead on the chorus part of the title track which otherwise is strictly Lennon territory). Lennon and McCartney co-wrote \"I'm Happy Just to Dance with You\", while McCartney wrote \"And I Love Her\", \"Can't Buy Me Love\", and \"Things We Said Today\". This is also one of three Beatles albums, along with \"Let It Be\" and \"Magical Mystery Tour\", in which Starr does not sing lead vocal on any songs. Starr sang the lead vocal on \"Matchbox\" during the sessions; it appeared instead on the", "score": 11.503768, "title_score": 0, "passage_id": "820150"}, {"title": "Joanne (album)", "text": "he felt leads to a \"compelling sense of urgency\". The singer's vocals are kept raw and untreated on the song, eschewing autotune. The composition consists of \"pulsing verses\" and a guitar-and-vocal breakdown before the final chorus, with Gaga singing the main title multiple times. Around the two minute mark, there is a key change for the final chorus. In \"Million Reasons\" Gaga talks about love which does not last, with the singer uttering the title in several variations on the verses. The composition consists of simple country-oriented piano and guitar instrumentation. During the song's chorus, Gaga sings, \"You're giving me", "score": 11.483253, "title_score": 0, "passage_id": "19393954"}, {"title": "George Jones Sings the Great Songs of Leon Payne", "text": "George Jones Sings the Great Songs of Leon Payne George Jones Sings the Great Songs of Leon Payne is an album by American country music artist George Jones, released in 1971 on the Musicor Records label. Leon Payne was a honky tonk songwriter who only had one chart hit, the sentimental \"I Love You Because\", but composed a slew of hits for other artists, most notably \"Lost Highway\" and \"They'll Never Ever Take Her Love From Me\" for country music icon Hank Williams. Jones had been recording Payne's songs since his early days on Mercury Records and this collection, which", "score": 11.46655, "title_score": 0, "passage_id": "9850948"}, {"title": "Johnny MacRae", "text": "Johnny MacRae Johnny MacRae (February 15, 1929\u2014July 3, 2013), born Fred A. MacRae, nicknamed \"Dog\" was an American country music composer credited with 235 songs released by recording artists including Ray Charles, George Jones, and Reba McEntire. His best known songs include \"You Can't Make a Heart Love Somebody\" (George Strait), \"Tonight the Heartache's on Me\" (Dixie Chicks), \"I'd Love to Lay You Down\" (Conway Twitty), \"I Still Believe in Waltzes\" (Loretta Lynn & Conway Twitty), \"Goodbye Says It All\" (Blackhawk), and \"Living Proof\" (Ricky Van Shelton). MacRae was a native of Independence, Missouri. He began composing at age 30.", "score": 11.460762, "title_score": 0, "passage_id": "20667297"}, {"title": "I Can't Make You Love Me", "text": "\"I Can't Make You Love Me\" was recorded against a quiet electric piano-based arrangement, with prominent piano fills and interpolations supplied by Bruce Hornsby. The singer depicts a now one-sided romantic relationship about to end in soft but brutally honest terms: \"Turn down the lights, turn down the bed/Turn down these voices inside my head/Lay down with me, tell me no lies/Just hold me close, don't patronize ... don't patronize me/'Cause I can't make you love me if you don't/You can't make your heart feel something that it won't,\" she sings. \"I Can't Make You Love Me\" received acclaim from", "score": 11.453361, "title_score": 0, "passage_id": "9774647"}, {"title": "No Me Queda Ma\u0301s", "text": "lush string arrangement. The song employs the traditional ranchera storyline, with the female singer agonizing over the end of a relationship. Its lyrics explore unrequited love; when the singer's lover leaves her for another woman, she nevertheless wishes them \"nothing but happiness.\" According to author Lori Beth Rodriguez, Selena sings the song \"in a low, sober voice\", and critic Howard Blumenthal adds that she does so in a \"desperate\" and \"sentimental\" way. Ramiro Burr of the \"San Antonio Express-News\" called her overdubbed vocals \"powerful\" and \"emotive\"; other critics have described \"No Me Queda M\u00e1s\" as \"torchy\", \"mournful\", \"piercing\" and \"heartbreaking\".", "score": 11.449716, "title_score": 0, "passage_id": "8420927"}, {"title": "Jason Sellers", "text": "album, \"Christmas Wish\". Although he has not released any singles since 2000, he holds several credits as a songwriter and harmony vocalist. Singles that Sellers co-wrote include \"You Can't Hide Beautiful\" by Aaron Lines, \"I'm a Saint\" by Mark Chesnutt, \"Some People Change\" by Montgomery Gentry, \"The One in the Middle\" and \"He Hates Me\" by Sarah Johns, \"If You Didn't Love Me\" by Phil Stacey, \"I Still Miss You\" by Keith Anderson, \"Strange\" by Reba McEntire, \"Don't You Wanna Stay\" by Jason Aldean and Kelly Clarkson, \"I Won't Let Go\" by Rascal Flatts, \"I Got You\" and \"If I", "score": 11.441917, "title_score": 0, "passage_id": "10250247"}, {"title": "Reba (TV series)", "text": "Lullaby\" which Reba performs at the end of the season one finale episode, \"It Ain't Over Till the Redhead Sings\", the second song is Carole King's \"So Far Away\" which Reba performs at the end of the episode entitled, \"Terry Holliway\", the third and final song that is unreleased is Reba's and Melissa's performance of the hit Dolly Parton song, \"9 to 5\" in the episode entitled \"Driving Miss Kyra.\" The house used in the exterior shots which served as Reba's house is located at 13522 Butterfly Lane, Houston, Texas 77079. \"Reba\" set a new all-time viewership record for any", "score": 11.438617, "title_score": 0, "passage_id": "19005931"}, {"title": "Tell Me You Love Me (song)", "text": "Lovato sings accompanied by guest choir while confetti raining down. Recording and management Personnel Credits adapted from the liner notes of \"Tell Me You Love Me\". Tell Me You Love Me (song) \"Tell Me You Love Me\" is a song by American singer and songwriter Demi Lovato. It was written by Kirby Lauryen, Stint and John Hill, with production handled by the latter two. It was initially released through Hollywood, Island and Safehouse Records on August 24, 2017, as the first promotional single from Lovato's sixth studio album of the same name (2017). It was released as the second and", "score": 11.425211, "title_score": 0, "passage_id": "20308060"}, {"title": "Songs About Me (song)", "text": "meets somebody on an early morning flight and that person asks him what he does. He says he sings \"country music mixed with a little rock and a little blues\". The guy says he's never been crazy about that hillbilly stuff. Later, Trace asks the guy to attend a country music concert. He says that he'll give it a try but doubts it'll \"change [his] opinion\" upon telling him he'll be busy. Then, he realizes that night that the songs relate to him as well (e.g. \"Songs about me and who I am / Songs about loving and living /", "score": 11.422538, "title_score": 0, "passage_id": "13249650"}, {"title": "Jan Bart", "text": "Bart \u2013 Seva 64 \u2212 Anatevka Jan Bart \u2013 Sings Fiddler on the Roof in Yiddish \u2013 Londisc \u2212 Do you love me Jan Bart \u2013 Sings Fiddler on the Roof in Yiddish \u2013 Londisc \u2212 Far from the home I love Jan Bart \u2013 Sings Fiddler on the Roof in Yiddish \u2013 Londisc \u2212 Fiddler on the roof Jan Bart \u2013 Sings Fiddler on the Roof in Yiddish \u2013 Londisc \u2212 If I were a rich man Jan Bart \u2013 Sings Fiddler on the Roof in Yiddish \u2013 Londisc \u2212 Matchmaker Jan Bart \u2013 Sings Fiddler on the Roof", "score": 11.418779, "title_score": 0, "passage_id": "19798478"}, {"title": "Girl Who Got Away", "text": "twirling in a slow dance through electronic caresses and the subtlest touches of strings. In the chorus, she sings, \"I wanna move with the seasons/And go with the flow\". Dido finds guests to keep her current, like Kendrick Lamar, whose vociferous rap tears through the conciliatory \"Let Us Move On\", a spooked trip hop song. The looping intro and muted snares on \"Blackbird\" are leveled off by her detached vocal and reassuringly familiar lyrics about the darker side of love (\"Why do I bring you love, when all you give me back is pain?\", she sings). While \"End of Night\",", "score": 11.411276, "title_score": 0, "passage_id": "16893305"}, {"title": "Let Me Love You (Tamara Todevska, Vrc\u030cak and Adrijan Gaxha song)", "text": "Skopje Fest with the song, \"Ka\u017ei Koj Si Ti\", losing to Karolina Go\u010deva, who went on to represent Republic of Macedonia at the Eurovision Song Contest 2007. Adrian Gaxha was a runner-up in the 2006 Macedonian Eurovision qualifier, having performed the song \"Ljubov E\" with Esma Red\u017eepova. Vr\u010dak, Tamara and Adrian have also taken some promotional photos of their Macedonian entry for the Eurovision Song Contest. \"Vo ime na ljubovta\" is an R&B-style song with several hip hop verses. Tamara sings about the person she loves, explaining that \"without you every second is killing me slowly\". She sings that \"I", "score": 11.406984, "title_score": 0, "passage_id": "11618529"}, {"title": "Reba McEntire", "text": "5\u00d7 Multi-Platinum by the RIAA in 1998. The album has gone to sell over 10 million copies worldwide, which makes it McEntire's best selling album to date. Her eighteenth studio release was 1994's \"Read My Mind.\" The album spawned five major hit singles onto the \"Billboard\" Country chart, including the No. 1 single \"The Heart Is a Lonely Hunter\". The further releases (\"Till You Love Me\", \"Why Haven't I Heard from You\", and \"And Still\") became Top 10 singles on the same chart, with \"Till You Love Me\" also reaching No. 78 on the \"Billboard\" Hot 100, a chart that", "score": 11.390983, "title_score": 0, "passage_id": "1670048"}, {"title": "Walk Away (Kelly Clarkson song)", "text": "who will support her, not disappear when she needs him the most. She asks if he thinks the relationship is worth fighting for. \"I wanna love/ I want a fire/ To feel the burn/ My desires/ I wanna man by my side/ Not a boy who runs and hides/ Are you gonna fight for me?/ Die for me?/ Live and breathe for me?/ Do you care for me?/ 'Cause if you don't then just leave,\" she sings. Pam Avoledo of Blogcritics wrote that \"[...] Clarkson vocals fiery and smoldering. She's come a long way from American Idol where she had", "score": 11.386047, "title_score": 0, "passage_id": "6552934"}, {"title": "Reba: Duets", "text": "The first collaborator on the album was LeAnn Rimes, who recorded the track, \"When You Love Someone Like That\" which also appeared on LeAnn Rimes's \"Family\" album that same year. Jurek called the duet between the pair \"stellar,\" while \"about.com\" called the pairing \"an undeniable outcome of perfection. Reba's strong country voice with LeAnn's young, soulful sound created a new sound like no other.\" The second track, \"Does That Wind Still Blow In Oklahoma\" was a collaboration with Ronnie Dunn (half of the duo Brooks & Dunn), who co-wrote the song with McEntire. The third track is a duet with", "score": 11.381237, "title_score": 0, "passage_id": "9968578"}, {"title": "Alistair Griffin", "text": "of the acoustic set he performed in Germany while supporting Robin Gibb. This included \"Bring it On\", \"You and Me (Tonight)\", \"In Your Smile\" and \"I Have Lived\" with a cover of \"I Can't Make You Love Me\". The limited edition CD was only made available for a short time at his concerts. At his Christmas concert in December 2006, he released another independently recorded, three track solo CD, \"Finding Boethius\", consisting of one co-written song, \"Let Love Speak Its Name\", a cover of \"Hallelujah\" which he regularly sings live, and an acoustic cover of \"Love Will Tear Us Apart\".", "score": 11.361482, "title_score": 0, "passage_id": "6404796"}, {"title": "Si Dios me quita la vida", "text": "country, accused of a crime he did not commit. Enrico does not only work but also gave him the same affection that he gave his own son. Antonio falls madly in love with the wife of the man who most wants and respects, and she does, too, although both try to resist this tormented and impossible love. Si Dios me quita la vida Si Dios me quita la vida (English title: \"If God takes away my life\") is a Mexican telenovela produced by Pedro Dami\u00e1n and Juan Osorio for Televisa in 1995. This is a remake of the 1961 telenovela", "score": 11.360109, "title_score": 0, "passage_id": "13157715"}, {"title": "Danny Orton", "text": "Danny Orton Danny Orton (born in Louisiana) is an American country music songwriter and producer signed to Warner/Chappell. Active since the late 1990s as a songwriter, he has had his songs recorded by Rascal Flatts, Tim McGraw, Reba McEntire, Pat Green, Love and Theft, and many other acts. His credits include the #1 single \"Stand\" by Rascal Flatts as well as others by the hit group, including \"Too Good Is True and \"Like I Am\"; the #2 single \"Fall Into Me\" by Emerson Drive; and the #12 single \"Let Me\" by Pat Green. He has also written for Tim McGraw,", "score": 11.344328, "title_score": 0, "passage_id": "17474889"}, {"title": "+ (Ed Sheeran album)", "text": "knows my name!' It's surreal, growing up listening to his music and now he is one of the people who sings my praises and helps my career and rings me up and actually has an interest in me\". Sheeran started performing with the acoustic guitar aged 11 and his love for the instrument was what \"got [him] into music and singing\". His musical inspirations from an early age surfaced from The Beatles and Bob Dylan, but he noted Damien Rice as a larger influence on his music whom he met after an intimate performance in Dublin. Throughout the production of", "score": 11.336146, "title_score": 0, "passage_id": "15751034"}, {"title": "Winter Dreams (Brandon's Song)", "text": "Winter Dreams (Brandon's Song) \"Winter Dreams (Brandon's Song)\" is a song by American recording artist Kelly Clarkson, from her sixth studio album, \"Wrapped in Red\" (2013). Produced by Greg Kurstin, Clarkson co-wrote the song with Ashley Arrison and Aben Eubanks for her husband (then-fianc\u00e9) Brandon Blackstock, stepson of American recording artist Reba McEntire. A slow-tempo Christmas neo-jazz pop song, \"Winter Dreams\" features a 50-piece chamber orchestra conducted and arranged by film composer Joseph Trapanese. Its lyrical theme mainly depicts love and escapism during the holidays, in which Clarkson sings about spending her first holiday with Blackstock, whom the song is", "score": 11.327478, "title_score": 0, "passage_id": "17874612"}, {"title": "Winter Dreams (Brandon's Song)", "text": "Winter Dreams (Brandon's Song) \"Winter Dreams (Brandon's Song)\" is a song by American recording artist Kelly Clarkson, from her sixth studio album, \"Wrapped in Red\" (2013). Produced by Greg Kurstin, Clarkson co-wrote the song with Ashley Arrison and Aben Eubanks for her husband (then-fianc\u00e9) Brandon Blackstock, stepson of American recording artist Reba McEntire. A slow-tempo Christmas neo-jazz pop song, \"Winter Dreams\" features a 50-piece chamber orchestra conducted and arranged by film composer Joseph Trapanese. Its lyrical theme mainly depicts love and escapism during the holidays, in which Clarkson sings about spending her first holiday with Blackstock, whom the song is", "score": 11.327478, "title_score": 0, "passage_id": "17874606"}, {"title": "Wait for Me/Song of Love", "text": "Love\", she sings mainly in a concert setting. Wait for Me/Song of Love \"\"Wait for Me\" and \"Song of Love\" were two singles from Christian pop rock musician Rebecca St. James. \"Wait For Me\" is perhaps one of St. James' most famous songs, encouraging sexual abstinence until marriage, from the 2000 album \"Transform\" (No. 166 in the \"Billboard\" 200 albums). \"Song of Love\" is a track from her 2002 modern worship album \"Worship God\" (in the \"Billboard\" 200 albums for 11 weeks, peaking at No. 94). In keeping with her advocacy of premarital abstinence, \"Wait for Me\" became the title", "score": 11.321761, "title_score": 0, "passage_id": "8256100"}, {"title": "The Barber of Seville (play)", "text": "Afterwards, the Count sings to Rosine (\"\"Vous l'ordonnez, je me ferai conna\u00eetre... Je suis Lindor\"\"), introducing himself as a poor man named Lindor who is in love with her. From inside the house, Rosine sings a verse to the tune of \"Ma\u00eetre en droit\", requiting his affections, before she is caught by someone else inside and is forced to retreat. Figaro and the Count go their separate ways, agreeing to meet again to put their plan in action. In Dr. Bartholo's house, Rosine writes a note to \"Lindor\". When Figaro drops in, she asks if he will deliver the note.", "score": 11.274594, "title_score": 0, "passage_id": "3094940"}, {"title": "Etta James Sings for Lovers", "text": "was a major R&B hit, however, it was not included on the album. The album, however, includes cover versions of Pop and Jazz standards, including \"Don't Take Your Love from Me\" and \"Someone to Watch Over Me.\" The album was re-issued on compact disc in 2013 and on audiophile 180 g vinyl (with bonus CD included) in 2014. Despite not being given a review, Allmusic gave \"Etta James Sings for Lovers\" three out of five stars. Singles - Billboard (United States) Etta James Sings for Lovers Etta James Sings for Lovers is the fourth studio album by American Blues artist,", "score": 11.270198, "title_score": 0, "passage_id": "13616367"}, {"title": "Bitter Sweet", "text": "(\"Ladies of the Town\"). Carl's earlier love, Manon, is another entertainer at the cafe, who has mixed feelings about Sarah (\"If Love Were All\"). Sarah begs Carl to quit the cafe and take them to a safer place (\"Evermore and a Day\"; \"Dear Little Caf\u00e9\"). He agrees, but that night is busy at the cafe (\"Tokay\"). Manon sings \"Bonne Nuit, Merci\". Sarah is asked to dance with an army captain who handles her boldly and steals a kiss on the dance floor (\"Kiss Me\"). Carl is enraged and strikes the military man. The captain challenges Carl to a duel and", "score": 11.269534, "title_score": 0, "passage_id": "2600323"}, {"title": "Don Pasquale", "text": "night draws in, Ernesto sings of his love for Norina, as he waits for her arrival (\"Com'\u00e8 gentil\" \u2013 \"How lovely\"). At last, Norina emerges, and they express their love: (\"Tornami a dir che m'ami\" \u2013 \"Tell me once more that you love me\"). Don Pasquale and Malatesta have observed and, as they reveal themselves, Ernesto covers himself with a cloak and runs to the house. Pasquale tries to confront Norina \u2013 he has caught her \"in flagrante\" \u2013 but this only provokes a fight that leaves the Don spluttering. She refuses to leave at his demand, so Malatesta, as", "score": 11.263892, "title_score": 0, "passage_id": "494776"}, {"title": "Love triangle", "text": "romance films also sustain this set-up until near the film's end, although they tend to establish a more clear-cut conclusion to the romantic entanglements than in long-running TV shows. The love triangle has been a recurring subject in many popular songs through the years. These \"love triangle songs\" include, but are not limited to: \"You Ain't Woman Enough\" and \"Fist City,\" both by Loretta Lynn; \"The Girl Is Mine\" by Michael Jackson and Paul McCartney; \"The Boy is Mine\" by Brandy and Monica; \"Make No Mistake, She's Mine\" by Kenny Rogers and Ronnie Milsap; \"Does He Love You\" by Reba", "score": 11.248708, "title_score": 0, "passage_id": "1745235"}, {"title": "Sinatra Sings of Love and Things", "text": "Sinatra Sings of Love and Things Sinatra Sings... of Love and Things is an album by Frank Sinatra, released in 1962. This is the fifth compilation of Capitol singles and B-sides. All songs are available in the box set \"The Complete Capitol Singles Collection\", except \"I Gotta Right to Sing the Blues,\" the final song Sinatra recorded for Capitol (which appears as a bonus track on the CD reissue of \"Come Swing with Me!\") and \"The Nearness of You,\" which appears as a bonus track on the CD reissue of \"Nice 'n' Easy\" (It was recorded at those sessions.) It", "score": 11.214184, "title_score": 0, "passage_id": "6413481"}, {"title": "Barry White Sings for Someone You Love", "text": "and are harder to find than the more common light brown fur with black letters cover. Barry White Sings for Someone You Love Barry White Sings for Someone You Love is the self-produced seventh album by soul singer Barry White, released in 1977 on the 20th Century label. The album topped the R&B albums chart, White's first to do so since 1975. It also reached No. 8 on the \"Billboard\" 200, his second to reach the top ten. The album was a success, yielding two Billboard R&B Top Ten singles, \"It's Ecstasy When You Lay Down Next to Me\", which", "score": 11.214184, "title_score": 0, "passage_id": "14237333"}, {"title": "Whoopee!", "text": "a ride with Henry Williams. As a hypochondriac, Henry has problems of his own, but Sally adds to his problems when she leaves a note saying they have eloped. A chase ensues, with the jilted Bob; Mary, Henry's nurse who is in love with him; and a cast of others. Along the way they arrive at the Indian Reservation where Wanenis lives. The movie star Leslie Daw enters the proceedings and sings the torchy, sentimental \"Love Me, or Leave Me.\" \"Whoopee!\" opened on Broadway at the New Amsterdam Theatre on December 4, 1928 and closed on November 23, 1929 after", "score": 11.213966, "title_score": 0, "passage_id": "2136229"}, {"title": "Guava Jelly (song)", "text": "Harry Hawke predicted that \"innocent\" listeners would not recognize the explicit lyrics because of its \"island charm\". Marley begins the track by singing the line: \"You said you love me\" and follows with: \"I said I love you\". By incorporating \"the concerns of soul\" into the lyrics, he sings into the chorus: \"Here I am / Me said, 'Come rub in 'pon me belly' / 'With you guava jelly, Damsel'\". His use of the word Damsel refers to a woman in a relationship experiencing \"emotional pain\". Furthermore, authors Monique Guillory and Richard Green found the song's title refer to a", "score": 11.207216, "title_score": 0, "passage_id": "19937171"}, {"title": "Forever Love (Reba McEntire song)", "text": "Forever Love (Reba McEntire song) \"Forever Love\" is a song recorded by American country music artist Reba McEntire, and written by Liz Hengber, Deanna Bryant and Sunny Russ. It was released in July 1998 as the second single from her studio album, \"If You See Him\" (1998). The song reached number four on the US \"Billboard\" Hot Country Singles & Tracks chart in November 1998. It was also the title song to a made-for-television movie \"Forever Love\" which aired the same year, starring Reba and Tim Matheson. It is her second single to have a movie named after one of", "score": 11.204193, "title_score": 0, "passage_id": "14605379"}, {"title": "Listen to the Lion", "text": "Lion\" has been said to rank amongst Morrison's greatest work. \"During the 11-minute voyage, he sings, shouts, improvises lines, delays and omits them, until he symbolically re-creates the sound of an unleashed lion within himself. It remains a considerable achievement.\" (Johnny Rogan) \"Listen to the Lion\" was one of the 1001 Songs written about in the 2006 book by critic Toby Creswell who says in part: \"Listen to the Lion has almost no words, just the phrase 'Listen to the Lion inside of me'...He sings the phrases like an incantation, sometimes desperate and longing for love and at other times", "score": 11.20244, "title_score": 0, "passage_id": "10059876"}, {"title": "Rumor Has It (Clay Walker album)", "text": "Randy Travis weeper, although the utterly clich\u00e9d lyrics are even more deadly. To be fair, Walker is adept at snappy, sappy fare like \"I'd Say That's Right\" and \"Heart Over Head Over Heels\". But most of this CD's value remains in the foldout miniposter that backs the packaging.\" \"Buffalo News\" gave the album two stars and wrote, \"I wish the man well, but his music just leaves me cold. Yes, he occasionally turns out a clever song like \"One, Two, I Love You\" from this set, but the man consistently does the unforgivable\u2014he sings without soul.\" \"The Dallas Morning News\"", "score": 11.195915, "title_score": 0, "passage_id": "10328728"}, {"title": "Flora-Bama", "text": "Alabama\u2013Florida State line. He sent me a little love both when he changed the lyrics to call the bar owner \"LuLu\" and when he asked me if I wanted to play the bar owner in the video. I mused for just a second, thinking\u2026hmmm\u2026 a woman who owns a bar, drinking a beer, jumps up on the stage and sings with the band. It wasn't much of a stretch! I had crazy fun shooting the video but I'm glad I have my day job!\" Kenny Chesney held a free concert at the Flora-Bama August 16, 2014 to promote his new", "score": 11.194083, "title_score": 0, "passage_id": "7174094"}, {"title": "Me and Juliet", "text": "Larry sings the part of Me in the scene, as the curtain falls (\"Finale of Our Play\"). The cast consisted mostly of unknowns, though Isabel Bigley, who had just originated Sister Sarah Brown in \"Guys and Dolls\", was given the leading role of chorus girl Jeanie. For Larry, the assistant stage manager who falls in love with Jeanie, they cast Bill Hayes, a well-known stage and television actor. William Tabbert, the original Lt. Joe Cable in \"South Pacific\" was considered for the part of Larry, but lost out because he was thought to be too tall to be afraid of", "score": 11.188375, "title_score": 0, "passage_id": "5834813"}, {"title": "Baby Don't Lie", "text": "a hip hop-inflected breakdown, in which Stefani raps, \"You can tell me what you're hidin' boy/And you can tell me if I'm gettin' warm\". Lyrically, the song discusses insecurities in a relationship, where Stefani questions her man's love. Nolan Feeney of \"Time\" complimented that the song is \"about falling in love with someone who's got a few skeletons in their closet.\" As noted by \"Spin\"'s Brennan Carley, \"Stefani sounds shattered as she sings, \"But there's something behind those eyes / Those eyes / That you can't that you can't disguise / Disguise.\" In the \"stomping, infuriatingly catchy\" chorus she sings,", "score": 11.185582, "title_score": 0, "passage_id": "18283144"}, {"title": "Surya Puthri", "text": "Surya Puthri On a festival day, Sage Narada (Master Rajagopal) meets the Sun God, also known as Surya, (Kothamangalam Subbu) and sings praises of him. He is accosted by Thailakethu, The king of Yakshas (K. S. Gopalakrishnan), who does not like Narada praising the Sun God. He is upset and decides to teach Narada a lesson. Thapathi (K. R. Chellam) is the daughter of the Sun God, and she falls in love with King Samvaran (Kothamangalam Seenu), even without meeting him. The Yakshas King is in love with her. So, he tries to blackmail her into giving up the king.", "score": 11.17758, "title_score": 0, "passage_id": "19445308"}, {"title": "If You Love Me (Let Me Know)", "text": "the country chart. If You Love Me (Let Me Know) \"If You Love Me (Let Me Know)\" is a song written by John Rostill that was a 1974 hit single for Olivia Newton-John. It was her second release to hit the top 10 in the United States, reaching number 5 on the pop chart and number 2 on the Easy Listening chart. It also reached number 2 on the \"Billboard\" country chart. As with her single \"Let Me Be There\", Mike Sammes sings a bass harmony. Brian Collins covered the song for Dot Records in 1977. His version went to", "score": 11.172611, "title_score": 0, "passage_id": "12823311"}, {"title": "If You Love Me (Let Me Know)", "text": "If You Love Me (Let Me Know) \"If You Love Me (Let Me Know)\" is a song written by John Rostill that was a 1974 hit single for Olivia Newton-John. It was her second release to hit the top 10 in the United States, reaching number 5 on the pop chart and number 2 on the Easy Listening chart. It also reached number 2 on the \"Billboard\" country chart. As with her single \"Let Me Be There\", Mike Sammes sings a bass harmony. Brian Collins covered the song for Dot Records in 1977. His version went to number 83 on", "score": 11.172611, "title_score": 0, "passage_id": "12823310"}, {"title": "Red Dragon (novel)", "text": "gives Lounds an interview in which he deliberately mischaracterizes the killer as an impotent homosexual. This infuriates Dolarhyde, who kidnaps Lounds, forces him to recant the allegations, bites off his lips and sets him on fire, leaving his maimed body outside his newspaper's offices. Lounds is taken to the hospital, but dies from his injuries soon afterward. At about the same time, Dolarhyde falls in love with a blind co-worker named Reba McClane, which conflicts with his homicidal urges. In beginning a relationship with Reba, Dolarhyde resists the Dragon's \"possession\" of him; he goes to the Brooklyn Museum, beats a", "score": 11.152104, "title_score": 0, "passage_id": "7905902"}, {"title": "Ilya Salmanzadeh", "text": "Ilya Salmanzadeh Ilya Salmanzadeh (; born 19 September 1986 in Stockholm), known mononymously as ILYA, is a Swedish Persian songwriter, producer and singer. He rose to prominence after co-writing and producing Ariana Grande's \"Problem\" and Jennifer Lopez's \"First Love\". In 2005 at the age of 19, Ilya signed with Warner/Chappell Music in Stockholm, Sweden. In 2009, he graduated from the Musicians Institute in Hollywood, California. \"Miss Me\", Mohombi & Nelly's song in 2010, was Ilya's first internationally acclaimed production. In 2011, he produced \"Mama\" and \"Reba\" from The Lonely Island's Grammy-nominated album, \"Turtleneck & Chain\". In 2013, he produced Cher", "score": 11.146721, "title_score": 0, "passage_id": "18028685"}, {"title": "Your Love Is a Lie", "text": "Your Love Is a Lie \"Your Love Is A Lie\" is the second single by Canadian rock band Simple Plan from their self-titled third studio album. The song exists in two versions. One is found on the explicit editions, in which lead singer Pierre Bouvier sings the word \"fucks\" in the second verse (\"and do you think about me when he fucks you\"). In the music video and for radio play, the word is omitted and sometimes replaced with \"touches\" (\"and do you think about me when he touches you\"). This is the second song in which Simple Plan uses", "score": 11.143972, "title_score": 0, "passage_id": "11535052"}, {"title": "The Heart Won't Lie", "text": "\"It worked out well in the end for everyone - except, I think, Vince. He doesn't really care for videos and this one turned into a four-day shoot. It was great to spend time with Vince and get to watch him do what he called his Gomer Pyle imitation for his character. But I had to promise him that if he ever does another song with me, he will never have to suffer through a four-day video shoot again!\" The two performed the song on the 1992 Academy of Country Music Awards. Reba and Vince performed the song on the", "score": 11.100757, "title_score": 0, "passage_id": "11704247"}, {"title": "ONiely", "text": "Love\" was released on the same day, featuring female singer Juniel. The video was filmed in Hoxton Studio Pacific in Japan. Niel made his solo comeback with \"Spring Love\" feat. Juniel on Mnet's \"M! Countdown\" on April 16, 2015. The album includes the ballads \"Call Me\", \"Epilogue\", and \"Song of an Angel\"; the funk pieces \"Affogato\" ; and the disco set \"Lovekiller\" in which he sings along to a steady acoustic guitar riff. The song \"Lovekiller\" was composed by Black Eyed Pilseung, who also wrote the melodies for Teen Top's \"Missing\" and \"I'm sorry.\"\"Lovekiller\" is a medium-tempo dance song with", "score": 11.090377, "title_score": 0, "passage_id": "18595928"}, {"title": "Craig Bickhardt", "text": "Springsteen and others. He moved to Los Angeles, California in 1974, where he and Michael Sembello began writing songs, including some which were recorded by Art Garfunkel. A re-established Wire and Wood later recorded for October Records, but never completed an album due to financial problems. Bickhardt signed to a publishing contract with EMI in 1982. Among his first musical recordings were two songs for the soundtrack to the 1983 film \"Tender Mercies\", one of which (\"You Are What Love Means to Me\") charted at No. 86 on the \"Billboard\" country singles chart. He also sang background vocals on Reba", "score": 11.089193, "title_score": 0, "passage_id": "13579359"}, {"title": "Love Is Strong (album)", "text": "also won a Dove Award for Country Recorded Song of the Year at the 24th GMA Dove Awards in 1993. All songs were written or co-written by Paul Overstreet. \"Lord She Sure is Good at Loving Me\" was co-written with country music artist Randy Travis. Christian music singers Susan Ashton and Lisa Bevill provided background vocals on a couple songs while Kathie Baillie, lead singer for the country group Baillie & the Boys sings back up on \"Me and my Baby\". Glen Campbell also sings harmony vocals on \"What's Going without Saying\". Taken from liner notes. Love Is Strong (album)", "score": 11.076974, "title_score": 0, "passage_id": "14061181"}, {"title": "Someone to Love Me (Naked)", "text": "April 5, 2011 following BET\u2019s \u201cThe Game.\u201d The video spotlights a blonde Mary as she wanders through a disorienting corridor and sings on the edge of a broken bridge, later linking up with Diddy and Lil Wayne as lightning flashes around them. Someone to Love Me (Naked) \"Someone to Love Me (Naked)\" is a song by American recording artist Mary J. Blige, taken from her tenth studio album \"My Life II... The Journey Continues (Act 1).\" Written by Jerry \"Wonder\" Duplessis and Leroy Watson, the song is a remix of \"Someone to Love Me\" from Diddy-Dirty Money's debut album, \"Last", "score": 11.05241, "title_score": 0, "passage_id": "15500765"}, {"title": "Consider Me Gone", "text": "describing it as \"an easy-going mid-tempo which focuses on the tail end of a fading relationship. The melody and production are a bit more stripped-down than most mainstream country radio, so this should do well as the second single.\" The music video was directed by Trey Fanjoy. It was a 2010 nominee for the CMT Music Awards' Female Video of the Year. It depicts Reba as a fashion designer working in a studio one night, while another woman is seen getting ready to go out. As she sings the song while working and on a spiral staircase, a storyline is", "score": 11.037085, "title_score": 0, "passage_id": "13692728"}, {"title": "When the Nightingale Sings", "text": "When the Nightingale Sings When The Nightingale Sings is a Middle English poem, author unknown, recorded in the British Library's Harley 2253 manuscript, verse 25. It is a love poem, extolling the beauty and lost love of an unknown maiden. When \u00fee nyhtegale singes \u00fee wodes waxen grene.
Lef ant gras ant blosme springes in aueryl y wene,
Ant love is to myn herte gon wi\u00fe one spere so kene
Nyht ant day my blod hit drynkes myn herte de\u00fe me tene. Ich have loved al \u00feis er \u00feat y may love namore,
Ich have siked moni syk lemmon for", "score": 11.034536, "title_score": 0, "passage_id": "10891637"}]}, {"dataset": "nq_dev_psgs_w100", "question": "where do the great lakes meet the ocean", "answers": ["the Saint Lawrence River"], "positive_ctxs": [{"title": "Great Lakes", "text": "Great Lakes The Great Lakes (), also called the Laurentian Great Lakes and the Great Lakes of North America, are a series of interconnected freshwater lakes located primarily in the upper mid-east region of North America, on the Canada\u2013United States border, which connect to the Atlantic Ocean through the Saint Lawrence River. They consist of Lakes Superior, Michigan, Huron, Erie, and Ontario, although hydrologically, there are four lakes, Superior, Erie, Ontario, and Michigan-Huron. The lakes are interconnected by the Great Lakes Waterway. The Great Lakes are the largest group of freshwater lakes on Earth by total area, and second largest", "score": 1000, "title_score": 1, "passage_id": "151960"}, {"title": "Great Lakes", "text": "Great Lakes The Great Lakes (), also called the Laurentian Great Lakes and the Great Lakes of North America, are a series of interconnected freshwater lakes located primarily in the upper mid-east region of North America, on the Canada\u2013United States border, which connect to the Atlantic Ocean through the Saint Lawrence River. They consist of Lakes Superior, Michigan, Huron, Erie, and Ontario, although hydrologically, there are four lakes, Superior, Erie, Ontario, and Michigan-Huron. The lakes are interconnected by the Great Lakes Waterway. The Great Lakes are the largest group of freshwater lakes on Earth by total area, and second largest", "score": 11.393292, "title_score": 0, "passage_id": "151960"}, {"title": "Great Lakes", "text": "its impact on the environment. On December 18, 2006, the Coast Guard announced its decision to withdraw the entire proposal. Officials said they would look into alternative ammunition, modifying the proposed zones and have more public dialogue before proposing a new plan. Dynamically updated data Great Lakes The Great Lakes (), also called the Laurentian Great Lakes and the Great Lakes of North America, are a series of interconnected freshwater lakes located primarily in the upper mid-east region of North America, on the Canada\u2013United States border, which connect to the Atlantic Ocean through the Saint Lawrence River. They consist of", "score": 10.97442, "title_score": 0, "passage_id": "152029"}, {"title": "Great Lakes", "text": "form a single, naturally interconnected body of fresh water, within the Great Lakes Basin. They form a chain connecting the east-central interior of North America to the Atlantic Ocean. From the interior to the outlet at the Saint Lawrence River, water flows from Superior to Huron and Michigan, southward to Erie, and finally northward to Lake Ontario. The lakes drain a large watershed via many rivers, and are studded with approximately 35,000 islands. There are also several thousand smaller lakes, often called \"inland lakes,\" within the basin. The surface area of the five primary lakes combined is roughly equal to", "score": 10.432816, "title_score": 0, "passage_id": "151963"}, {"title": "Lake Ontario", "text": "the Niagara River from Lake Erie. The last in the Great Lakes chain, Lake Ontario serves as the outlet to the Atlantic Ocean via the Saint Lawrence River. It is the only Great Lake not to border the state of Michigan. Lake Ontario is the easternmost of the Great Lakes and the smallest in surface area (7,340 sq mi, 18,960 km), although it exceeds Lake Erie in volume (393 cu mi, 1,639 km). It is the 14th largest lake in the world. When its islands are included, the lake's shoreline is long. As the last lake in the Great Lakes'", "score": 10.284986, "title_score": 0, "passage_id": "239917"}, {"title": "New York (state)", "text": "that includes within its borders parts of the Great Lakes and the Atlantic Ocean. The Hudson River begins near Lake Tear of the Clouds and flows south through the eastern part of the state, without draining Lakes George or Champlain. Lake George empties at its north end into Lake Champlain, whose northern end extends into Canada, where it drains into the Richelieu River and then ultimately the Saint Lawrence River. The western section of the state is drained by the Allegheny River and rivers of the Susquehanna and Delaware River systems. Niagara Falls is shared between New York and Ontario", "score": 10.10671, "title_score": 0, "passage_id": "9238055"}], "negative_ctxs": [{"title": "Not Alone Any More", "text": "career in 1956. Although he contributed the least as a writer, Orbison described the collaborative process as one in which \"there was no ego involved ... everyone would be throwing something in here and something in there.\" His principal contribution as a singer was on \"Not Alone Any More\". Harrison said that they had considerable difficulty writing a song that suited Orbison, given that his best songs from the 1960s contained unusual elements in their composition and structure. Initially, \"Not Alone Any More\" was \"simple beyond belief\", according to Lynne, and had just three chords. In its completed form, the", "score": 0, "title_score": 0, "passage_id": "15732698"}, {"title": "Archaeological Park of Dion", "text": "the stadium and parts of the city wall. The French archaeologist L\u00e9on Heuzey confirmed the discovery in 1855. He mapped parts of the city wall, found the foundations of some towers and noted the inscriptions of some tombstones. From 1912, the year of the liberation of Macedonia by the Ottomans, the ancient Dion was given more attention. The archaeologist G. P. Oikonomos collected and published all the inscriptions he found in the vicinity of Dion. The Rector of the University of Thessaloniki and Professor of Archeology, Georgios Sotiriadis, began with the first excavations. They began in June 1928 with the", "score": 0, "title_score": 0, "passage_id": "20286171"}, {"title": "Oier Sanjurjo", "text": "In his first full professional campaign, Oier started the first five matches at right back, as starter C\u00e9sar Azpilicueta was away on international duty. He then found his chances limited after the latter's return, and was subsequently loaned to Celta de Vigo on 11 July 2011. After being a starter for the Galicians as the season ended in promotion, Oier returned to Osasuna and renewed his contract until 2015. He scored two goals in 28 games in 2012\u201313, but the club returned to Segunda Divisi\u00f3n after a 14-year stay. Oier Sanjurjo Oier Sanjurjo Mat\u00e9 (born 25 May 1986 in Estella-Lizarra,", "score": 0, "title_score": 0, "passage_id": "13945049"}, {"title": "Jens Galschi\u00f8t", "text": "statue also found a permanent place in Copenhagen, Milano, Barcelona and Innsbruck. The anniversary was celebrated during the European Social Forum 12\u201315 November 2003 in Paris where two Beasts participated in the big manifestation accompanied by Survival of the Fattest and 14 Hunger Boys. The Children of Abraham is a dialogue project created by Jens Galschi\u00f8t, which highlights the three monotheistic religions: Judaism, Christianity and Islam. The project consists of the sculpture Fundamentalism, where 600 quotes from the Torah, the Bible and the Quran are displayed on the sculpture. The sculpture consists of letters forming the word \u201cFundamentalism\u201d, and the", "score": 0, "title_score": 0, "passage_id": "13476613"}, {"title": "Banksia wonganensis", "text": "for both drought and frost. Germination of seed appears to have a success rate of only about 50%; germination is rapid, often taking less than four weeks. Banksia wonganensis Banksia wonganensis is a large shrub endemic to Western Australia that, until 2007, was previously known as \"Dryandra wonganensis\". It occurs within a small area in the vicinity of the Wongan Hills. It grows on lateritic soils in open woodland or amongst dense shrub. It is rare, but does not appear to be endangered. It is a sprawling or erect shrub, up to high, without a lignotuber. Leaves are long, and", "score": 0, "title_score": 0, "passage_id": "9438516"}, {"title": "De revolutionibus orbium coelestium", "text": "People gave ear to an upstart astrologer who strove to show that the earth revolves, not the heavens or the firmament, the sun and the moon ... This fool wishes to reverse the entire science of astronomy; but sacred Scripture tells us [Joshua 10:13] that Joshua commanded the sun to stand still, and not the earth. When the book was finally published, demand was low, with an initial print run of 400 failing to sell out. Copernicus had made the book extremely technical, unreadable to all but the most advanced astronomers of the day, allowing it to disseminate into their", "score": 0, "title_score": 0, "passage_id": "3832818"}, {"title": "Sanctuary city", "text": "United States altogether, while opponents argue that regulatory policies on immigrants wouldn't affect their presence because immigrants looking for work will relocate towards economic opportunity despite challenges living there. Undocumented migrants tend to be attracted to states with more economic opportunity and individual freedom. Because there is no reliable data that asks for immigration status, there is no way to tell empirically if regulatory policies do have an effect on immigrant presence. A study comparing restrictive counties with nonrestrictive counties found that local jurisdictions that enacted regulatory immigration policies experienced a 1\u20132% negative effect in employment. A preliminary study's results", "score": 0, "title_score": 0, "passage_id": "10019759"}, {"title": "Eva Luna (TV series)", "text": "best friend, Daniel Villanueva (Guy Ecker), who is dating Leonardo's sister, Victoria (Vanessa Villela). Victoria and her mother, Marcela (Susana Dosamantes), dislike Eva, as they feel that Eva threatens Victoria's beauty. Daniel is a successful advertising executive of Publicidad Arismendi and widowed father of a young daughter named Laurita (Gaby Borges). Daniel & Eva are immediately attracted to each other. At first, the relationship between Daniel and Eva is a disastrous swing of love and hate, but in the end they fall madly, passionately in love. When Daniel leaves Victoria for Eva, Marcela takes action. She gives Victoria a cup", "score": 0, "title_score": 0, "passage_id": "15255379"}, {"title": "UPC Switzerland", "text": "the existing Internet capacities can be increased continuously on the existing network as required \u2013 by expanding the frequency range or bundling channels. The status quo of 500 Mbit/s can therefore be adjusted to meet future customer needs \u2013 without additional construction work in streets or houses being necessary. UPC, Sunrise and Swisscom offer various subscriptions for fixed network as well as for mobile telephony. All providers have special tariffs that vary according to the type of subscription. UPC Switzerland UPC is the largest cable operator in Switzerland with around 1.2 million residential and business customers and was formed in", "score": 0, "title_score": 0, "passage_id": "12083838"}, {"title": "The Christ Myth", "text": "Psalm 22, especially its lines: \"My God, my God, why have you forsaken me?\" (Psalm 22:1; Mark 15:34); \"They hurl insults, shaking their heads\". (Psalm 22:7; Mark 15:29); \"They divide my clothes among them and cast lots for my garment\". (Psalm 22:18; Mark 15:24). Other psalms present passages supporting the figure of the \"Suffering Servant\" of Yahweh (Psalm 1, 8, 15, 23, 24, 34, 37, 43, 69, 103, 109, 110, 116, 118, 121, 128, etc.) Drews also underlines the contribution of the character of the \"Just\" or the \"Righteous\" in the Book of Wisdom, and Sirach. Drews adds: [Ch. 7,", "score": 0, "title_score": 0, "passage_id": "16736949"}, {"title": "Brand Blanshard", "text": "dogma, he did not regard his Absolute as having the characteristics of a personal God but nevertheless maintained that it was a proper subject of (rational) religious inquiry and even devotion. Defining \"religion\" as the dedication of one's whole person to whatever one regards as true and important, he took as his own religion the service of reason in a very full and all-encompassing metaphysical sense, defending what he called the \"rational temper\" as a human ideal (though one exceedingly difficult to achieve in practice). His admiration for this temper extended his philosophical loyalties across \"party lines\", especially to the", "score": 0, "title_score": 0, "passage_id": "2907674"}, {"title": "Ve\u0301zelay", "text": "imposed one of his courtiers, Pierre de Balzac. The New Gate of V\u00e9zelay built at the end of the 15th century and where the sites are still visible. At the end of the 15th century, a new door was built in the precincts: the Porte Neuve. The latter is defended by two round towers about twelve meters in diameter with walls three meters thick, and two harrows are added to the door in order to be able to prohibit access. In 1538, a bull granted what the monks long demanded: namely secularization. The abbey becomes a simple collegiate church, a", "score": 0, "title_score": 0, "passage_id": "7745533"}, {"title": "South Bend, Indiana", "text": "County, to form Beacon Health System. Beacon is the largest employer in the city and in St. Joseph County, employing 7,088 people. Other notable businesses include Honeywell, Bosch, and PEI Genesis. AM General, Crowe Horwath, Tire Rack, Martin's Super Markets, and Schurz Communications all have corporate headquarters in South Bend. According to the 2017 Comprehensive Annual Financial Report, the city's top employers are: Efforts are under way to spur economic growth in South Bend. The St. Joe Valley Metronet is a 50-mile dark, fiber optic network that encircles South Bend and Mishawaka that allows for strong telecommunications connectivity. The South", "score": 0, "title_score": 0, "passage_id": "1059035"}, {"title": "Phisit Intharathat", "text": "this time, it was nearly 16:00. The crew loaded up; they had time enough for their third and final drop before sunset. Phisit notes it was a routine day, no different from others of his thousands of flying hours in Laos. During this flight, about ten minutes shy of the drop zone, while flying at 8,000 feet, the C-46 was hit by antiaircraft fire; its right engine caught afire. Because Phisit was an experienced parachutist, he hurried to help inexperienced crew members bail out of the stricken plane. DeBruin, Y.C. To, and the three Thai nationals parachuted to safety. Cheney", "score": 0, "title_score": 0, "passage_id": "10944637"}, {"title": "John Olguin", "text": "John Olguin John Main Olguin (February 18, 1921 \u2013 January 1, 2011) was an American aquarium official who served as the museum director of the Cabrillo Marine Museum, which has since been renamed the Cabrillo Marine Aquarium, from 1949 until 1987, when he became director emeritus. Olguin has been called the \"father of recreational whale watching\", as he was the founder of the Cabrillo Whalewatch program and a founding member of the American Cetacean Society. An authorized biography, entitled \"An Ocean of Inspiration - The John Olguin Story\" detailing John's life is being released October 16, 2011 at the Autumn", "score": 0, "title_score": 0, "passage_id": "15267949"}, {"title": "Eriq Zavaleta", "text": "Eriq Zavaleta Eriq Anthony Zavaleta (born August 2, 1992) is an American soccer player who plays as a center back for Toronto FC of Major League Soccer. Zavaleta played his freshman and senior seasons of high school soccer at Westfield High School in Westfield, Indiana. He scored 25 goals and nine assists as a freshman and 20 goals and 10 assists as a senior. He also spent his youth career with FC Pride, Real Salt Lake, and Chivas USA, and was also part of Columbus Crew's USL Super-20 championship team in 2011. On February 7, 2011, Zavaleta signed a letter", "score": 0, "title_score": 0, "passage_id": "17015041"}, {"title": "OpenQASM", "text": "OpenQASM Open Quantum Assembly Language (OpenQASM; pronounced \"open kazm\") is an intermediate representation for quantum instructions. The language was first described in a paper published in July 2017, and source code was released as part of IBM's Quantum Information Software Kit (QISKit) for use with their IBM Q Experience cloud quantum computing platform. The language has similar qualities to traditional hardware description languages such as Verilog. The following is an example of OpenQASM source code from the official library. The program adds two four-bit numbers. // quantum ripple-carry adder from Cuccaro et al, quant-ph/0410184 OPENQASM 2.0; include \"qelib1.inc\"; gate majority", "score": 0, "title_score": 0, "passage_id": "20447825"}, {"title": "Pinophyta", "text": "are the dominant plants over large areas of land, most notably the taiga of the Northern Hemisphere, but also in similar cool climates in mountains further south. Boreal conifers have many wintertime adaptations. The narrow conical shape of northern conifers, and their downward-drooping limbs, help them shed snow. Many of them seasonally alter their biochemistry to make them more resistant to freezing. While tropical rainforests have more biodiversity and turnover, the immense conifer forests of the world represent the largest terrestrial carbon sink. Conifers are of great economic value for softwood lumber and paper production. The earliest conifers in the", "score": 0, "title_score": 0, "passage_id": "772364"}, {"title": "Helvetia, Pennsylvania", "text": "1890s by Adrian Iselin, a New York investment banker.The Helvetia Mine was owned exclusively by Iselin and operated independently of the R&P until 1896, when it was joined to other R&P holdings. Thus it was Adrian Iselin who first put his stamp on the company town, not the R&P. After Helvetia opened, Iselin and the R&P seem to have acted cooperatively in a number of matters regarding wages, transportation rates, and mining and coking operations at Helvetia between 1891 and 1896. The mine was serviced via the Mahoning Valley Railroad, a one-and-three-quarter-mile-long spur built by Adrian Iselin to connect with", "score": 0, "title_score": 0, "passage_id": "15163729"}, {"title": "Stoney Trail", "text": "north of Stoney Trail. The northwest ring road opened on November 2, 2009, with traffic signals at Harvest Hills Boulevard but grading was completed for a future possible interchange. On November 25, 2009, the province announced construction of the Harvest Hills Boulevard Interchange to be opening in fall 2010. The cost of the interchange project was $14 million. The interchange opened to traffic in 2010. Grading has been completed for a future interchange at 14 Street NW. At present, there is a right-in-right-out access south of Stoney Trail into the Panorama Hills neighbourhood. No schedule had been set for the", "score": 0, "title_score": 0, "passage_id": "5384192"}, {"title": "Fox Sports Networks", "text": "individual team rights, some Fox Sports Networks maintain overflow feeds available via digital cable, telco and satellite providers in their home markets, which may provide alternate programming when not used to carry game broadcasts that the main feed cannot carry due to scheduling conflicts. Fox Sports Networks is headquartered in Houston, Texas, with master control facilities based in both Houston and Los Angeles; FSN also maintains production facilities at Stage 19 at Universal Studios Florida (which formerly served as home of Nickelodeon Studios until its closure in 2005). At the dawn of the cable television era, many regional sports networks", "score": 0, "title_score": 0, "passage_id": "836124"}, {"title": "Maikel Mesa", "text": "with Gimn\u00e0stic de Tarragona in the second tier. On 17 August 2018, Mesa was transferred to UD Las Palmas back in his native region, agreeing to a four-year contract. Maikel Mesa Maikel Mesa Pi\u00f1ero (born 4 June 1991), known simply as Maikel, is a Spanish footballer who plays for UD Las Palmas as a midfielder. Born in Santa Cruz de Tenerife, Canary Islands, Maikel finished his formation with hometown's CD Tenerife. He made his senior debuts with neighbouring CD Laguna in the 2010\u201311 season, in Tercera Divisi\u00f3n. In July 2012, Maikel signed a two-year contract with CA Osasuna, initially being", "score": 0, "title_score": 0, "passage_id": "17335215"}, {"title": "Eastmoreland Hospital", "text": "Eastmoreland Hospital Eastmoreland Hospital was a 100-bed medical center in Portland, Oregon, United States. Closed in January 2004 along with sister hospital Woodland Park, the facility was purchased by Reed College and torn down. Eastmoreland Hospital was established in the 1940s. In 1987, the hospital opened an osteopathic family practice residency for osteopathic physicians. Located in southeast Portland, the hospital was bought by Symphony Healthcare in 2002. By 2004 Symphony was bankrupt and sold the of land to Reed College for $5.2 million in February 2004. They also auctioned off everything inside the hospital that year. After acquiring the property,", "score": 0, "title_score": 0, "passage_id": "9956182"}, {"title": "Bobby Cruz", "text": "(Bobby Cruz sings for You), produced by Richie Ray. He also reached No.1 in the Latin Music Hit Charts with \"'Ya ni te Acuerdas\"\" (You don't even Remember). In 1974, they won first place in the Festival of Orchestras for the composition \"La Zafra\", whose lyrics describe the struggles of sugar cane workers in western Puerto Rico and elsewhere. Later that year Ray became a Christian convert. Initially Cruz refused to accept his friend's change, however two months' later he himself became a convert. As an experiment, they recorded what would become their most popular song, the salsa-merengue fusion \"Juan", "score": 0, "title_score": 0, "passage_id": "4339239"}, {"title": "Jan Mela", "text": "31, 2004 \u2013 a day after Mela's 16th birthday. On Christmas they ate typical Polish dishes like beetroot soup and they made a Christmas tree from snow. Jan Mela Jan \"Jasiek\" Mela (born December 30, 1988 in Gda\u0144sk) is a Polish explorer who, as a teenage double amputee, was the youngest person to reach the North Pole in 2004, and eight months later the South Pole. He created the Foundation \"Poza horyzonty\" (\"Beyond the horizons\"). The story began in 2002, when Jan, who comes from Malbork in Poland, was 13 years old. He was playing table tennis with some school", "score": 0, "title_score": 0, "passage_id": "10807686"}, {"title": "Territory of the Military Commander in Serbia", "text": "nationalities of the Kingdom of Yugoslavia have been mostly separated from Serbia and included within their respective ethnic states \u2013 e.g., the Croats, Bulgarians, Albanians, Hungarians, etc. Most of the Serbs however ended up outside the Nazi Serbian state, as they were forced to join other states. By the summer of 1942, is estimated that around 400,000 Serbs had been expelled or had fled from others parts of the Kingdom of Yugoslavia, and were living in the occupied territory. The autonomous area of the Banat was a multi-ethnic area with a total population of 640,000, of which 280,000 were Serbs,", "score": 0, "title_score": 0, "passage_id": "7717476"}, {"title": "Hasip Pektas", "text": "Bonn, Rome, Florence, Venice, Ortona, Lauzanne, Geneva, Nyon, Algeria, Nicosia, Sofia, Warsaw, Gliwice, Belgrade, Minsk, Moscow, Yaroslavl, Vienna, Wells, Salzburg, Prague, New York, Chicago, Edmonton, Helsinki, Beijing, Mexico City, San Miguel de Allende, Dolores Hidalgo, Guanajuato, Madrid, Londra, Porto, Lisbon, Ekaterinburg, Nizhny Tagil. He has organized 1st and 2nd International Ex-libris Competition in 2003-2007, 1st International Printmaking Biennial in 2008 and 33rd FISAE International Ex-libris Congress and Ex-libris Competition in 2010 in Istanbul. He is the President of Istanbul Ex-libris Society and Istanbul Ex-libris Museum. Awards: 2009 - Yaroslavl International Ex-libris Competition-Russia, \"Second Prize\". 2008 - 32nd International Ex-libris Biennial-China,", "score": 0, "title_score": 0, "passage_id": "8838046"}, {"title": "False sharing", "text": "caching system overhead required by true shared access of a resource. By far the most common usage of this term is in modern multiprocessor CPU caches, where memory is cached in lines of some small power of two word size (e.g., 64 aligned, contiguous bytes). If two processors operate on independent data in the same memory address region storable in a single line, the cache coherency mechanisms in the system may force the whole line across the bus or interconnect with every data write, forcing memory stalls in addition to wasting system bandwidth. False sharing is an inherent artifact of", "score": 0, "title_score": 0, "passage_id": "12100464"}, {"title": "South Sudan", "text": "star in the United States, where he plays for the Los Angeles Lakers; at the international level, he represents Great Britain. Other leading international basketball players from South Sudan include Manute Bol, Kueth Duany, Deng Gai, Ater Majok, and Thon Maker. The South Sudan national basketball team played its first match against the Uganda national basketball team on 10 July 2011 in Juba. One athlete from South Sudan, Guor Marial, competed in the 2012 Summer Olympics. Due to South Sudan not as yet possessing an official Olympics organization, and Marial not yet possessing American citizenship, he, along with three athletes", "score": 0, "title_score": 0, "passage_id": "15746608"}, {"title": "Papaver somniferum", "text": "that ban even having poppy seeds, not just growing the plants for them. The UAE has a long prison sentence for anyone possessing poppy seeds. The opium poppy, as its name indicates, is the principal source of opium, the dried latex produced by the seed pods. Opium contains a class of naturally occurring alkaloids known as opiates, that include morphine, thebaine, codeine, papaverine, noscapine and oripavine. The specific epithet \"somniferum\" means \"sleep-bringing\", referring to the sedative properties of some of these opiates. The opiate drugs are extracted from opium. The latex oozes from incisions made on the green seed pods", "score": 0, "title_score": 0, "passage_id": "3913104"}, {"title": "David Douglas Duncan", "text": "USS \"Missouri\" for the Japanese surrender. Duncan's wartime photographs were so impressive that after the war he was hired by \"Life\" to join its staff at the urging of J.R. Eyerman, \"Life\" chief photographer. During his time with \"Life\", Duncan covered many events, including the end of the British Raj in India and conflicts in Turkey, Eastern Europe, Africa, and the Middle East. Perhaps his most famous photographs were taken during the Korean War. He compiled many of these into a book, \"This Is War!\", (1951), with the proceeds going to widows and children of Marines who had been killed", "score": 0, "title_score": 0, "passage_id": "6956902"}, {"title": "Alex Otterlei", "text": "Alex Otterlei Alex Otterlei (born 17 September 1968 in Antwerp) is a multiple award-winning composer who writes evocative and often very filmic music for orchestra, concert band and other ensembles. Alongside, Otterlei has created music and sound effects for theatre, short films, video games, roleplaying games and art installations. His music appears on various albums. In the nineties Alex Otterlei pioneered the art of writing soundtracks for roleplaying games, resulting in popular rpg-soundtracks such as \u201cBattlethemes\u201d, \u201cArthur\u201d and \u201cWhere Evil Lurks\u201d. His Cthulhu-inspired orchestral soundtrack \u201cHorror on the Orient Express\u201d achieved international acclaim. Between 2003 and 2010 Alex Otterlei scored", "score": 0, "title_score": 0, "passage_id": "10991757"}, {"title": "Trimean", "text": "25%. This beneficial property has been described as follows: Despite its simplicity, the trimean is a remarkably efficient estimator of population mean. More precisely, for a large data set (over 100 points) from a symmetric population, the average of the 20th, 50th, and 80th percentile is the most efficient 3 point L-estimator, with 88% efficiency. For context, the best 1 point estimate by L-estimators is the median, with an efficiency of 64% or better (for all \"n\"), while using 2 points (for a large data set of over 100 points from a symmetric population), the most efficient estimate is the", "score": 0, "title_score": 0, "passage_id": "9833271"}, {"title": "EPC 2000", "text": "to filing in or for any member of the World Trade Organization (WTO), in addition to any state party to the Paris Convention for the Protection of Industrial Property. This amendment has been made to align the European Patent Convention with Article 2 of the TRIPS Agreement. Extensive changes were also made to the possibilities for the legal remedy of the failure to observe various time limits within the European patent system. Most particularly, the failure to pay various fees (filing fee, designation fee, search fee and examination fee) were, until the coming into force of the EPC 2000, excluded", "score": 0, "title_score": 0, "passage_id": "4200119"}, {"title": "Chloe Jasmine", "text": "was in the bottom two against boy band Stereo Kicks. Only Fernandez-Versini opted to save Chloe Jasmine, with the other three judges saving Stereo Kicks, meaning she finished in thirteenth place. On 29 January 2006, Chloe Jasmine appeared on \"Big Brother's Little Brother\" as part of Chantelle Houghton's fake band Kandy Floss, in a reunion special for the fourth series. After the performance, she introduced herself as \"CJ from Bournemouth\". Chloe Jasmine began modelling full-time aged 17, and has enjoyed an limited international career, appearing on some front covers during her short lived celebrity. She continues to perform internationally. In", "score": 0, "title_score": 0, "passage_id": "18307025"}, {"title": "Coroner", "text": "the Ministry of Justice appoints \"Inquirers into Sudden Deaths\" under the \"Code of Criminal Procedure\" to carryout an inquest into the death of a sudden, unexpected and suspicious nature. Some large cities such as Colombo and Kandy have a City Coroners' Court attached to the main city hospital, with a Coroner and Additional Coroner. In the United Kingdom a coroner is an independent judicial office holder, appointed and paid for by the relevant local authority. The Ministry of Justice, which is headed by the Lord Chancellor and Secretary of State for Justice has the responsibility for the coronial law and", "score": 0, "title_score": 0, "passage_id": "936650"}, {"title": "Gameplay of Eve Online", "text": "(\"low-sec\") systems in between. Surrounding these are regions with no security, or 0.0 (\"nullsec\" or \"zero-zero\"). Approximately 2,500 of these systems are known as J-Space or 'Wormhole Space.' Systems in J-Space lack stargates or other starship infrastructure, and are only connected to other systems via wormholes. Wormholes appear frequently but have a limited lifespan, so connections between these systems, and to New Eden, are unpredictable. The term J-Space comes from the fact that all(except one in particular which has the system name: Thera) has a J as a starting letter then random numbers in its system name. In some systems", "score": 0, "title_score": 0, "passage_id": "12508754"}, {"title": "Vitamin D deficiency", "text": "ng/mL (375 nmol/L) are usually found, although in some cases 25(OH)D levels may appear to be normal. Periodic measurement of serum calcium in individuals receiving large doses of vitamin D is recommended. The official recommendation from the United States Preventive Services Task Force is that for persons that do not fall within an at-risk population and are asymptomatic, there is not enough evidence to prove that there is any benefit in screening for vitamin D deficiency. In the United States and Canada as of 2016, the amount of vitamin D recommended is 400 IU per day for children, 600 IU", "score": 0, "title_score": 0, "passage_id": "12837575"}, {"title": "Yuvraj Singh", "text": "semifinal, he top-scored with 70 off 30 balls and also hit the longest six of the tournament ( off the bowling of Brett Lee). India won the match while Yuvraj was awarded another man of the match award. He was dismissed for 14 in the final against Pakistan as India went on to win by five runs and lift the trophy. All players of the victorious Indian team were given cash reward of 80 lakh by the BCCI while Yuvraj was rewarded with an additional 1 crore as well as a Porsche 911 by the BCCI vice president Lalit Modi.", "score": 0, "title_score": 0, "passage_id": "2570763"}, {"title": "Durham University Library", "text": "Design Award in 1988 and the online cataloguing of the library's stock beginning in 1990. In 1996 the Durham University Library also joined the Consortium of Research Libraries in the British Isles (now Research Libraries UK). In the succeeding years the University Library was expanded further with an extension of the main library in 1997 and also became the first library in 1998 to incorporate non-Roman scripts into its electronic catalogue system. Further in 2004, the Durham Cathedral Library became part of the University Library's management system for circulation and lending. A further major extension of the Main Library opened", "score": 0, "title_score": 0, "passage_id": "9368834"}, {"title": "Cycling in the Netherlands", "text": "In most cases, these bike paths are also physically separated from an adjacent footpath. Where protected bike paths exist, their use is in most cases obligatory for cyclists. Mopeds, mofas and the like are allowed and obliged to use them when their maximum speed is no more than 25 km/h (with a blue license plate) (though this has become controversial). When the maximum speed is 45 km/h (yellow license plate), mopeds are only allowed to use the cycle paths if that is indicated (mostly outside of the built-up area). Motorists are not allowed on bike paths, and to enforce this", "score": 0, "title_score": 0, "passage_id": "7453775"}, {"title": "African theatre of World War I", "text": "unopposed on 19 September. To forestall Belgian claims on the German colony, Smuts ordered Belgian forces back to Congo, leaving them as occupiers only in Rwanda and Burundi. The British were obliged to recall Belgian troops in 1917 and after this the Allies coordinated campaign plans. Major-General Jacob van Deventer began an offensive in July 1917, which by early autumn had pushed the Germans to the south. From 1917, Lettow-Vorbeck and the British fought a mutually costly battle at Mahiwa, with casualties and casualties. After the news of the battle reached Germany, Lettow-Vorbeck was promoted to \"Generalmajor\". British units forced", "score": 0, "title_score": 0, "passage_id": "7710219"}, {"title": "Saint-Lo\u0302", "text": "de Bayeux\". Thus, the current stud farm buildings date from 1884 (the first stone was laid on 11 June 1884), and the transfer was finished three years later. During World War I, five mares out of six were requisitioned, but no stallions. Grooms fought at the front, and German prisoners dug a pond. In 1939, the old stable housed the staff of the Haras de Strasbourg (40 stallions and staff) at the time of the German breakthrough. Then, in 1944, fifty horses were killed by the bombing and other stallions were stolen by German soldiers in flight. The old stud", "score": 0, "title_score": 0, "passage_id": "3243217"}, {"title": "Lost on the River: The New Basement Tapes", "text": "stated, \"Lost on the River\" recalls the spontaneity and sheer love of music-making of the original, but it\u2019s not hamstrung by reverence or caution. In \"Uncut\", Graeme Thomson wrote, \"Lost On The River\" is an album of good, sometimes excellent songs with a unique creation story which, in the end, adds little of substance to the narrative of perhaps the most mythologised recordings in history. As footnotes go, however, it\u2019s an entertaining, energised and often fascinating one. Among Bob Dylan\u2019s many cultural milestones, the legendary \"Basement Tapes\" \u2013 dozens of songs written and recorded by Dylan in 1967, backed by", "score": 0, "title_score": 0, "passage_id": "18228501"}, {"title": "The Physiology of Saint Petersburg", "text": "style of the introduction written by Belinsky suggested he was a de facto co-editor who took at least some part in compiling the material, Chukovsky argued. Among the works included into the collection were pieces by Dmitry Grigorovich, Ivan Panayev, Vladimir Dal, Evgeny Grebyonka as well as four articles by Vissarion Belinsky (\"The Introduction\", \"The Alexandrinsky Theatre\", \"Petersburg and Moscow\", \"The Literature of St. Petersburg\"), but Nekrasov's novelette was its centerpiece. Again, it caused trouble: censor Amply Otchkin found \"The Petersburg Corners\" \"outrageous and indecent,\" and Nekrasov had to wait almost a year before the offending item was finally censor-approved", "score": 0, "title_score": 0, "passage_id": "18425739"}, {"title": "Petri Kuljuntausta", "text": "the films \"Texas Scramble\", \"The Blow\", \"Days\", and \"Navigator\", all directed by Sami van Ingen. Kuljuntausta is the author of an 800-page history of Finnish electronic music, \"On/Off. Eetteri\u00e4\u00e4nist\u00e4 s\u00e4hk\u00f6musiikkiin\" (\"On/Off. From Ether Sounds To Electronic Music\") (Kiasma and Like Publishing). With the book was released a CD compilation (compiled, restored and produced by Kuljuntausta), which contains the first Finnish electronic compositions from the years 1958-1963 first time on the CD.http://www.like.fi In 2006 Kuljuntausta published his second book, \"\u00c4\u00e4nen eXtreme\" (\"eXtreme Sound\") (Like Publishing), on his own approach to music and sound. Together with the book was released a", "score": 0, "title_score": 0, "passage_id": "13842786"}, {"title": "Catholic Boy Scouts of Ireland", "text": "Boys' Brigade was viewed as an effective means of imprinting a Catholic ethos on the young men of Ireland. Father Farrell's brother, Father Tom Farrell, a curate in the Pro-Cathedral gave this fledgeling association the backing of the church and its resources. In 1927 the Catholic Boy Scouts of Ireland was officially founded, with a constitution drawn up and a headquarters from which the association could be organised, clothed and supplied. At an early stage John O'Neill, a motor works proprietor and former member of Seanad \u00c9ireann who had been associated with Fr. Ernest's Greystones venture, became Chief Scout. A", "score": 0, "title_score": 0, "passage_id": "4932243"}, {"title": "Kay Tse", "text": "released a new songs and greatest hits compilation, \"3/8\", in December 2007. The compilation's three new songs, \"3/8\", \"Zhong Wu Yan\" (\u937e\u7121\u8277) and \"The Retired Life of Wonder Woman\" (\u795e\u5947\u5973\u4fe0\u7684\u9000\u4f11\u751f\u6d3b) were all released as singles, with the latter two reaching number 1 on various charts. Tse explained that the album title, \"3/8\", refers to the eight stages of life, and the three-eights that she has travelled. This refers especially to her musical life, summing up her musical journey in the past three years. 2008 was a watershed moment for Tse's music career. Her first single of the year, \"17 Degrees\"", "score": 0, "title_score": 0, "passage_id": "6987828"}, {"title": "This Is Acid", "text": "the only producer and writer, plus Les Adams and keyboardist Mike Stevens for the remixes. This version would later be included in the Trax Records' 20th Anniversary compilation set in 2006. \"This Is Acid (A New Dance Craze)\" was Joshua's only hit single, but he did go on to be a Grammy Award-winning producer and remixer. \"This Is Acid\" was covered by German duo VooDoo & Serano off their album \"Radikal Techno 6\". The song can be heard in the video game \"\" on the in-game radio station . (on Maurice Joshua with Hot Hands Hula \u2013 \"I Gotta Big", "score": 0, "title_score": 0, "passage_id": "11826287"}, {"title": "Talisman (Alpha Flight)", "text": "of the Collective. She re-appeared in \"She-Hulk\" vol. 2 #16 (2007) when she tried to bypass a S.H.I.E.L.D. unit, as she had a cure that could end an attacking Wendigo's rampage. However it took a while to get past security and before Talisman could do anything, the She-Hulk and Wolverine had already taken him down. Over time, Elizabeth and her old teammate and mentor, Puck, became lovers. Talisman possesses vast supernatural powers as a result of her descent from forty generations of Sacree shamans, and was once described as \"a mortal channel through which the gods can fight\", as well", "score": 0, "title_score": 0, "passage_id": "7873468"}], "hard_negative_ctxs": [{"title": "Open and closed lakes", "text": "open lakes are usually fresh water: dissolved solids do not accumulate. Open lakes form in areas where precipitation is greater than evaporation. Because most of the world's water is found in areas of highly effective rainfall, most lakes are open lakes whose water eventually reaches the sea. For instance, the Great Lakes' water flows into the St. Lawrence River and eventually the Atlantic Ocean. Open lakes typically have stable levels which do not fluctuate because input is always matched by outflow to rivers downstream. If more water enters an open lake than was previously leaving it, then more water will", "score": 13.689648, "title_score": 0, "passage_id": "8204739"}, {"title": "Lake Michigan", "text": "shores of Lake Michigan include: Illinois Indiana Michigan Wisconsin The Saint Lawrence Seaway and Great Lakes Waterway opened the Great Lakes to ocean-going vessels. Wider ocean-going container ships do not fit through the locks on these routes, and thus shipping is limited on the lakes. Despite their vast size, large sections of the Great Lakes freeze in winter, interrupting most shipping. Some icebreakers ply the lakes. The Great Lakes are also connected by the Illinois Waterway to the Gulf of Mexico via the Illinois River (from Chicago) and the Mississippi River. An alternate track is via the Illinois River (from", "score": 13.592616, "title_score": 0, "passage_id": "239961"}, {"title": "Great Lakes", "text": "Lakes accessible to ocean-going vessels. However, shifts in shipping to wider ocean-going container ships\u2014which do not fit through the locks on these routes\u2014have limited container shipping on the lakes. Most Great Lakes trade is of bulk material, and bulk freighters of Seawaymax-size or less can move throughout the entire lakes and out to the Atlantic. Larger ships are confined to working in the lakes themselves. Only barges can access the Illinois Waterway system providing access to the Gulf of Mexico via the Mississippi River. Despite their vast size, large sections of the Great Lakes freeze over in winter, interrupting most", "score": 13.52596, "title_score": 0, "passage_id": "151969"}, {"title": "Ocean Champions", "text": "the introduction of The National Endowment for the Oceans, Coasts, and Great Lakes Act. This proposal is meant to preserve the ecosystems that coastal communities and economies depend on. Ocean Champions Ocean Champions, a 501(c)(4) environmental organization in the United States with a connected political action committee (Ocean Champions PAC), is the first national organization of its kind focused solely on oceans and ocean wildlife. Their goal is to create a political environment where protecting and restoring the oceans is a national government priority. They do this by helping to elect pro-ocean Congressional candidates and working to defeat the others.", "score": 12.760832, "title_score": 0, "passage_id": "12413188"}, {"title": "Geography of Mongolia", "text": "Asian Internal Drainage Basin, most often in the Great Lakes Depression, or at Hulun Lake, Ulaan Lake or Ulungur Lake. The few streams of southern Mongolia do not reach the sea but run into lakes or deserts. Mongolia's largest lake by area, Uvs Lake is in the Great Lakes Depression. Mongolia's largest lake by volume of water, Kh\u00f6vsg\u00f6l Nuur, drains via the Selenge river to the Arctic Ocean. One of the most easterly lakes of Mongolia, Hoh Nuur, at an elevation of 557 metres, is the lowest point in the country. In total, the lakes and rivers of Mongolia cover", "score": 12.275745, "title_score": 0, "passage_id": "254713"}, {"title": "Open and closed lakes", "text": "lake. Open and closed lakes Open and closed lakes refer to the major subdivisions of lakes - bodies of water surrounded by land. Exorheic, or open lakes drain into a river, or other body of water that ultimately drains into the ocean. Endorheic basins fall into the category of endorheic or closed lakes, wherein waters do not drain into the ocean, but are reduced by evaporation, and/or drain into the ground. An open lake is a lake where water constantly flows out under almost all climatic circumstances. Because water does not remain in an open lake for any length of", "score": 12.011218, "title_score": 0, "passage_id": "8204747"}, {"title": "Open and closed lakes", "text": "Open and closed lakes Open and closed lakes refer to the major subdivisions of lakes - bodies of water surrounded by land. Exorheic, or open lakes drain into a river, or other body of water that ultimately drains into the ocean. Endorheic basins fall into the category of endorheic or closed lakes, wherein waters do not drain into the ocean, but are reduced by evaporation, and/or drain into the ground. An open lake is a lake where water constantly flows out under almost all climatic circumstances. Because water does not remain in an open lake for any length of time,", "score": 12.011218, "title_score": 0, "passage_id": "8204738"}, {"title": "Lake surfing", "text": "to salty) and do not have to worry about the dangers from marine life (e.g. sharks, jellyfish, etc.) that ocean surfers may have to contend with. Popular lakes for surfing include the Great Lakes on the United States\u2013Canada border and Lake Tahoe on the California\u2013Nevada border. Strong storms, particularly in the winter and fall (at which time they may be referred to as a November Witch), can produce large waves on the Great Lakes in North America. During these surf seasons, there is often snow, shelf ice, and some ice in the water, making access difficult and conditions more dangerous.", "score": 11.694948, "title_score": 0, "passage_id": "9913715"}, {"title": "Lake freighter", "text": "largest major vessel to be wrecked on the Great Lakes. By way of the Saint Lawrence Seaway, smaller lakers have access to the Atlantic Ocean, and some ocean-going vessels have access to the lakes. Visiting ocean-going vessels are called \"salties\". Many modern ocean-going vessels are too large for the relatively small locks on the Saint Lawrence Seaway, so large salties cannot travel further inland than Montreal, Quebec. Because one of the Soo Locks is larger than any Seaway lock, salties that can pass through the Seaway may travel anywhere in the Great Lakes. Similarly, the largest lakers are confined to", "score": 11.279772, "title_score": 0, "passage_id": "4604756"}, {"title": "Whaling in Madagascar", "text": "off the continental coast, producing much needed data to increase predictability. Original technology of the buoy can date back thirty years, but with advancements in technology, the data collected nowadays do not just focus on the oceanic currents. Information gathered can reflect the wind patterns, temperatures, and certain densities of the ocean in specific areas, as all these factors are constantly fluctuating. These buoys are located all over the world, oceans and great lakes. The data collected goes to the National Data Buoy Center, where experts record and analyze the feedback. With relation to wave currents, the buoys use accelerometers", "score": 11.115592, "title_score": 0, "passage_id": "18795863"}, {"title": "Great Lakes Areas of Concern", "text": "the contiguous United States' Pacific and Atlantic coastlines combined. The lakes are a system of transport and shipping, as well as a place of recreation. An Area of Concern must have at least \"one beneficial use impairment which means that it has undergone a change in its chemical, physical, or biological integrity of a water body.\" These include: The Great Lakes Water Quality Agreement between the United States and Canada more specifically defines Areas of Concern as \"geographic areas that fail to meet the general or specific objectives of the agreement where such failure has caused or is likely to", "score": 10.828155, "title_score": 0, "passage_id": "7000319"}, {"title": "Omnibus Public Land Management Act of 2009", "text": "Survey. Title XII creates five new oceanic observation, research, and exploration programs at a cost of $2.6 billion, including programs for undersea research, undersea and coastal mapping, acidification research, and ocean conservation. One provision, the Integrated Coastal and Ocean Observation System Act, would \"establish a national integrated System of ocean, coastal, and Great Lakes observing systems, Federal and non-Federal components coordinated at the national level by the National Ocean Research Leadership Council\" in order to \"support national defense, marine commerce, navigation safety, weather, climate, and marine forecasting, energy siting and production, economic development, ecosystem-based marine, coastal, and Great Lakes resource", "score": 10.806433, "title_score": 0, "passage_id": "13035075"}, {"title": "Great Lakes", "text": "nations maintain coast guard vessels in the Great Lakes. During settlement, the Great Lakes and its rivers were the only practical means of moving people and freight. Barges from middle North America were able to reach the Atlantic Ocean from the Great Lakes when the Welland canal opened in 1824 and the later Erie Canal opened in 1825. By 1848, with the opening of the Illinois and Michigan Canal at Chicago, direct access to the Mississippi River was possible from the lakes. With these two canals an all-inland water route was provided between New York City and New Orleans. The", "score": 10.73987, "title_score": 0, "passage_id": "152007"}, {"title": "Great Lakes Waterway", "text": "lake freighters to travel from the system's saltwater outlet to its far interior. The Waterway has larger locks and deeper drafts than the lower Seaway, limiting large freighters to the four lakes upstream of the Welland Canal and Lake Ontario and similarly restricting passage beyond the canal by larger ocean vessels. The two waterways are often jointly and simply referred to as the \"St. Lawrence Seaway\", since the Great Lakes, together with the St. Lawrence River, comprise a single navigable body of freshwater linking the Atlantic Ocean to the continental interior. Shipping channels separate upbound traffic from downbound traffic. The", "score": 10.703835, "title_score": 0, "passage_id": "882103"}, {"title": "Ontario", "text": "River in Renfrew County. The Carolinian forest zone covers most of the southwestern region of the province. The temperate and fertile Great Lakes-Saint Lawrence Valley in the south is part of the Eastern Great Lakes lowland forests ecoregion where the forest has now been largely replaced by agriculture, industrial and urban development. A well-known geographic feature is Niagara Falls, part of the Niagara Escarpment. The Saint Lawrence Seaway allows navigation to and from the Atlantic Ocean as far inland as Thunder Bay in Northwestern Ontario. Northern Ontario occupies roughly 87 percent of the surface area of the province; conversely Southern", "score": 10.672957, "title_score": 0, "passage_id": "297988"}, {"title": "SS Aquarama", "text": "Company of Detroit. After being purchased, the ship was towed to Muskegon, Michigan where it was converted into a commercial passenger ship. The entire process took approximately two years to complete and cost nearly $8 million. The president of the Sand Products Company at the time, Max Mckee, wanted the \"Aquarama\" to be an ocean liner for the Great Lakes. The \"Aquarama\" began operation in 1956 by touring various Great Lakes ports. In 1957 the Michigan-Ohio Navigation Company, began service from Detroit to Cleveland, carrying automobiles and passengers. Once in service, the ship was able to transport its passengers and", "score": 10.672843, "title_score": 0, "passage_id": "12763158"}, {"title": "Atlantic Superior", "text": "free her from the shoal on 1 October 1982. In 1994 CSL shifted the vessel to the Pacific Ocean. In 1997 the vessel was moved back to the Atlantic Ocean, was renamed \"M.H. Baker III\", and started operating for the National Gypsum Company. CSL continued to own the vessel, and operated it on behalf of National Gypsum under a long term contract. She was renamed \"Atlantic Superior\" in 2003, and CSL operated her on the Great Lakes for several years. CSL operated her largely on the Atlantic Ocean again, making occasional voyages to the Great Lakes. Atlantic Superior Atlantic Superior", "score": 10.651412, "title_score": 0, "passage_id": "17405171"}, {"title": "Nature", "text": "importance to oceanography. The major oceanic divisions are defined in part by the continents, various archipelagos, and other criteria: these divisions are (in descending order of size) the Pacific Ocean, the Atlantic Ocean, the Indian Ocean, the Southern Ocean, and the Arctic Ocean. Smaller regions of the oceans are called seas, gulfs, bays and other names. There are also salt lakes, which are smaller bodies of landlocked saltwater that are not interconnected with the World Ocean. Two notable examples of salt lakes are the Aral Sea and the Great Salt Lake. A lake (from Latin \"lacus\") is a terrain feature", "score": 10.602922, "title_score": 0, "passage_id": "289896"}, {"title": "Chinook salmon", "text": "stocks might persist, but remain poorly studied. In 1967, the Michigan Department of Natural Resources planted Chinook in Lake Michigan and Lake Huron to control the alewife, an invasive species of nuisance fish from the Atlantic Ocean. Alewives then constituted 90% of the biota in these lakes. Coho salmon had been planted the year before and the program was a success. Chinook and Coho salmon thrived on the alewives and spawned in the lakes' tributaries. After this success, Chinook were planted in the other Great Lakes, where sport fishermen prize them for their aggressive behavior on the hook. The species", "score": 10.571837, "title_score": 0, "passage_id": "4165874"}, {"title": "Climate of Massachusetts", "text": "where there is a zone of conflict between polar and tropical air masses. The humid continental climate is marked by variable weather patterns and a large seasonal temperature variance. The seasonal temperature variance can be as great as , but is typically about to . The temperature difference between the warmest and coldest months increases as one moves further inland and away from the moderating influence of the ocean. Places with a hottest monthly temperature above and a coldest monthly temperature below , and which do not meet the criteria for an arid climate, are classified as continental. Beverly, Lynn,", "score": 10.562417, "title_score": 0, "passage_id": "12157617"}, {"title": "Joint Ocean Commission Initiative", "text": "these roundtables, the Joint Initiative brought together more than 250 local, state, tribal, and national leaders representing diverse industry, government, and nonprofit interests to identify creative solutions to critical ocean and coastal issues. Input from these roundtables is also reflected in the \"Ocean Action Agenda's\" suite of narrative stories, which highlight the importance of the oceans and Great Lakes to the lives of all Americans. In June 2013, the Joint Ocean Commission Initiative released \"Charting the Course: Securing the Future of America's Oceans.\" The report recommends actions for the Administration and Congress that prioritize areas where short-term progress can be", "score": 10.538318, "title_score": 0, "passage_id": "11602862"}, {"title": "Little Miami Railroad", "text": "second on June 2, 1836 in Xenia. The railroad was originally intended to run from Cincinnati to Springfield where it was expected meet the Mad River and Lake Erie Railroad, which was building south to Springfield from Sandusky on Lake Erie. At the time of incorporation, the National Road had not yet reached Columbus, and other than trails, the main shipping route for the Great Lakes region to the rest of the nation to the east of the Allegheny Mountains suitable for trade was via the rivers leading to the Great Lakes and from there, on to points east along", "score": 10.476202, "title_score": 0, "passage_id": "3568816"}, {"title": "East North Central states", "text": "is a large part of the Great Lakes region, although the latter also includes Minnesota, New York, Pennsylvania, and the Canadian province of Ontario. It has a low rate of population growth and the estimated population as of 2015 is 46,787,011. The region is part of the Great Lakes Megalopolis with an estimated 54 million people. The Great Lakes provide access to the Atlantic Ocean via the Great Lakes Waterway and St. Lawrence Seaway, or by the Erie Canal and the Hudson River or via the Gulf of Mexico from the Mississippi River and the Illinois Waterway. Chicago and Detroit,", "score": 10.474481, "title_score": 0, "passage_id": "3627734"}, {"title": "Great Lakes Airport", "text": "is equipped with Pilot Activated Lighting to facilitate 24-hour operations. Limited charter service is permitted to operate, however as a private venture, Great Lakes does not currently meet Civil Aviation Safety Authority standards as a licensed aerodrome and does not receive regular airline traffic. Great Lakes Airport Great Lakes Airport also known as Kepper Field is a private airport located approximately north of the town of Lakes Entrance in eastern Victoria, Australia. The airport was officially opened on 2 November 2003 and is capable of operating 24 hours. The airport facilities are designed to handle transport category aircraft, although there", "score": 10.463664, "title_score": 0, "passage_id": "17055279"}, {"title": "Geography of Minnesota", "text": "in elevation, much of the state is a gently rolling peneplain. Two continental divides meet in the northeastern part of Minnesota in rural Hibbing, forming a triple watershed. Precipitation can follow the Mississippi River south to the Gulf of Mexico, the St. Lawrence Seaway east to the Atlantic Ocean, or the Hudson Bay watershed to the Arctic Ocean. The state's nickname, \"The Land of 10,000 Lakes,\" is no exaggeration; there are 11,842 lakes over 10 acres in size. The Minnesota portion of Lake Superior is the largest at and deepest (at , 393 m) body of water in the state.", "score": 10.423736, "title_score": 0, "passage_id": "9111213"}, {"title": "Ship", "text": "Lakes. Lake freighters, also called lakers, are cargo vessels that ply the Great Lakes. The most well-known is , the latest major vessel to be wrecked on the Lakes. These vessels are traditionally called boats, not ships. Visiting ocean-going vessels are called \"salties.\" Because of their additional beam, very large salties are never seen inland of the Saint Lawrence Seaway. Because the smallest of the Soo Locks is larger than any Seaway lock, salties that can pass through the Seaway may travel anywhere in the Great Lakes. Because of their deeper draft, salties may accept partial loads on the Great", "score": 10.397566, "title_score": 0, "passage_id": "359957"}, {"title": "Great Lakes region", "text": "area urban planners call the Great Lakes Megalopolis, which has an estimated 59 million people. Chicago is emerging as the third megacity in the United States, after the New York City and Los Angeles metropolitan areas, with a metro population approaching ten million. Cities along the Great Lakes have access to the Atlantic Ocean through the St. Lawrence Seaway, making them international ports. The Palaeozoic strata, are but parts of a great area of similar strata hundreds of feet in thickness. These strata decline gently southward from the great upland of the Laurentian Highlands of eastern Canada. The visible upland", "score": 10.391198, "title_score": 0, "passage_id": "2532141"}, {"title": "Saint Lawrence Seaway", "text": "government of Mitchell Hepburn and the government of Quebec. In 1936, John C. Beukema, head of the Great Lakes Harbors Association and a member of the Great Lakes Tidewater Commission, was among a delegation of eight from the Great Lakes states to meet at the White House with US President Franklin D. Roosevelt to obtain his support for the seaway concept. Beukema and Saint Lawrence Seaway proponents were convinced that a nautical link would lead to development of the communities and economies of the Great Lakes region by permitting the passage of oceangoing ships. In this period, exports of grain,", "score": 10.362112, "title_score": 0, "passage_id": "370970"}, {"title": "Ron Johnson (Wisconsin politician)", "text": "didn't more eloquently express my sympathy for what Sen. McCain is going through.\" When asked about allowing additional drilling for oil in the continental US, including the Great Lakes if oil was to be found there, Johnson responded: \"We have to get the oil where it is, but we need to do it responsibly. We need to utilize American ingenuity and American technology to make sure we do it environmentally sensitively and safely.\" After criticism from the Feingold campaign, Johnson said in July 2010 that his answer did not mean he supported drilling in the Great Lakes. Johnson argues that", "score": 10.322667, "title_score": 0, "passage_id": "14735448"}, {"title": "United States rainfall climatology", "text": "ocean-effect snows are possible near Cape Cod. The Finger Lakes of New York are long enough for lake-effect precipitation. Lake-effect snow from the Finger Lakes occurs in upstate New York until those lakes freeze over. Bay-effect snows fall downwind of Delaware Bay, Chesapeake Bay, and Massachusetts Bay when the basic criteria are met. Ocean effect snows are possible downwind of the Gulf Stream across the Southeast. During the summer and early fall, mesoscale convective systems can move into the area from Canada and the Great Lakes. Tropical cyclones and their remains occasionally move into the region from the south and", "score": 10.321986, "title_score": 0, "passage_id": "9439906"}, {"title": "Ontario Highway 144", "text": "only gas station located on the highway north of Cartier. Just north of the Highway 560/Sultan Industrial Road intersection, the highway crosses the Laurentian Divide, the boundary between the Great Lakes and Arctic Ocean watersheds. North of this point, all streams and rivers flow north into Hudson Bay. A sign and a small picnic area mark the transition. The highway continues through isolated forests and curves east to meet Highway 661, a short spur serving the town of Gogama. The highway turns to the north and follows along the western side of Kenogamissi Lake for to Highway 101, just west", "score": 10.32015, "title_score": 0, "passage_id": "7003587"}, {"title": "National Ocean Service", "text": "authoritative source for accurate, reliable, and timely water-level and current measurements that support safe and efficient maritime commerce, sound coastal management, and recreation. The combined efforts, knowledge, and experience of CO-OPS's technicians, scientists, and engineers working to carry out a central mission has led to the development of a reliable center of expertise for coastal physical oceanography. CO-OPS is composed of four divisions: The Field Operations Division (FOD) operates and maintains all oceanographic and Great Lakes observing systems required to meet CO-OPS' mission objectives. The Division ensures the continuous operations of navigation and other real-time observing systems needed to support", "score": 10.319394, "title_score": 0, "passage_id": "3588425"}, {"title": "Continental Divide of the Americas", "text": "the watersheds that flow into the Great Lakes and Saint Lawrence River (ultimately into the Atlantic) from watersheds that flow to the Atlantic via the Missouri-Mississippi complex. Another secondary divide follows the Appalachian chain, which separates those streams and rivers that flow directly into the Atlantic Ocean from those that exit via the Mississippi River. Triple Divide Peak in Glacier National Park, Montana, is the point where two of the principal continental divides in North America converge, the primary Continental Divide and the Northern or Laurentian Divide. From this point, waters flow to the Pacific Ocean, the Atlantic Ocean via", "score": 10.290616, "title_score": 0, "passage_id": "1294259"}, {"title": "Chemocline", "text": "Chemocline A chemocline is a cline caused by a strong, vertical chemistry gradient within a body of water. A chemocline is analogous to a thermocline, the border at which warmer and cooler waters meet in an ocean, sea, lake, or other body of water. (In some cases, the thermocline and chemocline coincide.) Chemoclines most commonly occur where local conditions favor the formations of anoxic bottom water \u2014 deep water deficient in oxygen, where only anaerobic forms of life can exist. The Black Sea is the classic example of such a body, though similar bodies of water (classified as meromictic lakes)", "score": 10.286276, "title_score": 0, "passage_id": "10770545"}, {"title": "Americas", "text": "as the Salton Sea. The Columbia is a large river, long, in central western North America and is the most powerful river on the West Coast of the Americas. In the far northwest of North America, the Yukon drains much of the Alaskan peninsula and flows from parts of Yukon and the Northwest Territory to the Pacific. Draining to the Arctic Ocean of Canada, the Mackenzie River drains waters from the Arctic Great Lakes of Arctic Canada, as opposed to the Saint-Lawrence River that drains the Great Lakes of Southern Canada into the Atlantic Ocean. The Mackenzie River is the", "score": 10.238809, "title_score": 0, "passage_id": "407909"}, {"title": "Seawaymax", "text": "Seawaymax The term Seawaymax refers to vessels which are the maximum size that can fit through the canal locks of the St. Lawrence Seaway, linking the inland Great Lakes of North America with the Atlantic Ocean. Seawaymax vessels are in length, wide, and have a draft of and a height above the waterline of . A number of lake freighters larger than this size cruise the Great Lakes and cannot pass through to the Atlantic Ocean. The size of the locks limits the size of the ships which can pass and so limits the size of the cargoes they can", "score": 10.238729, "title_score": 0, "passage_id": "4607537"}, {"title": "Great Lakes Depression", "text": "and bar-headed goose (\"Anser indicus\"). Only a few individuals of great white pelican (\"Pelecanus onocrotalus\") remain in the Great Lakes Basin in Mongolia. They nest in catchment areas of rivers and lakes that have abundant fish and vegetation. Although the total number of fish species in the region is low, a large percentage of those that do occur are endemic or near-endemic, especially from the genera \"Oreoleuciscus\" (Altai osmans), \"Thymallus\" (graylings) and \"Triplophysa\" (a stone loach genus). Great Lakes Depression The Great Lakes Depression (, \"Ikh Nuuruudyn Khotgor\"), also called the Great Lakes' Hollow is a large semi-arid depression in", "score": 10.145581, "title_score": 0, "passage_id": "11545521"}, {"title": "Lessepsian migration", "text": "from the Western Atlantic, also invaded the Great Lakes by using the Welland Canal to bypass Niagara Falls. They colonized the Great Lakes and became abundant mostly in Lake Huron and Lake Michigan, reaching their peak abundance by the 1950s and 1980s. The white-eye bream (\"Ballerus sapa\") has invaded the Vistula River basin by migrating along the Dnieper\u2013Bug Canal in Belarus, which connects the Vistula drainage basin with that of the Dnieper River. A small number of species have used the Panama Canal to move from the Atlantic Ocean to the Pacific Ocean, and \"vice versa\". Six species of Atlantic", "score": 10.141054, "title_score": 0, "passage_id": "8398127"}, {"title": "Great Lakes Waterway", "text": "River between Huron and Erie. Usually, one or more U.S. Coast Guard icebreakers help keep the water passage open for part of the fall and early winter, although shipping usually ceases for two to three months thereafter. The Great Lakes Waterway is co-administered by the governments of Canada and the United States of America. The waterway allows passage from the Atlantic Ocean to the inland port of Duluth on Lake Superior, a distance of and to Chicago, on Lake Michigan, at . Together with the Saint Lawrence Seaway, the Waterway allows both ocean-going vessels and the ore, grain and coal-bearing", "score": 10.140955, "title_score": 0, "passage_id": "882102"}, {"title": "Krasnoyarsk Krai", "text": "the Kara Sea and Laptev Sea of the Arctic Ocean in the north. The krai is located in the basin of the Arctic Ocean; a great number of rivers that flow through the krai drain into it eventually. The main rivers of the krai are the Yenisei, and its tributaries (from south to north): the Kan, the Angara, the Podkamennaya Tunguska, and the Nizhnyaya Tunguska. There are also several thousand lakes in the krai. The largest lakes include Beloye, Belyo, Glubokoye, Itat, Khantayskoye, Labas, Lama, Pyasina, Taymyr, and Yessey. The rivers and lakes are rich with fish. The climate is", "score": 10.137741, "title_score": 0, "passage_id": "889944"}, {"title": "Algoma Equinox", "text": "renew their Great Lakes shipping fleet. The ship's keel was laid down on 21 April 2012 by Nantong Mingde Heavy Industries at their shipyard in Tongzhou, China. \"Algoma Equinox\" was launched on 24 December later that year and completed on 25 September 2013. The ship then crossed the Pacific Ocean and passed through the Panama Canal arriving at Port-Cartier, Quebec in September 2013. The vessel made its maiden voyage through the Great Lakes and Saint Lawrence Seaway in December 2013. \"Algoma Equinox\" primarily transports iron ore and grain in the Great Lakes and Saint Lawrence Seaway. Captain Ross Armstrong of", "score": 10.123072, "title_score": 0, "passage_id": "17383697"}, {"title": "Noosa River", "text": "Noosa River The Noosa River is a river situated in South East Queensland. The catchment starts in Wahpoonga Range near Mount Elliot in the coastal Great Sandy National Park and meanders south through a lakes district around Tewantin. Lakes situated on the river include Lake Cooloola, Lake Como, Lake Cootharaba, Lake Cooroibah and Lake Weyba. The catchment is mostly covered by sand dunes and has two major tributaries\u2014Kin Kin Creek and Teewah Creek. The Noosa River enters the Pacific Ocean at Noosa, where substantial residential development has encroached into areas previously occupied by the changing river path. The river is", "score": 10.106523, "title_score": 0, "passage_id": "11957113"}, {"title": "Sockeye salmon", "text": "Pacific salmon, feed extensively on zooplankton during both freshwater and saltwater life stages. They also tend to feed on small aquatic organisms such as shrimp. Insects are part of their diets at the juvenile stage. Sockeye salmon exhibit many different life histories with the majority being anadromous where the juvenile salmon migrate from freshwater lakes and streams to the ocean before returning as adults to their natal freshwater to spawn. Similar to most Pacific salmon, sockeye salmon are semelparous, meaning they die after spawning once. Some sockeye, called kokanee, do not migrate to the ocean and live their entire lives", "score": 10.103876, "title_score": 0, "passage_id": "4455248"}, {"title": "Southern Ocean", "text": "Interest in the potential exploitation of polymetallic nodules generated a great deal of activity among prospective mining consortia in the 1960s and 1970s. The icebergs that form each year around in the Southern Ocean hold enough fresh water to meet the needs of every person on Earth for several months. For several decades there have been proposals, none yet to be feasible or successful, to tow Southern Ocean icebergs to more arid northern regions (such as Australia) where they can be harvested. Icebergs can occur at any time of year throughout the ocean. Some may have drafts up to several", "score": 10.101551, "title_score": 0, "passage_id": "12774263"}, {"title": "Araruama", "text": "of the lakes, Araruama underwent a process of great tourist abandonment, but in recent years has growing and rapidly recovering, even more than in the past. Tourists are attracted by the beaches, especially the ocean, bathed by the crystalline waters of the Atlantic. Are also attractive plazas, parks, centers of gastronomy and entertainment centers. Araruama has the largest variety and diversity of beaches throughout the Lakes Region, both the lagoon (lapped by calm, warm waters of the Araruama Lagoon), the ocean (lapped by the blue waters of the icy Atlantic Ocean). The city's main beaches are: Hawk Beach, - calm", "score": 10.085362, "title_score": 0, "passage_id": "9484849"}, {"title": "Lake freighter", "text": "style and the second \"Algosoo\" was the final vessel designed this way. More recently built lakers, like CSL \"Niagara\", have a single large superstructure island at the stern. Vessel speeds are not as important on the Lakes as on the ocean. Ports are often closer together than in ocean trade, so cargo capacity is more important than speed. Lake vessels are designed with the greatest box coefficient to maximize the vessel's size in the many locks within the Great Lakes/St Lawrence Seaway system. Therefore, ship designers have favored bluff bows over streamlined bows. After World War II, several ocean freighters", "score": 10.085092, "title_score": 0, "passage_id": "4604766"}, {"title": "Crush's Coaster", "text": "\"Finding Nemo\", themed as Sydney Harbour, where Crush and his sea friends invite guests to climb aboard turtle shells for a ride through memorable scenes from the movie. The ride starts off with shells \"diving\" into the ocean. The first part of the attraction is a dark ride taking guests to the Great Barrier Reef, where they meet Nemo and Squirt, then to the darkness of the depths, which the sunlight cannot reach and where they encounter the voracious glowfish, and finally to the Sunken Submarine surrounded by an army of jellyfish where they meet the sharks and their chief,", "score": 10.077794, "title_score": 0, "passage_id": "10754829"}, {"title": "Saint Lawrence Lowlands", "text": "Saint Lawrence Lowlands The Great Lakes-St. Lawrence Lowlands is a bowl-shaped landform located near to the Great Lakes excluding Lake shed the land in the area downwards, depositing soil deeper into the earth, With this process no longer in effect, the deposited soil and land is currently rising up). The Great Lakes basin area effectively became a lake after the ice sheet melted. However, due to the presence of a deep fault line, all of this water was eventually siphoned into the ocean. Thus, the primary defining historic feature of the lowlands the presence of deep soils within the watershed", "score": 10.03078, "title_score": 0, "passage_id": "10319647"}, {"title": "History of Africa", "text": "spread from the Great Lakes to southern and east Africa. One early movement headed south to the upper Zambezi valley in the 2nd century BC. Then Bantu-speakers pushed westward to the savannahs of present-day Angola and eastward into Malawi, Zambia, and Zimbabwe in the 1st century AD. The second thrust from the Great Lakes was eastward, 2,000 years ago, expanding to the Indian Ocean coast, Kenya and Tanzania. The eastern group eventually met the southern migrants from the Great Lakes in Malawi, Zambia, and Zimbabwe. Both groups continued southward, with eastern groups continuing to Mozambique and reaching Maputo in the", "score": 10.030694, "title_score": 0, "passage_id": "187227"}, {"title": "Water in Michigan", "text": "The Great Lakes have been impaired by invasive species such as the sea lamprey, zebra mussel, quagga mussel, alewife, round goby, and Eurasian milfoil. Asian carp are a threat to enter the Great Lakes. The opening of the Welland Canal allowed the sea lamprey and alewife to bypass the natural barrier of Niagara Falls. Quagga, zebra mussels, and round gobies arrived in the ballast water of ocean-going ships that originated in Europe and Asia and discharged the water in the Great Lakes. Eurasian milfoil was intentionally introduced as an aquatic ornamental plant. Michigan has banned phosphorus in detergents and lawn", "score": 10.030578, "title_score": 0, "passage_id": "18620187"}, {"title": "Bulk carrier", "text": "between the European countries, the United States and Japan. Due to the economics of this trade, ocean bulk carriers became larger and more specialized. In this period, Great Lakes freighters increased in size, to maximize economies of scale, and self-unloaders became more common to cut turnaround time. The thousand-footers of the Great Lakes fleets, built in the 1970s, were among the longest ships afloat and in 1979, a record 214 million ton of bulk cargo were moved on the Great Lakes. Bulk carriers are segregated into six major size categories: small, handysize, handymax, panamax, capesize, and very large. Very large", "score": 10.030408, "title_score": 0, "passage_id": "4323990"}, {"title": "Discovery World", "text": "Discovery World Discovery World is a science and technology center located in Milwaukee, Wisconsin. The museum focuses on innovation and technology, as well as Great Lakes education and conservation. It contains interactive exhibits, the Reiman Aquarium, and two theaters, and is home to Wisconsin's official flagship, the \"Denis Sullivan\", a fully functional sailing vessel modeled after a 19th-century Great Lakes schooner. Many of the exhibits have to do with Milwaukee or the Great Lakes. The entire Great Lakes watershed, built to scale in the Great Lakes Future Exhibit, addresses freshwater issues, stewardship, and the human relationship with freshwater resources. Founded", "score": 10.003929, "title_score": 0, "passage_id": "2128718"}, {"title": "Refuge (ecology)", "text": "oceans' diel vertical migration, in which vast quantities of organisms hide in the lightless depths of the open ocean, arising after dark to consume phytoplankton. This allows them to avoid the large predatory fish of the open ocean, as these predators are primarily visual hunters and need light to effectively catch prey. Similar types of migration also occur in fresh water. For example, small European perch exhibit a daily horizontal migration in some lakes in Finland. During the day they move away from the vegetated areas where the predation threat in the clear water is great, into more turbid open", "score": 9.998326, "title_score": 0, "passage_id": "16337527"}, {"title": "Geography of Portugal", "text": "wildlife. In the Azores archipelago lakes were formed in the caldera of extinct volcanoes. Lagoa do Fogo and Lagoa das Sete Cidades (two small lakes connected by a narrow way) are the most famous lakes in S\u00e3o Miguel Island. Lagoons in the shores of the Atlantic exist. For instance, the Albufeira Lagoon and \u00d3bidos Lagoon (near Foz do Arelho, \u00d3bidos). In addition to continental Europe, Portugal consists of two Autonomous Regions in the Atlantic Ocean, consisting of the archipelagos of Madeira and Azores. Madeira is located on the African Tectonic Plate, and comprises the main island of Madeira, Porto Santo", "score": 9.987786, "title_score": 0, "passage_id": "676398"}, {"title": "Chinchaga River", "text": "Chinchaga River Chinchaga is a river in north-western Alberta. It is a tributary of the Hay River. Through the Hay River, its waters are carried to the Arctic Ocean via Great Slave Lake and Mackenzie River. The name Chinchaga is First Nations, and means \"Big Wood River\". Much of the Chinchaga watershed burned in 1950 during the Chinchaga fire. Chinchaga River originates in the Chinchaga Lakes, a series of small lakes in the muskeg of north-eastern British Columbia, at an elevation of 795 m. It flows east into Alberta, then continues north-east until west of Keg River, where it turns", "score": 9.980116, "title_score": 0, "passage_id": "8687480"}, {"title": "Great Eastern Highway", "text": "briefly through the north-eastern corner of Beelu National Park before coming to the rural community of Sawyers Valley, east of Mundaring. Beyond Sawyers Valley, Great Eastern Highway travels in a north-easterly direction, alongside and later within the northernmost part of the Jarrahdale State Forest. After , the highway reaches the Old Northam Road turnoff, which offers an alternative route through . The highway route bypasses the development by continuing east for to The Lakes, where it curves around to the north to meet Great Southern Highway, at the edge of the Perth Metropolitan Region. Great Eastern Highway continues past The", "score": 9.949191, "title_score": 0, "passage_id": "4544362"}, {"title": "Mackenzie River", "text": ". Six other lakes in the watershed cover more than , including the Williston Lake reservoir, the second-largest artificial lake in North America, on the Peace River. The river discharges more than of water each year, accounting for roughly 11% of the total river flow into the Arctic Ocean. The river is frozen for most of the year, with the ice typically breaking up by early to mid-May in the south, and late May-early June in the north. Ice breaks up earlier on the tributaries, sometimes causing ice jams and flooding where they meet the Mackenzie. In the middle of", "score": 9.895966, "title_score": 0, "passage_id": "1851300"}, {"title": "Geography of Northwest Territories", "text": "where the land is covered with soft woods and rich minerals. Two of the world's largest lakes (Great Slave and Great Bear) are located here. Great Slave Lake is the source of one of the world's longest rivers, the Mackenzie, that runs 1,120 miles (1,800 km) to its outlet into the Arctic Ocean. The Northwest Territories is the site of the northern end of Wood Buffalo National Park (est. 1922) and all of the Nahanni National Park (est. 1972). The Northwest Territories contains the Mackenzie dike swarm, which is the largest dike swarm known on Earth. Around 1,269-1,267 million years", "score": 9.859497, "title_score": 0, "passage_id": "9301198"}, {"title": "SS Carl D. Bradley", "text": "the title of \"Queen of the Lakes\" for 22 years as the longest and largest freighter on the Great Lakes. The Bradley Transportation's fleet of self-unloading ships was used to haul limestone from the Michigan Limestone quarry in Rogers City, Michigan. The \"Bradley\" was built to meet Michigan Limestone's lucrative contract with a cement firm in Gary, Indiana. By , she was longer than the second largest ship on the Great Lakes and her engine had almost twice the power of engines installed in most freighters. At , she was the longest freighter (and the largest self-unloader) on the lakes", "score": 9.838408, "title_score": 0, "passage_id": "6757360"}, {"title": "Endorheic basin", "text": "and wetlands. However, there is a class of water bodies that are located in closed or endorheic watersheds where the topography prevents their drainage to the oceans. These endorheic watersheds (containing water in rivers or lakes that form a balance of surface inflows, evaporation and seepage) are often called terminal lakes or sink lakes. Endorheic lakes are usually in the interior of a landmass, far from an ocean in areas of relatively low rainfall. Their watersheds are often confined by natural geologic land formations such as a mountain range, cutting off water egress to the ocean. The inland water flows", "score": 9.834335, "title_score": 0, "passage_id": "2117876"}, {"title": "Syracuse, New York", "text": "average snow of any metropolitan area in the United States. Syracuse usually wins the Golden Snowball Award, among Upstate cities. Its record so far is . The high snowfall is a result of the city receiving both heavy snow from the lake effect of nearby Lake Ontario (of the Great Lakes) and nor'easter snow from storms driven from the Atlantic Ocean. Snow most often falls in small (about ), almost daily doses, over a period of several days. Larger snowfalls do occur occasionally, and even more so in the northern suburbs. The Blizzard of 1993 was described as the Storm", "score": 9.827103, "title_score": 0, "passage_id": "386728"}, {"title": "Integrated Ocean Observing System", "text": "global ocean component is critical for providing data and information on basin scale forcings (e.g., ENSO events), as well as providing the data and information necessary to run coastal models (such as storm surge models). Alaska Ocean Observing System AOOS
Central California Ocean Observing System CeNCOOS
Great Lakes Observing System GLOS
Gulf of Maine Ocean Observing System GoMOOS
Gulf of Mexico Coastal Ocean Observing System GCOOS
Pacific Islands Ocean Observing System PacIOOS
Mid-Atlantic Coastal Ocean Observing Regional Association MACOORA
Northwest Association of Networked Ocean Observing Systems NANOOS
Southern California Coastal Ocean Observing", "score": 9.797311, "title_score": 0, "passage_id": "8694585"}, {"title": "Gun-Galuut Nature Reserve", "text": "Gun-Galuut Nature Reserve Gun-Galuut Nature Reserve, south-east of Ulaanbaatar, has a great diversity of ecosystems even though it has a comparatively small area. The complex of high mountains, steppes, rivers, lakes and wetlands are kept in their original condition. Visitors to Gun-Galuut see vast steppes seeming to meet the sky, the imposing mountains of Baits and Berkh, the homeland of rare creatures, Ikh-Gun and Ayaga lakes, a paradise of birds, Kherlen, the longest river of Mongolia and the Tsengiin Burd wetland, where water and wetland birds lay their eggs. Although limited research has been carried out on the reserve's fauna,", "score": 9.786109, "title_score": 0, "passage_id": "13223695"}, {"title": "Great Lakes Engineering Works", "text": "witness the event that marked the first new \"maximum seaway-size\" freighter on the Lakes. The \"Fitzgerald\" arguably became the most famous shipwreck in the history of Great Lakes shipping, made legendary by Gordon Lightfoot's popular ballad, the \"Wreck of the Edmund Fitzgerald\". The war years not only saw the construction but also the destruction of vessels. During World War I, the \"SS Vacuum\" (Hull # 99, Ecorse yard) commissioned by Ocean Freight Cargo Ship in 1912 as the \"SS Bayamon\" was sunk by German torpedo April 28, 1917 near Scotland. The \"SS Gratangen\" (Hull #156, Ashtabula) commissioned by Corona Coa", "score": 9.753016, "title_score": 0, "passage_id": "10954192"}, {"title": "Eastern Great Lakes and Hudson Lowlands (ecoregion)", "text": "system was developed by the United States Environmental Protection Agency. This region was glaciated during the last ice age, and contains prominent glacial features including till and drumlins, as well as the valleys containing the Finger Lakes. Part of the area was covered by Glacial Lake Iroquois, while regions further to the east were flooded under the Champlain Sea. At one point during the melting of the glaciers, the Great Lakes drained down the Hudson River to the Atlantic Ocean. This area is mostly temperate deciduous forest, dominated by trees including maple, beech and oak. Unlike forests further to the", "score": 9.752977, "title_score": 0, "passage_id": "16609326"}, {"title": "Mackinac Falls", "text": "new outlets, and the post-glacial rebound of this section of the Earth's crust, caused various freshwater lakes in this area to form, drain away, and re-form. During one of these periods, dated 10,000 years before the present, what is now the upper Great Lakes drained towards the Atlantic Ocean through a deep channel that passed eastward through Georgian Bay and what is now the small city of North Bay, Ontario. This channel was very efficient at draining water; the Great Lakes drainage basin was as big then as it is now, and collected a considerable amount of rainfall, but the", "score": 9.752645, "title_score": 0, "passage_id": "10882135"}, {"title": "Coastline of Tamil Nadu", "text": "of Mannar. The coastal corridor consists of 13 districts with 15 major ports and harbors, sandy beaches, lakes and river estuaries. The coastal stretch extends for from Pazhaverkadu of Thiruvallur district to Ezhudesam of Kanniyakumari district. Kanniyakumari, forms the southernmost tip of the Indian subcontinent where Indian Ocean, Bay of Bengal and Arabian Sea meet. Pamban Island forms part of Ramanathapuram district separating Gulf of Mannar and Palk strait with the Ram Setu connecting it with Sri Lanka. There are 13 districts that share the coastline namely Thiruvallur, Chennai, Kanchipuram, Villupuram, Cuddalore, Thiruvarur, Nagapattinam, Thanjavur, Pudukottai, Ramanathapuram, Thoothukudi, Tirunelveli and", "score": 9.751308, "title_score": 0, "passage_id": "18671641"}, {"title": "Borders of the oceans", "text": "defined the Southern Ocean as including the entire body of water between Antarctica and the south coasts of Australia and New Zealand. This delineation is basically the same as the original (first) edition of the IHO publication and effectively the same as the second edition. In the second edition, the Great Australian Bight was defined as the only geographical entity between the Australian coast and the Southern Ocean. Coastal maps of Tasmania and South Australia label the sea areas as \"Southern Ocean\", while Cape Leeuwin in Western Australia is described as the point where the Indian and Southern Oceans meet.", "score": 9.74589, "title_score": 0, "passage_id": "14964776"}, {"title": "Praia do Gunga", "text": "Praia do Gunga Praia do Gunga (Gunga's beach) is located 20 miles south of Macei\u00f3, Alagoas. It is considered as one of the most beautiful beaches in Brazil. The beach is surrounded by coconut trees and it positioned right between the Atlantic Ocean and Lagoa do Roteiro (Roteiro Lake). This position guarantees a unique color of the ocean surrounding the beach. It is bluer during the low tides and it turns greener during the high tides when the ocean waters meet the lake waters. This beach is part of the Roteiro region and you can get there by boat from", "score": 9.734447, "title_score": 0, "passage_id": "13177946"}, {"title": "Fishing Without Nets (2012 film)", "text": "(then 24 years old) convinced producing partners John Hibey (then 28) and Raphael Swann (then 24) to embark on a journey to do in-field research on the subject. What began as a trailer turned into a short film, written over a few weeks. In October 2012, on their first night on location in Mombasa, Kenya in the African Great Lakes region, the filmmakers were accused of trespassing by armed men in police and military uniforms. They were subsequently handcuffed and forced to swim out into the ocean. The cineastes were eventually released after paying a $150 bribe, the first of", "score": 9.683676, "title_score": 0, "passage_id": "16280966"}, {"title": "January 1998 North American ice storm", "text": "the Atlantic Ocean, which prevented these systems from moving further to the east, as most winter storms do when they pass over the Great Lakes\u2013St. Lawrence region. A series of surface low pressure systems passed in this atmospheric circulation between January 5 and January 10, 1998. For more than 80 hours, steady freezing rain and drizzle fell over an area of several thousand square miles of Eastern Ontario, including Ottawa and Kingston, an extensive area in southern Quebec, northern New York, and northern New England (including parts of Vermont, New Hampshire and Maine). Farther to the south, southern Ontario and", "score": 9.683189, "title_score": 0, "passage_id": "4464604"}, {"title": "Ruffe", "text": "North Sea, and is also found in Great Britain, parts of Scandinavia and some regions of the Arctic Ocean basin eastward to the dranage of the Kolyma. It has been introduced to parts of Western Europe (France, northern Italy) and Greece, as well as to the North American Great Lakes. In Eurasia, the ruffe diet mainly consists of zoobenthos: chironomids, small aquatic bugs and larvae, which are all found in the benthic zone of the water column. As far as researchers have been able to learn, it has kept the same diet in its transfer to the Great Lakes. The", "score": 9.658173, "title_score": 0, "passage_id": "2850257"}, {"title": "Great Basin Desert", "text": "Nevada that blocks moisture from the Pacific Ocean, while the Rocky Mountains create a barrier effect that restricts moisture from the Gulf of Mexico. Different locations in the desert have different amounts of precipitation, depending on the strength of these rain shadows. The environment is influenced by Pleistocene lakes that dried after the last ice age: Lake Lahontan and Lake Bonneville. Each of these lakes left different amounts of salinity and alkalinity. The Great Basin Desert is defined by its animals and plants, yet the boundaries are unclear. Scientists have different definitions of the Great Basin Desert, which are often", "score": 9.658173, "title_score": 0, "passage_id": "2277915"}, {"title": "Lake freighter", "text": "capable of hauling between 10,000 and 40,000 tons per trip depending on the individual boat. These smaller boats can serve smaller harbors around the Lakes which have irregular need for their services. The latest major vessel built for bulk cargoes on the lakes is the articulated tug/barge combo \"Ken Boothe Sr./Lakes Contender\". The 740-foot barge \"Lakes Contender\" and the tug \"Ken Boothe Sr.\" entered service in 2012. Because these vessels must traverse the locks of the Great Lakes Waterway, they all have features in common, and their appearance differs from similarly sized ocean-going freighters. For instance, they are narrower and", "score": 9.646478, "title_score": 0, "passage_id": "4604764"}, {"title": "The Great Lakes (album)", "text": "The Great Lakes (album) The Great Lakes is an album by Emm Gryner, \u201cwritten, recorded, mixed, printed, hand-stamped, stapled, embossed, cut, burned and packaged especially for you by me [Emm]\u201d. A creative companion to Gryner's \"The Great Lakes Living Room Tour\", the album was only available via pre-order directly from Dead Daisy Records, and did not appear in retail outlets. Each CD booklet is numbered in a limited sequence. Along with the disc itself, a purchaser also received a hand-written thank-you note from Gryner on her personal letterhead. The songs on the album do not represent a musical departure from", "score": 9.644298, "title_score": 0, "passage_id": "11624361"}, {"title": "Rhema FM Manning Great Lakes", "text": "area in the future. Rhema (\u03c1\u03b7\u03bc\u03b1) is the Ancient Greek word that describes the act of speaking. Rhema FM adopted the name because it is an affiliate of United Christian Broadcasters Australia , which required its stations to bear the Rhema name. Rhema FM changed its name from Radio Rhema to Rhema FM like many other UCB stations. The first to do so was Rhema FM Newcastle. Rhema FM is operated by volunteers and administered by the board of Manning Great Lakes Community Broadcasters Incorporated. Rhema FM Manning Great Lakes Rhema FM Manning Great Lakes is a Christian community radio", "score": 9.644181, "title_score": 0, "passage_id": "6380979"}, {"title": "Tethys Ocean", "text": "Tethys Ocean The Tethys Ocean (Ancient Greek: \u03a4\u03b7\u03b8\u03cd\u03c2), Tethys Sea or Neotethys was an ocean during much of the Mesozoic Era located between the ancient continents of Gondwana and Laurasia, before the opening of the Indian and Atlantic oceans during the Cretaceous Period. The name stems from the mythological Greek sea goddess Tethys, sister and consort of Oceanus, mother of the great rivers, lakes, and fountains of the world and of the Oceanid sea nymphs. The eastern part of the Tethys Ocean is sometimes referred to as Eastern Tethys. The western part of the Tethys Ocean is called Tethys Sea,", "score": 9.640903, "title_score": 0, "passage_id": "1298527"}, {"title": "Lakshmi Stuti", "text": "advised them to do Sagar Manthan with the help of the asuras. Sagar Manthan was performed with the help of Sri Vishnu himself, where he empowered the devas and the asuras, as well as the great serpent Vasuki, and also held the great mountain used to churn the ocean. From Sagar Manthan came many great wonders. Goddess Lakshmi appeared, and after being worshiped by the ocean personified and all the sacred rivers and Gods, took place in the heart of Lord Vishnu (Vaksha Sthal - chest). Then Amrit appeared and Lord Keshav tricked the asuras and devas and drank the", "score": 9.640503, "title_score": 0, "passage_id": "7971271"}, {"title": "Integrated Ocean Observing System", "text": "Integrated Ocean Observing System The Integrated Ocean Observing System (IOOS) is an organization of systems that routinely and continuously provides quality controlled data and information on current and future states of the oceans and Great Lakes from the global scale of ocean basins to local scales of coastal ecosystems. It is a multidisciplinary system designed to provide data in forms and at rates required by decision makers to address seven societal goals. IOOS is developing as a multi-scale system that incorporates two, interdependent components, a global ocean component, called the Global Ocean Observing System, with an emphasis on ocean-basin scale", "score": 9.634906, "title_score": 0, "passage_id": "8694583"}, {"title": "Russel Farnham", "text": "John Ledyard having twice failed to do so. Another account claims Farnham left with Hunt on the \"Pedler\" and was dropped off on the coast of Kamchatka on April 3, 1814 and, after arriving in St. Petersburg, instead left from Hamburg, Germany, whereupon he arrived to meet Astor in New York. Employed by Astor to oversee the business interests of American Fur Company in the Great Lakes region, he was arrested by the British as a spy during the War of 1812. Transported for trial to Prairie du Chien, several of his friends appealed to British authorities of his innocence", "score": 9.629921, "title_score": 0, "passage_id": "11936646"}, {"title": "Rift Valley lakes", "text": "gases seeping in.\" The Ethiopian Rift Valley lakes are the northernmost of the African Rift Valley lakes. In central Ethiopia, the Great Rift Valley splits the Ethiopian highlands into northern and southern halves, and the Ethiopian Rift Valley lakes occupy the floor of the rift valley between the two highlands. Most of the Ethiopian Rift Valley lakes do not have an outlet, and most are alkaline. Although the Ethiopian Rift Valley lakes are of great importance to Ethiopia's economy, as well as being essential to the survival of the local people, there were no intensive and extensive limnological studies undertaken", "score": 9.590902, "title_score": 0, "passage_id": "2865629"}, {"title": "Geography of New York (state)", "text": "the north. Additionally, New York touches the Atlantic Ocean to the southeast, and two of the Great Lakes: Lake Erie to the west and Lake Ontario to the northwest. New York is part of the Marcellus Shale, a gas-rich rock formation which also extends across Ohio, Pennsylvania and West Virginia. New York lies upon the portion of the Appalachian Mountains where the mountains generally assume the character of hills and finally sink to a level of the lowlands that surround the great depression filled by Lake Ontario and the St. Lawrence River. Three distinct mountain masses can be identified in", "score": 9.581774, "title_score": 0, "passage_id": "9689968"}, {"title": "Alki (boat)", "text": "firefighting authorities decided to permanently station a fireboat on the lakes, because it takes an hour for a fireboat to traverse the locks between the lakes and the Ocean. Alki was the vessel chosen. The boat has been taken out of service and was auctioned online beginning March 4, 2013. It was stipulated by the City ahead of time that the high bidder must meet certain requirements, including appropriate insurance and moorage. The vessel and sold for $71,000 on March 14, 2013, to an anonymous buyer, who subsequently backed out, when he or she found that new insurance for the", "score": 9.569494, "title_score": 0, "passage_id": "14133963"}, {"title": "Straight decker", "text": "Straight decker A straight decker is a ship built with its pilothouse forward and engines aft to provide a continuous hold in between. This design originated to meet the navigational demands on lake freighters on the U.S./Canadian Great Lakes routes. The term \"Straight Decker\" is commonly used upon the Great Lakes to denote a bulk/ore freighter which has not been equipped with self-unloading machinery. Straight Deckers are mainly owned by the Canadian fleets, such as Upper Lakes Shipping (ULS). One exception is the 730-foot U.S. lake freighter \"Edward L. Ryerson\" (nicknamed 'Fast Eddie' because of her 19-mph speed). Originally launched", "score": 9.558487, "title_score": 0, "passage_id": "4587264"}, {"title": "Quaternary glaciation", "text": "were invaded by the ocean. The Baltic Sea and the Great Lakes of North America were formed primarily in this way. The numerous lakes of the Canadian Shield, Sweden, and Finland are thought to have originated at least partly from glaciers' selective erosion of weathered bedrock. The climatic conditions that cause glaciation had an indirect effect on arid and semiarid regions far removed from the large ice sheets. The increased precipitation that fed the glaciers also increased the runoff of major rivers and intermittent streams, resulting in the growth and development of large pluvial lakes. Most pluvial lakes developed in", "score": 9.557624, "title_score": 0, "passage_id": "6911366"}, {"title": "Integrated Ocean Observing System", "text": "System SCCOOS
Southeast Coastal Ocean Observing Regional Association SECOORA
Caribbean Integrated Ocean Observing System CarICOOS Integrated Ocean Observing System The Integrated Ocean Observing System (IOOS) is an organization of systems that routinely and continuously provides quality controlled data and information on current and future states of the oceans and Great Lakes from the global scale of ocean basins to local scales of coastal ecosystems. It is a multidisciplinary system designed to provide data in forms and at rates required by decision makers to address seven societal goals. IOOS is developing as a multi-scale system that incorporates two, interdependent", "score": 9.547561, "title_score": 0, "passage_id": "8694586"}, {"title": "National Ocean Service", "text": "National Ocean Service The National Ocean Service (NOS), an office within the U.S. Department of Commerce National Oceanic and Atmospheric Administration (NOAA), is responsible for preserving and enhancing the nation\u2019s coastal resources and ecosystems along of shoreline bordering of coastal, Great Lakes, and ocean waters. Its mission is to \"provide science-based solutions through collaborative partnerships to address evolving economic, environmental, and social pressures on our oceans and coasts.\" NOS works closely with many partner agencies to ensure that ocean and coastal areas are safe, healthy, and productive. National Ocean Service scientists, natural resource managers, and specialists ensure safe and efficient", "score": 9.547561, "title_score": 0, "passage_id": "3588422"}, {"title": "Muggiaea kochii", "text": "warm temperate and subtropical Atlantic Ocean. It is present on the Gulf Coast of the United States where it often occurs in brackish water in bays. In the Mediterranean Sea it is often most abundant in the period April to June, but this varies from year to year. It also occurs in the Adriatic Sea where it was joined in the 1990s by the non-native \"M. atlantica\". This species was first detected in the marine lakes on the island of Mljet in southern Croatia in 2001, and since then, seems to have displaced \"M. kochii\" in the Great Lake there.", "score": 9.535574, "title_score": 0, "passage_id": "18718667"}, {"title": "Erie Canal", "text": "elevation of . Lake Erie has a mean surface elevation of . Erie Canal The Erie Canal is a canal in New York, United States that is part of the east\u2013west, cross-state route of the New York State Canal System (formerly known as the New York State Barge Canal). Originally, it ran from where Albany meets the Hudson River to where Buffalo meets Lake Erie. It was built to create a navigable water route from New York City and the Atlantic Ocean to the Great Lakes. When completed in 1825, it was the second longest canal in the world (after", "score": 9.535501, "title_score": 0, "passage_id": "128529"}, {"title": "Skimboarding", "text": "creeks, ponds, golf courses, puddles, or even wet grass. In the United States, flatland skim scenes have developed primarily in states not bordering the ocean. Flatland has also developed in British Columbia, Ontario, and along The Great Lakes. Australia (Melbourne and Parramatta), and Wellington, New Zealand also have dedicated flatland communities and riders. In Europe, the Flatland skim scene is growing fast, with the biggest group of skimboarders situated in Poland. Skimboarding is popular on many beaches where it is impossible to surf, for example, on Boa Viagem, Recife, Brazil, where surfing is banned due to the threat of shark", "score": 9.535148, "title_score": 0, "passage_id": "2563308"}, {"title": "National Ocean Service", "text": "- such as storms, wave heights, and sea level change. Such knowledge is needed for everything from retail to development planning. National Ocean Service The National Ocean Service (NOS), an office within the U.S. Department of Commerce National Oceanic and Atmospheric Administration (NOAA), is responsible for preserving and enhancing the nation\u2019s coastal resources and ecosystems along of shoreline bordering of coastal, Great Lakes, and ocean waters. Its mission is to \"provide science-based solutions through collaborative partnerships to address evolving economic, environmental, and social pressures on our oceans and coasts.\" NOS works closely with many partner agencies to ensure that ocean", "score": 9.525559, "title_score": 0, "passage_id": "3588444"}, {"title": "Great Lakes Avengers", "text": "up in court. While he claims that people simply \"didn't like them,\" he does comfort them by proclaiming that they could try to be in the spotlight again in a few years. Assisted the team by training them, but it is not clear if they joined. The GLA appeared in the climax of the \"JLA/Avengers\" miniseries, where they assisted in the defeat of Krona. In August 2009, \"TIME\" listed the Great Lakes Avengers among the \"Top 10 Oddest Marvel Characters\". Great Lakes Avengers The Great Lakes Avengers (also known as The Lightning Rods, The Great Lakes X-Men, The Great Lakes", "score": 9.473383, "title_score": 0, "passage_id": "5167798"}, {"title": "African Great Lakes", "text": "great biodiversity; 10% of the world's fish species live there. Countries in the African Great Lakes region (sometimes also called \"Greater Lakes region\") include Burundi, the Democratic Republic of the Congo, Kenya, Rwanda, Tanzania and Uganda. A conference was held on the lakes region in 2017 in Uganda. The Great Lakes area, where colonial era borders cut through ethnic groups, has in the last 20 years been a crucible of conflict that has launched multiple uprisings and invasions. The United Nations, the United States, and several European countries have special envoys or representatives to the Great Lakes region. On June", "score": 9.449593, "title_score": 0, "passage_id": "2767267"}, {"title": "Pororoca", "text": "river where its waters meet the Atlantic Ocean. During new and full moons, when the ocean tide is highest, water flows in from the Atlantic, rather than the other way around. The Amazon\u2019s flow reverses, the distance of which depends largely on the rainwater-generated outflow of the Amazon, and a water bulge speeds upstream often with great force, forming a tidal bore with an audible noise. The tidal phenomenon is best observed on biannual equinoxes in September and March during a spring tide). On an equinoctial spring tide, the Moon and Sun fall into direct alignment with the Earth, and", "score": 9.44572, "title_score": 0, "passage_id": "4095556"}, {"title": "Cape Delgado", "text": "Cape Delgado Cape Delgado () is the northernmost point of Mozambique and a coastal promontory on the country's border with Tanzania. It is the arc-shaped delta of the Rovuma River and was created from sediment deposited by the Rovuma as it empties into the Indian Ocean. It is sometimes identified with Prasum, the southernmost point of Africa known to the Roman geographers Marinus of Tyre and Ptolemy. In Ptolemy's \"Geography\", it marked the point where Africa turned eastward along a great unknown shore to meet southeast Asia and enclose the Indian Ocean. Medieval Islamic cartographers dispensed with the idea at", "score": 9.44572, "title_score": 0, "passage_id": "10841634"}]}, {"dataset": "nq_dev_psgs_w100", "question": "when does the new my hero academia movie come out", "answers": ["July 5 , 2018"], "positive_ctxs": [{"title": "My Hero Academia: Two Heroes", "text": "would be joining the cast as Melissa Shield and Katsuhisa Namase would play David Shield, both original characters. On June 11, 2018, \"Weekly Sh\u014dnen Jump\" announced that Rikiya Koyama had been cast as the film's villain, Wolfram. Masaki Suda performs the film's theme song , which was written and composed by Hiromu Akita of amazarashi. Funimation and Toho premiered the film at Anime Expo in Los Angeles on July 5, 2018, and it was later released in Japan on August 3 of that year. The first one million audience members to see the movie will receive a special book containing", "score": 1000, "title_score": 1, "passage_id": "20766125"}, {"title": "My Hero Academia", "text": "announced in the 44th issue of \"Weekly Sh\u014dnen Jump\" magazine of 2018. This was later confirmed with the airing of the final episode to season three on September 29, 2018. On December 19, 2018, the \"My Hero Academia\" website confirmed a release date of October 2019, along with a key visual. An anime film was announced in December 2017 and features an original story set after the manga's \"Final Exam\" arc. Titled , the film had its world premiere at Anime Expo on July 5, 2018, and the Japanese theatrical release began screening on August 3, 2018, with the staff", "score": 12.21437, "title_score": 0, "passage_id": "18433097"}, {"title": "My Hero Academia: Two Heroes", "text": "would be joining the cast as Melissa Shield and Katsuhisa Namase would play David Shield, both original characters. On June 11, 2018, \"Weekly Sh\u014dnen Jump\" announced that Rikiya Koyama had been cast as the film's villain, Wolfram. Masaki Suda performs the film's theme song , which was written and composed by Hiromu Akita of amazarashi. Funimation and Toho premiered the film at Anime Expo in Los Angeles on July 5, 2018, and it was later released in Japan on August 3 of that year. The first one million audience members to see the movie will receive a special book containing", "score": 11.710763, "title_score": 0, "passage_id": "20766125"}], "negative_ctxs": [{"title": "FS Class ALn 772", "text": "their production to war effort. The ALn 772 diesel engines were brand-new, powerful and compact, so they were mostly cannibalized to equip the Italian Navy's MAS torpedo boats. Fuel shortages and heavy bombing along the railroads made the remaining units useless for several years. OM could resume production only in 1948, thanks to the economic relief provided by the Marshall Plan and the huge efforts into bringing back the mangled national rail network to its pre-war standards. From 1948 to 1957 OM delivered 123 more units (two series, 3301-3341 and 3342-3423), demonstrating a slow but steady recovery of its factories", "score": 0, "title_score": 0, "passage_id": "8991770"}, {"title": "Martha Maxwell", "text": "frames over which to stretch the skins, rather than sewing the skins together and stuffing them, as most other taxidermists did. She also insisted that replica backgrounds portraying the animals' natural habitat were used. In 1876 Maxwell was asked to produce an exhibit for the Philadelphia Centennial Exhibition, the first official World's Fair. The Colorado commissioners agreed to pay for the packing and transportation of her specimens to and from Philadelphia and her living expenses while at the Centennial. To compensate Maxwell for her time, she would be allowed to keep the proceeds from the sale of any duplicate specimens", "score": 0, "title_score": 0, "passage_id": "12862130"}, {"title": "August Schmidhuber", "text": "Ulm in 1919, he signed up for 12 years' military service on 5 May. He was initially assigned to the \"Sch\u00fctzen Regiment\" (rifle regiment) Number 42. From 16 June 1919 until the beginning of October, Schmidhuber served with the 9th Company of his regiment and then spent nearly a year in 3 company. At the same time, beginning in May 1919 to mid-June, he also entered the ranks of the Freikorps, Major Franz Ritter von Epp. Schmidhuber then transferred to \"Gebirgs-J\u00e4ger-Regiment\" (mountain hunters) Number 19 and on 1 October 1922 was appointed to the rank of \"Gefreiter\" (private). He remained", "score": 0, "title_score": 0, "passage_id": "6912041"}, {"title": "Renato Peduzzi", "text": "Renato Peduzzi Renato Peduzzi (active 19th Century, died 1894) was an Italian sculptor. He was a resident of Milan, and competed in many exhibitions, obtaining prizes and accaim. In Parma, in 1870, he sent: a marble statuette of \"Springtime\"; to Milan, in 1872: a sculptural group for a fountain \"La pesca\" (Fishing); \"Il fanciullo che si trastulla con un cigno\"; to Naples in 1877: \"I primi salti\"; to Turin, in 1880: \"Conseguenze della guerra\"; \"Berenice\"; in 1883 at Milan: \"Portrait per monumento funebre\", and finally in Rome, in 1883: \"L'affarista a Trastullo infantile\". His \"Berenice\" was also exhibited at the", "score": 0, "title_score": 0, "passage_id": "17415142"}, {"title": "Diego Vela\u0301zquez", "text": "been effected since its creation; Luca Giordano, a contemporary Italian painter, referred to it as the \"theology of painting\", and in the eighteenth century the Englishman Thomas Lawrence cited it as the \"philosophy of art\", so decidedly capable of producing its desired effect. That effect has been variously interpreted; Dale Brown points out an interpretation that, in inserting within the work a faded portrait of the king and queen hanging on the back wall, Vel\u00e1zquez has ingeniously prognosticated the fall of the Spanish empire that was to gain momentum following his death. Another interpretation is that the portrait is in", "score": 0, "title_score": 0, "passage_id": "831439"}, {"title": "Galerius", "text": "of cultural influence in the region. Because the empire was able to sustain such constant warfare on so many fronts, it has been taken as a sign of the essential efficacy of the Diocletianic system and the goodwill of the army towards the tetrarchic enterprise. After the elevation of Constantius I and Galerius to the rank of \"Augustus\", two new Caesars were required to take their place. The two persons whom Galerius promoted to the rank of Caesar were very much his creatures, and he hoped to enhance his authority throughout the empire with their elevation. First was Maximinus Daia,", "score": 0, "title_score": 0, "passage_id": "809747"}, {"title": "Jackson Heights, Edmonton", "text": "surrounded by a number of residential neighbourhoods and light industrial subdivisions. Residential neighbourhoods are Kiniski Gardens to the south east and Greenview to the south west. At the neighbourhood's southwest point, it shares a short boundary with Minchau to the south. Industrial subdivisions are Roper Industrial to the north west, Pylypow Industrial to the north, and South East Industrial to the north east. Mill Woods Golf Course is located to the immediate west. Jackson Heights, Edmonton Jackson Heights is a residential neighbourhood in the Mill Woods area of Edmonton, Alberta, Canada. It is located in the Burnewood area of Mill", "score": 0, "title_score": 0, "passage_id": "10241447"}, {"title": "Lord Steppington", "text": "from mainstream critics, the album received a 79 score based on 11 reviews. David Jeffries of AllMusic gave the album four stars out of five, saying \"\"Lord Steppington\" is a niche album, but whenever a combination of 3rd Bass and Adult Swim is required, this one shows its pimp-hand with some dry, elevated humor.\" Luke Fox of \"Exclaim!\" gave the album an eight out of ten, saying \"Each participant is a double-threat in his own right, but [Alchemist] handles 13 of the LP's 14 dank instrumentals, and [Evidence]'s cadence hangs right alongside guest spots from respected wordsmiths Roc Marciano, Fashawn,", "score": 0, "title_score": 0, "passage_id": "14802989"}, {"title": "SYNCTHINK", "text": "SYNCTHINK SYNCTHINK, Inc. is a neuro-technology company with foundational intellectual property in eye-tracking metrics and devices. The Company was founded in 2008 and is headquartered in Palo Alto, California. SYNCTHINK was founded by Dr. Jam Ghajar, a clinical professor of neurosurgery at Stanford and founder and director of its Concussion and Brain Performance Center. He is also the founder of the Brain Trauma Foundation. Other notable board members include Alan Quasha, Ernie Santin, Kevin Quinn, and John van Merkensteijn. SyncThink sells its diagnostic device under the EYE-SYNC label. The EYE-SYNC is a high-performance device that uses virtual reality to assess", "score": 0, "title_score": 0, "passage_id": "16041007"}, {"title": "Internal Macedonian Revolutionary Organization", "text": "in Yugoslavia and Greece, which had long been a target of Bulgarian irredentism. IMRO was also active in organising Bulgarian militias in Italian and German occupation zones against Greek nationalist and communist groups as EAM-ELAS and EDES. With the help of Mihailov and Macedonian emigres in Sofia, several pro-Bulgarian armed detachments \"Ohrana\" were organised in the Kastoria, Florina and Edessa districts. These were led by Bulgarian officers originally from Greek Macedonia \u2013 Andon Kalchev and Georgi Dimchev. It was apparent that Mihailov had broader plans which envisaged the creation of a Macedonian state under a German control. It was also", "score": 0, "title_score": 0, "passage_id": "2684374"}, {"title": "Daniel Martin Varisco", "text": "to the anthropology of religion as a cultural system. It is argued that Geertz reflects philosophical reflections on Islam rather than his ethnographic observation of Muslims in Indonesia and Morocco. Gellner\u2019s use of Hume, Weber and Ibn Khaldun to explain the development of Islam is addressed by going back to these original sources. Varisco states that the authority of Gellner and Geertz as ethnographers who have \"been there\" supersedes incorporation of ethnographic data about real Muslims. Mernissi\u2019s\" Beyond the Veil\" is compared with early Orientalist and Arabic texts by tracing how each discusses the case of Muhammad\u2019s marriage to his", "score": 0, "title_score": 0, "passage_id": "12185823"}, {"title": "Sensors for arc welding", "text": "processing algorithms, information about the groove profile must also be provided in advance. This is carried out via teaching of templates, input of geometrical parameters or teach-in via test work pieces. A more comprehensive image processing for 2 and 3 D sensor systems requires normally a PC system for the evaluation; this is why commercially available PC interfaces are used for data exchange, uniform sensor interfaces do, however, not yet exist. In optical sensor systems, problems occur due to the operation principle through the scattered light of the open arc. Therefore, measuring in the working point directly is in most", "score": 0, "title_score": 0, "passage_id": "16912252"}, {"title": "Pauline Thornhill", "text": "Pauline Thornhill Pauline Thornhill is a Canadian television host and producer of Canadian Broadcasting Corporation\u2019s longest running regional television program, \"Land and Sea\". She has served in this capacity since 1993. Thornhill grew up in Bay L'Argent. She graduated in 1986 from the journalism program at the University of King's College. Thornhill started work as a journalist with CBC Television in St. John's, Newfoundland and Labrador on the news program . She became host and producer of CBC\u2019s \"Land and Sea\" in 1993. Thornhill received the 2004 Gracie Allen Award for the \"Land and Sea\" program \"Built from Scratch\", a", "score": 0, "title_score": 0, "passage_id": "19554512"}, {"title": "Bispehaven", "text": "now forced to move with new private properties for ownership and business to be built instead. Bispehaven Bispehaven (English: The Bishop Garden) is a housing project and the largest department of the housing cooperative \u00d8stjysk Bolig in Aarhus, Denmark. The project is located in the western suburb of Hasle and mostly consists of concrete apartments, but with small two-story attached town houses, too. The buildings were thoroughly renovated in 2004\u201307. Bispehaven has c. 2,500 inhabitants, with a high percentage of 1st- and 2nd-generation immigrants (approximately 70%). The area has been known as a so-called ghetto area, as one of many", "score": 0, "title_score": 0, "passage_id": "12337807"}, {"title": "April Scott (Home and Away)", "text": "self-medicate in order to deal with the stress caused by her HSC exams. Following her break up with Dexter, April decides to lose her virginity and ends up having a one-night stand with Heath Braxton (Daniel Ewing). On 23 May 2010, a reporter for \"The Daily Telegraph\" announced Fish had joined the cast of \"Home and Away\" as April Scott. Of the audition process, Fish told the official \"Home and Away\" website, \"It all happened so quickly. Monday was my first audition, I got a call back on Friday and by the next Monday I was sitting in the \"Home", "score": 0, "title_score": 0, "passage_id": "16076759"}, {"title": "Alexander Ostrovsky", "text": "a novelette, came out. Subtitled \"The Picture of the Moscow Life\" and telling the story of an impoverished nobleman who marries a rich merchant woman only to be horrified by her stinginess, it was not of Ostrovsky's best. By far more significant was his next one, \"A Prot\u00e9g\u00e9e of the Mistress\" (\u0412\u043e\u0441\u043f\u0438\u0442\u0430\u043d\u043d\u0438\u0446\u0430, 1859), continuing the 'degradation of the nobility' theme and written during his three weeks' visit to Saint Petersburg in 1858. It was banned from being staged on 23 October of the same year by Alexander Timashev after a censor in his report posed a question: \"Should we indeed", "score": 0, "title_score": 0, "passage_id": "4304528"}, {"title": "Capital gains tax in the United States", "text": "if there is a portion of the ownership period in which the home was not the principal residence of the taxpayer, spouse, or ex-spouse. Taxpayers can defer capital gains taxes to a future tax year using the following strategies: In 2011, President Barack Obama signed Executive Order 13531 establishing the National Commission on Fiscal Responsibility and Reform (the \"Simpson-Bowles Commission\") to identify \"policies to improve the fiscal situation in the medium term and to achieve fiscal sustainability over the long run\". The Commission's final report took the same approach as the 1986 reform: eliminate the preferential tax rate for long-term", "score": 0, "title_score": 0, "passage_id": "10369252"}, {"title": "Nathan Carruth", "text": "the firm name of F.S. & N. Carruth. They were associated in business for eight years, at the expiration of which time Nathan Carruth formed a co-partnership with his younger brother Charles, under the firm name of N. & C. Carruth. The latter concern had a most successful career in the drug business in Boston, covering a period of almost 40 years. The revolutionizing of traffic made possible by the advent of steam as a motive power found a most enthusiastic supporter in Nathan Carruth, who devoted much time, energy, and capital to the introduction of railway lines in Massachusetts", "score": 0, "title_score": 0, "passage_id": "12568780"}, {"title": "Prince-Bishopric of Mu\u0308nster", "text": "War. His successor, Maximilian Frederick of K\u00f6nigsegg-Rothenfels (1761\u201384), who was also Elector of Cologne, mostly left the administration of M\u00fcnster to a young cathedral canon, Franz Friedrich Wilhelm von F\u00fcrstenberg, during whose administration the principality attained unparalleled prosperity. However, at the election of an auxiliary bishop, von F\u00fcrstenberg was defeated by Maximilian Franz of Austria, who later succeeded to both the sees of M\u00fcnster and Cologne (1784\u20131801). Maximilian Franz fled Bonn in 1794 at the arrival of French revolutionary troops, who were to remain in permanent occupation of the part of the bishopric located on the left bank of the", "score": 0, "title_score": 0, "passage_id": "7512092"}, {"title": "James Madison University College of Business", "text": "Accreditation Commission of ABET. In 2014, \"USA Today\" (together with College Factual) ranked the James Madison University CIS program #2 in the United States. In 2013, JMU's undergraduate CIS program was ranked as the #10 information systems program in the country by Bloomberg Businessweek. In November 2008, TechRepublic, an online trade publication and social community for IT professionals owned by CBS Interactive, selected James Madison University's undergraduate Computer Information Systems program as one of the Top Ten Undergraduate Information Technology programs in the United States. There are three possible economics degrees at JMU: a B.B.A., B.A., and B.S. Also, students", "score": 0, "title_score": 0, "passage_id": "10633223"}, {"title": "Jim Mathers", "text": "Jim Mathers James Mathers (born May 5, 1955 in Los Angeles, California) is an American cinematographer and director of photography. He is the younger brother of former child television star Jerry Mathers of \"Leave It to Beaver\" fame. Mathers appeared under the name \"Jimmy Mathers\" in several TV and film productions between 1961 and 1968. His most memorable performance was in an episode of the TV comedy series \"Bewitched\" in 1964, when he played the role of an introverted boy who is afraid to play on the baseball team because of his overprotective mother. Mathers attended film school and held", "score": 0, "title_score": 0, "passage_id": "14674342"}, {"title": "Melanie Weisner", "text": "127th in the $10,000 No-Limit Hold-Em Championship Main Event, cashing for $49,108 and was the second-to-last woman standing in the event. She chip led the event during day 3 and 4, marking the first time a woman has been chip leader of the WSOP Main Event. At the 2012 World Poker Tour in Johannesburg, South Africa, Weisner claimed her first major title, taking down the $1,000 no-limit six-max event for $41,289, defeating former EPT champion Lucien Cohen heads-up. As of 2016, Weisner is ranked 38th on the Women's All Time tournament money list. Her total live tournament winnings exceed $775,000.", "score": 0, "title_score": 0, "passage_id": "14642246"}, {"title": "Lesjaverk", "text": "Ve\u00f8y. This change was made to provide the ironworkers at \"Lesjaverk\" with a convenient outlet for their products as well as providing them a market to purchases goods and food supplies such as stockfish and grain. \"Lesja jernverk\" (\"Lesja Iron Works\") or \"Lesjaverk\" formally operated from 1659 to 1812 in the municipality of Lesja, Norway, and was an important Dano-Norwegian iron works. When the forest was hewn, iron production was no longer economically viable at Lesjaverk, and the works were closed in 1812. The abandoned mines at Gruvlia, H\u00e5m\u00e5rfossen and Stellsteinberget, as well as the former iron smelter and charcoal", "score": 0, "title_score": 0, "passage_id": "4810822"}, {"title": "HMAS Shepparton (J248)", "text": "HMAS Shepparton (J248) HMAS \"Shepparton\" (J248/M248), named for the city of Shepparton, Victoria, was one of 60 \"Bathurst\"-class corvettes constructed during World War II, and one of 36 initially manned and commissioned solely by the Royal Australian Navy (RAN). Commissioned in early 1943, \"Shepparton\" was primarily employed as a survey vessel, tasked with updating Age of Sail-era charts and data for regions of New Guinea. The corvette was placed in reserve in 1946, and sold for scrap in 1958. In 1938, the Australian Commonwealth Naval Board (ACNB) identified the need for a general purpose 'local defence vessel' capable of both", "score": 0, "title_score": 0, "passage_id": "8579539"}, {"title": "Neotropical parrot", "text": "chief reasons for decline in parrot populations are habitat loss through deforestation by clear-cutting, burning, and flooding by construction of dams, capture for the pet trade, and introduction of non-native predators. The New World parrots are monophyletic, and have been geographically isolated for at least 30\u201355 million years by molecular dating methods. Though fairly few fossils of modern parrots are known, most of these are from tribe Arini of macaws and parakeets; the oldest are from 16 million years ago. They attest that modern genera were mostly distinct by the Pleistocene, a few million years ago. Neotropical parrots comprise at", "score": 0, "title_score": 0, "passage_id": "7874172"}, {"title": "Jerry Vlasak", "text": "him during an interview: \"I think violence is part of the struggle against oppression. If something bad happens to these people [animal researchers], it will discourage others. It is inevitable that violence will be used in the struggle and that it will be effective.\" Vlasak responded in a press release that the allegations were part of a smear campaign against him. He wrote: \"I was outraged by Jamie Doward's article in the \"Observer\" stating that I, a medical doctor who spends my entire life SAVING lives, is calling for or encouraging the assassination or killing of any being, human or", "score": 0, "title_score": 0, "passage_id": "4963745"}, {"title": "Hard Working Americans", "text": "Rafael, CA. It is composed entirely of cover songs from artists ranging from Randy Newman to Drivin N Cryin. The album was produced by Schools and Snider, and was mixed by John Keane. John Popper guests on harmonica. \"Hard Working Americans\" was released on January 21, 2014 on Thirty Tigers/Melvin Records In 2016, the band released their second album, \"Rest in Chaos,\" which unlike their previous record, is composed primarily of original songs written by the band themselves. The exception is the track \"The High Price of Inspiration,\" written by Guy Clark for his album \"My Favorite Picture of You\".", "score": 0, "title_score": 0, "passage_id": "17837343"}, {"title": "Natko Zrnc\u030cic\u0301-Dim", "text": "Natko Zrn\u010di\u0107-Dim Natko Zrn\u010di\u0107-Dim (; born 7 March 1986) is a World Cup alpine ski racer from Croatia. He won a bronze medal in super combined at the World Championships in 2009 at Val-d'Is\u00e8re, France, and is a member of SK Medve\u0161\u010dak. Born in Zagreb, SR Croatia, SFR Yugoslavia, Zrn\u010di\u0107-Dim's best World Cup result is second place in a super combined, achieved on 30 January 2011 in Chamonix, France. Compatriot Ivica Kosteli\u0107 won that race, his seventh of the month, and marked the first time that Croatians finished first and second in a World Cup race. Zrn\u010di\u0107-Dim incurred shoulder injury", "score": 0, "title_score": 0, "passage_id": "11588992"}, {"title": "Alexandros Kontostavlos", "text": "used to produce the first modern Greek currency, the \"Phoenix\". Under King Otto of Greece, he was elected several times to Parliament for Karystos, and served as Minister of Finance on 5 October 1855 \u2013 2 July 1856. From December 1856 to July 1856, he was Speaker of the Hellenic Parliament. He died in Athens in 1865. His son, Alexandros A. Kontostavlos, was a diplomat and politician. Alexandros Kontostavlos Alexandros Kontostavlos (; 1789, Chios \u2013 1865, Athens) was a Greek banker, magnate and politician. Konstavlos was born on the island of Chios in 1789 and descended from a noble family", "score": 0, "title_score": 0, "passage_id": "16285434"}, {"title": "Under Fire (film)", "text": "the murder of ABC reporter Bill Stewart and his translator Juan Espinoza by National Guard forces on June 20, 1979. ABC cameraman Jack Clark was shooting \"incidental\" footage, and caught the entire episode on tape. The footage was shown on national television in the United States and became a major international incident, undermining what remained of dictator Anastasio Somoza's support. The incident was the final straw for the Carter Administration's relationship with Somoza, whose regime fell on July 19. \"Under Fire\" opened October 21, 1983 in 816 theaters, earning $1,837,768 ($2,252 average per theater) its opening weekend. The film went", "score": 0, "title_score": 0, "passage_id": "7015951"}, {"title": "Richerenches", "text": "are for the maintenance of the church and parochial expenses. The village is crowded at this event, that takes place every third Sunday of January. In 1136, a local lord, Hugh of Bourbouton, gave the Knights Templar land at Richerenches. Two years later he gave even more, and the next day he took his vows as a Templar. He eventually became the Commander of the Templar commandery of Richerenches, which rose to be one of the most important Templar commanderies in Provence. The village is mentioned in Season 4 Episode 1 of the TV series \"Warehouse 13\" as being the", "score": 0, "title_score": 0, "passage_id": "6535198"}, {"title": "Vseti\u0301n", "text": "shortage of flats, shops, school premises and medical centres. Its orientation on the development of heavy industry and military production resulted in the closing down of a series of smaller industrial companies, mainly a knife-making plant and a plant producing glass beads used for the manufacture of electric cables. In connection with communist political development after February 1948, private trade successively declined. In the summer of 1949 Wallachian towns and municipalities organized an important local exhibition called Wallachia at Work. It took exactly 50 years to commemorate that exhibition by organizing a week-long event called Vala\u0161sk\u00e9 z\u00e1\u0159en\u00ed (Wallachian Shining). The", "score": 0, "title_score": 0, "passage_id": "6132390"}, {"title": "Colleen Doran", "text": "series Reign of the Zodiac. Her art also appeared in Amethyst, Princess of Gemworld #12, multiple issues of \"Who's Who in the DC Universe\" and \"Who's Who in the Legion of Superheroes\", \"Superman: Man of Steel Gallery\", \"Christmas with the DC Superheroes\", \"Captain Atom\", \"Star Trek\", and \"Hawkman Annual\". She did art for several \"Teen Titans\" and \"Wonder Woman\" projects. She illustrated portions of the \"\" and \"\" story arcs in Neil Gaiman's \"The Sandman\" series. The character Thessaly in Neil Gaiman's Sandman is based on Doran. Other Vertigo appearances include Shade, The Changing Man, Lucifer (DC Comics), Transmetropolitan and", "score": 0, "title_score": 0, "passage_id": "1901305"}, {"title": "Wilton Guerrero", "text": "released Guerrero following the 2002 season. A free agent once again, he opted to sign once more with the Reds. Guerrero did not make the Reds out of spring training, however, and spent the entire 2003 season with Triple-A Louisville. A free agent again for 2004, Guerrero signed with the Kansas City Royals. He spent most of 2004 with the Triple-A Omaha Royals, but did appear in 24 games with the Major League club, mostly as a backup, batting .219 with 1 RBI and a stolen base. He was signed by the St. Louis Cardinals to a minor league contract", "score": 0, "title_score": 0, "passage_id": "7313644"}, {"title": "National Humanities Center", "text": "understanding of topics and suggest approaches for more effective classroom teaching. Outreach \u2013 The National Humanities Center hosts a variety of public events, both to stimulate public awareness of humanities scholarship and to address special topics. In recent years, events have included appearances by A. S. Byatt, Michael Ignatieff, Oliver Sacks, Michael Pollan, Elaine Scarry, Wole Soyinka, Raymond Tallis, Wang Hui, and E. O. Wilson. From 2006 to 2009 the NHC sponsored an initiative exploring emerging issues in human self-understanding. This initiative, which involved fellowships, guest lectures, faculty seminars, and three annual conferences on \"The Human and The Humanities\" brought", "score": 0, "title_score": 0, "passage_id": "9085773"}, {"title": "Nucleus (video game)", "text": "a PSN release title it was before the introduction of the system. A patch has been released which offers a new mode of play, Nucleus+, which speeds up the gameplay, tweaks most of the existing levels (of which there are over 40), and introduces some new ones. Nucleus (video game) Nucleus is a downloadable game on the PlayStation Store, also known as Bacterius on the Japanese PSN. \"Nucleus\" is a puzzle-based shooting game with a dual stick control system similar to . Players are tasked with ridding a host body of a virus infestation, moving through the body's three main", "score": 0, "title_score": 0, "passage_id": "10063168"}, {"title": "Rascals and Robbers: The Secret Adventures of Tom Sawyer and Huckleberry Finn", "text": "Nixon and Anthony Michael Hall (co-starring as Huck). It was the first role for then-child actor Patrick Creadon who starred as Tom. The teleplay was written by Carlos Davis and David Taylor. It was directed by Dick Lowry and produced by his brother Hunt Lowry. The movie is set shortly after the ending of \"The Adventures of Tom Sawyer\" as St. Petersburg prepares for its 50th anniversary. Although billed as a sequel, the teleplay includes several elements of Mark Twain's \"The Adventures of Tom Sawyer\" and \"The Adventures of Huckleberry Finn\": Huckleberry bristling at the Widow Douglas' attempts to civilize", "score": 0, "title_score": 0, "passage_id": "20432623"}, {"title": "Darcy Richardson", "text": "ticket. Richardson was later a senior advisor to McCarthy's final presidential campaign, in which he ran as a candidate in the 1992 Democratic primaries. Richardson was a candidate for the lieutenant governor of Florida in 2010, running with independent gubernatorial candidate Farid Khavari. On October 21, 2011, Richardson filed as a candidate in the 2012 New Hampshire Democratic primary and became the first Democrat to file in a primary against President Barack Obama. A total of 14 Democrats, including Obama, eventually filed for the primary ballot. Richardson stated in an interview with the \"Los Angeles Times\" that he decided to", "score": 0, "title_score": 0, "passage_id": "16013218"}, {"title": "Scotland in the High Middle Ages", "text": "had fixed the boundaries with the Kingdom of the Scots with England and Norway respectively, its borders were close to the modern boundaries. After this time both Berwick and the Isle of Man were lost to England, and Orkney and Shetland were gained from Norway in the fifteenth century. The area that became Scotland in this period is divided by geology into five major regions: the Southern Uplands, Central Lowlands, the Highlands, the North-east coastal plain and the Islands. Some of these were further divided by mountains, major rivers and marshes. Most of these regions had strong cultural and economic", "score": 0, "title_score": 0, "passage_id": "7332969"}, {"title": "United States Football League", "text": "1985 game was originally to be played at the Pontiac Silverdome, but after the Panthers merged with Oakland, the game was awarded to Giants Stadium. Had there been a 1986 season, the championship game was scheduled to be played at Jacksonville's Gator Bowl Stadium on February 1, 1987. The USFL held its 1983, 1985 and 1986 college drafts at the Grand Hyatt Hotel in New York. The 1984 draft was held at the Roosevelt Hotel in New York. The 1983\u201385 drafts were in January while the 1986 draft was held in May. The USFL held an expansion draft in September", "score": 0, "title_score": 0, "passage_id": "749450"}, {"title": "Johannesburg", "text": "poor reputation. The suburbs to the south of the city are mainly blue collar neighbourhoods and situated closer to some townships. Greater Johannesburg consists of more than five hundred suburbs in an area covering more than . Although black Africans can be found throughout Johannesburg and its surrounding area, greater Johannesburg remains highly racially segregated. The suburbs to the west have in recent years floundered with the decline of the mining industry but have in some cases experienced some revival with properties being bought up by the local African middle class. The biggest sprawl lies to the east and north.", "score": 0, "title_score": 0, "passage_id": "695431"}, {"title": "Department of Extranormal Operations", "text": "they are responsible for the creation of fellow team member Menagerie, saying that \"These guys run a triple black alien immigration service that takes the galaxies' cast-offs an' turns them into weapons for the highest bidder. The West Nile glop in New York is one of theirs from the Microbio Division.\" The DEO was responsible for the \"orphanage\" seen in \"Young Justice\", in which Secret was kept, although a later conversation between Director Bones and Agent Chase suggested the conditions in which she was kept were not official policy. Another such orphanage was seen in the 1999 \"Titans\" series. The", "score": 0, "title_score": 0, "passage_id": "8013960"}, {"title": "Alec Douglas-Home", "text": "\"I went into politics because I felt that it was a form of public service and that as nearly a generation of politicians had been cut down in the first war those who had anything to give in the way of leadership ought to do so.\" His political thinking was influenced by that of Noel Skelton, a member of the Unionist party (as the Conservatives were called in Scotland between 1912 and 1965). Skelton advocated \"a property-owning democracy\", based on share-options for workers and industrial democracy. Dunglass was not persuaded by the socialist ideal of public ownership. He shared Skelton's", "score": 0, "title_score": 0, "passage_id": "1496259"}, {"title": "Dinosaur (Disney's Animal Kingdom)", "text": "Dinosaur (Disney's Animal Kingdom) Dinosaur, formerly known as Countdown to Extinction is a dark ride EMV attraction at Disney's Animal Kingdom in Walt Disney World, Lake Buena Vista, Florida. The ride features a turbulent journey through the late Cretaceous period, featuring prehistoric scenes populated with dinosaur audio-animatronics. Originally named \"Countdown to Extinction\" when the park opened in 1998, the ride's name was later changed to \"Dinosaur\" to promote the Disney animated film of the same name. However, the two dinosaurs most prominently featured in the ride have always been an \"Iguanodon\" and \"Carnotaurus\", which were both featured prominently in the", "score": 0, "title_score": 0, "passage_id": "6413916"}, {"title": "Gasoline", "text": "shouted: \"Hell, they send us food, when they know we can fight without food but not without oil.\" The solution had to wait for the repairing of the railroad lines and bridges so that the more efficient trains could replace the gasoline consuming truck convoys. In the 1950s oil refineries started to focus on high octane fuels, and then detergents were added to gasoline to clean the jets in carburetors. The 1970s witnessed greater attention to the environmental consequences of burning gasoline. These considerations led to the phasing out of TEL and its replacement by other antiknock compounds. Subsequently, low-sulfur", "score": 0, "title_score": 0, "passage_id": "318886"}, {"title": "Francisco de Sa\u0301 Carneiro", "text": "the party, only to be reelected to that office the next year. In the general election of late 1979, he led the Democratic Alliance, a coalition of his Social Democratic Party, the right-wing Democratic and Social Centre Party, and two smaller parties, to victory. The Alliance polled 45.2 percent of the popular vote and gained 128 of the 250 seats in the Assembly of the Republic; 75 of these were from the PSD. President Ant\u00f3nio Ramalho Eanes subsequently called on him to form a government on 3 January 1980, and formed Portugal's first majority government since the Carnation Revolution of", "score": 0, "title_score": 0, "passage_id": "3547275"}, {"title": "IBM India", "text": "economy was liberalized in 1991, relaxing FDI norms. IBM re-entered India in 1992 with a Tata joint-venture, named Tata Information Systems Ltd. Its business interest in India was still focused on product sales. IBM India has now grown to an extent where it poses a stiff challenge to homegrown Software companies of India in IT global delivery and manpower attraction/retention. It now operates the following business lines from India which contributes to worldwide IBM in a global delivery framework: India Software Labs (ISL), India Research Lab (IRL), Linux Technology Center, Global Business Services(GBS), Global Technology Services (GTS) formerly known as", "score": 0, "title_score": 0, "passage_id": "7777827"}, {"title": "Blackberry Blossom (tune)", "text": "the earlier version, is the account of Andrew Kuntz to the effect that \"Betty Vornbrock and others have noted a similarity between 'Garfield\u2019s Blackberry Blossom' and the West Virginia tune 'Yew Piney Mountain', a variant ... also played by Kentucky fiddlers J.P. Fraley and Santford Kelly\". Alan Snyder gives an alternate name of \"Strawberry Beds\". Although the tune is closely associated with the old time/ bluegrass traditions of the United States, it enjoys the distinction of being frequently played by traditional Irish musicians. This is a partial list of covers by Irish musicians and bands. According to Devon Wells, \"Blackberry", "score": 0, "title_score": 0, "passage_id": "15776990"}, {"title": "ASVOFF", "text": "a second edition of \"You Wear It Well\" in 2007. Besides the work of Diane Pernet and EGR, You Wear It Well featured video creations from Maison Martin Margiela, Nick Knight/Alexander McQueen, Jeremy Scott, Bernhard Willhelm, Marcelo Krasilcic, Jean-Charles de Castelbajac, NOKI and Ruben Toledo. In November 2007 Diane Pernet also co-curated the NOOVO fashion and photography festival in Santiago de Compostela. \"You Wear It Well\" was dissolved in 2007 when Pernet with the support of her current producer, David Herman, took the festival from a one-day program to a three-day program and to make it an extension of the", "score": 0, "title_score": 0, "passage_id": "15170393"}, {"title": "BAPS Shri Swaminarayan Mandir Chicago", "text": "where devotees sing the glory of God while a lighted wick is circulated before the murtis. After mangala aarti, the deities are bathed and offered food and garments that vary with the season. After the murtis have been adorned with garments, shangaar aarti is performed. At midday, rajabhoga aarti is performed and food is offered to the murtis. Food that has been offered to the deities is considered sanctified, and is distributed to devotees as holy prasadam. In the evening, sandhya aarti is performed before offering food to the murtis. The sadhus put the murtis to rest by adorning them", "score": 0, "title_score": 0, "passage_id": "8886130"}], "hard_negative_ctxs": [{"title": "My Hero Academia: Two Heroes", "text": "The \"Plus Ultra\" limited edition will contain an original video animation, adapting the \"All Might: Rising\" one-shot manga by Horikoshi. Funimation will release the movie on Blu-ray and DVD March 26, 2019. During the opening weekend, \"My Hero Academia: Two Heroes\" ranked 4th at the Japanese box office, grossing () in three days. The film later dropped to 7th in its second weekend, and later fell below the top 10 in its third weekend. The film sold its one millionth ticket during its fourth week. In the Japanese market, the film grossed a total of () revealed in 42nd issue", "score": 14.574574, "title_score": 0, "passage_id": "20766129"}, {"title": "My Hero Academia", "text": "season of \"My Hero Academia\" delivers thirteen episodes of fantastic action, elevated by a heartfelt story that's wrapped around a core cast of memorable and relatable characters.\" Osborn went on to state that the villains were underdeveloped. The manga won the Sugoi Japan Award in 2017. It also won the \"Japan Expo Awards\" in the same year. Due to the popularity of the series, characters of \"My Hero Academia\" were used to promote the Marvel Studios film \"\". My Hero Academia The manga was adapted into an anime television series by Bones. Its first season aired in Japan from April", "score": 14.399641, "title_score": 0, "passage_id": "18433101"}, {"title": "My Hero Academia: Two Heroes", "text": "praising the film as enjoyable, though criticizing the lack of development within the world of \"My Hero Academia\". A one-shot spin-off manga of \"My Hero Academia\", focusing on one of the film's original characters, Melissa Shield, was published in 2018's 35th issue of Shueisha's \"Weekly Sh\u014dnen Jump\" magazine on July 30, 2018. The manga is illustrated by Y\u014dk\u014d Akiyama. My Hero Academia: Two Heroes All Might is invited to a summer trip at \"I-Island\", a man-made island where the top scientists of the world reside and perform research on Quirks, superpowers that 80% of the world's population has. He takes", "score": 14.318317, "title_score": 0, "passage_id": "20766132"}, {"title": "Big Hero 6: The Series", "text": "villains. Hiro also faces academic challenges and social trials as the new prodigy at San Fransokyo Institute of Technology (SFIT). The show slightly retcons the ending of the movie. Among the differences are Aunt Cass knowing about Baymax, the Big Hero 6's team identities still being secret from the public, and Hiro attending SFIT as if everything is back to normal (and though a building is erected after Tadashi, Hiro does not receive a grant from the Institute). Hiro also does not come up with the name \"Big Hero 6\" like it is implied at the end of the movie,", "score": 13.847474, "title_score": 0, "passage_id": "19377319"}, {"title": "My Hero Academia", "text": "and cast from the anime series returning to reprise their roles. Funimation announced that they would release the film theatrically in the United States and Canada from September 25, 2018 to October 2, 2018. In October 2018, Legendary Entertainment acquired the rights to produce a live action adaptation of \"My Hero Academia\". A video game based on the anime, \"My Hero Academia: Battle for All\", was announced in November 2015. The game was developed by Dimps and published by Bandai Namco Entertainment for the Nintendo 3DS handheld game console, where it released in Japan on May 19, 2016. A second", "score": 13.589116, "title_score": 0, "passage_id": "18433098"}, {"title": "My Hero Academia", "text": "place on the weekly Oricon manga chart with 71,575 copies sold. It sold out almost immediately on its first printing. Volume 2 reached the 6th place, with 167,531 copies and, by January 18, 2015, had sold 205,179 copies. As of March 2017, there were over 10 million copies of \"My Hero Academia\" in circulation. As of August 2018, the manga had over 16 million copies in print. The story has been noted to take inspiration from elements in superhero comics, such as the aesthetics of its characters. Alex Osborn of IGN gave the anime series positive marks, saying \"The first", "score": 13.556466, "title_score": 0, "passage_id": "18433100"}, {"title": "My Hero Academia", "text": "Viz Media's Weekly Sh\u014dnen Jump. As of August 7, 2018, 14 volumes have been released. A spin-off series, \"My Hero Academia: Vigilantes\", began being published by \"Weekly Sh\u014dnen Jump\" in 2017. The series is licensed for the English language release in North America by Viz Media. The first volume was released in English on July 3, 2018. On October 29, 2015, the series' official Twitter announced that \"My Hero Academia\" would receive an anime adaptation produced by Studio Bones. With the anime announced, Toho registered the domain name \"heroaca.com\" as the anime's website. The anime is directed by Kenji Nagasaki,", "score": 13.492804, "title_score": 0, "passage_id": "18433093"}, {"title": "Porno Graffitti", "text": "\"\". Their single \"Oh! Rival\" is part of the soundtrack for the new Detective Conan film. Their 2016 single \"THE DAY\" was the first opening theme of the anime series My Hero Academia. They also provided the opening song \"Montage\" to the anime Puzzle & Dragons X. Shind\u014d appeared in the movie \"Road 88: Deai-michi Shikoku e\" (\u30ed\u30fc\u30c988 \u51fa\u4f1a\u3044\u8def\u3001\u56db\u56fd\u3078) in 2003 (road show in 2004). He played a gangster by the name of Bessho (\u5225\u6240). This is the first and only movie in which he has appeared. Porno Graffitti , also known as are a Japanese rock band from Onomichi", "score": 13.480783, "title_score": 0, "passage_id": "7915527"}, {"title": "My Hero Academia: Two Heroes", "text": "of Shueisha's Weekly Shonen Jump magazine.. According to Box Office Mojo, \"My Hero Academia : Two Heroes\" grossed total of () and ranked as 46th highest grossing Japan film of 2018. In North America, the film was a success, ranking third in the market at its highest despite its limited release. The film outperformed other films in the top 10, earning per screen more than other films, and grossed $5,754,556 in box office revenue during its theatrical run. The film also grossed US$204,835 in Australia and New Zealand as of November 18, 2018. In Hong Kong, the film grossed HK$870,000", "score": 13.099202, "title_score": 0, "passage_id": "20766130"}, {"title": "My Hero 2", "text": "be also involved with the triads, to help him get the information he needed for his comics. How did it turn out? Did it help him to succeed? My Hero 2 My Hero 2 (\u4e00\u672c\u6f2b\u756b\u95d6\u5929\u6daf2\u4e4b\u5999\u60f3\u5929\u958b) is a 1993 Hong Kong comedy film directed by Joe Chu, starring Dicky Cheung and Ng Man Tat. Despite the title, it is not a sequel to the movie \"\"My Hero (1990)\"\", starring Stephen Chow. The movie is about Cheung Kin-Hong's (Dicky Cheung) ploy to get a good story involving triads for his comics. He is a comics artist and writer who has not been", "score": 12.743241, "title_score": 0, "passage_id": "9667361"}, {"title": "My Hero Academia", "text": ") are the norm, Izuku Midoriya has dreams of one day becoming a Hero, despite being bullied by his classmates for not having a Quirk. After being the only one to try and save his childhood friend Katsuki Bakugo from a villain, All Might, the world's greatest Hero, bestows upon him his own Quirk \"One For All\". The story follows Izuku's entrance into , a school that cultivates the next generation of superheroes. As Izuku and his new friends try to balance their Hero training with ordinary school duties, they must face new challenges including the League of Villains, an", "score": 12.359623, "title_score": 0, "passage_id": "18433091"}, {"title": "My Hero Academia", "text": "evil organization established by All Might's archenemy, All For One, to destroy all Heroes and take control of society. \"My Hero Academia\" is a Japanese manga series written and illustrated by K\u014dhei Horikoshi. It began its serialization in the manga magazine \"Weekly Sh\u014dnen Jump\" in July 2014. As of September 4, 2018, the series been collected into twenty \"tank\u014dbon\" volumes. The series is licensed for the English language release in North America by Viz Media, who published the first volume on August 4, 2015. As the series is published in Japan, it is also released simultaneously in English digitally by", "score": 12.214239, "title_score": 0, "passage_id": "18433092"}, {"title": "My Hero Academia", "text": "My Hero Academia The manga was adapted into an anime television series by Bones. Its first season aired in Japan from April 3 to June 26, 2016, followed by a second season from April 1 to September 30, 2017, then a third season from April 7 to September 29, 2018, and an animated film titled \"\" was released on August 3 of that year. The series has been licensed for English-language release by Viz Media and began serialization in their weekly digital manga anthology \"Weekly Shonen Jump\" on February 9, 2015. In a world where people with superpowers (known as", "score": 12.213431, "title_score": 0, "passage_id": "18433090"}, {"title": "20 Dates", "text": "20 Dates 20 Dates is a 1998 American mockumentary film. Myles Berkowitz directs and stars as himself, a man who decides to combine \"the two biggest failures in my life--professional and personal\" by setting out on a filmed quest to have 20 dates and come out with both a movie career and a love interest. While most of his dates are disasters of varying stripes, Myles ultimately meets the lovely Elisabeth on his 17th date and they completely hit it off, leaving him with a new dilemma when he wants to finish the movie anyway and puts his new romance", "score": 12.114082, "title_score": 0, "passage_id": "12659103"}, {"title": "Hero (TV channel)", "text": "and local sports events, which was silently launched earlier on January 1. Hero was relaunched and demoted as a social media portal on February 7, 2018 and is being handled by the Lifestyle team from ABS-CBN Digital Media. Whilst its news content includes anime, gaming and pop culture, it will not carry anime titles nor establish an anime video-on-demand service. Meanwhile, its sister station Yey! has limited airing of some of the anime titles aired on Hero and will carry the last remaining new titles on Yey! channel including \"Ace of Diamond\" and \"My Hero Academia\". Hero had its two-hour", "score": 12.098257, "title_score": 0, "passage_id": "6197921"}, {"title": "My Hero Academia: Two Heroes", "text": "() in its opening weekend, entering the box office charts at number nine during the week ending November 18, 2018. In Argentina and Mexico, ranked eighth on its first weekend of release. Worldwide, the film has grossed a total of as of November 18, 2018. Reception from critics have been generally positive. The \"Los Angeles Times\" described the film as \"a high-energy blend of heroism, comedy, friendship and take-no-prisoners battles\", praising Briner's role as Deku, saying \"Briner keeps the character likable and believable\". Miranda Sanchez from IGN stated that \"\"My Hero Academia: Two Heroes\" is fun but lacks interesting stakes\",", "score": 12.097749, "title_score": 0, "passage_id": "20766131"}, {"title": "My Hero Academia: Two Heroes", "text": "October 17, 2018 in Singapore and Indonesia respectively. The film was acquired by Pioneer Films in the Philippines, with an initial fan screening occurring on October 16, 2018 and three additional advance screenings on October 20, following a delayed wider release, originally slated for October 17. Viz Media Europe acquired the rights to the film for French, German, and Italian-speaking regions of Europe. \"My Hero Academia: Two Heroes\" will be released on Blu-ray and DVD on February 13, 2019 in Japan by Toho Pictures. The release will be offered in standard editions, as well as a \"Plus Ultra\" limited edition.", "score": 12.097648, "title_score": 0, "passage_id": "20766128"}, {"title": "My Hero Academia: Two Heroes", "text": "manga by Horikoshi titled \"Vol. Origin All Might: Rising\", as well as character profiles and a \"secret dialogue\" between Horikoshi and Eiichiro Oda. Viz Media later published the \"All Might: Rising\" manga digitally on September 19, 2018. The film will receive 4D screenings in Japan, premiering on January 11, 2019. \"My Hero Academia: Two Heroes\" has been licensed in North America, Australasia, and the British Isles by Funimation, who premiered the English dub in Los Angeles on September 15, 2018, and a wider theatrical release in 400 theaters in the United States and Canada from September 25 through October 2,", "score": 12.097648, "title_score": 0, "passage_id": "20766126"}, {"title": "My Hero Academia: Two Heroes", "text": "My Hero Academia: Two Heroes All Might is invited to a summer trip at \"I-Island\", a man-made island where the top scientists of the world reside and perform research on Quirks, superpowers that 80% of the world's population has. He takes Izuku Midoriya as his guest and reminds him not to reveal to his good friend, former partner, and top scientist Professor David Shield the secret about their shared Quirk: One for All. After they arrive, they are greeted by Melissa Shield, David's daughter and a student of the island's academy hoping to be a scientist just like her father.", "score": 12.097648, "title_score": 0, "passage_id": "20766113"}, {"title": "My Hero Academia: Two Heroes", "text": "how Melissa and Midoriya are the next generation of heroes and how the world will be in good hands even after All Might's Quirk is gone. During the credits, scenes are shown of the students and All Might enjoying a barbecue on the island after their victory with the rest of the students from their class Class 1-A, who were also on I-Island when the events of the film happened. Melissa also visits David, who is now in the hospital recovering while the police watch over him. On December 11, 2017, \"Weekly Sh\u014dnen Jump\" announced that K\u014dhei Horikoshi's \"My Hero", "score": 11.996982, "title_score": 0, "passage_id": "20766123"}, {"title": "Staircase (film)", "text": "a camp comedy. Vincent Canby of \"The New York Times\" wrote, \"Although Burton and Harrison are interesting actors whose styles command attention even when the material does not, 'Staircase' is essentially a stunt movie ... Unlike Harry and Charlie, who eventually come to edgy terms with the emptiness of their lives, I couldn't quite come to terms with the emptiness of the movie.\" \"Variety\" wrote that \"Harrison and Burton have dared risky roles and have triumphed,\" but noted that the film \"comes uncomfortably close to being depressing.\" Roger Ebert gave the film 1 star out 4, calling it \"an unpleasant", "score": 11.995168, "title_score": 0, "passage_id": "10479678"}, {"title": "Velli Thirai", "text": "film released on 7 March 2008.The movie was failed to do well at box office. When Saravanan goes to Hyderabad, Kanniah plagiarizes his script and pitches it to a producer, under the condition that he has to play the hero in the film. Impressed by the script, the producer agrees to the condition. The movie turns Kanniah, now rechristened Dilipkanth, into a star. Saravanan does not give up and creates another story. However, he finds out he cannot make his film unless Dilipkanth plays the hero. Because of this, they lead into minor problems, which annoy Saravanan and their team.", "score": 11.989498, "title_score": 0, "passage_id": "9615515"}, {"title": "My Name Is Anthony Gonsalves (film)", "text": "and blames all the murders on Sikander's boss (Anupam Kher). To make it look real, Anthony does fake stunts, like blowing Murtaza's factory up and acting dead. In the climax, Anthony, Sikander, and the priest who raised Anthony, get together to kill Sikander's boss; that's when the police enter. Sikander gets arrested. Anthony marries Riya and becomes a big hero, a superstar, and his dreams come true. The soundtrack of the film is composed by Pritam and Himesh Reshammiya while the lyrics are penned by Sameer. My Name Is Anthony Gonsalves (film) My Name Is Anthony Gonsalves is a Bollywood", "score": 11.954239, "title_score": 0, "passage_id": "10218228"}, {"title": "Mannar Mathai Speaking", "text": "When she regains consciousness, they make her the lead actress of the troupe. To get the role of the hero, Gopalakrishnan mocks her as his cousin, and she will only act if they make him the hero. Balakrishnan however does not readily believe in this and he brings Gopalakrishnan's mom (Sukumari) to the camp to clarify. When the truth was about to come out, Gopalakrishnan tells his mom that he told everyone that she is his cousin because he is in love with her. His mom asks him to marry her. With no way out they try to mock their", "score": 11.786853, "title_score": 0, "passage_id": "14253705"}, {"title": "Someday My Prince Will Come", "text": "Someday My Prince Will Come \"Someday My Prince Will Come\" is a popular song from Walt Disney's 1937 animated movie \"Snow White and the Seven Dwarfs\". It was written by Larry Morey (lyrics) & Frank Churchill (music), and performed by Adriana Caselotti (Snow White's voice in the movie). It was also featured in the 1979 stage adaptation of the 1937 animated musical movie. In AFI's 100 Years...100 Songs, it was ranked the 19th greatest film song of all time. This song first appears 57:40 into the movie, when Princess Snow White sings a bedtime song for the dwarfs after their", "score": 11.628128, "title_score": 0, "passage_id": "7962623"}, {"title": "Academia Anta\u0301rtica", "text": "the Academia represents an important step toward the achievement of a Peruvian national literature and its recognition by European intellectuals. This recognition may have come from Spain's most influential author himself, Miguel de Cervantes, who in his \"Canto a Cal\u00edope\" (1583) celebrates the literature generated in Spain's American colonies, though he does not mention the Academia Ant\u00e1rtica by name. The most influential of the Academia Ant\u00e1rtica's works, the \"Primer parte del Parnaso Ant\u00e1rtico de obras amotorias\" (\"Antarctic Parnassus, Part One: Poems of Romance\") was printed in Seville in 1603. Its centerpiece is the new Spanish-language translation of Ovid's \"Heroides\", penned", "score": 11.626817, "title_score": 0, "passage_id": "13917033"}, {"title": "My Hero 2", "text": "My Hero 2 My Hero 2 (\u4e00\u672c\u6f2b\u756b\u95d6\u5929\u6daf2\u4e4b\u5999\u60f3\u5929\u958b) is a 1993 Hong Kong comedy film directed by Joe Chu, starring Dicky Cheung and Ng Man Tat. Despite the title, it is not a sequel to the movie \"\"My Hero (1990)\"\", starring Stephen Chow. The movie is about Cheung Kin-Hong's (Dicky Cheung) ploy to get a good story involving triads for his comics. He is a comics artist and writer who has not been very successful in the past. Then one day he encounters his hero, Brother Tat (Ng Man-Tat) at his regular cafe. He manages to convince Tat, who happens to", "score": 11.623693, "title_score": 0, "passage_id": "9667360"}, {"title": "Kevin Smith", "text": "tied up with the man\", and added \"No fucking movie is worth all this.\" He lamented that in addition to working with Weinstein, \"I sat out there talking about this man like he was a hero, like he was my friend, like he was my father.\" He then pledged to donate all his future residuals from his Weinstein-produced films to the non-profit organization Women in Film, which advocates for the inclusion of more women in film production. In 1997, Smith was hired by New Line to rewrite \"Overnight Delivery\", which was expected to be a blockbuster teen movie. Smith's then-girlfriend", "score": 11.610204, "title_score": 0, "passage_id": "709529"}, {"title": "The Donnas", "text": "film 2004 \"D.E.B.S.\". A cover version of the Kiss song \"Strutter\" was used in the soundtrack to the 1999 movie \"Detroit Rock City (film)\". \"Please Don't Tease\" was used in \"New York Minute\" and \"Everyone Is Wrong \" was featured in the movie \"Elektra\". Then Guitar Hero used \"Take It Off\" for 2009 Guitar Hero Smash Hits. \"Take It Off\" was also used in the 2009 hit movie \"The Hangover\". \"Play My Game\" was featured in a Season 1 episode of \"What's New, Scooby Doo?\". \"Who Invited You\" is featured on the soundtrack of the 2003 movie \"What a Girl", "score": 11.542706, "title_score": 0, "passage_id": "3132015"}, {"title": "Pretty Cure Dream Stars!", "text": "she tried it with her friends, it started to work. Whip then tells Sakura that she helped make her dream of viewing the flowers with all of her friends come true and thanked her for it. The ending shows various pictures of the Cures eating and enjoying the flower viewing. The film's score will be composed by Yuki Hayashi (\"My Hero Academia\", \"Death Parade\", \"Gundam Build Fighters\"). The film's opening theme is titled by Rie Kitagawa while the ending song is titled by Yoshino Kimura. The film is released in Japanese Theaters on March 18, 2017. Moviegoers in the film", "score": 11.525143, "title_score": 0, "passage_id": "19874337"}, {"title": "Casablanca (film)", "text": "elements can be criticized, citing unrealistic special effects and the stiff character/portrayal of Laszlo. Critic Leonard Maltin considers \"Casablanca\" to be \"the best Hollywood movie of all time.\" Rick, according to Rudy Behlmer, is \"not a hero ... not a bad guy\": he does what is necessary to get along with the authorities and \"sticks his neck out for nobody\". The other characters, in Behlmer's words, are \"not cut and dried\" and come into their goodness over the course of the film. Renault begins as a collaborator with the Nazis who extorts sexual favors from refugees and has Ugarte killed.", "score": 11.485003, "title_score": 0, "passage_id": "679577"}, {"title": "Sunrise (company)", "text": "creating CG for many of the company\u2019s shows (notably \"Tiger & Bunny\", \"Zegapain\", \"Cross Ange\", \"Valvrave the Liberator\", \"Gundam MS Igloo\" and \"Gundam The Origin\"). They also produce CG work for other animation studios, including XEBEC's \"Space Battleship Yamato 2199\". Formerly known as Ogikubo Studio (\u837b\u7aaa\u30b9\u30bf\u30b8\u30aa) or Sunrise Emotion, Nerima Studio is best known for the \"Freedom Project\", \"Valvrave the Liberator\", the \"King of Thorn\" anime film and \"Cross Ange\". Sunrise Origin Studio (\u30b5\u30f3\u30e9\u30a4\u30ba\u30aa\u30ea\u30b8\u30f3\u30b9\u30bf\u30b8\u30aa) is Sunrise's in-between animation studio that does in-between animation for other studio's anime titles such as \"My Hero Academia\" to \"The Boy and the Beast\". Most", "score": 11.403374, "title_score": 0, "passage_id": "709803"}, {"title": "Flora Kidd", "text": "Come Down' is a Scottish love ballad that predated Robert Burns and was refined by the latter into a wistful song. Flora Kidd adapts this popular song into a romantic novel. The following stanza from Robert Burns' song is introduced in the beginning of her story. 'O whistle, an' I'll come to ye, my lad; O whistle, an' I'll come to ye, my lad: Though father and mither should baith gae mad, O whistle, an' I'll come to ye, my lad. Like her 1967 release \"Whistle and I'll Come\", she sets up the hero and the heroine of \"When Birds", "score": 11.284863, "title_score": 0, "passage_id": "10468368"}, {"title": "This Is Spinal Tap (album)", "text": "\"Break Like the Wind\" album, while \"Jazz Odyssey\" and \"Saucy Jack\" later appeared on the \"Back from the Dead\" album. \"Lick My Love Pump\" and \"Heartbreak Hotel\" have not been officially released. Conversely, the song \"America\" from the soundtrack does not appear in the movie, other than in a brief scene where Nigel and David are shown attempting to record the guitar parts for the song. \"Gimme Some Money\" was featured in the 1991 comedy film \"Don't Tell Mom the Babysitter's Dead\". The song \"Tonight I'm Gonna Rock You Tonight\" is featured in the video game \"Guitar Hero II\". When", "score": 11.089852, "title_score": 0, "passage_id": "5860608"}, {"title": "Marina Rice Bader", "text": "giving so much time and energy to the whole thing, you want that to be your investment. You don\u2019t want to have to freaking cash out your IRA to make a lesbian movie when there\u2019s so many lesbians who are wanting content.\" Nonetheless, she says, \"I don\u2019t understand why all lesbians don\u2019t donate $10 for me to make a movie. But they don\u2019t, so I\u2019ve kind of come to the realization that I\u2019m not going to be able to create film for my community based on support from my community, and it\u2019s really heartbreaking.\" In 2009, she met her first", "score": 11.082876, "title_score": 0, "passage_id": "20492439"}, {"title": "Spawn (film)", "text": "During an interview on the \"Scott Ferrall\" show on Sirius radio, McFarlane said: \"It's coming out no matter what. Even if I have to produce, direct and finance it myself, it's going to come out.\" McFarlane announced on August 23, 2009 that he had begun writing the screenplay for a new movie based on the character, saying that \"The story has been in my head for 7 or 8 years\", that \"The movie idea is neither a recap or continuation. It is a standalone story that will be R-rated. Creepy and scary\", and that \"the tone of this \"Spawn\" movie", "score": 11.049934, "title_score": 0, "passage_id": "4443629"}, {"title": "My Hero Academia", "text": "video game, titled \"My Hero One's Justice\", was released for PlayStation 4, Nintendo Switch, Xbox One and Microsoft Windows on October 26, 2018. Izuku Midoriya is set to make an appearance in the crossover game \"Jump Force\". The manga was nominated for the 8th Manga Taish\u014d in 2015. It was nominated for the 40th Kodansha Manga Award for \"sh\u014dnen\" category in 2016. Before the anime adaptation's premiere, manga author Masashi Kishimoto praised K\u014dhei Horikoshi's work, believing it would be a success overseas; Horikoshi, meanwhile, has cited Kishimoto's \"Naruto\" series as a primary source of inspiration. Volume 1 reached the 7th", "score": 11.013066, "title_score": 0, "passage_id": "18433099"}, {"title": "Billa (2009 film)", "text": "with Ravi Teja as hero. I watched the movie again with Ravi Teja in my mind. I modified certain scenes to suit him. Then I opined that a high budget film might not work out with Ravi Teja as hero. The producer will end up suffering for the kind of budget we ask for. Hence we collectively decided not to make the movie. I got an offer to work with Prabhas. I told him another story and he didn\u2019t look excited enough. I casually asked him if he saw Billa. I told him that it has all elements of commercial", "score": 10.97333, "title_score": 0, "passage_id": "12625133"}, {"title": "History of Xinjiang", "text": "the Irtysh. There are many hero warriors with me. I have many riches. Now I have come to meet with you beggars, you remnants of the Oirats, in the time when the war for power begins. Will you support the enemy? My homeland is Altai, Irtysh, Khobuk-sari, Emil, Bortala, Ili, and Alatai. This is the Oirat mother country. By descent, I am the great-grandson of Amursana, the reincarnation of Mahakala, owning the horse Maralbashi. I am he whom they call the hero Dambijantsan. I came to move my pastures back to my own land, to collect my subject households and", "score": 10.936603, "title_score": 0, "passage_id": "8634946"}, {"title": "Anna Faris", "text": "producer guy what equipment I should buy on Amazon. And I just started recording my friends when they would come over. And then with my dear friend Sim, we started flushing out the whole thing, which clearly there's still a lot more flushing out to do. It started out as a dinky hobby\". As of May 2018, 122 episodes have been released. Faris reprised her voice-over role in \"\", the fourth installment in the \"Alvin and the Chipmunks\" film series. The movie was released on December 18, 2015 by 20th Century Fox. In 2016, she had a brief appearance as", "score": 10.925055, "title_score": 0, "passage_id": "1959746"}, {"title": "Pod People (Invasion of the Body Snatchers)", "text": "have not yet been taken over. They also seem to exhibit a kind of extra-sensory perception. When one character stabs his almost formed pod double, another pod person immediately emits the alien scream. This version does not end with the same hope with which the novel and previous movie do, but ends with the pod people taking over almost everyone on Earth. The movie shows several ships being stockpiled with pods to be sent out into other parts of the world. In the very last scene, Veronica Cartwright's character is happy to see the hero, played by Donald Sutherland, only", "score": 10.90403, "title_score": 0, "passage_id": "9265790"}, {"title": "The Care Bears Movie", "text": "Care Bear. A lot of effort went into bringing out their individuality.\" Some time afterward, Hirsh conceded that parents had to come to the film, out of respect for the dark content within. \"Frightening scenes,\" he said, \"are a necessity for the reality of the hero and villain\u2014just as it works in nursery rhymes. Kids work out their fears this way.\" TCFC's Jack Chojnacki offered this vindication in the \"Wall Street Journal\": \"We consider a film one of the many products we license. When we started the whole Care Bears project we knew the importance of bears in the market", "score": 10.867654, "title_score": 0, "passage_id": "3511283"}, {"title": "When Love Is Not Enough: The Lois Wilson Story", "text": "\"Everyone does a wonderful job in this movie -- but, in the end, it seems more like a rehash of writer Wiliam G. Borchert's 1989 'Hall of Fame' movie, \"My Name Is Bill W.\" than a real portrait of the woman whose idea helped millions of suffering families.\" Mathew Gilbert in \"The Boston Globe\" wrote; \"This new CBS Hallmark movie does its job effectively enough, bringing us through the ups and downs of Bill and Lois Wilson's marriage as they wrestle with his addiction.\" The film has been nominated for several awards; Screen Actors Guild Awards Satellite Awards Emmy Awards", "score": 10.851933, "title_score": 0, "passage_id": "14201941"}, {"title": "Roy Huggins", "text": "of all three of his sons from his second marriage. Huggins worked in TV through the 1980s, and served for three years as the executive producer of \"Hunter\". Stephen J. Cannell said of Huggins' time on \"Hunter\": \"Roy was in the driver's seat where he belonged. Nobody does it better or with more style...Roy Huggins is my Godfather, my Hero and my Friend. They don't come any better.\" At Warner Bros. Television, Huggins was repeatedly denied credit and compensation as the creator of several television programs. A Warner-owned property was used as the basis of the script for the first", "score": 10.845674, "title_score": 0, "passage_id": "6134342"}, {"title": "Patrick Macnee", "text": "several outfits himself for Steed based on the same basic theme. Steed was also the central character of \"The New Avengers\" (1976\u201377), in which he was teamed with agents named Purdey (Joanna Lumley) and Mike Gambit (Gareth Hunt). Macnee insisted on, and was proud of, never carrying a gun in the original series; when asked why, he explained, \"I'd just come out of a World War in which I'd seen most of my friends blown to bits.\" Lumley later said she did all the gun-slinging in \"The New Avengers\" for the same reason. However, the Internet Movie Firearms Database lists", "score": 10.791525, "title_score": 0, "passage_id": "335814"}, {"title": "Someday My Prince Will Come", "text": "small party. It later appears when Snow White is making a pie and once more in a more formal version when the prince takes Snow White away at the end. The American Film Institute listed this song at No. 19 on their list of the 100 greatest songs in movie history. Following \"When You Wish Upon A Star\" from \"Pinocchio\" at No. 7, this is the second highest ranked song from a Disney movie out of four, with the other two being \"Beauty and the Beast\" from \"Beauty and the Beast\" at No. 62 and \"Hakuna Matata\" from \"The Lion", "score": 10.759229, "title_score": 0, "passage_id": "7962624"}, {"title": "Mi historia en la Academia", "text": "Mi historia en la Academia Mi Historia en La Academia \"(My Story in The Academy)\" is the first release from Mexican singer Myriam. It is a compilation album released on December 2002 after winning the first season of the Mexican reality talent show \"La Academia\". The album contains the songs that Myriam performed during \"La Academia\". All of the songs had previously been released on the show-related albums that contained the songs by all contestants for each concert. The album does not contain the songs that Myriam performed as a duet: \"Believe\" with Wendolee; \"Suavemente\" with Nadia; and \"A Dios", "score": 10.72681, "title_score": 0, "passage_id": "12428251"}, {"title": "Benares State", "text": "was returning to his hermitage along with his students, an elderly housewife, with a bright golden face and wide eyes appeared from a house nearby. She called out for the sage and requested him to come near her. When the great sage approached her, she told him, \u201cGreat sage, my husband is very old. He does not take any food until he feeds a guest every day. But unfortunately no guest has arrived to-day to our house, asking for food. He is sitting hungry in the house. Could you please accept my invitation and come as a guest to our", "score": 10.713924, "title_score": 0, "passage_id": "8532957"}, {"title": "VVVVID", "text": "Man\" and \"Prison School\", and in October 2016 by \"Tokyo Ghoul\" 's 2 OVA and \"All Out!!\", in December 2016 by \"Parasyte\" and \"Death Parade\", in June 2017 by \"The Dragon Dentist\", in July 2017 by \"Drifters\" and the last 6 episodes of \"Hellsing Ultimate\", in October 2017 by \"\" and the second season of \"Attack on Titan\". In May 2018, \"Kill La Kill\" premiered on the platform, followed by \"My Hero Academia\" in August 2018. VVVVID VVVVID is an Italian video on demand service and a virtual community, with an offering that includes international movies, anime, series, music videos,", "score": 10.712473, "title_score": 0, "passage_id": "18943876"}, {"title": "What's the Matter with Helen?", "text": "\"Animal Crackers in My Soup\". On Rotten Tomatoes, the film holds an approval rating of 33% based on , with a weighted average rating of 5.1/10. Roger Ebert gave the film 1.5 out of 4 stars, calling it a \"menopausal metaphysical mystery movie\", and writing \"The whole movie is very 1930s, right down to the phony studio streets and the 20-foot shadow that comes around the corner five seconds before the actor does.\" Vincent Canby from \"New York Times\" wrote a particularly scathing review, writing, \"This new movie is so perfunctory, it's likely to give misogyny a bad name.\" \"Variety\"", "score": 10.703864, "title_score": 0, "passage_id": "12096001"}, {"title": "My Hero (Modern Family)", "text": "roller rink. Cam has no problem hanging out with someone who was dating Mitch before him, but when he learns that Teddy invited the whole family to the fundraiser and sees how friendly they all are with him, he gets upset. Even though Mitch reassures him that nothing is going on between him and Teddy anymore, Cam seems to not calm down. He only calms down when Jay tells him that although Teddy is a really good person and everyone likes him, he did not bring the best out of Mitch, something that Cam does. Jay (Ed O'Neill), knowing that", "score": 10.689375, "title_score": 0, "passage_id": "17395673"}, {"title": "Lone Hero", "text": "bikers who kept an eye on the villagers and frees everybody. When he asks for volunteers to fight when the others come back, only Tim and Pablo reluctantly agree. The rest of the gang comes back and a shootout occurs, culminating with a duel between John and Bart, during which John shoots Bart in the arm, disabling him. Some time after that, the Far West village still runs with some new additions : John's story is loosely adapted as an Old West tale and acted out for tourists. Lone Hero Lone Hero is a 2002 action film written and directed", "score": 10.649403, "title_score": 0, "passage_id": "15771634"}, {"title": "Tommy (1975 film)", "text": "his role as the Specialist, Jack Nicholson stated: \"In my whole career there was only one time when a director said to me, 'OK, come right down the pike and just look beautiful, Jack.' That was Ken Russell on \"Tommy\".\" The film currently holds a 77% approval rating on review aggregator website Rotten Tomatoes, based on 26 reviews, with an average grade of 6.8 out of 10. Vincent Canby of \"The New York Times\" declared, \"It may be the most overproduced movie ever made, but there is wit and reason for this. It is the last word in pop art", "score": 10.635517, "title_score": 0, "passage_id": "4179770"}, {"title": "Sam Berns", "text": "when Berns attended a Bruins game and met Ch\u00e1ra afterwards. Ch\u00e1ra had scored in that game and Berns blurted out \"You're the hero!\". Ch\u00e1ra responded: \"No, no, you're my hero, our hero.\" Before the puck dropped on Tuesday, January 14, 2014, the Bruins honored Berns with a moment of silence and a video tribute. Berns was to be an honorary captain when the New England Patriots hosted the Indianapolis Colts in a divisional playoff game on January 11, 2014; however, he died on January 10, the evening before the game. Patriots Chairman and CEO Robert Kraft issued a statement on", "score": 10.635147, "title_score": 0, "passage_id": "17802741"}, {"title": "Bulletproof Wallets", "text": "Stone\" said, \"\"Bulletproof Wallets\" is riveting because even on \"The Juks,\" when he's rhyming about getting paid, he comes off like a tough but fatally vulnerable anti-hero, forever trapped in the headlights of oncoming disaster.\" Mark Desrosiers of \"PopMatters\" said, \"\"Bulletproof Wallets\" doesn't have the peering-into-the-abyss street insanity of \"Ironman\", sure, but it does come close. And damn, it sure does air you out nonetheless.\" James Poletti of Yahoo! Music said, \"Whilst Ghostface remains in possession of one of the most diverse musical imaginations in the Clan, this is ultimately disappointing in its lack of innovation.\" Bulletproof Wallets Bulletproof Wallets", "score": 10.622642, "title_score": 0, "passage_id": "5483971"}, {"title": "Daredevil (film)", "text": "\"that's not so bad: The movie looks best when it looks like other, better movies.\" The \"Chicago Tribune\"s Michael Wilmington thought the film grabs the attention, but felt it does not reward it. The \"New York Post\"s Lou Lumenick panned the film, describing it as a \"mind-numbing, would-be comic-book franchise, which often seems as blind as its hero -- not to mention deaf and dumb.\" Character co-creator Stan Lee himself felt, \"[T]hey just wrote the whole thing wrong. They made him too tragic.\" Ben Affleck won the Golden Raspberry Award for Worst Actor for his work in the movie, as", "score": 10.582873, "title_score": 0, "passage_id": "4014000"}, {"title": "Africa (Petrarch)", "text": "however the poetic design is based on Virgil's \"Aeneid.\" Petrarch intentionally did this to increase the importance of Sophonisba to the level of a new Dido (queen of Carthage). In Book 6 Sophonisba is captured by the poem's hero, Cornelius Scipio. She commits suicide so she does not become Scipio's nor Rome's war prize. Here she shows her love for Massinissa. There is a fundamental difference between Virgil's \"Aeneid\" and Petrarch's \"Africa.\" Virgil's Dido blames Rome for the ruin of herself as does Sophonisba. In Petrarch's poem the hero, Scipio, does not come to an end. Petrarch could have chosen", "score": 10.578261, "title_score": 0, "passage_id": "9381213"}, {"title": "John Maus", "text": "social theory\" and his music as \"obviously some kind of art-school mindfuckery\". According to Maus, he does not think about aesthetic theory when \"working over the keyboard, or musing over musical ideas in my head. But when discussing it, we want to have some new thought about this new music. I wouldn't claim that my music is new, but generally speaking pop music begs for some kind of radical new way of talking about it.\" He also denies any intention for his work to come off as \"a sneering take on pop.\" Although he rejects the label, Maus is recognized", "score": 10.569058, "title_score": 0, "passage_id": "11509562"}, {"title": "Never Too Far/Hero Medley", "text": "for writing \u2018Hero\u2019 because it saved my life or it saved my father\u2019s life or my brothers or sisters life, or something of that nature, I said I always have to sing that song when I\u2019m performing because if I don\u2019t, you never know who I\u2019m leaving out and you know what, in times of my life I\u2019ve had to turn to that song lyrically and flip it onto my own life and sing it to myself. So its from the \u2018Music Box\u2019 album, and it\u2019s called \u2018Hero', this is for you.\" Elysa Gardner from \"USA Today\" called \"Never Too", "score": 10.562852, "title_score": 0, "passage_id": "5002651"}, {"title": "Spawn (upcoming film)", "text": "character, titled \"Spawn\", scheduled for release in 2008. During an interview on the \"Scott Ferrall\" show on Sirius radio, McFarlane said: \"It's coming out no matter what. Even if I have to produce, direct and finance it myself, it's going to come out.\" McFarlane announced on August 23, 2009 that he had begun writing the screenplay for a new movie based on the character, saying that \"The story has been in my head for 7 or 8 years\", that \"The movie idea is neither a recap or continuation. It is a standalone story that will be R-rated. Creepy and scary\",", "score": 10.550709, "title_score": 0, "passage_id": "20920573"}, {"title": "Big Hero 6 (film)", "text": "it \"sweet and sharp and exciting and hilarious\" and says that the film \"comes to the rescue of what's become a dreaded movie trope\u2014the origin story\u2014and launches the superhero tale to pleasurable new heights.\" Calvin Wilson of \"St. Louis Post-Dispatch\" gave the film 3.5 of 4 stars, writing that \"the storytelling is solid, propelled by characters that you come to care about. And that should make \"Big Hero 6\" a big hit.\" Bill Goodykoontz of \"The Arizona Republic\" gave the film a positive review, writing, \"Directors Don Hall and Chris Williams have made a terrific movie about a boy (Ryan", "score": 10.543669, "title_score": 0, "passage_id": "17286268"}, {"title": "Contraband (2012 film)", "text": "drag\" and observed that \"it's much more like a cynical hash job, whose faux-realistic manner can't hide all the hackneyed crime-movie situations.\" Peter Travers of \"Rolling Stone\" thought the film \"goes down in a sea of Hollywood clich\u00e9s\" and that Mark \"Wahlberg could sleepwalk through this role, and does. See this movie and you'll surely follow his lead.\" Kyle Smith of the \"New York Post\" derided the film, noting that \"watching a hero progress due in large part to lucky breaks and idiot moves by others does not make a movie\" and that \"it's puzzling why anyone considered this script", "score": 10.521104, "title_score": 0, "passage_id": "15535885"}, {"title": "History of anime", "text": "(2014), \"Parasyte -the maxim-\" (2014), \"One Punch Man\" (2015), \"My Hero Academia\" (2016), \"\" (2017), \"Black Clover\" (2017) and \"Cells at Work!\" (2018) On September 6, 2013 Hayao Miyazaki announced that \"The Wind Rises\" (2013) would be his last film, and on August 3, 2014 it was announced that Studio Ghibli was \"temporarily halting production\" following the release of \"When Marnie Was There\" (2014), further substantiating the finality of Miyazaki's retirement. The disappointing sales of Isao Takahata's comeback film \"The Tale of Princess Kaguya\" (2013) has also been cited as a factor. Several prominent staffers, including producer Yoshiaki Nishimura and", "score": 10.495503, "title_score": 0, "passage_id": "2122535"}, {"title": "Crayon Shin-chan: My Moving Story! Cactus Large Attack!", "text": "the cactus festival. When the killer cactus attacked, she tried to escape in the helicopter, but the cactus responded to the helicopter's sound and she was eaten up. They are a comedy group of Japan who had come to Madakueruyobaka. Hosogai-san was soon eaten up by the killer cactus. Akemi-chan was eaten too, but since she was a robot, the cactus vomited her out. It is the main villain of this movie. The new species of cactus was important to the town people as it had a fruit which resembled Dragon Fruit. But it soon turns into killer carnivorous cactus", "score": 10.480917, "title_score": 0, "passage_id": "18459464"}, {"title": "The Three Musketeers (1961 film)", "text": "fight. When d'Artagnan defends Mme Bonacieux against a couple of the cardinal's thugs, the director does not only use dramatic sound effects but furthermore lets Barray's punches look more explosive by taking out frames very precisely when he is about to hit. He is also capable of making us believe an outnumbered man could really win the day if only certain circumstances are given, because in Borderie's films the thugs are often so overly keen on decking the hero that they actually hinder each other to succeed. The film was the sixth most popular movie at the French box office", "score": 10.479607, "title_score": 0, "passage_id": "15925648"}, {"title": "Guitar Hero", "text": "of \"World Tour\" while offering similar features on Metallica's history and music as found in \"Guitar Hero: Aerosmith\". In addition, Metallicas album, \"Death Magnetic\", was available as downloadable content for \"Guitar Hero III\" simultaneously with the release of the album, with the content being forward-compatible with \"Guitar Hero World Tour\" and \"Guitar Hero: Metallica\". Since the PlayStation 2 version does not support downloading, three extra songs were included from Death Magnetic and are as follows: \"Broken, Beat, and Scarred\", \"Cyanide\", and \"My Apocalypse\". A new feature in the game, where the drummer can access a mode called Expert+, has also", "score": 10.47263, "title_score": 0, "passage_id": "9692302"}, {"title": "Bill Mitchell (economist)", "text": "academia, in disparaging terms, stating, only half-jokingly, that his work as a musician does less damage to people. \"I think my economics profession is very dangerous,\" he says. Mitchell is a \"passionate\" cyclist. He was an \"active bike racer\" when, in 1995, he founded the website Cyclingnews.com, which was sold in 1999 to the Australian media company Knapp Communications. (It was subsequently bought in 2007 by Future plc.) Bill Mitchell (economist) William Francis Mitchell (born March 1952) is a professor of economics at the University of Newcastle, New South Wales, Australia and a notable proponent of Modern Monetary Theory. Mitchell", "score": 10.458137, "title_score": 0, "passage_id": "15432672"}, {"title": "My Hero Academia: Two Heroes", "text": "Academia\" manga would be inspiring an anime film in the third quarter of 2018. Horikoshi is supervising the film, and is credited for the original work and character designs. Kenji Nagasaki is returning to direct the film at studio Bones based on a script written by Y\u014dsuke Kuroda. Yoshihiko Umakoshi provides the character designs for the film, and Yuki Hayashi is composing the music. The film is distributed in Japan by Toho. The film's title and release date were revealed during a stage presentation at AnimeJapan on March 25, 2018. On April 10, 2018, it was announced that Mirai Shida", "score": 10.443921, "title_score": 0, "passage_id": "20766124"}, {"title": "Doc (G.I. Joe)", "text": "Abysmia. When the Crimson Twins botch an instruction from Cobra Commander and order the prisoners' execution, a S.A.W. Viper steps up to the task. Doc is the first to be slain, followed by several others. The survivors wound the Viper and escape. He first appeared in the \"A Real American Hero\" mini-series, voiced by Buster Jones. Doc appears in the following episodes (in alphabetic order): Doc also appeared briefly in the 1987 animated film \".\" Near the end of the movie, his voice can be heard informing the Joe team that Duke had come out of his coma. Doc appears", "score": 10.409012, "title_score": 0, "passage_id": "11080305"}, {"title": "Ella Cinders", "text": "stepsisters react violently when they see the dress. The embarrassed Ella flees the ball, losing one of her slippers. Later, the judges come to the house and tell Ella that she is the winner because they were amused by the cross-eyed photo. Ella heads for Hollywood, where she is disappointed to discover the contest was a fraud. She nevertheless manages to land a movie contract. Waite turns out to be wealthy football hero George Waite, and the two are reunited. Ella also turned up in Big Little Books and comic books, including early issues of \"Tip Top\" and \"Sparkler Comics\",", "score": 10.408918, "title_score": 0, "passage_id": "10069351"}, {"title": "Rocco Nacino", "text": "Movie Press Club as the \"New Movie Actor of the Year\" in the 28th PMPC Star Awards for Movies; and by the Entertainment Press Society (Enpres) as \"Best Breakthrough Performance by an Actor\" in the 9th Golden Screen Awards. Nacino also did cameo roles in the movies \"My Valentine Girls\" and \"My Kontrabida Girl\". He also played the brother of Judy Ann Santos at the 37th Metro Manila Film Festival, \"\", directed by Jose Javier Reyes. He was also given the honor to portray Philippines' national hero Jose Rizal in the multi-awarded documentary narrated by Howie Severino, \"Pluma: Ang Dakilang", "score": 10.408195, "title_score": 0, "passage_id": "14218279"}, {"title": "My Hero (U.S. TV series)", "text": "of \"I Love Lucy\" and said \"Cummings brought a magnificent terribleness to his part.\" The show was executive produced and part owned by Don Sharpe, who was also connected with \"I Love Lucy\" and \"Terry and the Pirates\". When \"My Hero\" was released to bad reviews, Sharpe admitted it needed fixing. \"It's tricky to come up with something every week that's tricky and believable,\" he said. \"We hope that eventually the personality of Cummings will become so dominant to the viewer that the plots won't look bad.\" The \"Los Angeles Times\" later called some golfing scenes between Cummings and Reginald", "score": 10.3887, "title_score": 0, "passage_id": "17297174"}, {"title": "My Hero Academia", "text": "Sony Pictures UK handling subsequent seasons after the acquisition of Funimation by Sony Pictures Television. In Australia and New Zealand, the series is distributed by Universal Sony Pictures Home Entertainment, on behalf of Funimation. A second season was announced in the \"Weekly Sh\u014dnen Jump\" magazine's 30th issue of 2016. It premiered on April 1, 2017 on NTV and YTV, and ended on September 30, 2017, with the staff and cast from the first season returning to reprise their roles. The first opening theme is performed by Kenshi Yonezu and the first ending theme is , performed by Little Glee Monster.", "score": 10.386883, "title_score": 0, "passage_id": "18433095"}, {"title": "Uverworld", "text": "their 4th \"Men's Festival\" concert recording entitled \"Uverworld King's Parade 2017 Saitama Super Arena\". On May 2, 2018, they released 32nd single titled \"Odd Future\" which was chosen as the first opening theme for the third season of the anime series \"My Hero Academia\". It peaked at number three on the Oricon chart, and reached fifth place on the \"Billboard\" Japan Hot 100. On November 7, 2018, they released a new single \"Good and Evil / Eden e\". \"Good and Evil\" was used for the Japanese dubbed version of Marvel's film \"Venom\" which was theatrically released in Japan on November", "score": 10.386808, "title_score": 0, "passage_id": "7874466"}, {"title": "My Boomerang Won't Come Back", "text": "My Boomerang Won't Come Back \"My Boomerang Won't Come Back\" was a novelty record by British comedian Charlie Drake which became a hit on both sides of the Atlantic in 1961. The tune concerns a young Aboriginal lad (with Drake's signature Cockney accent) cast out by his tribe due to his inability to toss a boomerang. After months of isolation (and fighting off \"nasty bushwackin' animals\"), the local witch doctor takes pity on the lad and informs him \"\"if you want you boomerang to come back/well, first you've got to throw it!\"\" He does, and proceeds to bring down an", "score": 10.375087, "title_score": 0, "passage_id": "14570304"}, {"title": "Thiranottam", "text": "along with him. He mentioned, \"\"There is a boy who shared screen space with me in it. However, I am unable to remember who he was. If any of you know his identity, do come forward and inform me. I really wish to meet him once again\"\" However the search ended on a sad note. Prasad Nooranad, a freelance director, has found out that the boy is no more. When we contacted Prasad, he said, \"When Mohanlal posted the request, I started my search and found out from the scribe of the movie that Ajith Rajagopal, the boy in the", "score": 10.368349, "title_score": 0, "passage_id": "14232028"}, {"title": "Masashi Kishimoto", "text": "in 2006. Responding to \"Naruto\"'s success, Kishimoto said in \"Naruto Collector Winter 2007/2008\" that he was \"very glad that the American audience has accepted and understood ninja. It shows that the American audience has good taste... because it means they can accept something previously unfamiliar to them.\" While writing the manga, Kishimoto met Eiichiro Oda, author of \"One Piece\" who he considered his rival. When \"Naruto\" ended, Oda left a message in the series' final volume acknowledging him as a rival. According to Kishimoto \"That felt so gratifying.\" Additionally, before the anime adaptation's premiere of \"My Hero Academia\", he praised", "score": 10.342622, "title_score": 0, "passage_id": "3865405"}, {"title": "My Hero Academia: Two Heroes", "text": "also revealed to be on the island working as waiters. After spending the day enjoying the island's various events, Melissa invites Mineta and Kaminari to join them at a formal party that everyone else was invited to. Before the party, Melissa reveals to Midoriya that she is Quirkless like (unbeknownst to her) he once was. She also realizes his Quirk is similar to All Might's, and gives him a gauntlet she had designed that allows him to not get hurt when using his powers at 100%. Meanwhile, Wolfram, a mysterious villain who secretly arrived on the island prior, takes control", "score": 10.342622, "title_score": 0, "passage_id": "20766115"}, {"title": "Disney's My Son Pinocchio: Geppetto's Musical Tale", "text": "The Blue Fairy, satisfied that Geppetto and Pinocchio are now a real father and a real son, notes that her perfect wish record is still intact. The majority of the songs in this musical are from the movie soundtrack, but the musical does add a few new songs. Disney's My Son Pinocchio: Geppetto's Musical Tale Disney's My Son Pinocchio: Geppetto's Musical Tale is a musical based on Disney's 2000 made-for-television movie \"Geppetto\", which was in turn based on a book by David Stern, and features music and lyrics by Stephen Schwartz. Much like the movie, \"My Son Pinocchio\" is a", "score": 10.324433, "title_score": 0, "passage_id": "15974773"}, {"title": "Manu Tupou", "text": "character as it was scripted\u201d, Corin said. \u201cLiving the life of the character as the beats and moments suggested in the material. Then finding whatever new and original beats and moments come out of that by working with the director and living the life of the character organically in the moment. As it\u2019s scripted, this is what the character does - not me. That\u2019s how I separate myself from that. I don\u2019t use the Method. I\u2019m not going into my own past to create a psychological condition that would drive me as an actor to create that moment. When you", "score": 10.323663, "title_score": 0, "passage_id": "12953839"}, {"title": "Calvin Valentine", "text": "my 30s and say, 'If you'd come over when you were in your 20s, you'd've made it really big'. I'd rather go over to the States, go do the movie thing, the drama thing, or even fail - I'd rather go over and fail and have them say, 'You're not good enough, your accent's not right or your look's not right' - at least then I'd know and I'd have it out of my head. I always believe you regret the things you don't do. I don't want what-ifs hanging over me.\" Calvin first appeared as an honest, kind-hearted policeman.", "score": 10.32044, "title_score": 0, "passage_id": "9660315"}, {"title": "Enter the Invincible Hero", "text": "finds out the whole situation and decided to get all the money back from Pang. at first pang humiliates and defeats Ti-Meng. at the end fight Ti-meng defeats and kills pang with his new art In webpage Oocities the movie was fairly receive pretty well. J. Doyle Walls DVD talk mentioned that movie is fairly decent as a Bruceploitation standard Unlike usual Godfrey Ho movie the movie did not used that much cut and paste technique. However some of the achieve footage from Enter Three Dragons and The Magnificent have been used in the movie. Enter the Invincible Hero Black", "score": 10.317746, "title_score": 0, "passage_id": "18156615"}, {"title": "Cast My Cares", "text": "Phantom Tollbooth's Derek Walker said that \"The music may have as much variety as his name, but this does have some better lyrical content than the average.\" Jonathan Andre of Indie Vision Music stated that the listener was \"given 11 songs written out of a place of heartfelt brokenness and needing to rely solely on Christ alone.\" At New Release Tuesday, Sarah Fine said that \"\"Cast My Cares\" is one of the finest examples of raw, honest songwriting to come from a worship artist in a very long time.\" However, Fine pointed out that \"the first half of the album", "score": 10.307392, "title_score": 0, "passage_id": "17343661"}, {"title": "Jai Lava Kusa", "text": "out, but the actor seemed keen to work with Anil and asked him to come up with another script, for which he immediately came up with a new idea. However, in the later stages, K. S. Ravindra of \"Power\" fame joined the race to direct NTR and the star hero was to choose between Anil Ravipudi and Ravindra. Finally in December 2016, Nandamuri Kalyan Ram took to Twitter to announce that K. S. Ravindra would be directing Jr. NTR's 27th movie in the lead role. Kalyan Ram stated that he was delighted to produce his brother Tarak\u2019s 27th film on", "score": 10.299949, "title_score": 0, "passage_id": "20091421"}, {"title": "Aby (film)", "text": "parents (Sudheer Karamana and Vineetha Koshy), his friend Kunjoottan played by Aju Varghese and his lady love Anumol by Mareena Michael. Overall, this is one of those films with an unconventional underdog as the hero, for whom you would root with tears in your eyes and a smile on your face, and come out of the hall with a wholesome cinematic experience. Arathi Kannan of The New Indian Express has written that Aby is the kind of a movie where wishes written on the blue skies are made into a reality with sheer earnestness and persistence.She has mentioned that 'Aby's", "score": 10.299949, "title_score": 0, "passage_id": "19709469"}, {"title": "Someday My Prince Will Come", "text": "King\" at No. 99. The song was then briefly sung on the 1971 sitcom All in the Family by Edith Bunker in the episode \"Archie's Weighty Problem\". Someday My Prince Will Come \"Someday My Prince Will Come\" is a popular song from Walt Disney's 1937 animated movie \"Snow White and the Seven Dwarfs\". It was written by Larry Morey (lyrics) & Frank Churchill (music), and performed by Adriana Caselotti (Snow White's voice in the movie). It was also featured in the 1979 stage adaptation of the 1937 animated musical movie. In AFI's 100 Years...100 Songs, it was ranked the 19th", "score": 10.298169, "title_score": 0, "passage_id": "7962625"}, {"title": "Adonis Creed", "text": "about his hero going through something similar to kind of motivate him and cheer him up. That\u2019s how I came up with the idea for this movie.\" Although Sylvester Stallone was initially reluctant to help out with the film, he changed his mind upon meeting with Coogler and Jordan. In discussing Stallone's advice to him, Jordan said that he \"taught me how to throw punches and hit me in my chest a couple times.\". Adonis is torn between trying to preserve his father's legacy and build his own. A.O. Scott of \"The New York Times\" wrote that, \"Adonis is a", "score": 10.285269, "title_score": 0, "passage_id": "19178161"}, {"title": "Believe It or Not, Joe's Walking on Air", "text": "culture referencing films, music and media. Peter remembers a movie he watched with actor Jack Black in it, a (fictional) film called \"The Unconventional Butler\". When rock climbing Cleveland is saved from a fall by Spider-Man. Joe makes Cleveland, Quagmire and Peter sing and dance \"Good Morning\" from the film \"Singin' in the Rain\". The title is a based off the theme song to \"The Greatest American Hero\" called \"Believe it or Not, I'm Walking on Air\" sung by Joey Scarbury. The episode makes references to \"Family Guy\" itself. When Bonnie, Lois and Cleveland's new girlfriend come to dance at", "score": 10.280066, "title_score": 0, "passage_id": "9158882"}, {"title": "Sachein", "text": "composed by Devi Sri Prasad. \"Behindwoods\" gave 3.5/5 praised Vijay as \"It is a cakewalk for Vijay and his role has been etched out keeping his fans\u2019 expectations in mind. His comedy track with Vadivelu, who is his collegemate, is quite run-of-mill\" and \"Vijay looks best in roles, which require him to portray tenderness. He wins the competition as the successful romantic hero of this generation of actors\" It's one of my favourite movie. \"The Hindu\" stated `\"Sachein' is a movie that fans would watch for Vijay alone\" and said \"Vijay alone makes the movie extremely watchable\". Sachein Sachein is", "score": 10.276921, "title_score": 0, "passage_id": "7644302"}, {"title": "My Father the Hero (1991 film)", "text": "Promising Actress\" for her performance. Depardieu, already an established actor, provides a trademark comical performance as Andr\u00e9 the 'eager to please' father, doing the unthinkable for his daughter. My Father the Hero (1991 film) My Father the Hero (original French title: \"Mon p\u00e8re, ce h\u00e9ros\") is a 1991 French film directed by G\u00e9rard Lauzier. An English language remake of the movie was made in 1994 . The name of the film comes from a famous poem by the French poet Victor Hugo, \"\"Mon p\u00e8re, ce h\u00e9ros\",\" published in 1859. The story introduces Andr\u00e9 (G\u00e9rard Depardieu), a Frenchman who is divorced", "score": 10.271859, "title_score": 0, "passage_id": "4344973"}, {"title": "My Father the Hero (1991 film)", "text": "My Father the Hero (1991 film) My Father the Hero (original French title: \"Mon p\u00e8re, ce h\u00e9ros\") is a 1991 French film directed by G\u00e9rard Lauzier. An English language remake of the movie was made in 1994 . The name of the film comes from a famous poem by the French poet Victor Hugo, \"\"Mon p\u00e8re, ce h\u00e9ros\",\" published in 1859. The story introduces Andr\u00e9 (G\u00e9rard Depardieu), a Frenchman who is divorced from his wife. He takes his beautiful teenage daughter, V\u00e9ronique (Marie Gillain), on vacation to a paradise island with him. She is desperate to appear as a woman", "score": 10.271774, "title_score": 0, "passage_id": "4344971"}, {"title": "My Father Is a Hero", "text": "fact, it\u2019s the thrills and character interaction that makes The Enforcer much more than a stereotypical trip through the Asian underworld.\" Earl Cressey of DVD Talk rated it 4/5 stars and wrote that it \"combines some fantastic martial arts action and a decent story with great results\". David Johnson of DVD Verdict called it a \"disappointing action movie\" and wrote that he could not accept a child who fights against adult henchmen. My Father Is a Hero My Father Is a Hero (, released in the United States as The Enforcer and Jet Li's The Enforcer) is a 1995 Hong", "score": 10.271641, "title_score": 0, "passage_id": "8996051"}, {"title": "Lucky Jim (1957 film)", "text": "the USA a year later, Howard Thompson of \"The New York Times\" wasn't very impressed and called Ian Carmichael \"an English answer to Jerry Lewis\": \"Let's fervently hope this stale attempt at mirth, furiously sliding back and forth from leaden coyness to plain custard-pie confusion, doesn't mean the end of all the sly, civilized fun we've come to expect from the British specialists.\" In its 2010 obituary over Ian Carmichael, \"The Guardian\" wrote: \"One of his most characteristic and memorable sorties... was his portrayal of Kingsley Amis's Lucky Jim\u2014the anti-hero James Dixon, who savaged the pretensions of academia, as Amis", "score": 10.249866, "title_score": 0, "passage_id": "15443483"}, {"title": "My Hero Academia: Two Heroes", "text": "2018. The film premiered in Australia at Madman Anime Festival Melbourne on September 15, 2018, with Madman Entertainment screening a wider release on September 27, 2018 in Australia, and October 17, 2018 in New Zealand. The film premiered in the United Kingdom at Scotland Loves Anime in Glasgow on October 13, 2018, with Manga Entertainment providing a wider theatrical release in the UK and Ireland from December 4, 2018. The film was also distributed theatrically in Singapore and Indonesia through Odex, with limited screenings on October 6 and October 13, 2018 respectively; and wide releases beginning from October 11 and", "score": 10.23551, "title_score": 0, "passage_id": "20766127"}, {"title": "Let There Be Love (Christina Aguilera song)", "text": "because of that, because what he does is genius and he is a classic hitmaker. But when I was coming out it was at a time when we had the huge pop explosion, and he was all over radio and I just wanted to work with others like Linda Perry and do that route and do \"Beautiful\" and songs like that. We built a level of respect for each other. So at this point, coming together, especially embracing my true pop-starness, at this point in my career having come full circle, I was able to really truly embrace it, and", "score": 10.2204, "title_score": 0, "passage_id": "16885059"}, {"title": "Ben Carson 2016 presidential campaign", "text": "I think everybody has equal rights, but I'm not sure that anybody should have extra rights \u2013 extra rights when it comes to redefining everything for everybody else and imposing your view on everybody else.\" In a March 2015 interview with Chris Cuomo, Carson stated he believes homosexuality is a choice, saying: \"a lot of people go into prison straight, and when they come out, they're gay\". Later, in a Facebook post, Carson wrote that he \"realized that my choice of language does not reflect fully my heart on gay issues. I do not pretend to know how every individual", "score": 10.217995, "title_score": 0, "passage_id": "18388376"}, {"title": "Battlefield Earth (film)", "text": "all over me. They come up to you and they know who you are. And they go, 'We're really excited about \"Battlefield Earth\".'\" This did not impress Mechanic: \"Do you think in any way, shape, or form that weirding me out is going to make me want to make this movie?\" Travolta's involvement in \"Battlefield Earth\" was first publicized in late 1995. He told the \"New York Daily News\" that \"\"Battlefield Earth\" is the pinnacle of using my power for something. I told my manager, 'If we can't do the things now that we want to do, what good is", "score": 10.211535, "title_score": 0, "passage_id": "8745648"}, {"title": "Monkey on My Back (film)", "text": "Code seal of approval, claiming he had not heard back from his appeal for two weeks. This made \"Monkey on My Back\" the first movie to run into trouble with the Production Code since the code had been revised to allow treatment of illicit narcotics within limits. Reviews were generally strong. Monkey on My Back (film) Monkey on My Back is a 1957 biographical film directed by Andre DeToth, starring Cameron Mitchell as Barney Ross, a world champion boxer and World War II hero (based on a real-life titleholder). The movie is heavily fictionalized, but both the movie character and", "score": 10.208461, "title_score": 0, "passage_id": "14615266"}]}, {"dataset": "nq_dev_psgs_w100", "question": "who was the creator of victoria 's secret", "answers": ["Roy Raymond"], "positive_ctxs": [{"title": "Victoria's Secret", "text": "the show.\" Victoria's Secret Victoria's Secret is an American designer, manufacturer, and marketer of women's lingerie, womenswear, and beauty products. Founded in 1977 as a response to packaged underwear, which the company's founder considered to be \"ugly, floral-print nylon nightgowns\", the company is now the largest American retailer of women's lingerie. Victoria's Secret was founded by Roy Raymond, and his wife Gaye Raymond, in San Francisco, California, on June 12, 1977. Eight years prior to founding Victoria's Secret, in the late 1960s, Raymond was embarrassed when purchasing lingerie for his wife at a department store. Newsweek reported him looking back", "score": 1000, "title_score": 1, "passage_id": "13258931"}], "negative_ctxs": [{"title": "Alaska (novel)", "text": "local \"half-breed\" man of white and Eskimo descent. In a typical James Michener fashion, the final chapter is an interaction between various characters in preceding chapter or their descendants. Alaska is in the process of applying for statehood. Missy remains on the side advocating for statehood, while Tom Venn petitioned to keep Alaska a territory and under Seattle business control. In the end President Dwight D. Eisenhower signs the Alaska Statehood Act, making Alaska the 49th state of the Union. Michener invents characters and places although he also uses factual people or places in fictional events. Throughout the novel are", "score": 0, "title_score": 0, "passage_id": "2420146"}, {"title": "John Adams (miniseries)", "text": "than to break off and declare independence. He is also instrumental in the selection of then-Colonel George Washington as the new head of the Continental Army. However, in his zeal for immediate action, he manages to alienate many of the other founding fathers, going so far as to insult John Dickinson, who is for conciliation to the Crown, implying that the man suffers from a religiously based moral cowardice. Later, Benjamin Franklin quietly chastens Adams, saying it is \"perfectly acceptable to insult a man in private. He may even thank you for it afterwards. But when you do it in", "score": 0, "title_score": 0, "passage_id": "11143239"}, {"title": "Forty Fort, Pennsylvania", "text": "the approximate location of Forty Fort. In the years following the Revolutionary War, Forty Fort became home to both the Nathan Denison House (built around 1790) and the Forty Fort Meetinghouse (built in 1806\u201308), which is located in the borough's cemetery. Forty Fort was officially incorporated as a borough in 1887. The borough later became home to the Lower School of the Wyoming Seminary and a portion of the southern end of the Wilkes-Barre Wyoming Valley Airport. In June 1972, Hurricane Agnes caused the Susquehanna River to overflow its banks. In Forty Fort, a portion of the levee protecting the", "score": 0, "title_score": 0, "passage_id": "1214177"}, {"title": "Streetcleaner", "text": "Streetcleaner Streetcleaner is the debut studio album by English industrial metal band Godflesh. It was released on 13 November 1989 through Earache Records and was reissued with a second disc of previously unreleased material on 21 June 2010. The album is widely acclaimed by critics and is often cited as a landmark release in industrial metal; though not the genre's first release, \"Streetcleaner\" helped define what industrial metal would become. Recorded in three distinct sessions and partially refined from pre-Godflesh demos, \"Streetcleaner\" is a weighty, bleak album that blends heavy metal with industrial music by means of production-emphasised bass, distorted", "score": 0, "title_score": 0, "passage_id": "6770504"}, {"title": "HMS Sirius (F40)", "text": "'fly-the-flag' visits to a variety of ports. \"Sirius\" also took part in the Coronation of Taufa'ahau Tupou IV of Tonga. The following year, \"Sirius\" deployed to the West Indies.In 1968 she took part in Portsmouth 'Navy Days'. In 1970, \"Sirius\" again deployed to the West Indies, where she would perform the role of guard ship in that region. The West Indies Guardship deployment was eventually replaced by the Atlantic Patrol Task. While in the West Indies, \"Sirius\" assisted during the St. Kitts disaster, when a ferry sank, killing around 250 people. \"Sirius\" recovered 90 bodies from the sea. Only 90", "score": 0, "title_score": 0, "passage_id": "3031125"}, {"title": "Dolly Cifuentes Villa", "text": "Dolly Cifuentes Villa Dolly de Jesus Cifuentes Villa, born 14 June 1964, is a drug trafficker from Medell\u00edn, Colombia, associated with the Sinaloa Cartel of Mexico. She was arrested and extradited to the United States in August 2012. Villa was sentenced to five years in prison in January 2014 for conspiracy to import and manufacture cocaine and subsequently released in 2015 after serving two years in prison in Colombia and three in the United States. Very little is known about Villa's early life. Villa is part of a drug trafficking family known as the Cifuentes Villa clan or the Cifuentes-Villa", "score": 0, "title_score": 0, "passage_id": "19479833"}, {"title": "David A. Johnston", "text": "A. Johnston Memorial Fellowship for Research Excellence', a number of awards of this fellowship have been made over the years since it was launched. Following the eruption, the area where the Coldwater II observation post had been was sectioned off. Eventually, an observatory was built in the area in Johnston's name, and opened in 1997. Located just over from the north flank of Mount St. Helens, the Johnston Ridge Observatory (JRO) allows the public to admire the open crater, new activity, and the creations of the 1980 eruption, including an extensive basalt field. Part of the Mount St. Helens National", "score": 0, "title_score": 0, "passage_id": "3747341"}, {"title": "Shen of the Sea", "text": "Shen of the Sea Shen of the Sea is a collection of short stories written by Arthur Bowie Chrisman. It was first published by Dutton in 1925, illustrated with more than 50 silhouettes by Else Hasselriis. Chrisman won the 1926 Newbery Medal for the work, recognizing the previous year's \"most distinguished contribution to American literature for children\". The original title page shows subtitle \"A Book for Children\" and one early dustjacket shows \"Chinese Stories for Children\". Both subtitles have been used for later editions. Chrisman's 16 original stories are written in the style of humorous Chinese folk tales. The title", "score": 0, "title_score": 0, "passage_id": "6015819"}, {"title": "Ian Wallace (singer)", "text": "of his suitability for an operatic career, but in 1946 friends persuaded him to audition for the conductor Alberto Erede, who engaged him for the first season of the New London Opera Company. Wallace made his operatic d\u00e9but at the Cambridge Theatre in 1946, as Colline in \"La boh\u00e8me\". He sang there with established operatic stars such as Mariano Stabile and Margherita Grandi. His other roles with the company were the Sacristan (\"Tosca\"), Bartolo (\"The Barber of Seville\"), Ceprano (\"Rigoletto\") and Masetto (\"Don Giovanni\"). The critic of \"The Times\" thought Wallace overplayed the buffo element, both as the Sacristan and", "score": 0, "title_score": 0, "passage_id": "7999038"}, {"title": "Jean-Baptiste Henri Lacordaire", "text": "gave me a faith which henceforth nothing could shake.\" But in 1836 after such considerable success, he was still the object of mounting attacks on his theological stance. Suddenly his mother died. Lacordaire, aware of the need to continue his theological studies, retreated to Rome to study with the Jesuits. There, he published his \"Letter on the Holy See\" in which he reaffirmed with vigor his ultramontane positions, insisting on the primacy of the Roman Pontiff, \"the one and permanent trustee, supreme organ of the Gospel, and the sacred source of the universal communion.\" This text ran afoul of the", "score": 0, "title_score": 0, "passage_id": "1685686"}, {"title": "San Juan Capistrano, California", "text": "down a portion of the downtown area to make way for floats, horses, and people walking in the parade. The event holds the title of being the longest running, and largest non-motorized parade west of the Mississippi. San Juan is served by Capistrano Unified School District. In the 2007\u20132008 academic year San Juan Hills High School opened with about 600 freshman students. It is the city's only public high school. Ultimately, nearly all San Juan Capistrano's high school students will move to this campus as well as some students from Capistrano Beach, San Clemente High School, and southern Ladera Ranch.", "score": 0, "title_score": 0, "passage_id": "1015485"}, {"title": "Osinlokun", "text": "where he assumed headship of the town. While in Badagry, Adele attempted to violently retake the Lagos throne but his efforts were futile. Osinlokun died in 1829 and was succeeded by his son Idewu Ojulari. Osinlokun Oba Osinlokun or Eshinlokun (died 1829) reigned as Oba of Lagos from 1821 to 1829 . His father was Oba Ologun Kutere and his siblings were Obas Adele and Akitoye, making the Ologun Kutere Obaship line the dominant one in Lagos.. Among Osinlokun's children were Idewu Ojulari, Kosoko, and Opo Olu. Around 1820 or 1821, Osinlokun seized on the unpopularity of his younger brother", "score": 0, "title_score": 0, "passage_id": "19909199"}, {"title": "Alexei Shulgin", "text": "IS\" easylife.org/desktop/desktops.html is a project which reveals the contents of a few dozen participants actual desktops, and provides links to their contents. \"Turn off the tv set\" desk.nl/~you/turnoff/ is another example of Shulgin's net.art work in action, whereby the viewer is able to turn off and on a small television set in the middle of the screen, and from there the user is invited to interactively \"channel surf\" the set from the web. \"Remedy for Information Disease\" desk.nl/~you/remedy/ is one of the latest links provided on the easy life page. On the first page, the viewer is informed that \"All", "score": 0, "title_score": 0, "passage_id": "3208130"}, {"title": "Rafael Puignau", "text": "job offer from Casa Rodr\u00edguez in Madrid. This workshop employed around 20 workers and was the most modern in Spain at that time. Almost all the pipework came directly from Laukhuff company in Germany. In 1914 Puignau was recruited by Francisco Aragon\u00e9s as senior organ builder in a new settled organ building company: Viuda de Amezua, Aragon\u00e9s, Eleizgaray y Cia., in the village of Azpeitia in the province of Gipuzkoa. His main task would be the phonic part of organs, that is to say, everything related to pipes and its harmonization. In 1916 the name of the company changed to", "score": 0, "title_score": 0, "passage_id": "18777123"}, {"title": "Highley railway station", "text": "Highley railway station Highley railway station is a station on the Severn Valley Railway heritage line in Shropshire, near the west bank of the River Severn and just under a mile south-east of the village of Highley. Highley is the only staffed single-platform station on the line. Other stops with one platform are unstaffed halts. Highley station opened to the public on 1 February 1862 and closed on 9 September 1963, before the Beeching axe closures. Highley station was important as the transport hub of a colliery district, with four nearby coal mines linked to the Severn Valley line by", "score": 0, "title_score": 0, "passage_id": "7942992"}, {"title": "Postal Union Congress \u00a31 stamp", "text": "produce a more impressive souvenir for the visiting postal delegates to the Congress. Alternatively, others have simply seen it as a cynical attempt to extract as much money as possible from stamp collectors. Stanley Phillips said in Gibbons Stamp Monthly that the stamp was \"\"Britain\u2019s disgrace\"\". He also said that \"\"...the policy of issuing a set consisting of four low value stamps and then a one pound denomination is absolutely indefensible.\"\" The stamp was line engraved and recess printed by Bradbury, Wilkinson & Co. The contract was given to them on condition that the stamp would be engraved by J.A.C.Harrison.", "score": 0, "title_score": 0, "passage_id": "15295899"}, {"title": "Islam and antisemitism", "text": "and their outbursts at any time. On the contrary, the more we suffer and choose to conciliate them, the more they choose to act belligerently toward us. Mark Cohen quotes Haim Hillel Ben-Sasson, a specialist in medieval European Jewish history, who cautioned that Maimonides' condemnation of Islam should be understood \"in the context of the harsh persecutions of the 12th century and that furthermore one may say that he was insufficiently aware of the status of the Jews in Christian lands, or did not pay attention to this, when he wrote the letter\". Cohen continues by quoting Ben-Sasson, who argues", "score": 0, "title_score": 0, "passage_id": "1430793"}, {"title": "Cuban emerald", "text": "Cuban emerald The Cuban emerald (\"Chlorostilbon ricordii\") is a species of hummingbird in the family Trochilidae. It is found in a wide range of semi-open habitats in Cuba, the Isle of Pines, and the western Bahamas. This bird is known locally as zun-zun, and can be observed to be feeding throughout the day, perching on a wire to rest. The male is almost entirely metallic or iridescent green and measures up to long. He has a slight bluish tinge to the breast, white spot behind the eye and a forked black tail. The female differs with a grey throat, breast", "score": 0, "title_score": 0, "passage_id": "10546103"}, {"title": "Medical algorithm", "text": "with most science and medicine, algorithms whose contents are not wholly available for scrutiny and open to improvement should be regarded with suspicion. Computations obtained from medical algorithms should be compared with, and tempered by, clinical knowledge and physician judgment. Medical algorithm A medical algorithm is any computation, formula, statistical survey, nomogram, or look-up table, useful in healthcare. Medical algorithms include decision tree approaches to healthcare treatment (e.g., if symptoms A, B, and C are evident, then use treatment X) and also less clear-cut tools aimed at reducing or defining uncertainty. Medical algorithms are part of a broader field which", "score": 0, "title_score": 0, "passage_id": "4650403"}, {"title": "Battle of Quiberon Bay", "text": "Quiberon, which sighted the French fleet at 2pm on the 15th, 70 miles west of Belle-Isle. She met Hawke the next day and he sailed hard for Quiberon into a SSE gale. Meanwhile, had arrived in Quiberon Bay the night before to warn Duff and he had put his squadron to sea in the teeth of a WNW gale. Having struggled with unfavourable winds, Conflans had slowed down on the night of the 19th in order to arrive at Quiberon at dawn. 20 miles off Belleisle he sighted seven of Duff's squadron. Once he realised that this was not the", "score": 0, "title_score": 0, "passage_id": "2671026"}, {"title": "Vienna General Hospital", "text": "the beginning, the personnel hostels and the university clinics for child medicine were moved. In 1974, the building of the main house began. This consists of an outpatient clinic and OI area (approx. 50 OI halls) and two large, 22-floor high bed towers, which accommodate 2,200 beds. The AKH is connected with its own underground (metro) station (U6 Michelbeuern/AKH) to the public transportation network. The Zentralbau with the bed towers was officially opened in 1994, but already partly in use from 1991. The total construction costs are equivalent, in 2004 values, to approximately 4.5 billion euro, projected as 1 billion", "score": 0, "title_score": 0, "passage_id": "9967813"}, {"title": "John Anster Fitzgerald", "text": "with other artists. He existed mainly at his London club, the Savage Club. Fellow members, reminiscing of him post mortem, recalled that he was adept at imitating the great actors of earlier generations, Edmund Kean, Charles Kemble, and William Charles Macready. The final work Fitzgerald exhibited at the Royal Academy, in 1902, was a picture of Alice in Wonderland. Twentieth-century art forgers have been active in creating phony Fitzgerald fairy pictures. The forgeries were discovered when analysis revealed modern pigments. Brought to public attention by the 1998 exhibition of Victorian fairy paintings at the Royal Academy of Arts his paintings", "score": 0, "title_score": 0, "passage_id": "7931795"}, {"title": "Byte order mark", "text": "as UTF-7, see table below), and none of the sequences is likely to appear at the start of text streams stored in other encodings. Therefore, placing an encoded BOM at the start of a text stream can indicate that the text is Unicode and identify the encoding scheme used. This use of the BOM character is called a \"Unicode signature\". If the BOM character appears in the middle of a data stream, Unicode says it should be interpreted as a \"zero-width non-breaking space\" (inhibits line-breaking between word-glyphs). In Unicode 3.2, this usage is deprecated in favor of the \"Word Joiner\"", "score": 0, "title_score": 0, "passage_id": "995886"}, {"title": "By Appointment Only (1933 film)", "text": "By Appointment Only (1933 film) By Appointment Only is a 1933 American pre-Code film directed by Frank R. Strayer. Successful doctor Michael Travers (Lew Cody) juggles a busy schedule of patients, one of whom is the mother of 14-year-old Judy (Sally O'Neil). After Judy's mother dies, Travers and his fianc\u00e9, Diane Manners (Aileen Pringle), take responsibility for Judy's care. Upon returning from a three-year trip to Europe, Travers finds himself falling in love with Judy, despite her engagement to Diane's younger brother, Dick. Tensions rise as the four become aware of each other's feelings. Travers finally realizes how things must", "score": 0, "title_score": 0, "passage_id": "15101714"}, {"title": "Heroin", "text": "that examines each product individually. The opium poppy was cultivated in lower Mesopotamia as long ago as 3400 BCE. The chemical analysis of opium in the 19th century revealed that most of its activity could be ascribed to two alkaloids, codeine and morphine. Diamorphine was first synthesized in 1874 by C. R. Alder Wright, an English chemist working at St. Mary's Hospital Medical School in London. He had been experimenting with combining morphine with various acids. He boiled anhydrous morphine alkaloid with acetic anhydride for several hours and produced a more potent, acetylated form of morphine, now called \"diacetylmorphine\" or", "score": 0, "title_score": 0, "passage_id": "181234"}, {"title": "Jeronimo van Ballegoijen", "text": "divorced and he had to move to Sri Lanka with his mother and sister. On his return to the Netherlands, he enrolled in a high school with musical program. This landed him an acting and singing role in the 2007 coming-of-age film \"Timboektoe\", where he sings \"I Could Have Loved You\" produced and recorded by the band members of Relax. His debut charting hit in the Netherlands was \"I Am No Superman\" featuring rapper Stay-C (Stacey Seedorf) that reached #11 in the Single Top 100. This was followed by the 2012 album \"One Kiss\" and the successful title track hit", "score": 0, "title_score": 0, "passage_id": "18042341"}, {"title": "Expense management", "text": "Expense management Expense management refers to the systems deployed by a business to process, pay, and audit employee-initiated expenses. These costs include, but are not limited to, expenses incurred for travel and entertainment. Expense management includes the policies and procedures that govern such spending, as well as the technologies and services utilized to process and analyze the data associated with it. Software to manage the expense claim, authorization, audit and repayment processes can be obtained from organizations that provide a licensed software, implementation and support service, or alternatively, from software as a service (SaaS) providers. SaaS providers offer on-demand web-based", "score": 0, "title_score": 0, "passage_id": "10060093"}, {"title": "Pleasant Hill United Church of Christ", "text": "but it was later removed and replaced by a frame structure on the same site. It in turn was replaced by a brick building in Pleasant Hill; according to a congregation historian, this change was the result of an 1868 storm that virtually destroyed the old building. This structure served the congregation for slightly more than forty years; following the worship service of 10 April 1910, it was taken down to facilitate the construction of the present building on the same site. During the 20th century, the congregation became a part of the United Church of Christ, within which it", "score": 0, "title_score": 0, "passage_id": "16220889"}, {"title": "Flange", "text": "Pipes with flanges can be assembled and disassembled easily. A flange can also be a plate or ring to form a rim at the end of a pipe when fastened to the pipe (for example, a closet flange). A blind flange is a plate for covering or closing the end of a pipe. A flange joint is a connection of pipes, where the connecting pieces have flanges by which the parts are bolted together. Although the word flange generally refers to the actual raised rim or lip of a fitting, many flanged plumbing fittings are themselves known as 'flanges': Common", "score": 0, "title_score": 0, "passage_id": "557529"}, {"title": "1998\u201399 in English football", "text": "at this level, defeating Gillingham in a dramatic play-off final. Ambitious Reading could only manage an 11th-place finish in their first season at the impressive new Madejski Stadium, while Stoke City's early promise under Brian Little was short-lived and an eighth-place finish wasn't enough for an even a playoff place. Stoke then turned to Gary Megson in their quest to get back into Division One. This season proved a step too far for Macclesfield, who had been promoted from the Conference and Division Three in successive years, and they were relegated in bottom place. Lincoln City were unable to recover", "score": 0, "title_score": 0, "passage_id": "7164643"}, {"title": "Protection International", "text": "Colette Braeckman, specialist of the DRC, \"all the more relevant as Didace Namujimbo, another journalist from Bukavu who also worked for the Monuc -which didn't take any civil action for both of its contributors- was assassinated in similar circumstances in 2008\" In August 2009, after the assassination of Bruno Koko Chirambiza, journalist at the Bukavu private station Radio Star Protection International, along with four other NGO's (Action des chr\u00e9tiens pour l'abolition de la torture, F\u00e9d\u00e9ration de l'action des chr\u00e9tiens pour l'abolition de la torture, Frontline et Diakonie), asked the Congolese authorities to put an end to impunity, claiming that \"the", "score": 0, "title_score": 0, "passage_id": "14750147"}, {"title": "Andromeda (Rodin)", "text": "Andromeda (Rodin) Andromeda is a sculpture by the French artist Auguste Rodin, named after Andromeda. It is one of the sculptures produced as part of his \"The Gates of Hell\" project and appears on the left door next to the personification of Day and on the right door as part of the group showing a falling winged genius. It was exhibited for the first time in 1889 at the Galerie Georges Petit in a joint exhibition with Claude Monet. The poet Rainer Maria Rilke praised the work's expressive quality, which he held to be more disperse, grandiose and mysterious than", "score": 0, "title_score": 0, "passage_id": "20678989"}, {"title": "Bill 78", "text": "molotov cocktails, and the response of police with rubber bullets, tear gas and percussion bombs against protesters. Most other times protests were wholly peaceful. Several protesters wore masks in protest of Montreal's recent bylaw criminalizing their use in protests; the Harper government is seeking to make their use during unlawful assembly an offense punishable by up to 10 years' imprisonment. Police declared the weekend protests to be illegal from Montreal Bylaw P-6, arresting 69 persons on the night of the bill's passage, and 308 on the following night. Members of CLASSE voted on 20 May to call for continued protests", "score": 0, "title_score": 0, "passage_id": "16531365"}, {"title": "Pegeen Vail Guggenheim", "text": "exhibition at the Hanover Gallery. Rumney was an English New Realist and one of the founders, along with Guy Debord and Piero Simondo, of the Situationist International. Guggenheim married Rumney in 1958 and gave birth to her fourth son, Sandro Rumney, the same year. In 1959, the couple moved to Paris, where they lived first on the rue du Dragon and then on the \u00cele Saint-Louis. Guggenheim died in Paris on March 1, 1967, after overdosing on medication. She struggled all her life with depression. During her short career, Guggenheim exhibited her work in New York (including the Museum of", "score": 0, "title_score": 0, "passage_id": "14777667"}, {"title": "Exhaled nitric oxide", "text": "normal level of eNO in different studies ranges from 20 to 30 parts per billion. However, several major features influence the reference values. Men have higher eNO values than women. Smoking notoriously lowers eNO values, and even former smoking status can influence results. The levels are higher in people with an atopic constitution (a tendency towards allergies). The fraction of eNO is also flow-dependent (higher at lower flow rates and vice versa), so measurements are normally measured at 50 ml/s. Age or height could also considerably confound eNO values in children. The magnitude of these effects lies in the order", "score": 0, "title_score": 0, "passage_id": "12239094"}, {"title": "La Femme Pie\u0300ge", "text": "Jill returns to her hotel room where she takes two red pills of HLV, John's drug. The drug erases John from Jill's memory. Meanwhile, the news media are reporting about the block of concrete and the liberation of Horus, which was followed by the brutal murder of the workers who freed him onboard of the space vessel Europe I. Upon hearing this news, Jeff Wynatt, a friend of Jill Bioskop and former journalist, hurries towards the hotel where Jill is staying. He finds her in a deep coma and wakes her with cold water. Afterwards during a dinner in a", "score": 0, "title_score": 0, "passage_id": "5033306"}, {"title": "Forneus", "text": "can take many different forms but mainly prefers his human form. Forneus In demonology, Forneus is a Great Marquis of Hell, and has twenty-nine legions of demons under his rule. He teaches Rhetoric and languages, gives men a good name, and makes them be loved by their friends and foes. He is depicted as a great sea monster. He causes men to have a good name and to have the knowledge and understanding of tongues. He makes one beloved by his foes as well as of his friends. He is partly of the Order of Thrones, and partly of that", "score": 0, "title_score": 0, "passage_id": "1909051"}, {"title": "Fe\u0301de\u0301ration des producteurs de lait du Que\u0301bec", "text": "agreement. Milk producers joined forces in 1983 within the 'F\u00e9d\u00e9ration des producteurs de lait du Qu\u00e9bec (FPLQ), a federation of 14 syndicates that included two federations: the fluid milk producers (1970) and the industrial milk producers (1966). On May 1, 2014, the F\u00e9d\u00e9ration des producteurs de lait du Qu\u00e9bec became Les Producteurs de lait du Qu\u00e9bec. Out of concern for a lighter administrative load and consistency with their provincial joint marketing plan, the 14 regional syndicates and the Federation disbanded to form a single legal entity. It went from a federation of 14 member syndicates to one single organization where", "score": 0, "title_score": 0, "passage_id": "14978812"}, {"title": "Laikipia University", "text": "is situated in a serene environment which is conducive for learning. The Main Campus is the University nerve centre where most courses are offered and has the majority of students. The Main Campus has numerous facilities ranging from classrooms, laboratories, library, cyber cafe, bookshop, sports & games facilities, hostels for student accommodation, a health centre, restaurant, farm and Lake Chacha, among others.. The university is into collaborations with Embu college, Nakuru Teachers College, Elgon View College, Kenya Institute of Development studies and Karlstad University(Sweden). The Campus was established in 2002 as the Centre for Continuing Education to cater for the", "score": 0, "title_score": 0, "passage_id": "17421101"}, {"title": "Department of Tourism, Leisure and Transport", "text": "and the Department of Transport. Department of Tourism, Leisure and Transport The Department of Tourism, Leisure and Transport is a former department of the Isle of Man Government. Prior to 1990 the Department was known as the Department of Tourism and Transport. In 1990 the Department of Tourism and Transport was given the extra responsibility of Leisure and thus renamed the Department of Tourism, Leisure and Transport with a new Minister of Tourism, Leisure and Transport. In 1994 there was a departmental reorganisation. The Department of Highways Ports and Properties and this Department of Tourism, Leisure and Transport became the", "score": 0, "title_score": 0, "passage_id": "7073486"}, {"title": "1962 Dutch Grand Prix", "text": "driver Graham Hill driving a BRM P57. It was the first Grand Prix victory for the future dual-World Champion and the second time a BRM driver had won the race after Jo Bonnier in 1959. Hill finished over 27 seconds ahead of Team Lotus driver Trevor Taylor driving a Lotus 24. The reigning World Champion, Ferrari's Phil Hill (Ferrari 156) completed the podium. The race provided an indication of the season to come as the long-maligned British Racing Motors organisation were on their way to their first and ultimately only constructor's championship. It also signalled Hill's own rise in the", "score": 0, "title_score": 0, "passage_id": "4004653"}, {"title": "Scout Association of Japan", "text": "with an emphasis on developing each young person's character, health, abilities and sense of service to others. The Scout Association of Japan is a non-political, voluntary movement, with open subscription. The geographic structure of Japanese Scouting is the Council, generally conforming to prefecture boundaries. Japanese Scouting also exists abroad, in communities with large native Japanese populations, such as Amsterdam, Netherlands and Singapore. In recent years, SAJ held several international events, which include the sixth Nippon Agoonoree in Ehime in August 1999, the 5th Nippon Venture in \u014cita in August 2000, the National Rover Moot 2001 in Aichi in August 2001,", "score": 0, "title_score": 0, "passage_id": "6302857"}, {"title": "1935 FA Cup Final", "text": "with a knee injury since the semi-final. Harry Jones being the unlucky player to miss out. In hindsight the decision to play Carter was clearly a gamble and a mistake with no substitutes allowed. Carter was limping after only ten minutes of the match and missed two second half chances which he may have taken if he had been fully fit. Another controversial move by West Brom was the decision to leave out Arthur Gale who had played in all six FA Cup ties leading up to the final that season, scoring four goals from the right wing. Gale was", "score": 0, "title_score": 0, "passage_id": "9598081"}, {"title": "William C. Goggin", "text": "were added: As we first thought of it, the matrix organization was to be two-dimensional... the different businesses in Dow Corning were seen as: About Geographical areas Goggin further explained \"that each area is considered to be both a profit and a cost center. Dow Coming area organizations are patterned after our major U.S. organization. Although somewhat autonomous in their operation, they subscribe to the overall corporate objectives, operating guidelines, and planning criteria. During the annual planning cycle, for example, there is a mutual exchange of sales, expense, and profit projections between the functional and business managers headquartered in the", "score": 0, "title_score": 0, "passage_id": "18553262"}, {"title": "Akbank", "text": "Citigroup and Akbank announced that, following receipt of all required regulatory approvals, the parties have completed the acquisition by Citigroup of a 20% stake in Akbank. Under the terms of their agreement announced on 17 October 2006, Citigroup has acquired a 20% equity stake in Akbank for approximately $3.1 billion, at a price of 9.50 Yeni Kurus (YKr) per share. Citigroup obtained its shares in Akbank through (a) the purchase of shares equal to approximately 11.67% of the fully diluted capital of Akbank from Sabanci family members and Sabanci Holding subsidiaries at 9.50 YKr per share and (b) the issuance", "score": 0, "title_score": 0, "passage_id": "9739488"}, {"title": "Case IH Axial Flow Combines", "text": "the present day. International Harvester had launched the 15 series of conventional combine harvesters in 1968. In 1977, after extensive engineering efforts and a bottom up design, IH released the 1440 and 1460 models of harvester. In 1978, the larger model 1480 was released, as well as the specialty models 1470 (for hillside operation), and the 1482, designed to be pulled behind a tractor with PTO capability. Further models were introduced as the series was developed including the 1420 in 1980, In 1985, International Harvester and Case Corporation merged. The 16 series was the first harvester series released by the", "score": 0, "title_score": 0, "passage_id": "19013762"}, {"title": "United States v. Booker", "text": "was upheld on appeal by the US Court of Appeals. His sentence was later reduced by the new federal sentencing guidelines for crack cocaine offenses. He has a projected release date of 13 June 2015. The decision has been criticized for fear that defendants and prosecutors will suffer from greater uncertainty and that some plea agreements will be entered into or rejected because of mistaken beliefs on the sentences that the judge will impose if the case is taken to trial or settled with a guilty plea. United States v. Booker United States v. Booker, 543 U.S. 220 (2005), is", "score": 0, "title_score": 0, "passage_id": "5299816"}, {"title": "Bugang", "text": "is that of the Dipper as a pointer \u2014 and a conductor \u2014 stretching out from the pole of heaven to the belt of the celestial equator and, by its annual movement, like the outer leg of a compass, describing a circle which is the circumference of heaven\" (Andersen 1989:25). In Chinese terms, \"gang\" \u7db1 \"guiding rope of a net\" is the Dipper and \"ji\" \u7d00 \"leading thread\" is the circle, and their original meanings were semantically extended in \"gangji\" \u7db1\u7d00 \"social order and law\", the norms of conduct directed by the emperor. \"Gang\" and \"Ji\" connect in the constellation", "score": 0, "title_score": 0, "passage_id": "18013110"}, {"title": "Oliwa", "text": "the city of Gda\u0144sk. Oliwa Oliwa, also Oliva, is one of the quarters of Gda\u0144sk, Poland. From east it borders Przymorze and \u017babianka, from the north Sopot and from the south with the districts of Strzy\u017ca, VII Dw\u00f3r and Br\u0119towo, while from the west with Matarnia and Osowa. It is known for its medieval monastery, the 1627 Battle of Oliva and the 1660 Peace of Oliva. Oliwa is a part of the northern Polish city of Gda\u0144sk. It is bordered on the east by the Bay of Gda\u0144sk (Zatoka Gda\u0144ska), on the north by the town of Sopot, on the", "score": 0, "title_score": 0, "passage_id": "2728356"}, {"title": "Discovery and settlement of Hawaii", "text": "and briefly, as the population grew so did their agricultural imprint (forest clearing by burning) and building of \"heiau\" at those sites, as well as the decline of plants. The paleo-environmental data showed that during 1450-1778 the pace of construction of \"heiau\" slowed dramatically as did the clearing of agricultural land. Accordingly, the estimated population in 1778 around Cook's arrival was between 110,000 and 150,000. James Cook was not the first Westerner to visit Hawaii. Diseases to which Hawaiians lacked immunity may well have already been spread. Testing of a young woman's bones buried in O'ahu, dated sometime between AD", "score": 0, "title_score": 0, "passage_id": "19426834"}], "hard_negative_ctxs": [{"title": "The Time of Our Lives (TV series)", "text": "The Time of Our Lives (TV series) The Time of Our Lives is an Australian television drama series which premiered on ABC TV on 10 June 2013, at 8.30pm. It is a JAHM Pictures production in association with ABC TV and Film Victoria. The producer Amanda Higgs (co-creator of \"The Secret Life of Us\") and principal writer Judi McCrossin (\"The Secret Life of Us\", \"Tangle\", \"The Surgeon\", \"Beaconsfield\") were also co-creators. The show follows the lives of the Tivolli clan, an Australian extended family in inner-city Melbourne. Aged in their thirties and forties, the characters are occupied with career advancement,", "score": 9.641434, "title_score": 0, "passage_id": "16623292"}, {"title": "Private Practice (season 1)", "text": "\"Grey's Anatomy\". Even though network executives and series creator Shonda Rhimes did not confirm plans for \"Private Practice\", Wyatt called it a \"well-known secret\" as information about the casting and production was becoming increasingly more available. The spin-off was officially confirmed through subsequent media commentators, who stated that the two-part episode \"The Other Side of This Life\" would serve as the backdoor pilot for the new series. \"Grey's Anatomy\" cast members Ellen Pompeo and Katherine Heigl had mixed reactions to the decision to create a spin-off for Kate Walsh's character Addison Montgomery. \"Today\"'s Jeannette Walls reported that Pompeo was angry", "score": 9.342263, "title_score": 0, "passage_id": "13948085"}, {"title": "Lisa Jones", "text": "Hand\" and \"Stained\" were collaborations with Alva Rogers, who was also a Rodeo Caldonia member. In 1995, Jones and Rogers received a joint choreography and creator Bessie Award for their collaborative work. Lisa Jones Lisa Victoria Chapman Jones (born August 15, 1961) is an American playwright, essayist, journalist, and memoirist. Jones grew up in New York City and Newark, New Jersey. She is the daughter of poets Hettie Jones and Amiri Baraka (formerly known as LeRoi Jones). Jones graduated from Yale University and received a MFA in Film from New York University. She married Kenneth S. Brown in 2004 and", "score": 9.321074, "title_score": 0, "passage_id": "14582948"}, {"title": "Jorge Moreno", "text": "signature version of Babalu' on the Victoria Secret Fashion show broadcast worldwide and seen by over 40 million people. In 2011 Moreno won the International Songwriters contest as best Video for his song \"Thank you\" and came in as first runner up for the composition. Moreno can also add TV Producer to his many talents, he opened a Production company on South beach named Beach Pictures which focuses on Docu-Reality content. He has produced content for MTV, CURRENT TV, TLC and the CW. He was creator and Executive producer of the summer series \"The Catalina\" based on the real life", "score": 9.163783, "title_score": 0, "passage_id": "12211569"}, {"title": "Christopher Lee (writer)", "text": "Radio School. He was the creator and writer of the ABC drama series \"Stringer\", head writer and then script executive of the ABC-BBC drama series \"Police Rescue\". He wrote four of the six \"Cody\" telemovies, and was co-creator and Head Writer of \"Big Sky\". He was an originating writer (with Judi McCrossin) of \"The Secret Life of Us\" and co-creator and Head Writer of the short-lived soapie \"Echo Point\". He is the co-creator of the television series \"Rush\". He wrote the SBS teleplay \"That Man's Father\", co-wrote the telemovie, \"Secret Men's Business\" (with \"Nicholas Hammond\") and wrote the 4-hour mini-series", "score": 9.143245, "title_score": 0, "passage_id": "8513276"}, {"title": "The Secret Circle", "text": "up \"The Secret Circle\" with \"Dawson's Creek\" creator and \"The Vampire Diaries\" co-creator/executive producer Kevin Williamson attached. However, Williamson told The CW that \"The Vampire Diaries\" companion series he had been helming was put on hold as he did not have enough time for it. Williamson worked on an original script penned by Andrew Miller, creator of the Emmy-nominated web series \"Imaginary Bitches\", with writer credit shared by both men. On February 16, 2011, \"The Secret Circle\" booked Liz Friedlander to direct the pilot. Friedlander also directed episodes for \"The Vampire Diaries\", \"Pretty Little Liars\", \"90210\" and \"One Tree Hill\".", "score": 9.122294, "title_score": 0, "passage_id": "15013983"}, {"title": "The 39 Steps (2008 film)", "text": "her leaving with a man, whom he recalls seeing previously on the train and at the rally. With the notebook missing and finding out that Victoria disconnected the call she made to the Secret Service Bureau before it was connected, Hannay goes to Stirling Castle, believing Victoria to be a traitor. There, Victoria reveals she works for the Secret Service Bureau and he meets Kell (Alex Jennings) and Wakeham, the man Victoria left with earlier (Steven Elder), who reveal they used Hannay to distract the Germans and sent Victoria to keep an eye on him. Hannay deduces that Sir George", "score": 9.114311, "title_score": 0, "passage_id": "12833035"}, {"title": "Dennis Hopeless", "text": "Dennis Hopeless Dennis Hopeless is an American comics writer from Kansas City, Missouri who has written for Marvel Comics, Image Comics, Dark Horse Comics, Boom! Studios, Arcana Studio, and Oni Press. Hopeless has written multiple series starring teenage superheroes and has said that he \"tend[s] to write about the challenge of growing up.\" He's been praised by critics for including a female point-of-view in his comics. After finding success with two creator-owned comics, Hopeless began writing for Marvel in 2011. In 2015, Hopeless wrote two limited series as part of Marvel's \"Secret Wars\" event. The following year, Hopeless began scripting", "score": 8.993422, "title_score": 0, "passage_id": "19476977"}, {"title": "Secret Story 1 (Portuguese season)", "text": "a relationship with Daniela. He was the creator of the \"Boi Marinho Group\". Vasco was evicted on Day 14 with 69% of the votes, against V\u00edtor. Vera was 21 and lives in Sintra. She told her secret to other housemates on Day 22, without revealing it was hers, but still she was punished by losing all her account money. Her secret was that she had an affair with a famous Portuguese football player (Ruben Amorim). Vera is the only housemate who has never been nominated. Vera got third place. V\u00edtor Rangel was 37 and lives in Porto. His secret was", "score": 8.976294, "title_score": 0, "passage_id": "14943166"}, {"title": "Book of the Secret Supper", "text": "a secret supper in the kingdom of heaven. The book begins with the story of the opposing forces of the Invisible Father, the creator of good, and Satan, the creator of evil, who shines white before his fall and burns red after. Jesus tells John how Satan took over the world, descending from the third heaven and recruiting angels to join him \u201caccording to the plan of the Governor Most High.\u201d Satan brought forth all living things, plants, animals, fish and birds, then created man and woman from clay, animating the man with an angel from the second heaven and", "score": 8.937814, "title_score": 0, "passage_id": "20996458"}, {"title": "S.L.A.I.: Steel Lancer Arena International", "text": "The mid-ranged Carro has the most balanced specs out of all of the SVs. S&V Ma. Fabrik \u2013 A German robot company founded in 2016. S&V's Scoobie, the shortrange/melee-type Zwerg (German for Dwarf) has unique melee weapons like the EMP-Fist. American Stars - The American conglomerate that has been making some of the world's leading SVs from 2012 to 2071. It is the supplier of the heavy Hartman SV. Tolomeo, the creator of two secret SVs in the first Game, was removed from SLAI. Player \u2013 represents yourself in the Story mode of gameplay. You can determine your gender when", "score": 8.894482, "title_score": 0, "passage_id": "9716920"}, {"title": "Batman & Bill", "text": "to costume to the very character we all know and love. Bruce Wayne may be Batman's secret identity, but his creator was always a true mystery.\" The documentary features interviews with Marc Tyler Nobleman, Michael E. Uslan, Roy Thomas, Kevin Smith, Todd McFarlane, Charles Sinclair, Thomas Andrae, Fred Van Lente, Arlen Schumer, Carmine Infantino, Jerry Robinson, Bob Kane, Travis Langley, Athena Finger, Benjamin Zaido Cruz, Stacey C. Friends, and Alethia Mariotta. For more than 75 years Bob Kane had been the sole legally acknowledged creator of Batman. The 2012 book \"Bill the Boy Wonder: The Secret Co-creator of Batman\" by", "score": 8.792467, "title_score": 0, "passage_id": "20120018"}, {"title": "Sam Bawlf", "text": "Sam Bawlf Robert Samuel \"Sam\" Bawlf (June 7, 1944 \u2013 August 20, 2016) was a Canadian politician and author. In 1972, Bawlf was elected to Victoria City Council, the youngest person ever to have been so. In 1975, he was elected to the Legislative Assembly of British Columbia for the riding of Victoria as a member of the Social Credit Party. He was soon appointed Minister of Conservation and Recreation by Premier Bill Bennett. As minister, he oversaw the enactment of B.C.\u2019s first Heritage Conservation Act. He was defeated in the 1979 general election. Bawlf\u2019s book, \"The Secret Journey of", "score": 8.753814, "title_score": 0, "passage_id": "18730315"}, {"title": "Bratvaag Expedition", "text": "Bratvaag Expedition The Bratvaag Expedition was a Norwegian expedition in 1930 led by Dr. Gunnar Horn, whose official tasks were hunting seals and to study glaciers and seas in the Svalbard Arctic region. The name of the expedition was taken from its ship, M/S \"Bratvaag\" of \u00c5lesund, in which captain Peder Eliassen had sailed the Arctic seas for more than twenty years. The \"Bratvaag\" Expedition had a secret, but important mission: the annexation of Victoria Island for Norway. Although a successful landing on the island was achieved, Victoria Island was later annexed by the Soviet Union. The \"Bratvaag\" Expedition became", "score": 8.733723, "title_score": 0, "passage_id": "9532984"}, {"title": "The Secret Diary of Laura Palmer", "text": "The Secret Diary of Laura Palmer The Secret Diary of Laura Palmer is a 1990 spin-off novel from the television series \"Twin Peaks\" by Jennifer Lynch. Lynch, then aged 22, is the daughter of series co-creator David Lynch. It was published between the airing of the first and second season. The novel is said to be \"As seen by Jennifer Lynch,\" and is written in a matter-of-fact tone from the point of view of Laura Palmer, a small-town teenager \u2014a \"good girl gone bad\"\u2014 who is abused and terrorized by the demonic entity BOB. Lynch says she was told by", "score": 8.646545, "title_score": 0, "passage_id": "14688591"}, {"title": "Spymaker: The Secret Life of Ian Fleming", "text": "A Kill\", made an appearance. Spymaker: The Secret Life of Ian Fleming Spymaker: The Secret Life of Ian Fleming is a 1990 TV biographical film of the life of Ian Fleming, creator of the popular James Bond spy character, retracing his playboy youth, his expulsion from various colleges, his experiences as a newspaper writer and his tour of duty for the British intelligence agency during World War II. Fleming himself is played by Jason Connery, son of Sean Connery, the actor who helped make Bond an icon in the films made in the 1960s. Ex-Bond girl Fiona Fullerton , who", "score": 8.61812, "title_score": 0, "passage_id": "7723280"}, {"title": "Spymaker: The Secret Life of Ian Fleming", "text": "Spymaker: The Secret Life of Ian Fleming Spymaker: The Secret Life of Ian Fleming is a 1990 TV biographical film of the life of Ian Fleming, creator of the popular James Bond spy character, retracing his playboy youth, his expulsion from various colleges, his experiences as a newspaper writer and his tour of duty for the British intelligence agency during World War II. Fleming himself is played by Jason Connery, son of Sean Connery, the actor who helped make Bond an icon in the films made in the 1960s. Ex-Bond girl Fiona Fullerton , who appeared in \"A View To", "score": 8.61812, "title_score": 0, "passage_id": "7723279"}, {"title": "Creator (horse)", "text": "Elliot Walden explained, \"[Creator]'s been a very high-strung horse in the beginning. I liked what Steve had done with some of the Tapits he's had in the past, so that's why we sent Creator to him. ... I love his style.\" Just before the Belmont Stakes, celebrity chef Bobby Flay purchased a minority interest in the colt. Creator is a closer who likes to sit back and make a strong late move. In 2015 at the age of two, Creator ran four times, finishing second three times and fifth once. His first race on September 19 was typical: the chart", "score": 8.603544, "title_score": 0, "passage_id": "19562825"}, {"title": "Victoria Lord", "text": "Victoria Lord Victoria Lord is a fictional character and matriarch of the Lord family on the American soap opera \"One Life to Live\". The character was created as one of the main protagonists by series creator Agnes Nixon, and first cast to Gillian Spencer on the pilot aired July 15, 1968. Nixon later recast her with Erika Slezak, who became synonymous with the character role following a continual portrayal spanning her debut March 17, 1971 through the ABC Daytime finale January 13, 2012. Slezak reprised the role in The Online Network continuance of \"One Life to Live\" aired on Hulu,", "score": 8.597373, "title_score": 0, "passage_id": "5163217"}, {"title": "The Secret Circle (TV series)", "text": "and her powers a secret in order to keep her safe; as the circle soon finds out, their powers attract dark and dangerous forces that constantly puts them in harm's way. On October 28, 2010, L. J. Smith announced that the series had been optioned for a TV series by The CW. On February 8, 2011, The CW picked up \"The Secret Circle\" with \"Dawson's Creek\" creator and \"The Vampire Diaries\" co-creator/executive producer Kevin Williamson now attached. However, he told The CW that \"The Vampire Diaries\" companion series he was helming had been put on hold in order to focus", "score": 8.589378, "title_score": 0, "passage_id": "15410622"}, {"title": "Toni Tennille", "text": "Tennille Show\". From September 1998 to June 1999, Tennille performed as \"Victoria Grant/Count Victor Grazinski\" in the national tour of the play \"Victor Victoria\". With her then husband Dary Dragon, as Captain & Tennille, she recorded a Christmas song 'Saving Up Christmas' included in their DVD-boxset for 1976-1977's 'The Captain & Tennille Show'; this was followed by a full-length Christmas album titled 'The Secret of Christmas', released in 2007. In April 2016, Tennille released her memoir, \"Toni Tennille: A Memoir\", and went on a book tour to promote it later that summer. An 'audiobook' of the memoir was also released", "score": 8.568277, "title_score": 0, "passage_id": "11537195"}, {"title": "Secret Truths", "text": "Secret Truths \"Secret Truths\" is the two-part pilot episode of the American teen drama series \"South of Nowhere\" which premiered on November 4, 2005 on The N in the United States. It was written by series creator Thomas W. Lynch and directed by Donna Deitch. The episode introduces three siblings\u2014Spencer, Glen and Clay Carlin\u2014who start at a new school after their family moves from a small town in Ohio to Los Angeles. Lynch conceived \"South of Nowhere\" from the idea of a teenager's coming out after hearing that his friend's son had come out to his parents. Lynch pitched the", "score": 8.564528, "title_score": 0, "passage_id": "11284340"}, {"title": "Secret Truths", "text": "same time emphasising its own sexual aspects, setting \"a weird standard for young viewers\". Secret Truths \"Secret Truths\" is the two-part pilot episode of the American teen drama series \"South of Nowhere\" which premiered on November 4, 2005 on The N in the United States. It was written by series creator Thomas W. Lynch and directed by Donna Deitch. The episode introduces three siblings\u2014Spencer, Glen and Clay Carlin\u2014who start at a new school after their family moves from a small town in Ohio to Los Angeles. Lynch conceived \"South of Nowhere\" from the idea of a teenager's coming out after", "score": 8.564452, "title_score": 0, "passage_id": "11284354"}, {"title": "Roy Winsor", "text": "and Always Lock Your Bedroom Door. He died in 1987 at the age of 75 in Pelham Manor, New York. At one time during the late 1960's, he was creating a spin-off series from \"The Secret Storm\" entitled \"The Widening Circle\" for the CBS network. The series was not purchased by the network, and no episodes (except possibly a pilot) were produced. Roy Winsor Roy Winsor (April 13, 1912 - May 31, 1987) was an American soap opera writer, creator and novelist. Roy Winsor was born in Chicago, Illinois in 1912. He is most famous for creating some of the", "score": 8.538924, "title_score": 0, "passage_id": "11545754"}, {"title": "William Nicholson (Australian politician)", "text": "Haines resigned. Although it was actually Henry Chapman who devised the secret ballot motion, the fact that Nicholson moved it, gained him the credit, and when Haines resigned, he was invited by the Governor of Victoria Sir Charles Hotham to form a government, but he was unable to do so, and Haines became Premier again. In 1856, Nicholson visited England, where he was congratulated for his work in establishing the secret ballot, which had been advocated by the Chartist movement there. The system was introduced in Victoria on 19 March 1856, and in South Australia on 2 April in the", "score": 8.491105, "title_score": 0, "passage_id": "5062220"}, {"title": "Laura Lippman", "text": "Dagger Award. In addition to the Tess Monaghan novels, Lippman wrote 2003's \"Every Secret Thing\", which was made into a 2014 movie starring Diane Lane. Lippman lives in the South Baltimore neighborhood of Federal Hill and frequently writes in the neighborhood coffee shop Spoons. In addition to writing, she teaches at Goucher College in Towson, Maryland, just outside Baltimore. In January 2007, she taught at the 3rd Annual Writers in Paradise at Eckerd College. In March 2013, she was the guest of honor at Left Coast Crime. Lippman is married to David Simon, another former \"Baltimore Sun\" reporter, and creator", "score": 8.479976, "title_score": 0, "passage_id": "4742769"}, {"title": "Mike Costa", "text": "Mike Costa Mike Costa is an American comic book and television writer. His first published work was 2008's \"The Secret History of the Authority: Hawksmoor\" with artist Fiona Staples for WildStorm. He also wrote \"Resistance\", a comic book series based on the Resistance video games. Costa has written \"Transformers\" for IDW. Costa is currently writing IDW Publishing\u2019s \"\" and \"Blackhawks\" for DC Comics. His work on the GI Joe franchise was critically acclaimed and lauded by Brian K. Vaughn as an example of a licensed comic equal in quality to mainstream or creator-owned works. He began writing for the FOX", "score": 8.479976, "title_score": 0, "passage_id": "13631756"}, {"title": "Little penguin", "text": "was once pecked by a little penguin while on holiday in Australia. Reportedly, this encounter encouraged Torvalds to select Tux as the official Linux mascot. A Linux kernel programming challenge called the Eudyptula Challenge has attracted thousands of persons; its creator(s) use the name \"Little Penguin\". Penny the Little Penguin was the mascot for the 2007 FINA World Swimming Championships held in Melbourne, Victoria. Little penguin The little penguin (\"Eudyptula minor\") is the smallest species of penguin. It grows to an average of in height and in length, though specific measurements vary by subspecies. It is found on the coastlines", "score": 8.443491, "title_score": 0, "passage_id": "242279"}, {"title": "SpyBoy", "text": "one-shots and a crossover 3-issue miniseries with DC Comics, called \"SpyBoy/Young Justice\" (David is also creator of this DC team) published in 2002 and later compiled in one volume. This is the story of Alex Fleming, a young boy who was bullied in his school and had a normal life. But he doesn't know that he's a sleeper agent, codenamed as \"SpyBoy\", who works for secret organization S.H.I.R.T.S. (acronym for \"Secret Headquarters International Reconnaissance, Tactics, and Spies\"), in order to stop criminal organization S.K.I.N.S. (acronym for \"Supreme Killing Institute\"). SpyBoy SpyBoy is a comic book series created in 1999 by", "score": 8.439334, "title_score": 0, "passage_id": "8983473"}, {"title": "Uncle Grandpa", "text": "2012. Despite the failure, \"Secret Mountain Fort Awesome\" went on to win several awards, including the coveted Crystal Award for \"Best Television Production\" at Annecy International Animated Film Festival, the first US-based production to do so. This helped boost Browngardt's profile in getting \"Uncle Grandpa\" greenlit as a series. Finally, another factor that has contributed to the launch of the show was the redesign of the character by John Kricfalusi, \"The Ren & Stimpy Show\"s creator. On July 27 and 28, 2013, Cartoon Network aired a sneak peek of the series as part of Big Fan Weekend, along with \"Clarence\"", "score": 8.411283, "title_score": 0, "passage_id": "17259614"}, {"title": "Ermac", "text": "therefore warranted his inclusion in the series. Boon clarified the rumors on Twitter in 2011, and said he had kept the meaning of the \"ERMACS\" listing secret in hopes of stirring up fan speculation about the character. NetherRealm Studios (formerly Midway Games) has inserted allusions to the rumors and \"EGM\" hoax in subsequent \"Mortal Kombat\" games and related media. Ermac appeared on one panel in a \"Mortal Kombat II\" comic book prequel that was written and illustrated by \"Mortal Kombat\" co-creator John Tobias and published by the company in 1994. \"'s\" training mode contained a message that read, \"It is", "score": 8.403737, "title_score": 0, "passage_id": "3643815"}, {"title": "Panic (comics)", "text": "Secret Life of Walter Winchell\", a negative book based on a series of negative magazine articles about him written by Stuart, but his rhetoric cost him $21,500 after Stuart sued for libel. Stuart used the money to start his own publishing house. \"Mad\" was quickly and widely imitated, to the point where creator and editor Harvey Kurtzman mocked his competitors' wave of copycat humor comic books in \"Mad\"'s 17th issue. But he was particularly unhappy with EC's own imitation. \"I was pretty bitter about it,\" Kurtzman said in 1965. \"The publisher and I got into a series of ever-increasing arguments", "score": 8.403084, "title_score": 0, "passage_id": "9389122"}, {"title": "The Evil of the Daleks", "text": "The Evil of the Daleks The Evil of the Daleks is the mostly missing ninth and final serial of the fourth season in the British science fiction television series \"Doctor Who\", which originally aired in seven weekly parts from 20 May to 1 July 1967. This serial marked the debut of Deborah Watling as the Doctor's new companion, Victoria Waterfield. Only episode two, the episode in which Victoria first appears, is held in the BBC archives; the other six remain missing. \"Evil\" was initially intended to be the last Dalek story on \"Doctor Who\". Writer Terry Nation, the creator of", "score": 8.398486, "title_score": 0, "passage_id": "3226809"}, {"title": "Ordre Reaux Croix", "text": "The original creator of the C\u2234B\u2234C\u2234S\u2234, was Jean Baptiste Willermoz (1730 \u2013 1824), close friend and student of Martinez de Pasqually: When Pasqually died in 1774, the teachings of his master were at risk of being lost, and Willermoz then decided to use a Masonic body as a vehicle for the inner and secret teachings of the Order of Elus Cohens. Willermoz was a pragmatic esoteric scholar and innovator. His work as a Freemason is of fundamental impact and erudition, but has been forgotten over the centuries. But he is often viewed as an ardent knight of truth fighting to", "score": 8.370988, "title_score": 0, "passage_id": "13954805"}, {"title": "Haitian Vodou", "text": "even become a hushed voice on the wind. Though other Haitian and West African families believe there is an afterlife in paradise in the realm of God. The cultural area of the Fon, Ewe, and Yoruba peoples share a common metaphysical conception of a dual cosmological divine principle consisting of Nana Buluku, the God-Creator, and the voduns(s) or God-Actor(s), daughters and sons of the Creator's twin children Mawu (goddess of the moon) and Lisa (god of the sun). The God-Creator is the cosmogonical principle and does not trifle with the mundane; the voduns(s) are the God-Actor(s) who actually govern earthly", "score": 8.369685, "title_score": 0, "passage_id": "8028578"}, {"title": "The Castle of Wolfenbach", "text": "was consoled by others for his loss with no one suspecting that he was the one who actually started the fire. In addition, the Count discusses his plans to murder both Victoria and her servant, Margarite, so that there would be no remaining people who could reveal his secret. He was able to kill Margarite and as he took Victoria to the woods to kill her, he was thrown from his horse and Victoria was able to escape as the Count and his servant were distracted. Another example of secrecy in this novel is the true identity of Mr. Weimar.", "score": 8.36158, "title_score": 0, "passage_id": "11291732"}, {"title": "Secret du Roi", "text": "Secret du Roi For a period of over twenty years, King Louis XV split his diplomacy into official and secret channels. The secret channels became collectively known as the King's Secret (\"\"\"\" or \"\"\"\" in French), established in 1722. It actually outlived its creator and some of its agents were involved in bringing France (and its allies) into the American War of Independence, although it was technically dissolved upon Louis's death in 1774. Louis XV's secret diplomacy was born from the secret candidacy of the Prince de Conti to the Polish Throne, as he could not involve France in this", "score": 8.359773, "title_score": 0, "passage_id": "6838162"}, {"title": "Libra (DC Comics)", "text": "of Libra and the connection between his original appearance and \"Final Crisis\" was then made apparent in a one-shot story by his original creator, Len Wein, in \"Final Crisis: Secret Files & Origins\" in December 2008. In \"Final Crisis\": Secret Files #1, it was shown that Libra was born Justin Ballantine, who lost his mother at the age of eight due to an alcoholic pharmacist mismeasuring medicine his mother needed. Soon after his father turned to alcoholism himself and brutally abused Justin regularly. Justin would later use all the money he had to buy a telescope so that he could", "score": 8.358908, "title_score": 0, "passage_id": "11815406"}, {"title": "Elsie Tanner", "text": "Linda (Anne Cunningham) and Dennis (Philip Lowrie), from her marriage to Arnold Tanner (Frank Crawshaw). Linda had trouble with her Polish husband Ivan Cheveski (Ernst Walder) and his short temper, but they eventually reconciled and had two sons, Paul (Victoria Elton, Marcus Saville and Nigel Greaves) and Martin (Jonathan Caplan). \"Coronation Street\"'s creator, Tony Warren, had originally planned the character of Dennis to be rather gritty and a real \"bad boy\", but actor Philip Lowrie's charm and knack for comedy led to Dennis becoming much more lighthearted. Dennis was shown to be sneaky and up to shenanigans, and embarked on", "score": 8.350986, "title_score": 0, "passage_id": "5092273"}, {"title": "Secret ballot", "text": "secret only in so much as the law says the information should not be accessed. In Australia, secret balloting appears to have been first implemented in Tasmania on 7 February 1856. Until the original Tasmanian \"Electoral Act 1856\" was \"re-discovered\" recently, credit for the first implementation of the secret ballot often went to Victoria, where it was pioneered by the former mayor of Melbourne, William Nicholson, and simultaneously South Australia. Victoria enacted legislation for secret ballots on 19 March 1856, and South Australian Electoral Commissioner William Boothby generally gets credit for creating the system finally enacted into law in South", "score": 8.346799, "title_score": 0, "passage_id": "2674355"}, {"title": "Homer's Barbershop Quartet", "text": "\"The Simpsons\". When Harrison arrived at the recording studio in West Los Angeles to record his lines, the casting director told the episode's show runners, Al Jean and Mike Reiss, that Harrison was coming and that they were not allowed to tell anybody about it because it was intended to be a secret to the staff. Jean, Reiss, and the show's creator Matt Groening went to see Harrison in the studio, and when they returned to the writer's room, Groening said, \"Guess who I just met? George Harrison!\", not knowing that it was supposed to be a secret. Harrison arrived", "score": 8.317897, "title_score": 0, "passage_id": "4849993"}, {"title": "The Quest Begins", "text": "The company and Victoria Holmes agreed to write about bears after discarding dogs, horses and dolphins. The novel was released in the US on 27 May 2008 and has also been released in the UK, Canada and translated into Russian. Critical reception was positive with reviewers praising the realistic behaviour of the bears. \"The Quest Begins\" began as a request from HarperCollins who wanted Victoria Holmes, editor and creator of the \"Warriors\" series which followed the adventures of feral cats, to write another series about animals. The company suggested dogs to Holmes, but the idea was rejected since dogs behave", "score": 8.310286, "title_score": 0, "passage_id": "13792305"}, {"title": "The Secret History of Twin Peaks", "text": "co-creator, writer and director David Lynch, when asked what he thought of the book, stated that he hadn't read it and that it was \"\"his\" [Frost's] history of Twin Peaks\". Devan Coggan of \"Entertainment Weekly\" wrote \"More than 25 years after Laura Palmer was found wrapped in plastic, Twin Peaks co-creator Mark Frost returns to the Pacific Northwest with a new novel structured as a secret dossier. Assembled by a mysterious \u201carchivist\u201d and annotated by an FBI agent known only as TP, this enigmatic collection includes undiscovered Lewis and Clark diary entries, UFO sightings, and personal journals of Twin Peaks", "score": 8.303735, "title_score": 0, "passage_id": "20150946"}, {"title": "Louis C.K.", "text": "standup special. HBO dropped C.K.'s appearance on an upcoming \"Night of Too Many Stars\" autism television special and removed his content from their on-demand services. TBS suspended production of, and eventually scrapped its animated series \"The Cops\". Illumination Entertainment terminated their relationship with C.K., being replaced with Patton Oswalt in the upcoming \"The Secret Life of Pets\" sequel. The Disney Channel also removed C.K. from reruns of \"Gravity Falls\", redubbing his character's voice with series creator Alex Hirsch. On August 26, 2018, Louis C.K. made an unannounced appearance at the Comedy Cellar in Manhattan, New York. It was reported that", "score": 8.289012, "title_score": 0, "passage_id": "5181734"}, {"title": "Mark Johnson (producer)", "text": "Sopranos\" creator David Chase and starring James Gandolfini, \"Chasing Mavericks\" directed by Curtis Hanson and starring Gerard Butler, and \"Won't Back Down\" starring Viola Davis, Maggie Gyllenhaal and Holly Hunter. He produced 2015's thriller \"Secret in Their Eyes\". Johnson was an executive producer on AMC's Emmy Award-winning series \"Breaking Bad\". He is also an executive producer on the Sundance Channel original series \"Rectify\", and AMC's \"Breaking Bad\" spinoff, \"Better Call Saul\". Johnson is a member of the Board of Governors of the Academy of Motion Picture Arts and Sciences (Producers Branch). Mark Johnson (producer) Mark Johnson (born December 27, 1945)", "score": 8.288655, "title_score": 0, "passage_id": "9366858"}, {"title": "Doom Patrol", "text": "a black doctor named Dr. Eleanor Poole, to create a transgender transracial gestalt entity known as Rebis. The new writer introduced some new characters to the team, including the multiple personality-afflicted Crazy Jane; and sentient roadway Danny the Street. Morrison used DC's \"Invasion\" crossover to restart the book. He incorporated bizarre secret societies, elements of Dada, surrealism, and the cut-up technique pioneered by William S. Burroughs and Brion Gysin. He also borrowed the ideas of Jorge Luis Borges and Heinrich Hoffmann. The original creator, Arnold Drake, said Morrison's was the only subsequent run to reflect the intent of the original", "score": 8.286551, "title_score": 0, "passage_id": "2992841"}, {"title": "Prime Minister parodies (Private Eye)", "text": "Lewis and \"Not the Nine O'Clock News\" series co-creator/producer John Lloyd on the comedy album \"Iron Lady: The Coming Of The Leader\". The album was written by Wells who also appeared on it performing multiple characters. Lewis and Lloyd produced. Margaret Thatcher was portrayed by Janet Brown. The Secret Diary of John Major (aged 47\u00be) was a weekly spoof diary entry based on \"The Secret Diary of Adrian Mole, Aged 13\u00be\" in which John Major was characterised as being hopelessly na\u00efve and optimistic, as well as dull, weak and obsessed by trivia. The diary reappears occasionally, such as after the", "score": 8.285865, "title_score": 0, "passage_id": "11331773"}, {"title": "The Unusuals", "text": "The Unusuals The Unusuals is a comedy-drama television series that aired on ABC from April 8 to June 17, 2009 in the U.S. and Global in Canada. The pilot and first episode were written by Noah Hawley, a former writer and producer for Fox's \"Bones\". An ABC press release described \"The Unusuals\" as \"like a modern-day \"M*A*S*H\"\" that \"explores both the grounded drama and comic insanity of the world of New York City police detectives, where every cop has a secret\". Its premise elaborated: The initial series order was for 10 episodes. Show creator Noah Hawley announced via his Twitter", "score": 8.281731, "title_score": 0, "passage_id": "12686373"}, {"title": "Mercedes Lackey bibliography", "text": "play an important role in keeping the world safe. In \"Invasion,\" the world is invaded by a mysterious force of armored Nazi soldiers, from the disbanded arcane Thule Society, some of whom are subsequently found not to be human. While \"The\" \"Secret World Chronicles\" is not set in the same world as the \"SERRAted Edge\" and \"Bedlam's Bard\" series, it does share certain elements in common with those books: one of \"Invasion\"'s central characters, Victoria Victrix Nagy, is referred to as a Knight of Underhill. The first book of \"The Secret World Chronicles\" began serialization in podcast form in September", "score": 8.260885, "title_score": 0, "passage_id": "12386743"}, {"title": "Secret Santa (30 Rock)", "text": "holiday song is, \"Oh, Meatbowl of Verduke, you bring me such pizza. Meatbowl.\" When Tracy Jordan (Tracy Morgan) tells Kenneth that they made up their religion, he goes into shock at the idea that all religions are made up by man. His faith is restored when the three are arrested for the bomb threat Liz called in, using their phone. \"Secret Santa\" was written by series' creator, executive producer and lead actress Tina Fey. The director of this episode was Beth McCarthy-Miller, a long-time television director who worked with Fey on the sketch comedy show \"Saturday Night Live\". This was", "score": 8.25865, "title_score": 0, "passage_id": "14093181"}, {"title": "Eidolon (video game)", "text": "this in Victoria, but its effectiveness is unknown. \"Eidolon\"'s primary creator, Kevin Maxon, began work on the game as a thesis project while studying game design at Western Washington University, and it was then developed over 20 months by Maxon's company Ice Water Games. Thematically, Maxon intended to contrast the transience of human civilization with the permanence of nature. This theme is reflected in the game's use of Walt Whitman's poem \"Eidolons\", which provided not only the title but quotations that appear when the protagonist sleeps. Maxon describes the game as \"post-human\" rather than \"post-apocalyptic\" because of the absence of", "score": 8.250267, "title_score": 0, "passage_id": "19457976"}, {"title": "Pau Villalonga", "text": "of the known works by Villalonga, the Llibre d'atril includes unidentified works possibly by other composers (although most of the folios are unreadable). Villalonga's compositions have received high appraisal from Felipe Pedrell\u2014comparing them to those of Victoria and Palestrina\u2014Georges Jean-Aubry, and Manuel de Falla. Work list (polyphonic settings, four voices): Ad coronam, Ave Regina, Ave Maria stella Ave Regina caelorum Exultant laudibus, Himnum in festo S. Michaelis et Cor Christi, Jesu corona virginum, 3 Magnificats, Pange lingua, Salve Regina, Salve sancta parens, Sanctorum meritis, Veni creator, Vexilla regis Pau Villalonga Pau Villalonga (died Palma de Mallorca 29 March 1609) was", "score": 8.245004, "title_score": 0, "passage_id": "12096288"}, {"title": "Victoria (ship)", "text": "possible to complete the project in time for the celebration of the bicentennial in 2010, the project\u2019s creator received a Presidential Medal from the President of Chile. Victoria (ship) Victoria (or Nao \"Victoria, as well as Vittoria\") was a Spanish carrack and the first ship to successfully circumnavigate the world. \"Victoria\" was part of a Spanish expedition commanded by the Portuguese explorer Ferdinand Magellan, and after his death during the voyage, by Juan Sebasti\u00e1n Elcano. The expedition began on August 10, 1519 with five ships. However, \"Victoria\" was the only ship to complete the voyage, returning on September 6, 1522.", "score": 8.242907, "title_score": 0, "passage_id": "5220089"}, {"title": "Episode 9 (Twin Peaks)", "text": "Episode 9 (Twin Peaks) \"Episode 9\", also known as \"Coma\", is the second episode of the second season of the American mystery television series \"Twin Peaks\". The episode was written by Harley Peyton, and directed by series co-creator David Lynch. It features series regulars Kyle MacLachlan, Michael Ontkean, Ray Wise and Richard Beymer; and guest stars Chris Mulkey as Hank Jennings, Miguel Ferrer as Albert Rosenfield, David Patrick Kelly as Jerry Horne. Don S. Davis as Major Garland Briggs, Victoria Catlin as Blackie O'Reilly, Don Amendolia as Emory Battis, Frances Bay as Mrs. Tremond, Grace Zabriskie as Sarah Palmer, and", "score": 8.240468, "title_score": 0, "passage_id": "20188454"}, {"title": "Secret Squirrel", "text": "revived in 1993 for back-up segments of TBS Superstation's animated series \"2 Stupid Dogs\". Titled Super Secret Secret Squirrel, these new cartoons featured Secret Squirrel (voiced by Jess Harnell) and Morocco Mole (voiced by Jim Cummings). \"2 Stupid Dogs\" creator Donovan Cook was asked by then-new Hanna-Barbera president Fred Seibert to choose a classic studio cartoon to revive within the main show, and Super Secret Secret Squirrel was the result. After Cook guided the updated design with artists Paul Rudish and Craig McCracken, supervising producer Larry Huber, the \"adult supervision\" assigned by Seibert, was responsible for all further aspects of", "score": 8.235261, "title_score": 0, "passage_id": "12473476"}, {"title": "The Castle of Wolfenbach", "text": "is evident when Matilda discovers lines written in the window which detail the grief and torment of Victoria, who at the time Matilda reads it, is unknown to her. The anonymity of the writer of the lines etched into the window provides another example of how identities in this novel are kept secret. As the reader of the lines, Matilda is able to learn only what the writer wants her to know while the other aspects of the author's life are kept secret and hidden (). A very prominent storyline in Parson's novel is what the Count did with Victoria", "score": 8.196179, "title_score": 0, "passage_id": "11291729"}, {"title": "Cecilia Underwood, 1st Duchess of Inverness", "text": "Cemetery. The Duchess of Inverness continued to reside at Kensington Palace until her death thirty years later in August 1873. She was buried next to her second husband. Lady Cecilia is portrayed briefly in the 2016 ITV series \"Victoria\", Episode 6 \"The Queen's Husband\" by Daisy Goodwin, creator of the series and its main writer. The portion of this episode relative to Lady Cecilia is thus described: \"Victoria curries favour with her uncle the Duke of Sussex, who is unable to present his wife at court because their morganatic marriage was in violation of the Royal Marriages Act 1772. Although", "score": 8.178576, "title_score": 0, "passage_id": "6670155"}, {"title": "White Bear (Black Mirror)", "text": "she has just experienced in the \"White Bear Justice Park\", named after Jemima's teddy bear. Victoria is driven back to the compound past a crowd who are baying for her blood, and returned to where she awoke. As she is shown footage of Jemima, Baxter places electrodes on her head, wiping her memory of the day's events. Over the end credits, the new day's events are seen from the point of view of the park staff and the park visitors who play the part of those filming Victoria. Series creator Charlie Brooker originally envisioned the episode as \"a straightforward [zombie]", "score": 8.149012, "title_score": 0, "passage_id": "18456102"}, {"title": "Remy Blumenfeld", "text": "Remy Blumenfeld Remy Blumenfeld (born 1965) is a British television producer and format creator, who co-founded the production company Brighter Pictures which he sold to Endemol in 2004. He is the TV format creator of \"There's Something About Miriam\", \"Gay, Straight or Taken?\", \"Wudja Cudja\" and \"Undercover Lovers\". According to \"The Guardian\", Blumenfeld has created and produced more than 30 original television series, which also include BBC1's \"Tabloid Tales with Piers Morgan\" and \"My Worst Week\", and BBC2's \"Get a New Life\". Blumenfeld was born in Paris, the son of American parents. His father Yorick Blumenfeld is a writer. His", "score": 8.138691, "title_score": 0, "passage_id": "15894566"}, {"title": "Secret Garden (Once Upon a Time)", "text": "Victoria tried to buy up previously. Rogers meets up with Weaver to learn more about Eloise, but while he has suspicions about Victoria, Rogers believes Eloise to be innocent. At the same at the hospital, a doctor is looking for a donor to run tests in order to find a match for Lucy, and Henry volunteers. Back at Gothel's lair, Ivy and Victoria find a way to escape as Victoria snagged a pulley and the two escaped. While that was taking place, Rogers visits Eloise, who tries to charm him but is unaware that Anastasia is hiding in the closet.", "score": 8.107967, "title_score": 0, "passage_id": "20434218"}, {"title": "Victoria's Secret", "text": "In 2016, Victoria's Secret stopped selling swimwear, shoes, accessories and apparel that were only sold in online Victoria's Secret stores to stay more focused on the lingerie, fragrances and sleepwear that are still available in stores and online. In 2017 Victoria's Secret began to put more emphasis on bralettes (bras without underwire, often intended to be worn visibly) and sports bras (under the Victoria Sport label) to appeal to a younger customer base. The company announced that it would bring back swimwear starting from spring 2019. Victoria Secret's operations are organized into three divisions: Victoria's Secret Stores (stores), Victoria's Secret", "score": 8.088641, "title_score": 0, "passage_id": "13258893"}, {"title": "Ronald Ryan", "text": "an old man. Starke reported that the Premier of Victoria, Sir Henry Bolte, insisted that the death sentence be carried out. Bolte's cabinet was unanimous although there were at least four State cabinet members who opposed capital punishment. When it became apparent that Bolte intended to proceed with the execution, a secret eleventh-hour plea for mercy was made by four of the jury members. They sent petitioning letters to the Governor of Victoria, Sir Rohan Delacombe, stating that in reaching their verdict they believed that capital punishment had been abolished in Victoria and requested that the governor exercise the Royal", "score": 8.076681, "title_score": 0, "passage_id": "3905162"}, {"title": "Van Partible", "text": "would become \"Johnny Bravo\". The short was produced for Cartoon Network's new animation showcase titled \"World Premiere Toons\". Partible initially roomed with Craig McCracken (creator of \"The Powerpuff Girls\", \"Foster's Home For Imaginary Friends\" and \"Wander Over Yonder\"), Paul Rudish (a designer on that series) and Genndy Tartakovsky (creator of \"Dexter's Laboratory\"). The only two cartoonists who worked at Hanna-Barbera fresh out of college were Partible and Seth MacFarlane (creator of \"Family Guy\", \"American Dad!\" and \"The Cleveland Show\"). Partible changed his character from \"Mess O' Blues\" around so that \"he would be more of this '50's iconic James Dean-looking", "score": 8.047676, "title_score": 0, "passage_id": "7807995"}, {"title": "Rothenburg ob der Tauber", "text": "inspired the look of the town in the Japanese manga and anime series \"A Little Snow Fairy Sugar\" (2001). Rothenburg's famous street Kobolzeller Steige and Spitalgasse is depicted on the cover of two Blackmore's Night albums, 1999's \"Under a Violet Moon\" and their 2006 album \"Winter Carols\". It is often thought to have inspired the town center of M\u00eal\u00e9e Island in the 1990 point-and-click graphic adventure game \"The Secret of Monkey Island\", but creator Ron Gilbert has claimed the resemblance is a coincidence. The video game \"Team Fortress 2\" features a map titled \"Rottenburg\", a play on the original's namesake", "score": 8.041311, "title_score": 0, "passage_id": "4574393"}, {"title": "TimeSplitters: Future Perfect", "text": "the help of hippie secret agent Harry Tipper, to rescue his girlfriend, Kitten Celeste. After defeating Khallos, Anya reveals to Cortez that a mansion burned down in the 90's. In 1994, he is (painfully) greeted by a striking teenager named Jo Beth Casey. She tells Cortez that the house is haunted, and the two battle zombies and ghosts inside the abandoned mansion. After discovering that the creator of the TimeSplitters is a mad scientist named Dr. Jacob Crow, Cortez embarks on a new mission to foil the scientist's plans by destroying his labs throughout all of the time periods Crow", "score": 8.038461, "title_score": 0, "passage_id": "4045243"}, {"title": "I Wonder If I Take You Home", "text": "1985 in \"The Village Voice\"s annual Pazz & Jop critics poll. Robert Christgau, the poll's creator, ranked it twelfth on his own list of the year's best singles. Its chorus has been interpolated in The Black Eyed Peas's 2005 hit song, \"Don't Phunk With My Heart\", Fabolous's song with Lil' Mo entitled \"Take You Home\" & in the Angie Martinez single \"Take You Home\" featuring Kelis. The song has also been sampled by Kylie Minogue (in her song \"Secret (Take You Home)\"), Pitbull (in his song \"I Wonder\", featuring Oobie), R&B singer Paula Campbell in her single \"Take You Home,\"", "score": 8.023775, "title_score": 0, "passage_id": "9437884"}, {"title": "The Secret Life of an American Wife", "text": "a movie star who is known as an international sex symbol (Walter Matthau). Upon hearing that The Movie Star (the character is not given a name, and Matthau is credited as \"The Movie Star\" in the closing credits) indulges in the services of prostitutes, Victoria decides to pose surreptitiously as one in order to prove to herself that she is still sexually attractive. The Secret Life of an American Wife The Secret Life of an American Wife is a 1968 comedy film written and directed by George Axelrod. The film was released by 20th Century Fox in 1968, and was", "score": 8.012431, "title_score": 0, "passage_id": "8313165"}, {"title": "The Secret Life of an American Wife", "text": "The Secret Life of an American Wife The Secret Life of an American Wife is a 1968 comedy film written and directed by George Axelrod. The film was released by 20th Century Fox in 1968, and was considered a box-office failure. It features a music score by Billy May. Edy Williams has a supporting role in the film as the Laytons' blonde bombshell neighbor. Victoria Layton (Anne Jackson) is a suburban housewife who is dissatisfied with her marriage and fears that her sex appeal is fading. Her husband (Patrick O'Neal) works as a press agent, and his only client is", "score": 8.009439, "title_score": 0, "passage_id": "8313164"}, {"title": "Celia Paul", "text": "2007 and since then she has concentrated on her four sisters, especially her sister Kate. \"\u2026[T]he real strength of Paul's project becomes apparent with time: the concentrated emotional energy of chronicling a family and its subtle shifts over many years\". Recently her work has taken a new direction and she has been focussing on landscape and the sea. \"[S]he \u2026is a creator of subterranean images. Her canvases are Impressionism in conversation with modernism- objective but felt\". British Museum, London; National Portrait Gallery, London, Victoria and Albert Museum, London; Saatchi Collection, London; Abbot Hall, Kendal; Metropolitan Museum of Art, New York;", "score": 7.999431, "title_score": 0, "passage_id": "15953996"}, {"title": "Scrapyard Detectives", "text": "notions about others. Scrapyard Detectives has been used by Dr. Robyn A. Hill, Teacher Educator, who included the series in a free online book, \"Secret Origin of Good Readers\". The Secret Origin of Good Readers also organizes a panel on using graphic novels to promote literacy, which has run at Comic Con International and at WonderCon. The first three issues of Scrapyard Detectives are collected into a graphic novel titled \"The Scrapyard Detectives: Collected Cases, Volume One\" (). This 104 page collected edition also includes an origin story written by Supernatural Law creator/writer Batton Lash, which details how the three", "score": 7.998902, "title_score": 0, "passage_id": "9978806"}, {"title": "Gumball (video game)", "text": "Electronics Show. In 2016, an Apple II software cracker team found an Easter egg hidden by the game's creator 33 years prior. Cook had hidden a secret congratulations screen in the game for players who entered a specific keyboard key combination at a specific time and solved the resulting series of substitution ciphered clues. Cook congratulated the cracker team on Twitter. The crackers found the secret while working to preserve the game for the Internet Archive by removing its digital copyright protections. One of the crackers said that while most 1980s games could be cracked by automation, \"Gumball\" protections, coded", "score": 7.994494, "title_score": 0, "passage_id": "19577323"}, {"title": "Victoria's Secret", "text": "padded push-up bras\" were niche products during this period found \"alongside feathered boas and provocative pirate costumes at Frederick's of Hollywood\" outside of the mainstream product offerings available at department stores. In 1977, Raymond borrowed $40,000 from his parents and $40,000 from a bank to establish Victoria's Secret: a store in which men could feel comfortable buying lingerie. The company's first store was located in Stanford Shopping Center in Palo Alto, California. Raymond picked the name \"Victoria\" after Queen Victoria of the United Kingdom to associate with the refinement of the Victorian era. The \"Secret\" was what was hidden underneath", "score": 7.993436, "title_score": 0, "passage_id": "13258882"}, {"title": "Secret Story: Desafio Final 3", "text": "Secret Story 5. She was given a pass to \"Desafio Final\" by the finalists of Secret Story 4, who chose her between the housemates that had already left the house. Wilson Teixeira was a housemate in Secret Story 3 and . He entered on Day 1. In this All-Stars season there are two secrets: house's secret and \"A Voz\"'s secret. On Day 71 of Secret Story 5, it was given 3 passes to the next \"Desafio Final\". The first one was given to Bruno, the finalists of Secret Story 4 chose him between the housemates that were still in the", "score": 7.992352, "title_score": 0, "passage_id": "18476688"}, {"title": "The Garden of Forking Paths (Once Upon a Time)", "text": "well with Rogers. Finally, the construction workers deliver a coffin to Victoria, and she opens it, revealing the still preserved body of Anastasia, as it turns out that Victoria was never cursed, thus revealing that she was Tremaine all along. She then visits a secret location in Belfrey Tower to see a woman who she had chained up. Tremaine wants the woman to come up with a spell to strip Lucy of her belief in order to revive Anastasia, but the woman refuses and warns Tremaine/Victoria that by doing so will not only destroy Lucy, but will have to deal", "score": 7.990497, "title_score": 0, "passage_id": "20282001"}, {"title": "The Crossovers", "text": "a home hospice worker. They have two children, Cris, 15, and Cliff, 10 and a dachshund Cubby. They begin their day with breakfast like all normal families. Each member has a secret life that none of the others know. Carter is Archetype; a superhero created by Biotix with enemies such as Mountebank, a dro\u00efd creator. Calista is a vampire slayer trying to save the young Andata Enfier from Baron Arcan Corpescu, a vampire. Cris knows a secret passage in the basement which can lead her to another world where she is warrior princess Eradika who fights with the Bellekosin, a", "score": 7.984533, "title_score": 0, "passage_id": "14869742"}, {"title": "Hitman (franchise)", "text": "revealed that Victoria is a clone, like 47, created in secret by Travis, whom the ICA would train to be an assassin. Diana did what she did to protect the girl from becoming like 47. The assassin soon comes into conflict with Blake Dexter, the head of Dexter Industries and a top figure in the criminal underworld, who wishes to sell Victoria to the highest bidder. 47 finds himself fighting to keep Victoria safe as she is hunted by Dexter's forces and the ICA. 47 eventually kills Dexter and his conspirators along with Travis and his lieutenants, saving Victoria. At", "score": 7.970323, "title_score": 0, "passage_id": "2915023"}, {"title": "Sos and Victoria Petrosyan", "text": "Silver and 3 Bronze Medals. In 2016, they auditioned for America's Got Talent (season 11), they got 4 yeses in the audition and made it through to the quarterfinal, but was sent home afterward. Sos and Victoria Petrosyan Sos and Victoria Petrosyan are a German-Armenian/Russian husband and wife quick-change artist act. Sos & Victoria Petrosyan \u201cThe World Best Quick Change Act\u201d The Fashion Design Creator - The Transformationists The lightning-fast and world famous Quick Change artists Sos & Victoria have perfected their modern interpretation of traditional performance art by combining fashion, stage-craft, and sleight-of-hand in a display that has dazzled", "score": 7.940722, "title_score": 0, "passage_id": "16558231"}, {"title": "Victoria's Secret", "text": "Catalog sales accounted for 55% of the company's $7 million annual sales in 1982. The Victoria's Secret stores at this time were \"a niche player\" in the underwear market. The business was described as \"more burlesque than Main Street.\" In 1982, Victoria's Secret had grown to five stores, a 40-page catalog, and was grossing $6 million annually. Raymond sold Victoria's Secret Inc. to Leslie Wexner, creator of Limited Stores Inc of Columbus, Ohio, for $1 million. In 1983, Wexner revamped Victoria's Secret's sales model. He discarded the money-losing model of selling lingerie to male customers and replaced it with one", "score": 7.929492, "title_score": 0, "passage_id": "13258884"}, {"title": "Mighty Mouse: The New Adventures", "text": "Bakshi's own 1960 creations\u2014The Mighty Heroes\u2014appear, aged, in the episode \"Heroes and Zeroes\". Fellow Terrytoons characters Heckle and Jeckle also appear, in \"Mighty's Wedlock Whimsy\". The show was considered revolutionary at the time, and, along with 1988's \"Who Framed Roger Rabbit\", inspired a wave of animated shows that were much zanier than those that had dominated children's animation in the previous two decades. It is credited by some as the impetus for the \u2018creator-driven\u2019 animation revolution of the 1990s. It was a huge springboard for many cartoonists and animators who would later become famous, among them John Kricfalusi (creator of", "score": 7.91548, "title_score": 0, "passage_id": "5030621"}, {"title": "Secret Well", "text": "Secret Well Secret Well is a 2007 Cambodian horror film. The film provides a horror style similar to 2002's The Ring. A family moves into an old villa that belonged to their relative for a hundred years. But when they find a strange well behind their house, something strange begins to happen, with mysterious deaths in the family, until they unlock a secret, buried in the well, about a young girl who was killed and her body buried behind the house. Now she has come back for her revenge against someone in the family who kept it secret, so that", "score": 7.904806, "title_score": 0, "passage_id": "12133192"}, {"title": "Thomas Lyon-Bowes, Master of Glamis (born 1821)", "text": "did actually exist, but even described him \u2013 half frog, half man!\", also claiming he was the rightful earl. Details published about the mystery of Glamis during the reign of Queen Victoria scarcely mention a monster and are instead focused on the possibility of members of a rival clan dying while locked in the secret room. The earliest surviving reference dates from 1908, in which it was claimed that \"in the Castle of Glamis is a secret chamber. In this chamber is confined a monster, who is the rightful heir to the title and property, but who is so unpresentable", "score": 7.899622, "title_score": 0, "passage_id": "3571019"}, {"title": "The Secret Woman (novel)", "text": "\"The French Lieutenant\u2019s Woman.\" The book's success was likely also bolstered by the success of Hibbert's previous novels such as \"Mistress of Mellyn\" and \"The Shivering Sands\". The positive reception of these works eventually gave Hibbert the title of \u201cQueen of Romantic Suspense\u201d and driving the sales of Victoria Holt novels to over 56 million copies worldwide. The Secret Woman (novel) The Secret Woman is a Gothic romance and suspense novel written by English author Eleanor Hibbert under the pseudonym Victoria Holt. It was originally published in 1970 and is considered to be a bestseller. Set in 1887, it chronicles", "score": 7.893995, "title_score": 0, "passage_id": "20367390"}, {"title": "My Secret Romance", "text": "My Secret Romance My Secret Romance () is a 2017 South Korean television series starring Sung Hoon and Song Ji-eun. It aired on cable network OCN at 21:00 every Monday and Tuesday, from April 17 to May 30, 2017 for 13 episodes. It was also released on SK Telecom's \"oksusu\" mobile app, \"My Secret Romance\" was selected in the 2017 Top Creator Audition held by KOCCA. The series is the first OCN drama to air on Mondays and Tuesday, as well as the first romance-themed OCN drama. Jin-wook and Yoo-mi meet at a Gangwon-do resort and get caught up in", "score": 7.880593, "title_score": 0, "passage_id": "20048611"}, {"title": "Sonny Liew", "text": "Artist. With Roger Landridge (Writer). Artist, Co-Creator Artist, Writer Editor, Artist, Writer Artist, Co-Creator . With Tommy Kovac (Writer). Artist, Co-Creator. With Mike Carey (Writer), Marc Hempel (Inker). Artist, Writer Artist, Writer Artist, Co-Creator. With Mike Carey (Writer), Marc Hempel (Inker). Artist, Writer Pin-up Artist Artist, Writer Sonny Liew Sonny Liew (born 26 September 1974) is a Malaysia-born comic artist/illustrator based in Singapore. He is best known for his work \"The Art of Charlie Chan Hock Chye\", the first graphic novel to win the Singapore Literature Prize for fiction in 2016. Born in Seremban, Malaysia, Liew attended school at Victoria", "score": 7.870054, "title_score": 0, "passage_id": "8863967"}, {"title": "Victoria Lord", "text": "Slezak reprised the role onscreen upon Prospect Park resumption of the serial from April 29, 2013 through the final episode released August 19, 2013. Two other actresses portrayed Victoria while Slezak was on maternity and personal leave: Christine Jones in 1980 and 1981, and Judith Barcroft in 1987. In the summer of 2003, Slezak's real-life daughter, Amanda Davies, portrayed a teenaged Victoria in flashbacks. Leah Marie Hays played the role of a young Victoria Lord in a series of flashbacks as well. At the death of show and character creator Agnes Nixon in 2016, Slezak eulogized that, \"When she hired", "score": 7.867798, "title_score": 0, "passage_id": "5163221"}, {"title": "The Secret Saturdays", "text": "20, 2009. Comic adventures of \"The Secret Saturdays\" appeared semi-monthly in 2010 as part of \"Cartoon Network Action Pack\" comic books published by DC Comics. A line of action figures and play sets was released by Mattel. The Secret Saturdays The Secret Saturdays is an American animated television series created by Canadian cartoonist Jay Stephens (creator of the Emmy-winning cartoon \"Tutenstein\") for Cartoon Network. It debuted on October 3, 2008, in the United States. The series follows the adventures of the Saturdays, a family of cryptozoologists that work to keep the truth about cryptids from getting out, in order to", "score": 7.856044, "title_score": 0, "passage_id": "11150500"}, {"title": "Gord Downie", "text": "Downie's legacy and commitment to Canada's First Peoples. Chanie Wenjack was a young aboriginal boy who died trying to escape a residential school, who became the centre of Downie's \"Secret Path\" project. The Gord Downie and Chanie Wenjack Fund is a registered charity. At the Assembly of First Nations in Gatineau, Quebec, on December 6, 2016, National Chief Perry Bellegarde honoured Downie with an eagle feather, a symbol of the creator above, for his support of the indigenous peoples of Canada. Bellegarde also bestowed on Downie an honorary aboriginal name, Wicapi Omani, which is Lakota for \"man who walks among", "score": 7.851015, "title_score": 0, "passage_id": "3048961"}, {"title": "Masque of the Red Death (Ravenloft)", "text": "monsters, driving people insane, moving whole areas and locations, and affecting the very fabric of reality. The Red Death is an extremely powerful force that comes and goes at its own whim, and is the source of all evil in the Masque of The Red Death world. An adventure titled \"Jigsaw\" appeared in \"Dungeon\" #61 (Sep/Oct 1996). The plot concerns a golem (a Frankenstein's Monster like creation) named Udo who wants to marry Victoria Von Lendstein, his creator. She is engaged to another man, and he would rather see her dead. The players must protect Victoria from her creation. An", "score": 7.850489, "title_score": 0, "passage_id": "6838359"}, {"title": "Fairly Secret Army", "text": "Fairly Secret Army Fairly Secret Army is a British sitcom which ran to thirteen episodes over two series between 1984 and 1986. Though not a direct spin-off from \"The Fall and Rise of Reginald Perrin\", the lead character, Major Harry Truscott, was very similar to Geoffrey Palmer's character of Jimmy in that series, and the scripts were written by Reginald Perrin's creator and writer David Nobbs. Harry Kitchener Wellington Truscott (ex \"Queen's Own West Mercian Lowlanders\") is an inept and slightly barmy ex-army man intent on training a group of highly unlikely people into a secret paramilitary organisation. This idea", "score": 7.849377, "title_score": 0, "passage_id": "4765613"}, {"title": "Spotify", "text": "effort to \"shine a light on these people behind the scenes who play such a big role in some of the most important moments of our lives. When the general public hears a song they automatically associate it with the artist who sings it, not the people behind the scenes who make it happen, so we thought the title Secret Genius was appropriate\", Spotify's Global Head of Creator Services Troy Carter told \"Variety\". The first awards ceremony will take place in late 2017, and is intended to honour \"the top songwriters, producers and publishers in the industry as well as", "score": 7.846746, "title_score": 0, "passage_id": "12672599"}, {"title": "Le Secret (EP)", "text": "Le Secret (EP) Le Secret (French for \"The Secret\") is an EP by French band Alcest, released in May 2005 through Drakkar Productions. It is Alcest's first release with creator Neige as sole member, as former members Aegnor and Argoth both left after the 2001 demo \"Tristesse Hivernale\", and the only release with Neige as sole performer. The lyrics to the track \"\u00c9l\u00e9vation\" come from the eponymous poem by Charles Baudelaire's from his 1857 volume of poetry \"Les Fleurs du mal\". The album was re-recorded and re-released in 2011, with the involvement of new member Winterhalter. Although the original release", "score": 7.845264, "title_score": 0, "passage_id": "10542837"}, {"title": "Le Secret (EP)", "text": "Le Secret (EP) Le Secret (French for \"The Secret\") is an EP by French band Alcest, released in May 2005 through Drakkar Productions. It is Alcest's first release with creator Neige as sole member, as former members Aegnor and Argoth both left after the 2001 demo \"Tristesse Hivernale\", and the only release with Neige as sole performer. The lyrics to the track \"\u00c9l\u00e9vation\" come from the eponymous poem by Charles Baudelaire's from his 1857 volume of poetry \"Les Fleurs du mal\". The album was re-recorded and re-released in 2011, with the involvement of new member Winterhalter. Although the original release", "score": 7.845264, "title_score": 0, "passage_id": "10542835"}, {"title": "Vairam (1974 film)", "text": "the diamonds. A furious Senthil Nathan sends some henchman to kill the traitor and retrieve the diamonds. The henchman (Sreekanth) corners and kills the traitor, but later has succeeded in hiding the diamonds somewhere. Meanwhile, a Victoria driver (S. V. Sahasranamam) of the eponymous, Victoria, who was found near the dead body is arrested based on circumstantial evidence. Somewhere else, two old golden-hearted crooks, Durai (M. R. R. Vasu) and Sami (S. A. Ashokan) are to be released. Durai had an infant son who was kidnapped from a park. To date, Durai doesn't know who kidnapped him or whether his", "score": 7.822976, "title_score": 0, "passage_id": "19027538"}, {"title": "Gandalf", "text": "Maiar, Gandalf was not a mortal Man but an angelic being who had taken human form. As one of those spirits, Ol\u00f3rin was in service to the Creator (Eru Il\u00favatar) and the Creator's 'Secret Fire'. Along with the other Maiar who entered into the world as the five Wizards, he took on the specific form of an aged old man as a sign of his humility. The role of the wizards was to advise and counsel but never to attempt to match Sauron's strength with his own, and hopefully the kings and lords of Middle-earth would be more receptive to", "score": 7.822256, "title_score": 0, "passage_id": "639623"}, {"title": "Klutter!", "text": "would change different colors in almost every episode. He was voiced by Cam Clarke. Wade Heap is the middle child with a mild attitude. He does not say much, but that is because he is quiet most of the time. He has a distinctive low/Geeky voice. He was voiced by Savage Steve Holland, the co-creator. Kopp is a character that is very crazy and paranoid sometimes lazy. He is an underachiever, who has a not so secret crush on Vanna. It is known that Kopp was based on the real Bill Kopp, who could not participate to work on \"Klutter\".", "score": 7.802892, "title_score": 0, "passage_id": "10854552"}, {"title": "Romane\u0301", "text": "Roman\u00e9 Roman\u00e9 is a Chilean soap opera (telenovela) that was first aired on March 6, 2000 as part of the first semester prime-time lineup of soap operas on TVN. It competed against Canal 13\u2019s \"Sabor A Ti\". The last time Jovanka Antich (Claudia Di Gir\u00f3lamo) was in Chile, she was a teenager and had a secret, torrid affair with Raphael Dominguez (Francisco Melo) the son of a local well-to-do family. The affair ended badly, with both of them believing that the other betrayed them when really it was Raphael\u2019s mother Victoria North (Mar\u00e9s Gonz\u00e1lez) with the help of the power", "score": 7.798511, "title_score": 0, "passage_id": "14444138"}, {"title": "Bruce Davison", "text": "of Charles Graiman, a protege of Wilton Knight who was the creator of the Knight Industries Three Thousand in NBC's revival of the television series \"Knight Rider\". Davison also played the role of Dr. Silberman, the psychiatrist who once tormented Sarah Connor, in the seventh episode of \"\". He portrayed Nick Anderson, a secret Santa Claus, in the TV movie \"Christmas Angel\", in 2009. In May 2010, Davison was cast to portray art dealer Wilhelm Van Schlagel for several episodes on ABC's \"General Hospital\" to begin airing in July 2010. In 2010, he starred in the TV movie \"Titanic II\".", "score": 7.786559, "title_score": 0, "passage_id": "2981558"}, {"title": "White Bear (Black Mirror)", "text": "in the centre of it.\" It was ranked eleventh out of the thirteen episodes by Charles Bramesco of \"Vulture\", who said its message is \"lost beneath a simplistic twist that pulls a switcheroo and [it] fails to do much else\". White Bear (Black Mirror) \"White Bear\" is the second episode of the second series of the British science fiction anthology series \"Black Mirror\". It was written by the series creator and showrunner Charlie Brooker and directed by Carl Tibbetts. The episode follows Victoria (Lenora Crichlow), a woman who does not remember who she is and wakes up in a place", "score": 7.784029, "title_score": 0, "passage_id": "18456128"}, {"title": "Softball in Victoria", "text": "improve the men's game. In 1982, the state organisation's newsletter wrote about the distances some of the men in the state were travelling in order to compete, including one player, Mark Buls, who travelled from Swan Hill, Victoria to Knox, Victoria in order to play in Saturday games. In 1985, Australia had an unofficial test team of all-stars who played against the New Zealand national team in Melbourne. Team members from Victoria included S. Adams and N. Tsoukalas. Softball in Victoria Softball is played in the Australian state of Victoria. Softball in Victoria grew after the bombing of Darwin and", "score": 7.772014, "title_score": 0, "passage_id": "16379310"}, {"title": "Black Light Attack!", "text": "in the November 12, 2009, episode \"The Problem Solvers\", and would later guest star on \"Secret Santa\". Series' creator, executive producer and lead actress Tina Fey had seen Jackson in the Broadway musicals \"Xanadu\" and \"Damn Yankees\", the latter that starred Jane Krakowski, who plays Jenna on the show. According to Jackson in a November 2009 interview, Fey set up a meeting to interest him in a role on the program. In an interview with the \"Los Angeles Times\", it was revealed that it was Krakowski who brought Jackson to the attention of the \"30 Rock\" producers. While at the", "score": 7.766401, "title_score": 0, "passage_id": "14194711"}]}, {"dataset": "nq_dev_psgs_w100", "question": "when did wesley leave last of the summer wine", "answers": ["2002"], "positive_ctxs": [{"title": "Gordon Wharmby", "text": "made his debut in \"Last of the Summer Wine\" in 1982, as Wesley Pegden, the boilersuit wearing, tinkering mechanic and would be inventor. He appeared as a regular cast member for 16 series between 1985 and 2002. Thora Hird played his nagging wife Edie. Wharmby had small roles in programmes such as Troy Kennedy Martin's nuclear thriller \"Edge of Darkness\" (1985), \"Brookside\" (1985), \"All Creatures Great and Small\" (1988), \"A Very British Coup\" coronation street as a milkman (1982) \"Agatha Christie's Poirot\" (1990), \"Heartbeat\" (1994), and \"Hetty Wainthropp Investigates\" (1996). At his time of death, he had been due to", "score": 1000, "title_score": 1, "passage_id": "4441861"}, {"title": "Gordon Wharmby", "text": "start recording the 25th series of \"Last of the Summer Wine\". Gordon died of cancer on 18 May 2002, aged 68. Gordon Wharmby Gordon Wharmby (6 November 1933 \u2013 18 May 2002) was a British television actor. He was best known for the role of Wesley Pegden on \"Last of the Summer Wine\". He was born in Manchester, Lancashire, in 1933, and served in the Royal Air Force during his national service. Wharmby was originally employed as a painter and decorator and had no formal training as an actor. He gained stage experience with Oldham Repertory Theatre and worked part-time", "score": 13.225002, "title_score": 0, "passage_id": "4441862"}, {"title": "Gordon Wharmby", "text": "made his debut in \"Last of the Summer Wine\" in 1982, as Wesley Pegden, the boilersuit wearing, tinkering mechanic and would be inventor. He appeared as a regular cast member for 16 series between 1985 and 2002. Thora Hird played his nagging wife Edie. Wharmby had small roles in programmes such as Troy Kennedy Martin's nuclear thriller \"Edge of Darkness\" (1985), \"Brookside\" (1985), \"All Creatures Great and Small\" (1988), \"A Very British Coup\" coronation street as a milkman (1982) \"Agatha Christie's Poirot\" (1990), \"Heartbeat\" (1994), and \"Hetty Wainthropp Investigates\" (1996). At his time of death, he had been due to", "score": 11.04914, "title_score": 0, "passage_id": "4441861"}, {"title": "Gordon Wharmby", "text": "Gordon Wharmby Gordon Wharmby (6 November 1933 \u2013 18 May 2002) was a British television actor. He was best known for the role of Wesley Pegden on \"Last of the Summer Wine\". He was born in Manchester, Lancashire, in 1933, and served in the Royal Air Force during his national service. Wharmby was originally employed as a painter and decorator and had no formal training as an actor. He gained stage experience with Oldham Repertory Theatre and worked part-time as a jobbing actor. Early television roles included bit-parts in programmes such as \"Bill Brand\" (1976), \"The One and Only Phyllis", "score": 11.045026, "title_score": 0, "passage_id": "4441859"}, {"title": "Last of the Summer Wine", "text": "of \"Last of the Summer Wine\". While presenting an OBE to Roy Clarke in 2002, Prince Charles said that his grandmother, the Queen Mother, had introduced him to the show. The Queen told Dame Thora Hird during a 2001 meeting that \"Last of the Summer Wine\" was her favourite television programme. A 2003 survey by \"Radio Times\" found that \"Last of the Summer Wine\" was the programme readers most wanted to see cancelled. With nearly 12,000 votes in the survey, the show received one-third of the total vote, and twice as many votes as the runner up in the poll,", "score": 10.982203, "title_score": 0, "passage_id": "808446"}, {"title": "Last of the Summer Wine (series 2)", "text": "Jones (1975) (Both these two characters only appeared in this series) Blamire (1973-1975) The box set for series 1 and 2 was released by Universal Playback in September 2002. Last of the Summer Wine (series 2) Last of the Summer Wine's second series originally aired on BBC1 between 5 March and 16 April 1975. All episodes from this series were written by Roy Clarke and produced and directed by Bernard Thompson. Although ratings from the first series were not good, the BBC ordered a second series of \"Last of the Summer Wine\" after the first season aired but", "score": 10.698597, "title_score": 0, "passage_id": "11997016"}, {"title": "Not All Dogs Go to Heaven", "text": "Sirtis as Troi; LeVar Burton as Chief Engineer Geordi La Forge; Wil Wheaton as Wesley Crusher; and Denise Crosby, whose character Tasha Yar died during \"Star Trek: The Next Generation\"s first season. It is also the first time the cast, minus Crosby, has worked together since the 2002 feature film \"Star Trek Nemesis\", although the actors did not meet when they recorded their speaking parts. Including Crosby, the last time that the entire cast worked together was the 1990 episode \"Yesterday's Enterprise\". Wil Wheaton, who played Wesley Crusher on \"\", recorded his parts for the episode on September 20, 2007.", "score": 9.579905, "title_score": 0, "passage_id": "13082239"}], "negative_ctxs": [{"title": "Quinalow", "text": "preschool building was finished at Quinalow School. The building was then opened in March 1984 as Quinalow Library and underwent a major refurbishment in 2014. Quinalow was affected by the 2010\u20132011 Queensland floods. Rising floodwaters isolated the town, surrounding the Quinalow pub. Myall Creek was not thought to have risen as high as it did in the 1981 flood. In the , Quinalow had a population of 411. The Toowoomba Regional Council operate a public library in Daly Street. Quinalow Quinalow is a town and a locality in the Toowoomba Region, Queensland, Australia. The town is located on Darling Downs", "score": 0, "title_score": 0, "passage_id": "15247772"}, {"title": "Irina Derevko", "text": "an unknown extent in the Prophet Five organization. Irina is seen observing Sydney's interrogation under hypnosis at the end of the episode \"The Horizon\". It is revealed she had Kelly Peyton kidnap Sydney to recover information about the Horizon, a Rambaldi artifact that would grant its wielder immortality. After Sydney appears to reveal the code crucial to her abductors' attempts to find the Horizon, Irina tells Peyton to make Sydney comfortable and leaves the observation room. In the episode \"Maternal Instinct\" she reunites briefly with Sydney and Jack, during which they discover her affiliation with Prophet Five and Irina also", "score": 0, "title_score": 0, "passage_id": "2885187"}, {"title": "Charles Bayard Mitchell", "text": "He was then sent to the Philippines, serving until his retirement in 1928. Charles Bayard Mitchell Charles Bayard Mitchell was an American Bishop of the Methodist Episcopal Church, elected in 1916. He also distinguished himself as a pastor and in service to his denomination. Charles was born 27 August 1857 in Allegheny City, Pennsylvania. He was the son of the Rev. Daniel Patrick Mitchell (a M.E. preacher) and Anne Eliza (Baker) Mitchell. At the age of five, Daniel moved his family to Kansas. Charles married Miss Clara Aull of Pittsburgh, Pennsylvania 6 July 1882. She was the daughter of James", "score": 0, "title_score": 0, "passage_id": "9084211"}, {"title": "Bruce Gradkowski", "text": "that removed him from the game, Gradkowski threw a touchdown while snapping the ball while the Browns were still in the huddle. He then appeared during a Week 13 match up against the Pittsburgh Steelers, completing 3-of-6 passes for 17 yards with one interception. On March 13, 2013, Gradkowski signed a three-year deal with his hometown team, the Pittsburgh Steelers. Ultimately, Gradkowski had very few career snaps with the Steelers. He played in none of the regular season games during 2013. In 2014, he played in one game. He missed almost the entire 2015 season due to hand and shoulder", "score": 0, "title_score": 0, "passage_id": "6936807"}, {"title": "The Way of All Flesh (1927 film)", "text": "The Way of All Flesh (1927 film) The Way of All Flesh is a 1927 American silent drama film directed by Victor Fleming, written by Lajos B\u00edr\u00f3, Jules Furthman, and Julian Johnson from a story by Perley Poore Sheehan. It is now considered a lost film. In the story, which opens in the early 1900s, Jannings plays August Schiller, a bank clerk in Milwaukee who is happy with both his job and his family. But when bank officials ask him to transport $1,000 in securities to Chicago, he meets a blond seductress on the train, who sees what he is", "score": 0, "title_score": 0, "passage_id": "4090959"}, {"title": "Nyon", "text": "way of the Route Suisse, the A1 Motorway and the railways of the \"Arc L\u00e9manique\". Nyon derives from one of the names used by the Romans for the town, \"Noviodunum\" or \"Noiodunum\". Other names for the town, particularly of colonies placed there, are \"Colonia Iulia Equestris\" or \"Colonia Julia Equestris\", \"Colonia Equestris Noiodunum\", \"Equestris\", \"Civitas Equestrium\", and \"Civitas Equestrium Noiodunum\". Nyon is first mentioned around 367-407 as \"civitas Equestrium id est Noiodunus\" (in the \"Notitia Galliarum\"). In 1236, it was mentioned as \"Neveduni\" and in 1292 as \"Nyons\". A few scattered neolithic items were discovered in the 19th century. North", "score": 0, "title_score": 0, "passage_id": "2892464"}, {"title": "Hardy Brothers Building", "text": "2016, the building is occupied by the Bank of Queensland. Hardy Brothers is a Victorian era Italianate building located at 116 Queen Street. It consists of two storeys and a basement and is built predominantly of stuccoed brick on a stone foundation. The lower level Queen Street facade has undergone numerous changes while the upper level is mostly intact. This consists of three semicircular arched window openings, the central arch being larger than the ones to either side. This central arch originally had two smaller archways supported on a slender central Corinthian column above which was a small circular window.", "score": 0, "title_score": 0, "passage_id": "17357709"}, {"title": "Wallonia", "text": "The rooster was chosen as an emblem by the Walloon Assembly on 20 April 1913, and designed by Pierre Paulus on 3 July 1913. The Flag of Wallonia features the red rooster on a yellow background. An anthem, (), written by Theophile Bovy in 1900 and composed by Louis Hillier in 1901, was also adopted. On September 21, 1913, the \"national\" feast day of Wallonia took place for the first time in Verviers, commemorating the participation of Walloons during the Belgian revolution of 1830. It is held annually on the third Sunday of September. The Assembly also chose a motto", "score": 0, "title_score": 0, "passage_id": "968619"}, {"title": "Music", "text": "contrasting) sections called \"episodes\". It may be asymmetrical (ABACADAEA) or symmetrical (ABACABA). A recurring section, especially the main theme, is sometimes more thoroughly varied, or else one episode may be a \"development\" of it. A similar arrangement is the ritornello form of the Baroque concerto grosso. Arch form (ABCBA) resembles a symmetrical rondo without intermediate repetitions of the main theme. It is normally used in a round. Variational forms are those in which variation is an important formative element. Theme and Variations: a theme, which in itself can be of any shorter form (binary, ternary, etc.), forms the only \"section\"", "score": 0, "title_score": 0, "passage_id": "247259"}, {"title": "Somerville House", "text": "away on the Terrace was rented for extra Boarders and two primary classes. Harker and Jarrett gained little income from the school, as teacher-proprietors had little chance of financing a modern expanding school, especially one with boarding facilities. In 1918, due to these financial struggles, they transferred ownership to the newly formed Presbyterian and Methodist Schools Association, while retaining their Principalship. In 1920 the school moved from Wickham Terrace to its present site on Mater Hill, in South Brisbane, opening with an enrolment of 225 pupils. The boarding-school occupied \"Cumbooquepa\",the now heritage-listed former home of prominent Brisbane businessman, newspaper publisher,", "score": 0, "title_score": 0, "passage_id": "6548547"}, {"title": "20th Battalion, London Regiment (Blackheath and Woolwich)", "text": "recognition of the detachments of volunteers from the parent units who had served in the Second Boer War. The new battalion formed part of 5th London Brigade in the TF's 2nd London Division. The outbreak of war on 4 August saw the men of the 20th Londons at Perham Down on Salisbury Plain, where they had just arrived for their annual training camp with the rest of 2nd London Division. They were immediately recalled to Blackheath to complete their mobilisation and by mid-August the battalion had reached its war station at Hatfield, Hertfordshire. Meanwhile, \"On Wednesday, August 5, 1914, and", "score": 0, "title_score": 0, "passage_id": "18251485"}, {"title": "Salburua", "text": "Beto\u00f1o, in which the last animals and plants characteristic of these environments barely survived. Negative impacts on the area were included poaching, slums, and waste disposal. Ecological restoration work began with the reversal of the drainage of Lake Beto\u00f1o. In 1998 a dam was built in the Canal de la Balsa to help this process. Through these activities it has been possible to recover an area of more than , of which, at times of maximum flooding, are covered by water. The restoration of Salburua serves as protection against flooding in the city of Vitoria-Gasteiz, which uses the lagoons and", "score": 0, "title_score": 0, "passage_id": "15463645"}, {"title": "Abdel Latif Moussa", "text": "Wa Agwiba Sharia Hawl Al Qadiyah Al Filistaniyah\" [Juristic Questions and Answers Regarding the Palestinian Cause]. This book was published by the Beit al-Maqdis Publishing House, and was praised by Sheikh Mohamed Safwat Nour Al Din. On 14 August 2009, he proclaimed an \"Islamic Emirate\" in the Palestinian Territories. Early 15 August, Hamas police stormed his Ibn Taymiyah mosque in Rafah, and ended the rebellion. Moussa died in an explosion, officials said, but it was not clear whether he blew himself up. The mosque was destroyed in the fighting. The total death toll was 24. Abdel Latif Moussa Abdel Latif", "score": 0, "title_score": 0, "passage_id": "13698643"}, {"title": "Australian rules football in Tasmania", "text": "formed in 1877 and the Oatlands and Railway clubs in 1879. New Town formally started in 1878 and along with City and Richmond formed the basis of the game in Hobart, while in Launceston the abovementioned clubs formed the basis for the NTFA. On 1 May 1879 members of the Tasmanian Cricket Association met and decided to form a club for their members, to be called Cricketers. They initially adopted English Association Rules (soccer) before succumbing to the pressure to play Victorian Rules. The history of local Tasmanian football differs considerably from any of the mainland states. Whereas mainland states", "score": 0, "title_score": 0, "passage_id": "7617886"}, {"title": "Avia, Messenia", "text": "was built at the site of the temple of Asclepius. From the mid-19th century, the inhabitants of Megali Mantineia began to settle in the beach area again, in the settlements \"Palaiochora\", \"Archontiko\" and \"Kopanoi\" (the modern \"Akrogiali\"). Palaiochora became the seat of the community of Megali Mantineia in 1924. In 1926 both the settlement Palaiochora and the community were renamed to Avia. In 1998, the community Avia merged with 7 other communities to form the new municipality Avia, with its seat in Kampos. The municipal unit Avia is subdivided into the following communities (constituent villages in brackets): Avia, Messenia Avia", "score": 0, "title_score": 0, "passage_id": "8433976"}, {"title": "Anti-Indian sentiment", "text": "of leaked cables. Thereafter several newspapers apologized. The fake cables were believed to have been planted by Inter-Services Intelligence. The Indo-British film \"Slumdog Millionaire\" was the subject of many controversies in terms of its title, its depiction of Indian slums and its language use. The film's title was consistently challenged for having the word \"dog\" in it. The protest took place in Patna where it was written on a signboard \"I Am Not a Dog\". Activists stated that slum dwellers would continue to protest until the film's director deleted the word \"dog\" from the title. The Hindu organisations Hindu Janjagruti", "score": 0, "title_score": 0, "passage_id": "8072068"}, {"title": "Kerosene lamp", "text": "A lamp set too high will burn off its soot harmlessly if quickly turned down, but if not caught soon enough, the soot itself can ignite, and a \"runaway lamp\" condition can result. One popular model of mantle lamp uses only a wick and is unpressurized. Pressurized mantle lamps contain a gas generator and require preheating the generator before lighting. An air pump is used to deliver fuel under pressure to the gas generator. Large fixed pressurized kerosene mantle lamps were used in lighthouse beacons for navigation of ships, brighter and with lower fuel consumption than oil lamps used before.", "score": 0, "title_score": 0, "passage_id": "1580928"}, {"title": "Maya Lindholm", "text": "by President Joachim Gauck in November 2012, They were also named Team of the Year in Disability Sports for 2012, an annual award voted for by 3,000 members of the Association of German Sports Journalists. Lindholm's local team, Hamburger SV, which also included national teammates Mareike Adermann and Edina M\u00fcller (and Australia's Bridie Kean) won the women's national championship for the eighth time in 2013. Lindholm was also part of the Hamburger SV team that had previously won it in 2010. The German national team was not so fortunate, losing the final of the European Championship to the Netherlands before", "score": 0, "title_score": 0, "passage_id": "17862596"}, {"title": "Variable-length quantity", "text": "is also used in the WAP environment, where it is called variable length unsigned integer or uintvar. The DWARF debugging format defines a variant called LEB128 (or ULEB128 for unsigned numbers), where the least significant group of 7 bits are encoded in the first byte and the most significant bits are in the last byte (so effectively it is the little-endian analog of a variable-length quantity). Google Protocol Buffers use a similar format to have compact representation of integer values, as does Oracle Portable Object Format (POF) and the Microsoft .NET Framework \"7-bit encoded int\" in the BinaryReader and BinaryWriter", "score": 0, "title_score": 0, "passage_id": "10649725"}, {"title": "Ecumenical Institute for Study and Dialogue", "text": "the first theological journals on Buddhist-Christian encounter. The journal was founded by Lynn de Silva in order to move the prevailing atmosphere between Buddhists and Christians in Sri Lanka away from diatribe and towards dialogue. This journal has published articles on a wide range of topics including \"the existence of God, the idea of the soul, working towards shared ethical practice, monastic life, globalisation and women in religion.\" After Lynn de Silva's death in 1982, the EISD was directed by Rev. Kenneth Fernando, and it is currently directed by Marshal Fernando. Rev. Fr. Aloysius Pieris, S. J., who had been", "score": 0, "title_score": 0, "passage_id": "12211150"}, {"title": "Megan Beyer", "text": "in math and a 13% in reading in just three years. Beyer presented the 2009-16 PCAH report to the White House, summarizing accomplishments of the Obama administration's contributions to expanding cultural activities in the United States. Over the past 25 years Beyer has served on more than a dozen of national, state and local boards. She served on the Virginia State Board for Community Colleges; on the board of the Virginia Foundation for Community College Education; as a trustee of Washington's public television station, WETA-TV; and on the national board of Reading Is Fundamental. She held leadership positions with the", "score": 0, "title_score": 0, "passage_id": "12572147"}, {"title": "Bowery", "text": "the 'studios' of the tattoo artists,\u2014and here most in evidence are the 'down and outs'\". Prohibition eliminated the Bowery's numerous saloons: One Mile House, the \"stately old tavern... replaced by a cheap saloon\" at the southeast corner of Rivington Street, named for the battered milestone across the way, where the politicians of the East Side had made informal arrangements for the city's governance, Pressure for a new name after World War I came to naught and in the 1920s and 1930s, it was an impoverished area. From the 1940s through the 1970s, the Bowery was New York City's \"Skid Row,\"", "score": 0, "title_score": 0, "passage_id": "3682665"}, {"title": "Kikuyu people", "text": "that the following sets were grouped under \"Maina\" \u2013 \"K\u0129n\u0169thia\", \"Karanja\", \"Nj\u0169g\u0169na\", \"K\u0129nyanjui\", \"Gathuru\" and \"Ng\u2019ang\u2019a\". Professor M\u0169ri\u0169ki however puts these sets much earlier, namely \"Karanja\" and \"K\u0129n\u0169thia\" belong to the \"Ciira\" ruling generation which ruled from the year 1722 to 1756, give or take 25 years, according to \"M\u0169ri\u0169ki\". \"Nj\u0169g\u0169na\", \"K\u0129nyanjui\", \"Ng\u2019ang\u2019a\" belong to the \"Mathathi\" ruling generation that ruled from 1757 to 1791, give or take 20 years, according to M\u0169ri\u0169ki. Professor M\u0169ri\u0169kis list must be given precedence in this area as he conducted extensive research in this area starting 1969, and had the benefit of all earlier", "score": 0, "title_score": 0, "passage_id": "1505650"}, {"title": "Western Visayas", "text": "429\" pending the approval of an implementation plan for the orderly transfer of Palawan from Region IV-B to Region VI. Hence, Palawan is currently still part of Region IV-B. By virtue of \"Executive Order No. 183\" issued on May 29 of 2015, by President Benigno Aquino III, the province of Negros Occidental and its capital, Bacolod City, were both removed from Western Visayas in order to form the Negros Island Region along with Negros Oriental. But later regained Negros Occidental and its capital, Bacolod City back into Western Visayas on August 9, 2017 when President Rodrigo Duterte dissolved the Negros", "score": 0, "title_score": 0, "passage_id": "2036088"}, {"title": "Michael Alden Bayard", "text": "Bayard performed the Ingolf Dahl Duettino for Flute and Percussion with Paul Renzi, principal flautist with the San Francisco Symphony. In 1993, Bayard joined violinist Sarn Oliver to form the Sarn Oliver Continuum. In 1993, Bayard performed the Trio for Violin, String Bass, and Conga Drums by composer Charles Wuorinen, as part of a Chamber Music Society of Sacramento program. In 1994, Bayard launched his company Rhythm Magic!\u00ae that offers an arts enrichment percussion performance to youth and adults throughout the United States. This performance engages a blend of percussion instruments from all over the world and hands-on student participation", "score": 0, "title_score": 0, "passage_id": "19298985"}, {"title": "Shelby County Airport (Alabama)", "text": "Shelby County Airport (Alabama) Shelby County Airport is a public use airport located four nautical miles (7 km) southeast of the central business district of Alabaster, a city in Shelby County, Alabama, United States. It is owned by the Shelby County Commission. The airport is situated in the city of Calera, Alabama. This airport is included in the FAA's National Plan of Integrated Airport Systems for 2011\u20132015 and 2009\u20132013, both of which categorized it as a \"general aviation\" facility. This was a change from the 2007\u20132011 NPIAS Report, when it was categorized as a \"reliever airport\". Although most U.S. airports", "score": 0, "title_score": 0, "passage_id": "6503566"}, {"title": "Ronald D. Moore", "text": "of weeks later, with \"\" and \"Barge of the Dead\" as his only credits. In a January 2000 interview for \"Cinescape\" magazine, Moore cited problems in his working relationship with Braga for his short stay: Moore and Braga can be heard talking together on the commentary tracks for the DVD release of \"Star Trek Generations\" and \"Star Trek: First Contact\". After leaving \"Voyager\", Moore briefly worked as a consulting producer on \"Good vs Evil\" before joining \"Roswell\" as a co-executive producer and staff writer at the start of its second season in 2000. Moore and series creator Jason Katims jointly", "score": 0, "title_score": 0, "passage_id": "3978155"}, {"title": "If It's Over", "text": "as the second single released from the EP in late 1992. The live single version omits the second verse and chorus, as the songs were shortened for the show. It received a very limited release, being featured as an airplay only single in certain territories. Its only peak was in the Netherlands, where it reached number eighty. Carey performed \"If It's Over\" live during the 34th annual Grammy Awards and on \"Saturday Night Live\". During promotion for Carey's self-titled debut album (1990), she appeared on \"The Arsenio Hall Show\" to perform her first single, \"Vision of Love\". During the very", "score": 0, "title_score": 0, "passage_id": "5034440"}, {"title": "Holland Township, New Jersey", "text": "Alexandria Township on March 4, 1878. The township was reformed and separated as a municipality of its own again on March 11, 1879. Milford was created on April 15, 1911 from portions of Holland Township, based on the results of a referendum held on May 8, 1911. The township was named by Dutch settlers for Holland. The Volendam Windmill Museum is a working mill driven by wind, used for grinding raw grain into flour. The structure is seven stories high with sail arms from tip to tip. The windmill is located on the Charlie Brown Christmas Tree Farm, a property", "score": 0, "title_score": 0, "passage_id": "1150387"}, {"title": "Fantome Island Lock Hospital and Lazaret Sites", "text": "the hospital, a new school, new island telephone system and a new well. By October 1946 a visitors' quarters was under construction and another water tank was provided by June 1947. By June 1948 radio communication with Palm Island was installed, along with a 16 mm movie plant for entertainment of the patients. The women's huts at the lazaret were in a bad condition after the war, notwithstanding the poor design of all of the 1939-40 patients' huts. By September 1946 there were 38 women in 15 huts, when there were supposed to be two people per hut. The skillion-roofed", "score": 0, "title_score": 0, "passage_id": "19617298"}, {"title": "Joe Cimperman", "text": "make the city government a full partner in a collaborative effort by Greater Cleveland's four largest hospital systems to improve the health of city residents. Cimperman strongly champions for food justice for low-income and minority residents, citing the disparities in health between inner-city and suburban residents. Cimperman sees the connection between food and the issues of social, economic, and racial justice. In December 2007, Cimperman entered the race for the Democratic nomination for Ohio's 10th Congressional District, which was represented by veteran politician Dennis Kucinich. Cimperman's aggressive campaign was one factor in Kucinich's decision to drop out of the Presidential", "score": 0, "title_score": 0, "passage_id": "11495042"}, {"title": "Umineko When They Cry", "text": "A manga version of \"Legend of the Golden Witch\" drawn by Kei Natsumi began serialization in the January 2008 issue of Square Enix's \"Gangan Powered\", which was later transferred to the debut May 2009 issue of \"Gangan Joker\" after \"Gangan Powered\" was discontinued, and continued until the September 2009 issue. An adaptation of \"Turn of the Golden Witch\" drawn by Jir\u014d Suzuki began serialization in the August 2008 issue of Square Enix's \"GFantasy\". The manga adaptation of \"Banquet of the Golden Witch\" began serialization in the October 2009 issue of \"Gangan Joker\" and is illustrated by Kei Natsumi. S\u014dichir\u014d draws", "score": 0, "title_score": 0, "passage_id": "10488103"}, {"title": "Telford Town Park", "text": "activities of Saxon land clearance and subsequent land management through the medieval ages, this would have been converted to a patchwork of arable farmland, grassland and copses. By the Industrial Revolution, much of the Park area would have contained spoil mounds and quarry pits with isolated remnants of woodland and grassland habitats. Since the abandonment of industry, the pit mounds and surrounding areas have reverted to heathland and extensive areas of grassland; the quarried areas have become lakes and ponds; and woodland, scrub and hedges have established elsewhere, including alongside the old canal and railway. This mosaic of different habitats", "score": 0, "title_score": 0, "passage_id": "7146841"}, {"title": "PODS (company)", "text": "The jury awarded PODS $62 million in damages. The new PODS containers built by Wabash have a steel frame construction with completely recyclable panels made of steel skins and a high-density polyethylene core and are produced in three sizes: approximately 8-by-7-by-7 feet, 8-by-8-by-12 feet and 8-by-8-by-16 feet. The top is a translucent durable polymer material that allows ambient light to pass through and illuminate the inside of the container. The entry is a light-weight steel roll up door. PODS franchises around the country provided units for collection of donations as well as providing units for storm victims of Hurricane Katrina.", "score": 0, "title_score": 0, "passage_id": "13757011"}, {"title": "Batman (Thomas Wayne)", "text": "to be none other than Martha driven insane by grief following Bruce's murder. Batman cannot bring himself to kill the Joker, as he feels responsible for the Joker's crimes. After Batman saves one of Dent's children who had accidentally been shot by Gordon during a rescue attempt, Batman resumes pursuing the Joker. During a showdown, Batman reveals his recent discovery that \"they\" were supposed to die that night at Crime Alley and \"how\" they are alive now. Batman promises the Joker that he will do whatever it takes to bring Bruce back, even if it costs their lives; Batman's revelation", "score": 0, "title_score": 0, "passage_id": "16952134"}, {"title": "Miss March", "text": "a Razzie Award for \"worst supporting actor\". On \"Miss March\"'s opening weekend, the film grossed $2.4 million, which put the film in 10th place of all movies that weekend. The film grossed $4.54 million at the box office in the United States and Canada. The film was released on both Blu-Ray and DVD. Miss March Miss March is a 2009 comedy film directed by and starring Trevor Moore and Zach Cregger, stars of the IFC show \"The Whitest Kids U' Know\". The film was released in the United States on March 13, 2009. The movie begins with Eugene (Zach Cregger)", "score": 0, "title_score": 0, "passage_id": "12894947"}, {"title": "Queen of heaven (antiquity)", "text": "Sumerian (It comes from the words NIN meaning \"lady\" and AN meaning \"sky\"), although the cuneiform sign for her name (Borger 2003 nr. 153, U+12239 \ud808\ude39) is not historically a ligature of the two. In several myths, Inanna is described as being the daughter of Nanna, the ancient Sumerian god of the Moon. In other texts, however, she is often described as being the daughter of either Enki or An. These difficulties have led some early Assyriologists to suggest that Inanna may have been originally a Proto-Euphratean goddess, possibly related to the Hurrian mother goddess Hannahannah, accepted only latterly into", "score": 0, "title_score": 0, "passage_id": "12291967"}, {"title": "History of Christianity in Slovakia", "text": "following Samo's death around 659, Avar power was reestablished for another 150 years. The period around 650 experienced an apparent change in burial rite: barrows with horizontal wooden revetting at the base of the mound appeared in the region, and the cremated remains were deposited on the top of the mound. The Slavs seems to have come under Avar cultural influence, and acquired some of their religious practices. Many burials and grave goods from the 7th\u20138th centuries unearthed at Dev\u00ednska Nov\u00e1 Ves exhibit distinctly Avar elements. Avar power was broken at the end of the 8th century by Charlemagne, king", "score": 0, "title_score": 0, "passage_id": "15773348"}, {"title": "Lakemore, Ohio", "text": "(677.3/km\u00b2). There were 1,018 housing units at an average density of 696.3 per square mile (269.2/km\u00b2). The racial makeup of the village was 97.81% White, 0.47% African American, 0.35% Native American, 0.04% Asian, 0.04% Pacific Islander, 0.16% from other races, and 1.13% from two or more races. Hispanic or Latino of any race were 0.51% of the population. There were 969 households out of which 32.1% had children under the age of 18 living with them, 52.3% were married couples living together, 13.5% had a female householder with no husband present, and 27.3% were non-families. 21.7% of all households were", "score": 0, "title_score": 0, "passage_id": "1189087"}, {"title": "Harbin", "text": "yet, had a population of 5,282,083 people. The encompassing metropolitan area was estimated by the OECD (Organisation for Economic Co-operation and Development) to have, , a population of 10.5 million. The demographic profile for the Harbin metropolitan area in general is relatively old: 10.95 percent are under the age of 14, while 8.04 percent are over 65, compared to the national average of 16.6% and 8.87 percent, respectively. Harbin has a higher percentage of males (50.85 percent) than females (49.15 percent). Harbin currently has a lower birth rate than other parts of China, with 6.95 births per 1,000 inhabitants, compared", "score": 0, "title_score": 0, "passage_id": "1278469"}, {"title": "Ulysses S. Grant", "text": "met weekly with Lincoln and Stanton in Washington. After protest from Halleck, Grant scrapped a risky invasion plan of North Carolina, and adopted a plan of five coordinated Union offensives on five fronts, so Confederate armies could not shift troops along interior lines. Grant and Meade would make a direct frontal attack on Robert E. Lee's Army of Northern Virginia, while Sherman, whom Grant named chief of the western armies, was to destroy Joseph E. Johnston's Army of Tennessee and take Atlanta. Major General Benjamin Butler would advance on Lee from the southeast, up the James River, while Major General", "score": 0, "title_score": 0, "passage_id": "434024"}, {"title": "Brest Fortress", "text": "the Main Entrance, the Obelisk, the Main Monument, the sculpture \"Thirst\". This site was added to the UNESCO World Heritage Tentative List on January 30, 2004, in the Cultural category. Preservation and development is being carried out by the Brest Fortress Development Foundation. The Brest Fortress is used as a symbol of the Belarussian city of Brest. Brest Fortress Brest Fortress (, '; , '; ), formerly known as Brest-Litovsk Fortress, is a 19th-century Russian fortress in Brest, Belarus. In 1965, the title Hero Fortress was given to the Fortress to commemorate the defence of the frontier stronghold during the", "score": 0, "title_score": 0, "passage_id": "6115648"}, {"title": "Admiralty House, Sydney", "text": "was built in neo-Gothic style . Kirribilli House, situated next door to Admiralty House, serves today as the official Sydney residence of the Prime Minister of Australia. In 1855, during the Crimean War, Governor William Denison reclaimed the tip of Kirribilli Point, on which fortifications were built. These fortifications, along with Fort Denison, were intended to strengthen the defences of Sydney Harbour, as it was feared that the Russians might attack. In 1856, Lieutenant-Colonel George Barney, a Royal Engineers officer, lived in \"Wotonga\" and designed and supervised the installation of a battery of five, muzzle-loading guns on Kirribilli Point, as", "score": 0, "title_score": 0, "passage_id": "2802905"}, {"title": "Max Mara Art Prize for Women", "text": "Max Mara Art Prize for Women The Max Mara Art Prize for Women is a biennial arts prize awarded to a young female artist working in the United Kingdom. It is organised by the Max Mara fashion company and the Whitechapel Gallery in London. The prize includes a six-month residency in Italy, during which the artist creates an art project to be exhibited at the Whitechapel Gallery and at the Collezione Maramotti in Reggio Emilia, in Emilia-Romagna in northern Italy. Between 2006 and 2016 the winners of the prize were Margaret Salmon, Hannah Rickards, Andrea B\u00fcttner, Laure Prouvost, Corin Sworn", "score": 0, "title_score": 0, "passage_id": "9788493"}, {"title": "Serena Reeder", "text": "before she graduated from Juilliard in \"Get Rich or Die Tryin\"'. She was cast as 50 Cent's mother by the six time Academy Award nominee Jim Sheridan. This marked her film debut and the first time she worked with two time Academy Award nominee Viola Davis, playing her daughter. The movie was released November 9, 2005. In the summer of 2005, she was cast in The Architect, directed by Matt Tauber marking the second time she would play the daughter of Viola Davis. In 2006, she was cast as the lead in Jazz in the Diamond District. Reeder was cast", "score": 0, "title_score": 0, "passage_id": "16577457"}, {"title": "Thorington Players", "text": "Thorington Players The Thorington Players are an amateur orchestra based in London. The orchestra gives frequent concerts for charity. It is conducted by David Cairns. It has often played at St. John's, Smith Square, in the chapel of Merton College, Oxford and at the Suffolk festival \"Summer on the Peninsula\", but its main base is St. Mary's Church, Putney (the scene of the Putney Debates in 1647). The orchestra was founded in 1983 by David Cairns with the help of friends, after week-ends of chamber music at Thorington Hall in Suffolk. Soloists who have performed with the orchestra include: Gina", "score": 0, "title_score": 0, "passage_id": "8473169"}, {"title": "ArcelorMittal Orbit", "text": "it looked less and less like a work of art and more like a vanity project. In an online poll published by \"The Guardian\", 38.6% of readers considered it a \"grand design\", while 61.4% for considered it \"garbage\". Responding to concerns from \"The Times\" that ArcelorMittal's sponsorship and naming of \"Orbit\" would represent an improper incursion of corporate branding into public life, Johnson stated that Olympic rules mean that it cannot carry any corporate branding during the games. Felicity Carus of \"The Guardian's\" environment blog questioned whether ArcelorMittal's record on carbon emissions was good enough to mean Orbit represented a", "score": 0, "title_score": 0, "passage_id": "14430993"}, {"title": "Shadow Fighters", "text": "broken and is left outside the border of the country. The slightly mad hero Creeper, along with Bruce and Mona, have several adventures inside Eclipso's country, from which they barely escape. In issue 13, Nov 1993, the fight against Eclipso has gained new members, led by the former Suicide Squad leader Amanda Waller. A portion of the group are sent to Eclipso's stronghold. Creeper, Peacemaker, Dr. Midnight II, Major Victory I, Commander Steel, the second Wildcat and Manhunter all are killed. It is later revealed that the Manhunter slain was a 'ringer', another man brought in to fight under the", "score": 0, "title_score": 0, "passage_id": "7913005"}, {"title": "Fletcher Henderson", "text": "studies with his mother and further engaged himself in lessons on European art. Although a talented musician, Henderson decided to dedicate himself to math and science. At age 18 he moved to Atlanta, Georgia, and changed his name to Fletcher Henderson, giving up James, his grandfather's name. He attended Atlanta University (where he was a member of the fraternity Alpha Phi Alpha) and graduated in 1920 with a bachelor's degree in chemistry and mathematics. After graduation, he moved to New York City with the intention of attending Columbia University for a master's degree in chemistry, but no evidence proves he", "score": 0, "title_score": 0, "passage_id": "1468696"}, {"title": "Healthcare in Israel", "text": "funds. Finally, there were some private doctors and very few private hospitals, and some highly expensive health plans covered private healthcare. The level of health coverage provided varied among Kupot Holim. Furthermore, Clalit was the only one not to restrict entry to new members based on age, pre-existing conditions, or other factors, and membership in the Histadrut was a pre-condition for membership with Clalit. This meant that people who did not have such an affiliation and could not join another insurance plan lacked health insurance coverage. Over 90% of the population was insured. In 1988 the government appointed a Commission", "score": 0, "title_score": 0, "passage_id": "11646148"}], "hard_negative_ctxs": [{"title": "Last of the Summer Wine", "text": "to Barry (Mike Grady). Also making her first appearance in the film was Thora Hird as Seymour's sister and Glenda's mother, Edie, as well as re-introducing Gordon Wharmby as Edie's husband Wesley, previously seen in three popular one-off appearances. The second film proved a success and all four new characters were carried over to the show beginning with the ninth series in 1986. A documentary film was commissioned to celebrate the 25th anniversary of \"Last of the Summer Wine\". Produced and directed by Alan J. W. Bell, it featured interviews with the majority of cast and crew members, outtakes from", "score": 13.078156, "title_score": 0, "passage_id": "808428"}, {"title": "John Wesley", "text": "to refer to them as bishops rather than superintendents, overruling Wesley's objections to the change. His brother, Charles, was alarmed by the ordinations and Wesley's evolving view of the matter. He begged Wesley to stop before he had \"quite broken down the bridge\" and not embitter his [Charles'] last moments on earth, nor \"leave an indelible blot on our memory.\" Wesley replied that he had not separated from the church, nor did he intend to, but he must and would save as many souls as he could while alive, \"without being careful about what may possibly be when I die.\"", "score": 12.847395, "title_score": 0, "passage_id": "528317"}, {"title": "Wyatt's Watchdogs", "text": "viewing figures - that the programme had not really caught on with viewers, and it was dropped after its initial series. However, with the production of this series, Wilde and Bell managed to settle their differences regarding \"Last of the Summer Wine\", and the following year in 1989, when the next series of \"Summer Wine\" was due to start filming and actor Michael Aldridge having to leave the show for personal reasons, the character of Seymour Utterthwaite had to be replaced and Brian agreed to return as Foggy Dewhurst, staying with the series for seven more years. Episode One: \"One", "score": 12.506208, "title_score": 0, "passage_id": "7024357"}, {"title": "Last of the Summer Wine", "text": "new book titled \"Last Of the Summer Wine - From The Directors Chair\" was released and was written by producer and director Alan J.W. Bell. During its first series, \"Last of the Summer Wine\" did not receive a high ratings share. The second series proved to be a success, however, and two episodes made it to the top ten programmes of the week. The programme has since consistently been a favourite in the ratings, peaking at 18.8 million viewers for an episode shown on 10 February 1985. The premiere of the 28th series in 2007 brought in an 18.6 percent", "score": 12.071985, "title_score": 0, "passage_id": "808444"}, {"title": "Last of the Summer Wine", "text": "Ferguson), and Ivy's nephew, \"Crusher\" Milburn (Jonathan Linsley). Further additions came the following year when the film \"Uncle of the Bride\" introduced Seymour's sister, Edie, played by veteran actress Thora Hird, and her family, who were brought over to the programme the following series. The only addition with no professional acting experience was the Holmfirth resident Gordon Wharmby, who performed so well during his audition as mechanic Wesley Pegden, that Alan J. W. Bell cast him in one episode. Pegden would make two more appearances before being retconned as Edie's husband and Seymour's brother-in-law after positive audience reception, becoming a", "score": 11.993387, "title_score": 0, "passage_id": "808417"}, {"title": "I Know What You Did Last Summer (The Vampire Diaries)", "text": "as she leaves for Whitmore College since neither of them wants to leave each other after their newly started relationship. Jeremy (Steven R. McQueen) stays behind under the guardianship of Damon, who takes Jeremy back to school. No one knows yet that Bonnie (Kat Graham) is dead, except for Jeremy, who sees her and talks to her and also answers everyone's mails and texts that are sent to her. Also no one knows that Silas (Paul Wesley) is not gone and Stefan is at the bottom of the lake. At college, Elena and Caroline expect Bonnie to join them soon,", "score": 11.973663, "title_score": 0, "passage_id": "17532930"}, {"title": "Keith Clifford", "text": "Keith Clifford Keith Clifford (born 20 June 1938 in Halifax, West Riding of Yorkshire) is a British actor best known for his role as Billy Hardcastle in Last of the Summer Wine between 1999 and 2006. He played Billy Hardcastle on the British sitcom \"Last of the Summer Wine\" from 1999 until he decided to leave the series following the 27th series of 2006. (Billy was a comedy character who believed he was a direct descendant of Robin Hood.) He also made guest appearances on \"Heartbeat\", \"Dalziel and Pascoe\" and an episode of \"Cold Feet\", and appeared in the TV", "score": 11.930991, "title_score": 0, "passage_id": "8658260"}, {"title": "Burnsville, North Carolina", "text": "Burnsville may now operate an ABC store; retail establishments may now sell beer and wine; and restaurants may sell beer, wine, and mixed drinks. Graham County is the last remaining dry county in the state of North Carolina. In addition to the Nu-Wray Inn, the Bald Creek Historic District, Chase-Coletta House, Citizens Bank Building, John Wesley McElroy House, Yancey Collegiate Institute Historic District, and Yancey County Courthouse are listed on the National Register of Historic Places. The Nu-Wray Inn, used as a hotel since its construction in 1833. The Parkway Playhouse, founded in 1947, as a summer stock theatre, is", "score": 11.863393, "title_score": 0, "passage_id": "1175976"}, {"title": "Lincoln Mystery Plays", "text": "from the Mystery Plays themselves, there are occasionally other performances. For example, in 2003, \"Mister Wesley\", a new play by Roy Clarke, who also wrote Last of the Summer Wine, was performed in Lincoln and Southwell. In 2014, \"The Last Post\" was performed by the Lincoln Mystery Plays company at The Drill Hall, and based on the true story of the Beechey brothers. The Beecheys' were a local family in the first World War, who had eight brothers, all of which signed up to fight. Of the eight, five were killed and one was badly injured. The family's youngest daughter,", "score": 11.5997, "title_score": 0, "passage_id": "11052124"}, {"title": "Last of the Summer Wine", "text": "themes from \"Last of the Summer Wine\". Ronnie Hazlehurst used the resulting list for an independently released CD collection titled \"Last of the Summer Wine: Music from the TV Show\". BBC Radio released audio-only versions of episodes starting in 1995. Peter Sallis provided narration to compensate for the loss of the televised visual elements. All twelve audio episodes were released in CD format. In 1976, a selection of early scripts from the series was published as \"Last of the Summer Wine Scripts\". A companion guide to the show, \"Last of the Summer Wine: The Finest Vintage\", was released in 2000.", "score": 11.400429, "title_score": 0, "passage_id": "808442"}, {"title": "John Wesley", "text": "published his sermons. Wesley practised a vegetarian diet and in later life abstained from wine for health reasons. Wesley warned against the dangers of alcohol abuse in his famous sermon, \"The Use of Money,\" and in his letter to an alcoholic. In his sermon, \"On Public Diversions\", Wesley says: \"You see the wine when it sparkles in the cup, and are going to drink of it. I tell you there is poison in it! and, therefore, beg you to throw it away\". However, other materials show less concern with consumption of alcohol. He encourages experimentation in the role of hops", "score": 11.269921, "title_score": 0, "passage_id": "528332"}, {"title": "Last of the Summer Wine (series 1)", "text": "Last of the Summer Wine (series 1) Last of the Summer Wine's first series originally aired on BBC1 between 4 January 1973 and 29 December 1973. All episodes from this series were written by Roy Clarke and produced and directed by James Gilbert. The pilot episode, alternately known as \"The Last of the Summer Wine\" and \"Of Funerals and Fish,\" originally premiered on the BBC's \"Comedy Playhouse\" on 4 January 1973 \"The Last of the Summer Wine\" was the first episode of that show's fourteenth series. The pilot received a positive enough reaction that the BBC ordered a full series", "score": 11.213186, "title_score": 0, "passage_id": "11459550"}, {"title": "Last of the Summer Wine", "text": "Last of the Summer Wine Last of the Summer Wine is a British sitcom created and written by Roy Clarke and originally broadcast by the BBC from 1973 to 2010. It premiered as an episode of \"Comedy Playhouse\" on 4 January 1973, and the first series of episodes followed on 12 November 1973. From 1983 to 2010, Alan J. W. Bell produced and directed all episodes of the show. The BBC confirmed on 2 June 2010 that \"Last of the Summer Wine\" would no longer be produced and the 31st series would be its last. Subsequently, the final episode was", "score": 11.088019, "title_score": 0, "passage_id": "808390"}, {"title": "Newton K. Wesley", "text": "family also says that in the 1950s, he campaigned to get \"contact lens\" into the dictionary. In 1942, a year after he married the late Cecilia Sasaki Wesley, the optometrist and his family \u2014 including two young children \u2014 were sent to the Minidoka War Relocation Center in Idaho. Dr. Wesley, who for business purposes Anglicized his name to what he thought sounded similar to his Japanese last name, was able to receive permission to leave the camp \u2014 though his family stayed. The optometrist moved to the Midwest and attended Earlham College in Indiana, then settled in Chicago. When", "score": 11.069021, "title_score": 0, "passage_id": "15013084"}, {"title": "Gordon Wharmby", "text": "Dixey\" (1978), and \"Coronation Street\" (1982). He was then auditioned for a one-line part in Last of the Summer Wine, which had begun in 1973, filmed in and around the Yorkshire town of Holmfirth. The producer, Alan J.W. Bell, was so impressed with Wharmby's \"natural\" performance that, instead, he cast him in the more prominent role of the bumbling Wesley Pegden for another episode and Clarke later wrote him in as a regular. Although initially overawed by working with Thora Hird as his screen wife from 1986, Wharmby eventually started giving her \"notes\", to the veteran actress's great amusement. Wharmby", "score": 11.049947, "title_score": 0, "passage_id": "4441860"}, {"title": "Last of the Summer Wine", "text": "enough positive response that a full series was commissioned to be broadcast before the end of the year. Although the initial series did not do well in the ratings, the BBC ordered a second series in 1975. The site for the exterior shots of \"Last of the Summer Wine\" was, in part, suggested by television producer Barry Took, who was familiar with the area. Took had, in the 1950s, toured as a stand-up comic, often appearing at working men's clubs. One such appearance was at Burnlee Working Men's Club, a club in the small West Yorkshire town of Holmfirth, and", "score": 11.007274, "title_score": 0, "passage_id": "808399"}, {"title": "Last of the Summer Wine (series 12)", "text": "Last of the Summer Wine (series 12) The Last of the Summer Wines twelfth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. With the departure of Michael Aldridge who had left to nurse his ill wife, the character of Foggy Dewhirst returned to the fold. The trio in this series consisted of: When Compo and Clegg inform Seymour that the caning of children in the UK was now illegal. Seymour is clearly disappointed by this news despite him knowing it about in the 1987 feature-length episode", "score": 10.985669, "title_score": 0, "passage_id": "12163972"}, {"title": "Last of the Summer Wine", "text": "consecutive full series of episodes. The entire series is now available on home video, both in box sets with two series of episodes each, and in a complete collection which features every episode of \"Last of the Summer Wine\" plus all films and specials. Three \"best of\" collections as well as sets devoted to individual series have been released for region one. The first, simply titled \"Last of the Summer Wine\", was released in 2003 and includes early episodes from the 1970s and 1980s. The second collection, titled \"Last of the Summer Wine: Vintage 1995\", followed in 2004 and includes", "score": 10.983786, "title_score": 0, "passage_id": "808430"}, {"title": "Last of the Summer Wine (series 13)", "text": "Last of the Summer Wine (series 13) The Last of the Summer Wines thirteenth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. Notably, this series of the show was shot entirely on videotape. Prior to this, the show had used videotape for studio scenes and film for location footage. From the following series until 2004, when it started being shot digitally in High-Definition, the show moved to being shot entirely on film, although the laughter track is still included, respectively. The completed shows were still assembled", "score": 10.982573, "title_score": 0, "passage_id": "12174124"}, {"title": "Last of the Summer Wine (series 9)", "text": "(1986) Regular series Christmas Special (1987) When recordings were \"repackaged\" for overseas sale, UK series 9 (12 episodes) was split into \"Season 9\" and \"Season 10\" (each of 6 episodes), with all subsequent \"seasons\" being renumbered accordingly. As a result, (for example) \"Series 27\" in the UK may be referred to as \"Season 28\" in the USA. The box set for series nine was released by Universal Playback in May 2008, mislabelled as a box set for series 9 & 10. Last of the Summer Wine (series 9) Last of the Summer Wine's ninth series originally aired on BBC1 between", "score": 10.980464, "title_score": 0, "passage_id": "12006128"}, {"title": "Kenneth Perez", "text": "were later dismissed by Perez and Martin van Geel, the technical director of Ajax. Perez stated it was in fact PSV who initiated the transfer by telling Perez he no longer had a future at the club after just four months. Ajax, on the other hand, was still looking for a replacement for star midfield player Wesley Sneijder who was sold to Real Madrid and saw Ten Cate leave for Chelsea last September thus paving the way for Perez to move back to Amsterdam. Van Geel added that Ajax only wanted to buy Aissati last summer and he had no", "score": 10.936021, "title_score": 0, "passage_id": "4543847"}, {"title": "Last of the Summer Wine", "text": "Mildred\", where he played the hen-pecked husband to a strong-willed woman. In 2008, the BBC announced that Russ Abbot would join the cast in series 30 as a relatively youthful actor. Abbot was cast to allow Sallis and Thornton to reduce their role on the show to indoor scenes only. Abbot portrayed Luther \"Hobbo\" Hobdyke, who formed a new trio with Entwistle and Alvin. Entwistle, played by Burt Kwouk, had been a supporting character brought in to replace Wesley Pegden after the death of actor Gordon Wharmby, but his role on the show steadily increased in the previous two series.", "score": 10.884821, "title_score": 0, "passage_id": "808414"}, {"title": "August Wesley", "text": "journalist in the newspaper \"Vaba Maa\". Wesley also translated literature to Estonian and Finnish. One of his translations is the 1937 Estonian version of Laozi's famous work, \"Tao Te Ching\". During the 1920s and 1930s, Wesley contacted the Finnish government several times asking to return to Finland, but the answer was always the same; the general pardon did not apply to the Red Guard leaders. When the Soviet Union occupied Estonia in June 1940, Wesley went underground. He was last seen in Narva in 1941. According to some newspaper sources, Wesley starved to death in the Siege of Leningrad in", "score": 10.860063, "title_score": 0, "passage_id": "20097778"}, {"title": "Last of the Summer Wine (series 3)", "text": "play this role twice: between 1976 and 1985 and then again from 1990 until 1997, when he was forced to leave due to health problems. The third series was released on DVD in region 2 as a combined box set with series 4 on 26 July 2004. A box set featuring just series 3 was released for region 1 on 11 March 2008. The trio in this series consisted of: Foggy (1976-1985, 1990-1997) Gordon Simmonite (1976) (Only made a few appearances in this series) Miss Moody (1976) (Only series this character appeared in) Big Malcolm Simmonite (Only series this character", "score": 10.716256, "title_score": 0, "passage_id": "11998991"}, {"title": "Last of the Summer Wine (series 1)", "text": "episodes, however the pilot still was not included in the re-release. The pilot episode was released on the final boxset series 31 & 32 as an extra on disc four on 15 August 2016. Last of the Summer Wine (series 1) Last of the Summer Wine's first series originally aired on BBC1 between 4 January 1973 and 29 December 1973. All episodes from this series were written by Roy Clarke and produced and directed by James Gilbert. The pilot episode, alternately known as \"The Last of the Summer Wine\" and \"Of Funerals and Fish,\" originally premiered on the BBC's \"Comedy", "score": 10.698714, "title_score": 0, "passage_id": "11459552"}, {"title": "Last of the Summer Wine (series 2)", "text": "Last of the Summer Wine (series 2) Last of the Summer Wine's second series originally aired on BBC1 between 5 March and 16 April 1975. All episodes from this series were written by Roy Clarke and produced and directed by Bernard Thompson. Although ratings from the first series were not good, the BBC ordered a second series of \"Last of the Summer Wine\" after the first season aired but were delayed due to strike action. The second series was eventually produced and aired during March and April 1975. For the first time, series 2 saw two episodes make it into", "score": 10.698644, "title_score": 0, "passage_id": "11997014"}, {"title": "Last of the Summer Wine (series 4)", "text": "4 was released by Universal Playback in July 2004. In addition, \"Last of the Summer Wine: Vintage 1977\" has been released on 9 September 2008 in Region 1 and included all episodes from the fourth series including a rare 1977 interview with Roy Clarke. Last of the Summer Wine (series 4) Last of the Summer Wine's fourth series originally aired on BBC1 between 9 November 1977 and 4 January 1978. All episodes from this series were written by Roy Clarke and produced and directed by Sydney Lotterby. The fourth series was released on DVD in region 2 as a combined", "score": 10.696605, "title_score": 0, "passage_id": "11999298"}, {"title": "First of the Summer Wine", "text": "original series making an appearance in the prequel. With the success of \"Last of the Summer Wine\", the BBC approved a new series which Roy Clarke would carry over characters of the original show. With the new series, Clarke hoped to show the lives of his characters as they were in the \"first summer\" of their lives, as opposed to the last summer depicted in \"Last of the Summer Wine\". While there would still be the \"shadow of the Grim Reaper\" hanging over them, this time it would be because of World War II, not due to their old age.", "score": 10.668832, "title_score": 0, "passage_id": "5525492"}, {"title": "Aria Montgomery", "text": "with Aria, as a couple. Season 3 picks up five months after the liars discovered that Mona was A. It starts at a party at Spencer's where they discuss what they did in the summer. Near the beginning of the season Aria meets Ezra's mother and younger brother Wesley Fitzgerald-who Aria shares a brief kiss with, (Gregg Sulkin). Wesley tells Aria about a girl called Maggie, (Larisa Oleynik) that Ezra got pregnant when he was younger. Wesley accidentally lets it slip after finding out his mother tried to pay Aria to \"disappear\" from her son's life, which is what she", "score": 10.639123, "title_score": 0, "passage_id": "14725592"}, {"title": "Bill Owen (actor)", "text": "Bill Owen (actor) William John Owen Rowbotham, (14 March 1914 \u2013 12 July 1999), known professionally as Bill Owen, was an English actor and songwriter. He was the father of actor Tom Owen. He is best known for portraying Compo Simmonite in the Yorkshire based BBC comedy series Last of the Summer Wine for 27 years. He died in July 1999, his last appearance on-screen being shown in April 2000. Born in London, Owen made his first film appearance in 1944, but did not achieve lasting fame until 1973, when he took the starring role of William \"Compo\" Simmonite in", "score": 10.61789, "title_score": 0, "passage_id": "1409970"}, {"title": "Peter Sallis", "text": "Clegg. The pilot was successful and the BBC commissioned a series. Sallis had already worked on stage with Michael Bates, who played the unofficial ringleader Blamire in the first two series. Sallis played the role of Clegg from 1973 to 2010, and was the only cast member to appear in every episode. He also appeared, in 1988, as Clegg's father in \"First of the Summer Wine\", a prequel to \"Last of the Summer Wine\" set in 1939. He appeared in the children's series \"The Ghosts of Motley Hall\" (1976\u201378), in which he played Arnold Gudgin, an estate agent who did", "score": 10.573234, "title_score": 0, "passage_id": "3689609"}, {"title": "Last of the Summer Wine", "text": "of the Summer Wine\" in the months leading up to World War II. Unlike its mother show, \"First of the Summer Wine\" was not filmed in Holmfirth. Period music was used instead of Ronnie Hazlehurst's score to create a more World War II era atmosphere. New supporting characters were added to those from \"Last of the Summer Wine\". Peter Sallis and Jonathan Linsley were the only actors from the original series to appear in the spin-off: Sallis played the father of his own character from the original show and Linsley appeared during the second series as a different character. The", "score": 10.555262, "title_score": 0, "passage_id": "808432"}, {"title": "Last of the Summer Wine", "text": "Emerick appealed for funding through crowd-sourcing sites in the hopes of gaining enough support to produce a feature film featuring the duo or even a television series. Associate Producer Terry Bartlam believed there was enough of a scope with Cooper and Walsh that they could carry their own series and that this spin-off could be the answer to those who believed \"Last of the Summer Wine\" should have been given a proper ending. A live production of \"Last of the Summer Wine\", known informally as the \"summer season\", was produced in Bournemouth in 1984. While Bill Owen and Peter Sallis", "score": 10.541139, "title_score": 0, "passage_id": "808434"}, {"title": "Last of the Summer Wine", "text": "the majority of the play was improvised, with Kitson and Emerick each deriving their cues of what to do from the audience. The play was successfully performed in Holmfirth, after which dates were announced in Emerick's hometown on the Wirral Peninsula. Coronet Books released a novelisation of \"Last of the Summer Wine\" in 1974. Written by Roy Clarke as an unbroadcast original story, the novel featured Compo, Clegg and Blamire helping their friend, Sam, enjoy one last night with a glam girl. The book became the basis for the \"Last of the Summer Wine\" film, \"Getting Sam Home\", with Blamire", "score": 10.510786, "title_score": 0, "passage_id": "808440"}, {"title": "Peter Sallis", "text": "Sallis died at the Denville Hall nursing home in Northwood, London, on 2 June 2017 at the age of 96. He was buried next to fellow \"Last of the Summer Wine\" actor Bill Owen in the churchyard of St John's Parish Church, Upperthong, near the town of Holmfirth in Yorkshire, the home of \"Last of the Summer Wine\". Peter Sallis Peter John Sallis, (1 February 1921 \u2013 2 June 2017) was an English actor. He was the voice of Wallace in the Academy Award-winning \"Wallace and Gromit\" films and played Norman \"Cleggy\" Clegg in \"Last of the Summer Wine\" from", "score": 10.427485, "title_score": 0, "passage_id": "3689617"}, {"title": "Last of the Summer Wine", "text": "regular character starting in \"Uncle of the Bride\". The increasingly large cast ensured a sense of continuity with the changing configuration of the trio, especially following the death of Bill Owen. When Alan J. W. Bell took over as producer, the plots of \"Last of the Summer Wine\" moved away from the original dialogue-packed scenes in the pub and the library; guest actors were brought in to interact with the trio in new situations. Although many of these guest appearances lasted for only one episode, some led to a permanent role on the show, as in the cases of Gordon", "score": 10.398296, "title_score": 0, "passage_id": "808418"}, {"title": "Bill Owen (actor)", "text": "the Labour Party; Peter Sallis has claimed that Owen's left-wing views contrasted so much with the right-wing opinions of Michael Bates that \"Last of the Summer Wine\" was almost not made because of their arguments. Owen was a founding member of the Keep Sunday Special campaign group. He was awarded the MBE in 1976. Owen was the subject of \"This Is Your Life\" in 1980 when he was surprised by Eamonn Andrews in Trafalgar Square. While filming the \"Last Of The Summer Wine\" French special for the millennium of 2000, Owen fell ill but insisted on continuing despite being in", "score": 10.396783, "title_score": 0, "passage_id": "1409975"}, {"title": "Last of the Summer Wine", "text": "Wharmby, Thora Hird, Jean Alexander, Stephen Lewis, Dora Bryan, Keith Clifford, Brian Murphy, Josephine Tewson, June Whitfield, Barbara Young, and Trevor Bannister. Other noted guests on the programme included John Cleese, Ron Moody, Sir Norman Wisdom, Eric Sykes, Liz Fraser, Stanley Lebor, and Philip Jackson. \"Last of the Summer Wine\" focused on a trio of older men and their youthful antics. The original trio consisted of Compo Simmonite, Norman Clegg, and Cyril Blamire. Blamire left in 1976, when Michael Bates fell ill shortly before filming of the third series, requiring Clarke to hastily rewrite the series with a new third", "score": 10.394297, "title_score": 0, "passage_id": "808419"}, {"title": "Last of the Summer Wine", "text": "hated this at first and insisted that it remain a temporary working title, while the cast worried that viewers would forget the name of the show. The working title was changed later to \"The Library Mob\", a reference to one of the trio's regular haunts early in the show. Clarke switched back to his original preference shortly before production began, a title that was shortened to \"Last of the Summer Wine\" after the pilot show. \"The Last of the Summer Wine\" premiered as an episode of BBC's \"Comedy Playhouse\" on 4 January 1973. The pilot, \"Of Funerals and Fish\", received", "score": 10.353075, "title_score": 0, "passage_id": "808398"}, {"title": "Last of the Summer Wine", "text": "Barry trying to better himself (at the insistence of Glenda), and Tom trying to stay one step ahead of the repo man. \"Last of the Summer Wine\" is the longest-running comedy programme in Britain, and the longest running situation comedy in the world. Each series has between six and twelve episodes; most were thirty minutes in length, with some specials running longer. There were 295 episodes and 31 series between 1973 and 2010, counting the pilot, all episodes of the series, specials, and two films. In 1978, the BBC commissioned a \"Last of the Summer Wine\" Christmas special instead of", "score": 10.353025, "title_score": 0, "passage_id": "808423"}, {"title": "Last of the Summer Wine", "text": "episodes from series seventeen and the 30th anniversary documentary. A 2008 release named \"Last of the Summer Wine: Vintage 1976\" focuses on the third series of the show and includes bonus interviews with Peter Sallis, Brian Wilde, and Frank Thornton. Subsequently, every episode from the third to the twenty-seventh series has been released on DVD in \"Vintage\" collections, many including special features and interviews. A spin-off prequel show, \"First of the Summer Wine\", premiered on BBC1 in 1988. The new programme was written by Roy Clarke and used different actors to follow the activities of the principal characters from \"Last", "score": 10.35072, "title_score": 0, "passage_id": "808431"}, {"title": "Last of the Summer Wine", "text": "\"Heartbeat\". Alan J. W. Bell responded that Radio Times has always been anti-\"Last of the Summer Wine\", and Roy Clarke remarked that people who dislike the show \"shouldn't switch it on\" unless they are \"too idle to turn it off\". A 2008 survey by \"County Life\" magazine, which named the show the worst thing about Yorkshire, was disputed by members of the Holme Valley Business Association, who said the show was good for business. The BBC wanted to cancel \"Last of the Summer Wine\" for years in favour of a new programme aimed at a younger audience, but the show", "score": 10.350688, "title_score": 0, "passage_id": "808447"}, {"title": "Last of the Summer Wine", "text": "broadcast on 29 August 2010. Since its original release, all 295 episodes, comprising thirty-one series \u2014 including the pilot and all films and specials \u2014 have been released on DVD. Repeats of the show are broadcast in the UK on Gold, Yesterday, and Drama. It is also seen in more than twenty-five countries, including various PBS stations in the United States and on VisionTV in Canada. \"Last of the Summer Wine\" is the longest-running comedy programme in Britain and the longest-running sitcom in the world. \"Last of the Summer Wine\" was set and filmed in and around Holmfirth, West Yorkshire,", "score": 10.348829, "title_score": 0, "passage_id": "808391"}, {"title": "Last of the Summer Wine", "text": "Situation Comedy Series award (in 1973 and 1979) and three times for the Best Comedy Series award (in 1982, 1983, and 1985). The show was also considered for the National Television Awards four times since 1999 (in 1999, 2000, 2003, and 2004), each time in the Most Popular Comedy Programme category. In 1999 the show won the National Television Award for Most Popular Comedy Programme. Last of the Summer Wine Last of the Summer Wine is a British sitcom created and written by Roy Clarke and originally broadcast by the BBC from 1973 to 2010. It premiered as an episode", "score": 10.346018, "title_score": 0, "passage_id": "808449"}, {"title": "Glaucus (son of Minos)", "text": "Oracle had said that the seer would restore the child alive. Minos shut Polyidus up in the wine-cellar with a sword. When a snake appeared nearby, Polyidus killed it with the sword. Another snake came for the first, and after seeing its mate dead, the second serpent left and brought back a herb which then brought the first snake back to life. Following this example, Polyidus used the same herb to resurrect Glaucus. Minos refused to let Polyidus leave Crete until he taught Glaucus the art of divination. Polyidus did so, but then, at the last second before leaving, he", "score": 10.321901, "title_score": 0, "passage_id": "13337501"}, {"title": "John Wesley Ryles", "text": "on Warner, he did not release an album for the label. Since the release of his last single in 1988, Ryles has served primarily as a background vocalist. John Wesley Ryles John Wesley Ryles (born December 2, 1950) is an American country music artist. Ryles recorded a string of hit country songs, beginning in 1968 when he was still a teenager, and continuing through the 1980s. He no longer records as a headline artist but remains active in the music industry as a session musician. At age 17, he made his debut in 1968 with the single \"Kay\", a Top", "score": 10.30227, "title_score": 0, "passage_id": "11771067"}, {"title": "The Camomile Lawn", "text": "The Camomile Lawn The Camomile Lawn is a 1984 novel by Mary Wesley beginning with a family holiday in Cornwall in the last summer of peace before the Second World War. When the family is reunited for a funeral nearly fifty years later, it brings home to them how much the war acted as a catalyst for their emotional liberation. The title refers to a fragrant camomile lawn stretching down to the cliffs in the garden of their aunt's house. Mary Wesley first began writing \"The Camomile Lawn\" after the death of her second husband left her destitute. She finished", "score": 10.143065, "title_score": 0, "passage_id": "8102642"}, {"title": "Fred Goodwill", "text": "in Tamil in Year 10. His name carries respect and honour at the Wesley Tamil Church at Haines Road, Fraser Town Bangalore and at the Goodwills School. Fred Goodwill left India in 1924. According to his daughter Fred did not want to leave India, but his wife wanted to return to England. On the one hand Fred was extremely sad to leave India after 25 years, but there was also happiness of the thought of seeing their children who were growing up in England. Before their departure, they received an address from the Wesley Tamil Church, Kolar Gold Fields, which", "score": 10.14176, "title_score": 0, "passage_id": "17391507"}, {"title": "Angel (season 4)", "text": "of season three. It turns out that Wesley (who had been banished from the group for betraying Angel's trust) has been independently searching for them both as well. Using information coerced from Justine, Wesley is able to deduce Angel's location and bring him back to shore and to his friends at Angel Investigations. After Angel forces Connor to leave the Hyperion Hotel in retribution for what he did to him, Angel does everything he can to find Cordelia whose whereabouts are still unknown. Angel and Co. eventually learn that Cordelia is happy and they decide to leave her in peace", "score": 10.131365, "title_score": 0, "passage_id": "14815261"}, {"title": "There Goes the Groom", "text": "long-term fan of Summer Wine Kriss Akabusi makes a guest appearance as a disgruntled milkman. 30 years of Last of The Summer Wine by Morris Bright & Robert Ross There Goes the Groom \"There Goes The Groom\" is a 1997 Christmas special of the BBC sitcom \"Last of the Summer Wine\" first shown on 28 December 1997. It was the first to feature Frank Thornton as new third man leader Herbert \"Truly of the Yard\" Truelove, the episode also marked the final appearance of Foggy. The Trio in this episode was Compo (Bill Owen), Clegg (Peter Sallis) and Truly (Frank", "score": 10.084827, "title_score": 0, "passage_id": "9769573"}, {"title": "Yuppy Love", "text": "seen in Last of the Summer Wine when Eli falls behind the bar, Two years earlier, in the episode The Naked Now, Data did a similar pratfall on the bridge of the Enterprise in . Note: \"The Spell! (Get Down With The Genie)\" and \"Enchanted Lady\" are removed on the VHS, DVD and iTunes versions and over-dubbed with generic music, leading to some scenes of dialogue being removed. Yuppy Love \"Yuppy Love\" is an episode of the BBC sitcom, \"Only Fools and Horses\". It originally aired on 8 January 1989 and is the first episode of series six, marking the", "score": 10.076231, "title_score": 0, "passage_id": "8665924"}, {"title": "Daniel Wesley (athlete)", "text": "Daniel Wesley (athlete) Daniel Wesley (aka Daniel Westley) is a Canadian athlete who won 12 medals while competing in the Paralympic Games. Wesley grew up in New Westminster, British Columbia and lost both his legs in 1973 when he fell under a moving train. While recovering from his accident, Wesley met Rick Hansen who inspired him to try wheelchair athletics. He began wheelchair racing in 1978 and track and field competitions in 1979 and earned a place on the team for the 1988 Summer Paralympics in Seoul, South Korea. He competed in both the winter and summer games in several", "score": 10.065317, "title_score": 0, "passage_id": "13376695"}, {"title": "Last of the Summer Wine", "text": "job down as he felt that the BBC's idea for a programme about three old men was a dull concept for a half-hour sitcom. Instead, Clarke proposed that the men should all be unmarried, widowed, or divorced and either unemployed or retired, leaving them free to roam around like adolescents in the prime of their lives, unfettered and uninhibited. Clarke chose the original title, \"The Last of the Summer Wine\", to convey the idea that the characters are not in the autumn of their lives but the summer, even though it may be \"the last of the summer\". BBC producers", "score": 10.063331, "title_score": 0, "passage_id": "808397"}, {"title": "White wine", "text": "Rhine to provide the Legions with a healthy drink as opposed to water which was rarely drinkable. The wine was drunk cool in summer and warm in winter a practice which still continues in the 21st century. Wine merchants failed to survive the fall of the Western Roman Empire and viticulture declined dramatically. The Germanic tribes preferred to drink beer and did not see the value of the wine trade. The decline of viticulture was intensified when Vikings cut the sea lanes in the Atlantic. In the south the Saracens were making \"Ghazw\" or raids. These campaigns in southern Europe", "score": 9.989409, "title_score": 0, "passage_id": "3646730"}, {"title": "Jonathan Linsley", "text": "lasted for only one series. Shortly after this, Linsley resumed- this time on television- the role of large and strong, but dim-witted, \"Crusher\" Milburn in \"Last of the Summer Wine\". He appeared in this role until 1987 when he elected to go on a diet. In 1989 Linsley starred as Chunky Livesey in the second and final series of the spin off prequal \"First of the Summer Wine\", to replace Anthony Keetch who starred as the character in the first series in 1988. Linsley also appeared as a leading character in the TV shows \"Emmerdale\" (Albert Mistlethwaite), \"Casualty\" (DC Newby),", "score": 9.951398, "title_score": 0, "passage_id": "11317859"}, {"title": "Last of the Summer Wine (series 31)", "text": "Last of the Summer Wine (series 31) Last of the Summer Wine's 31st and final series was aired in 2010, beginning on 25 July. All six episodes in series 31 were 30 minutes in length. All of the episodes were written by Roy Clarke and directed by Alan J. W. Bell. The series was the first in 19 years to be only six episodes long, due in part to the BBC axing the show and then recommissioning it. Actress Juliette Kaplan (Pearl) wrote on her website that the series was a result of fan response to rumours of the show's", "score": 9.875295, "title_score": 0, "passage_id": "13769143"}, {"title": "Last of the Summer Wine (series 30)", "text": "of insurance for the actors at their age on location. The trio in this series consisted of: New Year Special (2008) Regular series This comedy show is criticised for its speculated loss of quality and the fact that it is generally aimed at the older generation. Despite this, the show still gains respectable viewing figures. The box set for series thirty was released by Universal Playback in August 2016, mislabelled as a box set for series 31 & 32. Last of the Summer Wine (series 30) Last of the Summer Wine's 30th series originally aired 19 April 2009. All eleven", "score": 9.875257, "title_score": 0, "passage_id": "12318441"}, {"title": "Last of the Summer Wine (series 13)", "text": "on videotape (with credit and title captions being added during this stage) until the 1995 series. The trio in this series consisted of: 'Regular series Christmas Special (1991) The box set for series thirteen was released by Universal Playback in December 2008, mislabelled as a box set for series 13 & 14. Last of the Summer Wine (series 13) The Last of the Summer Wines thirteenth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. Notably, this series of the show was shot entirely on videotape. Prior", "score": 9.875257, "title_score": 0, "passage_id": "12174125"}, {"title": "Last of the Summer Wine (series 3)", "text": "Last of the Summer Wine (series 3) Last of the Summer Wine's third series originally aired on BBC1 between 27 October 1976 and 24 December 1976. All episodes from this series were written by Roy Clarke and produced by Sydney Lotterby Five episodes were directed by Sydney Lotterby but two, the two parter, \"The Great Boarding House Bathroom Caper\" and \"Cheering Up Gordon\", were directed by Ray Butt. Although none of the episodes from series 3 made it into the top ten programmes of the week on their initial screening, a repeat showing of the final episode, \"Isometrics and After,\"", "score": 9.875257, "title_score": 0, "passage_id": "11998989"}, {"title": "Last of the Summer Wine (series 25)", "text": "26. Last of the Summer Wine (series 25) Last of the Summer Wine's twenty-fifth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. The trio in this series consisted of: Louis Emerick takes over from Tony Capstick as the 2nd Policeman following the latter's death a year before. The former previously played the role twice in the late 1980s. Christmas Special (2003) Regular series The box set for series twenty five was released by Universal Playback in September 2014, mislabelled as a box set for series 25", "score": 9.874007, "title_score": 0, "passage_id": "12220486"}, {"title": "Last of the Summer Wine (series 25)", "text": "Last of the Summer Wine (series 25) Last of the Summer Wine's twenty-fifth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. The trio in this series consisted of: Louis Emerick takes over from Tony Capstick as the 2nd Policeman following the latter's death a year before. The former previously played the role twice in the late 1980s. Christmas Special (2003) Regular series The box set for series twenty five was released by Universal Playback in September 2014, mislabelled as a box set for series 25 &", "score": 9.874007, "title_score": 0, "passage_id": "12220485"}, {"title": "Last of the Summer Wine (series 14)", "text": "Last of the Summer Wine (series 14) The Last of the Summer Wines fourteenth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. This was the first series to be shot entirely on film, although the complete episode was still assembled on videotape. This and the following series were broadcast in a 16:10 aspect ratio, compared to the standard 4:3 aspect ratio that it was broadcast in for its previous 13 series. The trio in this series consisted of: Regular series Christmas Special (1992) The box set", "score": 9.874007, "title_score": 0, "passage_id": "12161447"}, {"title": "Last of the Summer Wine (series 5)", "text": "Last of the Summer Wine (series 5) Last of the Summer Wine's fifth series originally aired on BBC1 between 18 September and 30 October 1979. All episodes from this series were written by Roy Clarke and produced and directed by Sydney Lotterby. The fifth series was something of a departure; it was the first to include two-part episodes and introduced a small number of new characters such as Compo's oft-mentioned but never seen nephew and was also notable for an increase in the more physical comedy for which the programme would become more well-known latterly. The fifth series was released", "score": 9.87389, "title_score": 0, "passage_id": "11999368"}, {"title": "Last of the Summer Wine (series 5)", "text": "on DVD in region 2 as a combined box set with series 6 on 5 March 2007. The trio in this series consisted of: Regular series Christmas Special (1979) The box set for series 5 and 6 was released by Universal Playback in March 2007. Last of the Summer Wine (series 5) Last of the Summer Wine's fifth series originally aired on BBC1 between 18 September and 30 October 1979. All episodes from this series were written by Roy Clarke and produced and directed by Sydney Lotterby. The fifth series was something of a departure; it was the first to", "score": 9.873832, "title_score": 0, "passage_id": "11999369"}, {"title": "Last of the Summer Wine (series 30)", "text": "Last of the Summer Wine (series 30) Last of the Summer Wine's 30th series originally aired 19 April 2009. All eleven episodes in series 30 were 30 minutes in length. A New Years Special aired on 31 December 2008. All of the episodes were written by Roy Clarke and directed by Alan J. W. Bell. This series is notable for forming a new trio composed of Alvin, Entwistle and Hobbo, who was introduced in the New Years Special. Peter Sallis (Clegg) and Frank Thornton (Truly) are now demoted to secondary characters, filmed only in studio scenes due to the cost", "score": 9.873756, "title_score": 0, "passage_id": "12318440"}, {"title": "Last of the Summer Wine (series 14)", "text": "for series fourteen was released by Universal Playback in October 2009, mislabelled as a box set for series 15 & 16. Last of the Summer Wine (series 14) The Last of the Summer Wines fourteenth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. This was the first series to be shot entirely on film, although the complete episode was still assembled on videotape. This and the following series were broadcast in a 16:10 aspect ratio, compared to the standard 4:3 aspect ratio that it was broadcast", "score": 9.872078, "title_score": 0, "passage_id": "12161448"}, {"title": "Last of the Summer Wine (series 31)", "text": "episode was also the final acting turn for Clegg's actor Peter Sallis before his death in 2017. The box set for series 31 was released by Universal Playback in August 2016, mislabelled as a box set for series 31 & 32. Last of the Summer Wine (series 31) Last of the Summer Wine's 31st and final series was aired in 2010, beginning on 25 July. All six episodes in series 31 were 30 minutes in length. All of the episodes were written by Roy Clarke and directed by Alan J. W. Bell. The series was the first in 19 years", "score": 9.872032, "title_score": 0, "passage_id": "13769147"}, {"title": "Last of the Summer Wine (series 3)", "text": "appeared in) Mr Wainwright (1973, 1976) The box set for series 3 and 4 was released by Universal Playback in July 2004. Last of the Summer Wine (series 3) Last of the Summer Wine's third series originally aired on BBC1 between 27 October 1976 and 24 December 1976. All episodes from this series were written by Roy Clarke and produced by Sydney Lotterby Five episodes were directed by Sydney Lotterby but two, the two parter, \"The Great Boarding House Bathroom Caper\" and \"Cheering Up Gordon\", were directed by Ray Butt. Although none of the episodes from series 3 made", "score": 9.871973, "title_score": 0, "passage_id": "11998992"}, {"title": "Last of the Summer Wine (series 4)", "text": "Last of the Summer Wine (series 4) Last of the Summer Wine's fourth series originally aired on BBC1 between 9 November 1977 and 4 January 1978. All episodes from this series were written by Roy Clarke and produced and directed by Sydney Lotterby. The fourth series was released on DVD in region 2 as a combined box set with series 3 on 26 July 2004. A box set featuring just series 4 was released for region 1 on 9 September 2008. The trio in this series consisted of: Regular series Christmas Special (1978) The box set for series 3 and", "score": 9.871898, "title_score": 0, "passage_id": "11999297"}, {"title": "Last of the Summer Wine (series 7)", "text": "Last of the Summer Wine (series 7) Last of the Summer Wine's seventh series originally aired on BBC1 between 25 December 1982 and 27 December 1983. All episodes from this series were written by Roy Clarke and produced and directed by Sydney Lotterby, except for \"Getting Sam Home\", which is produced and directed by Alan J.W. Bell. The seventh series was released on DVD in region 2 as a combined box set with series 8 on 3 March 2008. The trio in this series consisted of: PC Cooper (aka 1st Policeman) (1983-2010) Sid (1973-1983) Christmas Special (1982) Regular series Christmas", "score": 9.871797, "title_score": 0, "passage_id": "12006043"}, {"title": "Last of the Summer Wine (series 7)", "text": "Special (1983) The box set for series 7 and 8 was released by Universal Playback in March 2008. Last of the Summer Wine (series 7) Last of the Summer Wine's seventh series originally aired on BBC1 between 25 December 1982 and 27 December 1983. All episodes from this series were written by Roy Clarke and produced and directed by Sydney Lotterby, except for \"Getting Sam Home\", which is produced and directed by Alan J.W. Bell. The seventh series was released on DVD in region 2 as a combined box set with series 8 on 3 March 2008. The trio in", "score": 9.869086, "title_score": 0, "passage_id": "12006044"}, {"title": "I Know What You Did Last Summer (novel)", "text": "I Know What You Did Last Summer (novel) I Know What You Did Last Summer (1973) is a suspense novel for young adults by Lois Duncan. It was later adapted into the film of the same name. In an unnamed town, high-school senior Julie James receives a sinister note from an elusive stalker telling her, \"I know what you did last summer.\" The note refers to events of the previous year, when Julie, her boyfriend Ray Bronson, Ray's best friend Barry Cox, and Barry's girlfriend and Julie's best friend Helen Rivers accidentally ran over and killed a young boy named", "score": 9.856958, "title_score": 0, "passage_id": "11211127"}, {"title": "Last of the Summer Wine (series 12)", "text": "\"Big Day at Dream Acre.\" Returning SMILER Foggy (1976\u20131985, 1990-1997) Seymour (1985\u20131990)
Barry (1985-1990, 1996\u20132010) Regular series Christmas Special (1990) The box set for series twelve was released by Universal Playback in December 2008, mislabelled as a box set for series 13 & 14. Last of the Summer Wine (series 12) The Last of the Summer Wines twelfth series aired on BBC1. All of the episodes were written by Roy Clarke and produced and directed by Alan J. W. Bell. With the departure of Michael Aldridge who had left to nurse his ill wife, the character of Foggy Dewhirst returned", "score": 9.795891, "title_score": 0, "passage_id": "12163973"}, {"title": "Last of the Summer Wine (series 8)", "text": "released by Universal Playback in March 2008. Last of the Summer Wine (series 8) Last of the Summer Wine's eighth series originally aired on BBC1 between 30 December 1984 and 17 March 1985. All episodes from this series were written by Roy Clarke and produced and directed by Alan J. W. Bell. The eighth series was released on DVD in region 2 as a combined box set with series 7 on 3 March 2008. The trio in this series consisted of: Crusher \"Milburn\" (1984-1987) Howard (1985-2010) Pearl (1985-2010) Marina (1985-2010) Foggy (1976-1985, 1990-1997) Christmas Special (1984) Regular series The box", "score": 9.792509, "title_score": 0, "passage_id": "12006066"}, {"title": "Last of the Summer Wine (series 8)", "text": "Last of the Summer Wine (series 8) Last of the Summer Wine's eighth series originally aired on BBC1 between 30 December 1984 and 17 March 1985. All episodes from this series were written by Roy Clarke and produced and directed by Alan J. W. Bell. The eighth series was released on DVD in region 2 as a combined box set with series 7 on 3 March 2008. The trio in this series consisted of: Crusher \"Milburn\" (1984-1987) Howard (1985-2010) Pearl (1985-2010) Marina (1985-2010) Foggy (1976-1985, 1990-1997) Christmas Special (1984) Regular series The box set for series 7 and 8 was", "score": 9.792509, "title_score": 0, "passage_id": "12006065"}, {"title": "Last of the Summer Wine (series 9)", "text": "Last of the Summer Wine (series 9) Last of the Summer Wine's ninth series originally aired on BBC1 between 1 January 1986 and 27 December 1987. All episodes from this series were written by Roy Clarke and produced and directed by Alan J. W. Bell. The ninth series was released on DVD in region 2 as a box set on 5 May 2008. The trio in this series consisted of: Seymour (1986\u20131990) Edie (1986\u20132003) Barry (1986-1990, 1996\u20132010) Glenda (1986\u20132010) Eli (1987\u20132002) PC Walsh (1986\u20132010) (aka Second Policeman) Wally Batty (1975, 1976\u20131987) \"Crusher\" Milburn (1984\u20131987) New Year Special (1986) Christmas Special", "score": 9.792405, "title_score": 0, "passage_id": "12006127"}, {"title": "Water into Wine", "text": "However, Kevin Shirley, when mixing, said, \"It's a straightforward song to mix and it would make a good b-side. It's not a single. It drags.\" Water into Wine \"Water into Wine\" is a song by Australian rock band Cold Chisel. It was released in December 1998 as the second single from their sixth studio album, \"The Last Wave of Summer\". The song peaked at number 46 in Australia. Biographer Michael Lawrence said, \"From very early on its lifetime, this song was touted as a possible single. A catchy ballad that sees acoustic guitar appearing in a Cold Chisel song for", "score": 9.644236, "title_score": 0, "passage_id": "19890485"}, {"title": "Wesley College (Victoria)", "text": "Book is presented when students leave the College. Wesley College participates in the Debaters Association of Victoria (DAV) Schools' Competition and other debating & public speaking tournaments organised by Rotary, the RSL and the United Nations Youth Association of Australia. In 2006, Wesley won the DAV's Schools British Parliamentary debating competition, competing against Scotch College, Sydney Grammar School, and Melbourne Grammar School. The Public Questions Society (PQS) was established at Wesley College in May 1924 and was instituted to provide a forum in which contemporary and controversial issues could be discussed. In the 1970s, College Headmaster, Mr David Prest convinced", "score": 9.642797, "title_score": 0, "passage_id": "5548195"}, {"title": "Earl Wesley Berry", "text": "sedative. He elected not to take his last shower and did not make any phone calls. However, his mother, brother, sister-in-law and two friends visited him on the day of his execution. His Last Words were \"No Comment\". Berry was pronounced dead at 6:15pm on May 21, 2008. Earl Wesley Berry Earl Wesley Berry (May 5, 1959 \u2013 May 21, 2008) was a convicted kidnapper and murderer from the United States. He was on Mississippi's death row with 64 others but was issued a stay of execution in October 2007 by the U.S. Supreme Court. He was ultimately executed on", "score": 9.635864, "title_score": 0, "passage_id": "11107012"}, {"title": "Summer Wesley", "text": "Summer Wesley Summer Wesley (born 1981 in Choctaw), who also goes by Chahta Summer, is an attorney, writer, and activist from Oklahoma. She is a member of the Choctaw Nation. Summer Wesley was born and raised in rural Southeastern Oklahoma and is a citizen of the Choctaw Nation. She attended school in the small town of Rattan, graduating high school a year early, in 1998. Wesley earned four degrees from the University of Oklahoma: A Bachelor of Liberal Studies (2005), a master's in Administrative Leadership (2008), during which time she also completed the course requirements for a master's in Interprofessional", "score": 9.614918, "title_score": 0, "passage_id": "18041449"}, {"title": "Last of the Summer Wine", "text": "and the actors love being involved\" and that it would be a terrible blow to the shops and businesses in Holmfirth who have come to depend on tourist revenue. The BBC denied these claims, saying that a decision had not yet been reached whether to commission another series or not. It was confirmed on 26 June 2009 that a 31st series of 6 episodes had been commissioned for transmission in 2010. In June 2010 the BBC announced that it would not renew \"Last of the Summer Wine\" after its thirty-first series was broadcast during the summer of 2010. Tom Owen", "score": 9.603775, "title_score": 0, "passage_id": "808410"}, {"title": "The Ring (Angel)", "text": "event. Wesley warns that a raid is going to happen there tonight, so the couple decides to leave, leaving Cordelia and Wesley their tickets. Inside, Baker beats on Angel, who still won't fight back. Cordelia and Wesley enter, spotting Darin, who's holding a bracelet. Wesley notes that these demon matches have been revived from the Roman Empire and that the bracelets kill people if they\u2019re wearing them when they cross the red line. Darin puts the bracelet down and gestures for a guard to drop a knife into the pit. Baker picks the knife up, cutting Angel's arm with it.", "score": 9.601264, "title_score": 0, "passage_id": "5692363"}, {"title": "Cotah Ramaswami", "text": "being different from that of his brothers. He studied in Wesley High School, Wesley College and the Presidency. On one occasion while at Wesley, he put on more than 200 runs for the last wicket to win a match after his team was 50 for nine, himself scoring 188*. He joined Cambridge University in 1919 where he studied until 1923. In the summer of 1920, he won singles the Doherty Cup tennis tournament open to all students in the university. He won a 'half blue' that year, representing Cambridge in the doubles, and earned a blue in 1921. On a", "score": 9.578292, "title_score": 0, "passage_id": "5872812"}, {"title": "Last of the Summer Wine (series 31)", "text": "having a loyal fan base. To commemorate the show's final appearance, the BBC broadcast \"Songs of Praise\" from Holmfirth, and a special of \"Countryfile\" about Holmfirth and the surrounding area (where the series was primarily filmed). The \"Countryfile\" special aired on 25 July straight after the first episode of the final series. \"Songs of Praise\" from Holmfirth aired on 29 August, the day the last ever episode was broadcast. That final episode, \"How Not to Cry at Weddings\" was dubbed \"The Very Last of the Summer Wine\" in the \"Radio Times\" edition dated 28 August - 3 September 2010. That", "score": 9.555549, "title_score": 0, "passage_id": "13769145"}, {"title": "James Gilbert (producer)", "text": "the last series, Gilbert won a BAFTA in 1974 for Best Comedy, and was also nominated that year for \"Last of the Summer Wine\" in the category. He succeeded Michael Mills as the BBC's Head of Comedy from 1973\u20131977. Gilbert was appointed as the BBC's Head of Light Entertainment in 1977, in succession to Bill Cotton, remaining in the post and with the BBC until 1982. Subsequently, he worked as a freelance. In 2003, Gilbert appeared on the documentary special \"30 Years of Last of the Summer Wine\" to discuss his role in helping to create the series. James Gilbert", "score": 9.554148, "title_score": 0, "passage_id": "11460870"}, {"title": "First of the Summer Wine", "text": "station Gold. The show was broadcast in Australia on the Australian Broadcasting Corporation network in the early 1990s. \"First of the Summer Wine\" was a prequel to Clarke's long running show, \"Last of the Summer Wine\", portraying the youth of the principal characters from the mother show in the months leading up to World War II. With the possibility of war hanging over them, the young men and women enjoy their youth while trying to find a place for themselves in the world. The show used young, mostly unknown actors to play the characters, with only two actors from the", "score": 9.532048, "title_score": 0, "passage_id": "5525491"}, {"title": "First of the Summer Wine", "text": "For the new series, Clarke used mostly young, inexperienced actors to fill the roles of the characters carried over from the original series. The actors were required to mimic the vocal characteristics and mannerisms already established in \"Last of the Summer Wine\" to create a continuity between the two series. The show features much 1920s and 1930s music, which adds to the nostalgic feel of the show. The theme tune is \"Sweet and Lovely\", sung by Al Bowlly, accompanied by Roy Fox and his Band. The recording was made in London on 18 September 1931. \"First of the Summer Wine\"", "score": 9.532033, "title_score": 0, "passage_id": "5525493"}, {"title": "Last of the Summer Wine", "text": "being replaced by Foggy. In the late 1980s, Roy Clarke wrote novels featuring Compo, Clegg and Seymour. The books were published by Penguin Books under the series heading \"Summer Wine Chronicles\", and included such titles as \"Gala Week\" and \"The Moonbather\". Clarke later adapted \"The Moonbather\" into a stage play. In the early 1980s, a daily comic strip based on the show was drawn by Roger Mahoney and appeared in the \"Daily Star\". A compilation of these strips, published by Express Books, was released in 1983. In 1993, the Summer Wine Appreciation Society asked their members for their favourite musical", "score": 9.522492, "title_score": 0, "passage_id": "808441"}, {"title": "Thomas Maxfield (Methodist)", "text": "pamphlet charging the Wesleys with turning the hearts of the people from George Whitefield during his absence in America, and John Wesley replied with \"A Letter to the Rev. Thomas Maxfield, occasioned by a late Publication\". In 1779 there was more talk of reunion, but Charles Wesley insisted that an acknowledgment of fault on Maxfield's side was needed. Wesley expressed personal affection for him, but nothing came of the negotiations. Wesley did visit Maxfield in his last illness, and preached in his chapel. Maxfield died at his house in Moorfields on 18 March 1784. Maxfield published: Also \"A Collection of", "score": 9.51972, "title_score": 0, "passage_id": "18280254"}, {"title": "Ordination of women in Methodism", "text": "to preach. In the summer of 1771, Bosanquet wrote to John Wesley to defend hers and Crosby's work preaching at her orphanage, Cross Hall. Bosanquet's letter to Wesley is considered to be the first full and true defense of women's preaching in Methodism. Her argument was that women should be able to preach when they experienced an 'extraordinary call,' or when given permission by God. Wesley accepted this idea, and formally began to allow women to preach in Methodism. Later, Wesley also licensed other women as preachers, including Grace Murray, Sarah Taft, Hannah Ball and Elizabeth Ritchie. Wesley's appreciation for", "score": 9.501866, "title_score": 0, "passage_id": "13999680"}, {"title": "Eric Sykes", "text": "adaptation of Mervyn Peake's \"Gormenghast\", which was the last production to feature both Milligan and Sykes (although they did not appear together on screen). In 2001, he had one of his few serious screen roles, playing a servant in the blockbuster supernatural thriller film \"The Others\", starring Nicole Kidman. In 2005, he played Frank Bryce in \"Harry Potter and The Goblet of Fire\". In 2007, he appeared in \"Last of the Summer Wine\" and in \"New Tricks\", as well as taking a small role in an episode of the sitcom \"My Family\". In October 2010 Sykes appeared in \"Hallowe'en Party\",", "score": 9.497764, "title_score": 0, "passage_id": "841918"}, {"title": "Sarah Crosby", "text": "was not the only instance in which her work was opposed. During the summer of 1770, John Wesley went to preach at a church, and was told that he would not be allowed to because the parishioners had heard about a Methodist woman preaching nearby. Sarah Crosby had recently been to a nearby church in Huddersfield, but had only led a class there and did not preach. Wesley did not seem to be angered by the ordeal, and told Crosby that their preaching would be welcomed elsewhere. On 24 October 1804, at the age of 75, Sarah Crosby died in", "score": 9.489175, "title_score": 0, "passage_id": "19148312"}, {"title": "Summer Wesley", "text": "support of three young rape victims from Norman, Oklahoma. They left school after being bullied following reporting the attacks on them. Wesley was quite vocal in her support of the Oklahoma City Public School's decisions to end land run reenactments, as well as the board's vote to eliminate the \"redskins\" mascot used by Capital Hill High School. Wesley live-tweeted meetings on the topic and her account of a community educational forum on the topic was published. Summer Wesley Summer Wesley (born 1981 in Choctaw), who also goes by Chahta Summer, is an attorney, writer, and activist from Oklahoma. She is", "score": 9.487911, "title_score": 0, "passage_id": "18041456"}, {"title": "Kiel Brown", "text": "and his team mates also set up a slushy machine in their area of the athlete village. He was given a welcome pack when he got there that included \"body wash, hand sanitiser and a USB drive.\" It did not contain condoms, an item which had been distributed to 2004 Summer Olympics competitors. Brown is a midfielder. Brown plays club hockey for Wesley South Perth and was with the team in 2007. He played in the 22nd round of the Men's Wizard Home Loans Cup against YMCA Coastal City where his team lost 6-2. He did not compete in the", "score": 9.4452, "title_score": 0, "passage_id": "16350066"}]}] diff --git a/test/samples/embeddings/embedding_1.txt b/test/samples/embeddings/embedding_1.txt deleted file mode 100644 index 4142375db7..0000000000 --- a/test/samples/embeddings/embedding_1.txt +++ /dev/null @@ -1,769 +0,0 @@ -# Embedding originating from "The capital of Germany is the city state of Berlin." -2.229200750589370728e-01 -1.077704504132270813e-02 -3.353824615478515625e-01 --7.272654771804809570e-02 --1.981195658445358276e-01 --5.645373463630676270e-02 -6.092614531517028809e-01 -2.872290611267089844e-01 --7.739712297916412354e-02 --2.238762378692626953e-01 --5.474619269371032715e-01 --1.086768746376037598e+00 -2.957215309143066406e-01 -7.539058923721313477e-01 --3.361538350582122803e-01 -1.946664899587631226e-01 -2.922970242798328400e-02 -6.560229063034057617e-01 -2.676166892051696777e-01 --3.813763558864593506e-01 --2.985824644565582275e-01 --1.892075389623641968e-01 -6.072467565536499023e-01 -1.677098423242568970e-01 -2.755770385265350342e-01 --9.339866638183593750e-01 -4.316486120223999023e-01 --1.009297221899032593e-01 --4.821339547634124756e-01 -7.309586554765701294e-02 --4.850001335144042969e-01 --1.171929016709327698e-01 --2.781780958175659180e-01 -6.611959636211395264e-02 -4.154573082923889160e-01 -3.251289948821067810e-02 -2.665463089942932129e-01 -1.300133466720581055e-01 -3.523490130901336670e-01 --6.647316813468933105e-01 --6.833727359771728516e-01 --3.161530196666717529e-01 -3.672671914100646973e-01 --4.051270782947540283e-01 --8.204193413257598877e-02 --1.002076387405395508e+00 --2.105239331722259521e-01 -9.382371306419372559e-01 --2.960956990718841553e-01 --1.827087998390197754e-01 --9.053340554237365723e-01 -2.687701582908630371e-01 -3.291319012641906738e-01 -9.000702500343322754e-01 -4.341595470905303955e-01 --5.657433271408081055e-01 --7.947875857353210449e-01 --9.830372035503387451e-02 --1.015505045652389526e-01 -1.177189648151397705e-01 -2.487688213586807251e-01 -2.645682096481323242e-01 --1.217085719108581543e-01 -3.547798097133636475e-01 -7.251137495040893555e-01 -4.652934670448303223e-01 --4.091851413249969482e-02 --8.674740791320800781e-03 --2.215012535452842712e-02 --6.340540647506713867e-01 --9.916223883628845215e-01 --2.934761047363281250e-01 --3.775480091571807861e-01 --3.206850886344909668e-01 -7.979419082403182983e-02 --4.511791765689849854e-01 -1.617217957973480225e-01 -2.019417881965637207e-01 -2.185516655445098877e-01 -8.893802762031555176e-02 -9.314009547233581543e-02 --1.688676625490188599e-01 -1.937414705753326416e-01 -9.801741689443588257e-03 -3.965679705142974854e-01 -3.251888751983642578e-01 --3.598170727491378784e-02 --3.050830662250518799e-01 --2.913770377635955811e-01 --2.598717808723449707e-01 --2.331165969371795654e-02 -8.392083048820495605e-01 -1.925602704286575317e-01 -1.109006628394126892e-01 --6.460183858871459961e-02 --7.442702651023864746e-01 -1.639689952135086060e-01 -1.135909706354141235e-01 -2.352073639631271362e-01 -1.822426170110702515e-01 --1.766875982284545898e-01 -1.265169084072113037e-01 -3.984827399253845215e-01 -2.408041357994079590e-01 -4.778962582349777222e-02 --6.284007430076599121e-01 --4.661247730255126953e-01 -3.312299400568008423e-02 --2.507611364126205444e-02 -4.357390403747558594e-01 --2.454110383987426758e-01 --2.200425714254379272e-01 -8.924855291843414307e-02 --4.655413702130317688e-02 --1.380364745855331421e-01 -5.564597845077514648e-01 -5.611656308174133301e-01 --9.593920707702636719e-01 --2.868362329900264740e-02 -2.679112553596496582e-01 -4.453867301344871521e-02 -8.509775400161743164e-01 --6.113862991333007812e-02 --1.983727514743804932e-01 -4.687910899519920349e-02 --5.062779784202575684e-01 -1.343037933111190796e-01 -7.621676921844482422e-01 --2.646075189113616943e-01 -4.188762605190277100e-02 -2.891806364059448242e-01 -5.621543526649475098e-01 -2.112514227628707886e-01 -3.102817833423614502e-01 -7.219618558883666992e-02 --5.729638934135437012e-01 -3.834050893783569336e-01 -1.929313540458679199e-01 --4.105568677186965942e-02 -6.540393829345703125e-02 --7.691016793251037598e-01 --3.997266292572021484e-01 -4.274137318134307861e-04 --8.615588396787643433e-02 -6.743724644184112549e-02 --6.332622766494750977e-01 -1.295094043016433716e-01 --7.983018755912780762e-01 --1.864523589611053467e-01 --3.744871169328689575e-02 -6.274693459272384644e-02 -5.532386898994445801e-01 --1.182875186204910278e-01 -2.222552150487899780e-01 --3.888924419879913330e-01 --5.071425437927246094e-02 -1.176562309265136719e+00 -1.063209399580955505e-01 -4.879177212715148926e-01 -1.309451013803482056e-01 -5.198720693588256836e-01 --5.094241499900817871e-01 -7.241661548614501953e-01 -2.546791732311248779e-02 -4.714670181274414062e-01 -2.114182412624359131e-01 -7.247392535209655762e-01 -8.811700940132141113e-01 -5.082897841930389404e-03 --2.566633746027946472e-02 --7.888150215148925781e-01 --3.999445736408233643e-01 -4.353733360767364502e-01 --1.850487440824508667e-01 --3.407649695873260498e-03 --3.349660336971282959e-02 --5.417585968971252441e-01 -1.263211816549301147e-01 -2.608076930046081543e-01 -6.733991205692291260e-03 --2.971451878547668457e-01 -8.470416069030761719e-01 --9.335912019014358521e-02 -5.284559726715087891e-01 --3.992432057857513428e-01 -1.126932501792907715e-01 --1.439833045005798340e-01 -1.674625724554061890e-01 --5.153211951255798340e-02 -4.324131011962890625e-01 -4.548313915729522705e-01 --4.173695445060729980e-01 -2.249873280525207520e-01 --7.205624878406524658e-02 -1.141345351934432983e-01 -4.923084676265716553e-01 --8.986659049987792969e-01 -5.711457133293151855e-01 --4.192935228347778320e-01 -3.952406942844390869e-01 -1.149247437715530396e-01 --6.056919693946838379e-01 -5.722514390945434570e-01 --2.093413621187210083e-01 --2.339971512556076050e-01 -1.252374202013015747e-01 -1.886790543794631958e-01 --1.653491705656051636e-01 -1.092862710356712341e-01 -3.671270981431007385e-02 --8.382377028465270996e-02 --7.060584425926208496e-01 -2.022314667701721191e-01 --2.552375495433807373e-01 -1.095139533281326294e-01 --1.316596865653991699e-01 --6.152526736259460449e-01 --3.038299381732940674e-01 -1.378949582576751709e-01 --4.247864484786987305e-01 -4.531964957714080811e-01 --1.980511471629142761e-02 --4.475849866867065430e-01 -2.152265757322311401e-01 -1.430305391550064087e-01 -1.777189821004867554e-01 --7.886476814746856689e-02 -5.669621229171752930e-01 --4.944795966148376465e-01 --2.127390503883361816e-01 --6.916448473930358887e-03 -3.484785556793212891e-02 --1.287058889865875244e-01 --3.834495693445205688e-02 -5.889341980218887329e-02 --6.581305861473083496e-01 --5.362144708633422852e-01 -2.551229894161224365e-01 -8.755547404289245605e-01 --4.754149615764617920e-01 -9.529559016227722168e-01 -1.357856839895248413e-01 -1.231204420328140259e-01 -5.057177543640136719e-01 -1.488031595945358276e-01 -4.042004346847534180e-01 -2.763728201389312744e-01 --2.472992390394210815e-01 --8.071435689926147461e-01 -4.836043417453765869e-01 --1.853746175765991211e-01 --1.950245797634124756e-01 --1.259218156337738037e-01 -7.700300961732864380e-02 -1.421366035938262939e-01 --3.080878853797912598e-01 -1.590892970561981201e-01 -3.259545862674713135e-01 -1.598847657442092896e-01 -6.177800297737121582e-01 -2.018097415566444397e-02 --3.506714403629302979e-01 --6.725504994392395020e-01 -4.138171672821044922e-03 --2.711460590362548828e-01 -7.782593369483947754e-02 --2.490911781787872314e-01 --3.052634298801422119e-01 -2.253655940294265747e-01 -3.727595508098602295e-01 -3.855817317962646484e-01 --1.093969941139221191e-01 --3.473147153854370117e-01 --1.129195243120193481e-01 -1.299156546592712402e-01 -8.060790598392486572e-03 -3.920609503984451294e-02 -1.973358541727066040e-02 --6.532639265060424805e-01 --1.248000748455524445e-02 --1.324806511402130127e-01 -7.226893901824951172e-01 --2.425798624753952026e-01 --1.254415035247802734e+00 --1.321722567081451416e-02 --1.109186649322509766e+00 -8.784583210945129395e-01 --3.460637331008911133e-01 --3.959231972694396973e-01 -7.506304979324340820e-01 --6.054728105664253235e-02 -3.241688013076782227e-03 --1.875303089618682861e-01 -1.402277648448944092e-01 --2.828385829925537109e-01 -1.333177983760833740e-01 -1.896256953477859497e-01 --8.865744620561599731e-02 -2.123409509658813477e-01 --2.994567155838012695e-01 --1.227536678314208984e+00 -3.141155540943145752e-01 --6.146685779094696045e-02 -5.755669623613357544e-02 -4.745312333106994629e-01 --4.229356348514556885e-01 --4.827856272459030151e-02 -1.427830904722213745e-01 --5.565702915191650391e+00 --3.732101023197174072e-01 --3.543207049369812012e-01 --4.245140552520751953e-01 --2.425279170274734497e-01 -6.067085862159729004e-01 -1.827954798936843872e-01 -4.263537377119064331e-02 --3.055633306503295898e-01 --5.304043889045715332e-01 -8.724419474601745605e-01 -1.090793609619140625e-01 -2.244358696043491364e-02 -6.749649643898010254e-01 -2.530656754970550537e-01 -3.885923027992248535e-01 -1.197095066308975220e-01 --3.200657367706298828e-01 --3.318552970886230469e-01 --2.448843270540237427e-01 --3.521001935005187988e-01 --2.818458080291748047e-01 -8.555752038955688477e-01 -1.621814072132110596e-01 -7.852475643157958984e-01 --2.963813394308090210e-02 --2.884979546070098877e-01 -6.535680592060089111e-02 --7.087953686714172363e-01 --8.049001097679138184e-01 -4.424397647380828857e-02 --4.290588796138763428e-01 -3.264676928520202637e-01 --1.532442867755889893e-01 -3.990801572799682617e-01 -4.896099120378494263e-02 -4.127607643604278564e-01 -3.941829204559326172e-01 -1.940521597862243652e-01 --4.933945834636688232e-01 --2.292006462812423706e-02 -4.952664077281951904e-01 --6.726042181253433228e-02 -1.919217407703399658e-02 -5.966454744338989258e-01 --2.275462448596954346e-01 --1.711596995592117310e-01 --5.571029335260391235e-02 --8.217661380767822266e-01 -5.469788908958435059e-01 -7.129400968551635742e-02 -2.397237271070480347e-01 -3.991563916206359863e-01 --4.605466723442077637e-01 --3.689226508140563965e-01 -4.648056626319885254e-01 -9.516095370054244995e-02 -4.604864120483398438e-01 --4.567398726940155029e-01 -1.108226403594017029e-01 --2.065288424491882324e-01 -1.953805424273014069e-02 --1.973924785852432251e-01 --1.143592298030853271e-01 --2.018085122108459473e-02 --1.261275112628936768e-01 --7.953326106071472168e-01 -6.667110323905944824e-01 -2.220246791839599609e-01 -7.371812313795089722e-02 --2.254238128662109375e-01 --8.226252794265747070e-01 -2.405637204647064209e-01 --6.111376881599426270e-01 --6.114128232002258301e-01 --1.459523558616638184e+00 --1.376494765281677246e-04 --5.295290946960449219e-01 -1.476662456989288330e-01 -3.542955815792083740e-01 --6.838529109954833984e-01 -1.973737031221389771e-01 --1.562242507934570312e-01 --1.393158361315727234e-02 -1.523473262786865234e-01 --1.783633232116699219e-01 --2.451187670230865479e-01 -4.621908068656921387e-02 -6.598109602928161621e-01 --5.493320226669311523e-01 --3.592513501644134521e-01 --8.365867137908935547e-01 -4.378204643726348877e-01 --7.469946146011352539e-01 --6.132229566574096680e-01 -5.132728815078735352e-01 --8.537944406270980835e-02 --5.951195955276489258e-01 -6.631251424551010132e-02 --2.916390597820281982e-01 -3.565423488616943359e-01 --2.109354138374328613e-01 --6.861786246299743652e-01 --4.685586094856262207e-01 -2.968673110008239746e-01 -1.225276961922645569e-01 -3.368560373783111572e-01 -6.651212573051452637e-01 -8.235745429992675781e-01 --4.333616197109222412e-01 --4.600137472152709961e-01 -9.839697927236557007e-02 --2.061403356492519379e-02 --9.260077476501464844e-01 -4.215398728847503662e-01 --1.040923595428466797e+00 --8.313461542129516602e-01 -7.406153082847595215e-01 -2.035968899726867676e-01 --3.544585406780242920e-01 --1.007140874862670898e-01 -6.063780784606933594e-01 --1.257275938987731934e-01 --7.542469352483749390e-02 --4.758917689323425293e-01 --8.337471634149551392e-03 --7.372215390205383301e-01 -8.116918802261352539e-02 --4.761471226811408997e-02 -1.164480522274971008e-01 -6.714048981666564941e-02 -8.097329735755920410e-02 -4.065750241279602051e-01 --6.494665890932083130e-02 -6.714456081390380859e-01 -1.644751876592636108e-01 -2.042869478464126587e-01 --3.853097856044769287e-01 --1.565494388341903687e-01 --7.147974371910095215e-01 -2.022021561861038208e-01 -5.643728971481323242e-01 -3.260150849819183350e-01 -1.325489133596420288e-01 -7.734246551990509033e-02 --3.405841290950775146e-01 --1.978092640638351440e-02 -2.235562652349472046e-01 --4.013369679450988770e-01 --6.394700706005096436e-02 -8.092927932739257812e-01 -6.281705498695373535e-01 --6.668373942375183105e-03 --1.859176754951477051e-01 --8.266904354095458984e-01 -2.901017069816589355e-01 -3.717469871044158936e-01 -3.633828461170196533e-01 -3.301775455474853516e-01 --1.595072448253631592e-01 -4.058104455471038818e-01 --6.382607221603393555e-01 --4.459266066551208496e-01 -3.864688277244567871e-01 -5.879924893379211426e-01 --1.678373478353023529e-02 --8.564216494560241699e-01 --1.461684256792068481e-01 -1.478837579488754272e-01 --3.025810718536376953e-01 -3.040861785411834717e-01 --3.632892668247222900e-01 --1.379310637712478638e-01 -2.163119018077850342e-01 --2.879379093647003174e-01 -2.178674936294555664e-01 -1.859050393104553223e-01 -2.634488344192504883e-01 -3.996433615684509277e-01 -7.094170153141021729e-02 --7.549644261598587036e-02 --5.979362130165100098e-01 --4.811022281646728516e-01 -8.866333365440368652e-01 --2.077746242284774780e-01 -4.675184786319732666e-01 -2.695072069764137268e-02 -3.047565817832946777e-01 -1.976987421512603760e-01 -2.018974274396896362e-01 -7.081500887870788574e-01 --1.892064809799194336e-01 --2.486308068037033081e-01 -1.314123421907424927e-01 --3.776242733001708984e-01 --8.654680252075195312e-01 -2.816977202892303467e-01 -2.681364491581916809e-02 --3.595795333385467529e-01 --1.679078489542007446e-01 -3.395635187625885010e-01 -5.143527388572692871e-01 --5.054584741592407227e-01 -1.138908788561820984e-01 -5.565179139375686646e-02 --2.442906200885772705e-01 -5.045812726020812988e-01 -6.745055317878723145e-02 -1.219124719500541687e-01 -3.034650981426239014e-01 --1.175314664840698242e+00 --2.730637788772583008e-03 --2.873891592025756836e-01 -5.575245022773742676e-01 --4.761013686656951904e-01 --2.242747545242309570e-01 -6.084183454513549805e-01 --8.362288475036621094e-01 --2.736880630254745483e-02 -1.361133009195327759e-01 -4.854311794042587280e-02 -3.302182555198669434e-01 -2.458487451076507568e-02 --2.143803685903549194e-01 --1.554514169692993164e-01 -4.742682874202728271e-01 --5.269496887922286987e-02 --3.603656291961669922e-01 -1.465944647789001465e-01 --7.305315732955932617e-01 -4.516331553459167480e-01 --5.789173766970634460e-02 --1.149880960583686829e-01 --5.437690019607543945e-02 --5.840757861733436584e-02 --1.259196549654006958e-01 -3.546364903450012207e-01 -1.665020920336246490e-02 --2.820132076740264893e-01 -1.539016962051391602e-01 -7.343258857727050781e-01 -6.290215253829956055e-01 -1.655526608228683472e-01 --2.536472976207733154e-01 -2.582869827747344971e-01 --2.233524918556213379e-01 -1.370916515588760376e-01 --7.111111283302307129e-02 --7.293164730072021484e-01 -3.143068253993988037e-01 --1.948461383581161499e-01 --1.882906556129455566e-01 --5.518731474876403809e-01 --5.860670804977416992e-01 -7.767801284790039062e-01 --3.322035670280456543e-01 -1.260092258453369141e-01 -6.825061142444610596e-02 -2.424655407667160034e-01 --4.792602360248565674e-01 --2.644228935241699219e-01 --1.464149914681911469e-02 --1.630767285823822021e-01 -4.911354482173919678e-01 --7.559486478567123413e-02 --4.348745346069335938e-01 --4.707964062690734863e-01 -2.315330505371093750e-01 -6.865990906953811646e-02 --4.672498106956481934e-01 --3.498463034629821777e-01 --1.564570516347885132e-01 -2.269007563591003418e-01 --3.050552010536193848e-01 -5.147860199213027954e-02 -7.423413991928100586e-01 -3.087519705295562744e-01 -3.737786710262298584e-01 --3.727069199085235596e-01 -4.087692797183990479e-01 --4.393447041511535645e-01 -9.285502135753631592e-03 -2.118987441062927246e-01 --8.820632100105285645e-01 -2.798423767089843750e-01 --9.615238904953002930e-01 --1.065042093396186829e-01 -4.377257823944091797e-01 --6.856992840766906738e-01 --7.097013294696807861e-02 -2.030184566974639893e-01 --7.746644616127014160e-01 --3.589856922626495361e-01 -2.298175990581512451e-01 --1.637177169322967529e-02 -3.966447412967681885e-01 -3.037472963333129883e-01 -7.594509720802307129e-01 -3.053265511989593506e-01 -1.132410317659378052e-01 --3.048960566520690918e-01 -7.165358662605285645e-01 -5.994936227798461914e-01 --3.412231504917144775e-01 -8.017694205045700073e-02 -2.740603685379028320e-01 --1.893082112073898315e-01 --7.035820186138153076e-02 -6.314914822578430176e-01 --2.667667865753173828e-01 --3.600589931011199951e-02 --4.596940055489540100e-02 -4.133414477109909058e-02 -6.209387183189392090e-01 --4.056736826896667480e-01 -3.149551153182983398e-01 -8.510101437568664551e-01 --1.574504077434539795e-01 -1.327786147594451904e-01 -3.336026668548583984e-01 --1.682735979557037354e-01 --8.255195021629333496e-01 -3.416328132152557373e-01 -2.601369470357894897e-02 -1.496093571186065674e-01 -3.421335220336914062e-01 -3.766241073608398438e-01 --1.452240943908691406e-01 --6.066910549998283386e-02 -1.321901381015777588e-01 -1.176740229129791260e-01 -7.030912041664123535e-01 --5.538882315158843994e-02 -1.806678771972656250e-01 --9.274666905403137207e-01 --2.987461686134338379e-01 -1.826695352792739868e-01 -5.050233006477355957e-01 --4.158281981945037842e-01 -4.030080437660217285e-01 -2.746552824974060059e-01 -5.335844755172729492e-01 --2.667261958122253418e-01 -3.710058629512786865e-01 -6.669887900352478027e-01 --2.881216444075107574e-02 --3.362966775894165039e-01 --4.081276804208755493e-02 -2.424060553312301636e-01 --3.957792520523071289e-01 -6.246498823165893555e-01 --2.115248702466487885e-02 --9.019157290458679199e-02 -6.279945373535156250e-04 -2.013897597789764404e-01 --2.378374040126800537e-01 -2.334988713264465332e-01 -2.536354064941406250e-01 --1.482794284820556641e-01 --1.295099407434463501e-01 -1.570332050323486328e-01 --3.176831305027008057e-01 -9.301763027906417847e-03 -2.087312638759613037e-01 --2.709045708179473877e-01 -1.729099750518798828e-01 --2.842829748988151550e-02 --1.263489201664924622e-02 --5.575006604194641113e-01 --4.003717005252838135e-01 -4.377794861793518066e-01 -2.395138442516326904e-01 --9.833662211894989014e-02 --4.748430848121643066e-01 -7.464012503623962402e-02 -2.650299072265625000e-01 --2.557063102722167969e-01 --4.046093821525573730e-01 -6.110837459564208984e-01 -2.094314992427825928e-01 --4.909022152423858643e-01 --3.798094093799591064e-01 --4.077388048171997070e-01 --8.395939469337463379e-01 --4.450404942035675049e-01 -1.324279010295867920e-01 --2.895122021436691284e-02 --4.052945971488952637e-01 -1.101345866918563843e-01 -2.928230538964271545e-02 --7.394228130578994751e-03 --3.826035857200622559e-01 -2.009422183036804199e-01 --1.563786119222640991e-01 --6.310981512069702148e-02 --8.389230370521545410e-01 -2.183815091848373413e-01 -4.240171909332275391e-01 --1.119219884276390076e-02 --2.060869336128234863e-02 -8.837475776672363281e-01 -2.981536686420440674e-01 --1.019493266940116882e-01 -3.510154187679290771e-01 -1.737364977598190308e-01 -4.607968330383300781e-01 --1.500928699970245361e-01 --4.060938060283660889e-01 --5.451609492301940918e-01 -8.193147182464599609e-02 -5.161030888557434082e-01 --8.942211270332336426e-01 --2.191828191280364990e-01 -3.073011040687561035e-01 --2.763916179537773132e-02 --1.367473602294921875e-01 -3.673955798149108887e-01 --3.470633924007415771e-01 --2.817058004438877106e-02 -1.097267866134643555e-02 -2.900093793869018555e-02 --2.609634697437286377e-01 -4.643400609493255615e-01 -7.830610275268554688e-01 -4.339039325714111328e-01 -2.949826121330261230e-01 -8.194679021835327148e-01 -6.359387636184692383e-01 --4.214586913585662842e-01 -3.452744185924530029e-01 --7.680466175079345703e-01 --5.417476892471313477e-01 --8.857697993516921997e-02 -1.314342021942138672e-01 --5.252216458320617676e-01 -4.551128149032592773e-01 -6.917221546173095703e-01 -6.686831712722778320e-01 --5.474264621734619141e-01 --7.704618573188781738e-01 --1.669697761535644531e-01 -4.414687752723693848e-01 -5.662152171134948730e-01 -3.579284250736236572e-02 -2.172621488571166992e-01 --9.866213798522949219e-02 --4.864633679389953613e-01 -2.946435287594795227e-02 --8.257517814636230469e-01 -3.906469941139221191e-01 -3.403709828853607178e-01 -3.161120414733886719e-01 -9.328252673149108887e-01 --1.610678620636463165e-02 -2.672928273677825928e-01 --3.855374082922935486e-02 -3.503604829311370850e-01 --4.220077693462371826e-01 -8.676919937133789062e-01 -1.730170845985412598e-01 diff --git a/test/samples/embeddings/embedding_2.txt b/test/samples/embeddings/embedding_2.txt deleted file mode 100644 index 2953239bf9..0000000000 --- a/test/samples/embeddings/embedding_2.txt +++ /dev/null @@ -1,769 +0,0 @@ -# Embedding originating from "Berlin is the capital and largest city of Germany by both area and population." --3.502739965915679932e-02 --2.484321892261505127e-01 -6.228392124176025391e-01 --2.020227462053298950e-01 --3.854050636291503906e-01 -2.255208790302276611e-01 -3.626493811607360840e-01 -5.045546889305114746e-01 --4.234780371189117432e-01 --3.490226268768310547e-01 --3.920424580574035645e-01 --1.298452973365783691e+00 -2.678418755531311035e-01 -8.421413302421569824e-01 --1.045955568552017212e-01 -3.086782991886138916e-01 -2.046920806169509888e-01 -4.044455289840698242e-01 -1.461375355720520020e-01 -4.344026744365692139e-02 --2.073505222797393799e-01 --1.237093359231948853e-01 -6.034350395202636719e-01 -2.231094688177108765e-01 -4.063991010189056396e-01 --8.633465766906738281e-01 -6.710440665483474731e-02 --1.640948057174682617e-01 --2.017186582088470459e-01 -2.266811132431030273e-01 --4.990834891796112061e-01 -3.955666720867156982e-02 --2.565738856792449951e-01 -1.366611123085021973e-01 -4.949018657207489014e-01 --3.792238235473632812e-01 -4.399447143077850342e-02 -7.740900665521621704e-02 -1.659917533397674561e-01 --6.059023737907409668e-01 --6.719690561294555664e-01 --3.251989185810089111e-01 -4.573221802711486816e-01 --5.732034891843795776e-02 --1.816687285900115967e-01 --9.466534852981567383e-01 --3.484762907028198242e-01 -7.924351096153259277e-01 --5.791589021682739258e-01 --5.665747076272964478e-02 --8.121170401573181152e-01 -2.753389254212379456e-02 -1.858740299940109253e-01 -8.353408575057983398e-01 -4.107508361339569092e-01 --3.476085066795349121e-01 --8.524277210235595703e-01 -2.697597444057464600e-02 --3.207877874374389648e-01 --2.518910765647888184e-01 -4.477213025093078613e-01 -3.113864660263061523e-01 --1.981526166200637817e-01 -4.737851619720458984e-01 -9.639080166816711426e-01 -1.643400341272354126e-01 -3.545603528618812561e-02 --6.741285324096679688e-03 --8.140398561954498291e-02 --7.247864007949829102e-01 --7.031484842300415039e-01 --2.288515567779541016e-01 --4.465312361717224121e-01 --1.466204226016998291e-01 --2.654379904270172119e-01 --5.924498438835144043e-01 -1.210229098796844482e-02 -2.233944833278656006e-03 -1.679812371730804443e-01 --1.216832846403121948e-01 --1.350424736738204956e-01 --3.923714160919189453e-01 -2.452432811260223389e-01 --1.922561973333358765e-01 -5.044607520103454590e-01 -2.308002263307571411e-01 --3.788992464542388916e-01 --2.257384955883026123e-01 --4.108154177665710449e-01 --2.896271646022796631e-01 --2.014661207795143127e-02 -6.420840024948120117e-01 -3.615587651729583740e-01 -7.816328853368759155e-02 --8.873444050550460815e-02 --5.393957495689392090e-01 -1.738593578338623047e-01 -2.291528582572937012e-01 -1.937232725322246552e-02 --1.403790116310119629e-01 --2.777118980884552002e-01 -1.508077532052993774e-01 -4.774484038352966309e-01 -5.508863925933837891e-02 --8.282089978456497192e-02 --6.452873349189758301e-01 --2.453381717205047607e-01 -2.008201479911804199e-01 -5.365056991577148438e-01 -1.911260336637496948e-01 --2.883971333503723145e-01 --3.708280324935913086e-01 --7.513069361448287964e-02 --4.337211251258850098e-01 --2.395299226045608521e-01 -2.267377227544784546e-01 -3.622814714908599854e-01 --6.491210460662841797e-01 -7.341821491718292236e-02 --1.849381476640701294e-01 --1.406001895666122437e-01 -6.902623176574707031e-01 --4.208654165267944336e-03 -3.372412919998168945e-02 --1.040379703044891357e-01 --5.126581192016601562e-01 -2.855188846588134766e-01 -6.140494346618652344e-01 --3.642800748348236084e-01 --1.791049391031265259e-01 --3.401936888694763184e-01 -6.934932470321655273e-01 -1.681368947029113770e-01 -8.190722763538360596e-02 --1.265876591205596924e-01 --2.710527181625366211e-01 --1.739282160997390747e-03 -5.963726639747619629e-01 --1.994928717613220215e-01 --1.853744536638259888e-01 --8.673938512802124023e-01 --3.303422927856445312e-01 --1.450583338737487793e-01 --5.847023800015449524e-03 --1.165279150009155273e-01 --5.520762205123901367e-01 --1.821550428867340088e-01 --9.687544107437133789e-01 -1.344068646430969238e-01 --2.164810597896575928e-01 -1.596091091632843018e-01 -7.347629070281982422e-01 --5.407872796058654785e-01 -1.334261149168014526e-01 --1.096783652901649475e-01 --2.300061881542205811e-01 -1.117222785949707031e+00 -1.230664625763893127e-01 -5.514910817146301270e-01 -1.478784382343292236e-01 -2.544640898704528809e-01 --5.221973657608032227e-01 -6.918817758560180664e-01 -9.903263300657272339e-03 -2.306111454963684082e-01 --2.409939467906951904e-02 -8.558548092842102051e-01 -4.044151306152343750e-01 --4.355117678642272949e-02 -2.062727324664592743e-02 --4.837723970413208008e-01 --3.050129413604736328e-01 -4.568521380424499512e-01 -1.494464874267578125e-01 --3.678355365991592407e-02 --7.695698738098144531e-02 --6.352967023849487305e-02 -7.867153733968734741e-02 -3.235890865325927734e-01 --3.122358918190002441e-01 --3.001871109008789062e-01 -6.281623244285583496e-01 --1.435851454734802246e-01 -7.487190961837768555e-01 -1.294909510761499405e-02 -4.964344203472137451e-02 --2.500869035720825195e-01 -4.042009413242340088e-01 --1.525480598211288452e-01 -3.551239669322967529e-01 -5.694060325622558594e-01 --7.017244696617126465e-01 --4.436770379543304443e-01 --3.601619973778724670e-02 -2.702530920505523682e-01 -2.540213167667388916e-01 --3.798457384109497070e-01 -4.183891713619232178e-01 --3.447666168212890625e-01 -5.346086025238037109e-01 --3.111899793148040771e-01 --5.414998531341552734e-01 -3.031770288944244385e-01 --1.430436521768569946e-01 --3.132767379283905029e-01 -1.961032450199127197e-01 -1.358014196157455444e-01 --2.774290740489959717e-02 -2.619241178035736084e-01 -3.114521875977516174e-02 -3.583562374114990234e-02 --8.885195255279541016e-01 --4.751917719841003418e-02 --3.924608528614044189e-01 --8.642072975635528564e-02 --3.059253692626953125e-01 --7.023161649703979492e-01 --1.895882785320281982e-01 -2.782574594020843506e-01 --1.035739853978157043e-01 -7.075327038764953613e-01 -1.376476287841796875e-01 --1.702647060155868530e-01 -3.275733441114425659e-02 -3.351456224918365479e-01 -2.080757915973663330e-02 --8.767645806074142456e-02 -3.289588689804077148e-01 --2.380729019641876221e-01 --3.962414562702178955e-01 --1.079846918582916260e-01 -1.344443261623382568e-01 --2.462389171123504639e-01 -2.790791392326354980e-01 --1.552606225013732910e-01 --4.747542440891265869e-01 --2.840235829353332520e-01 -1.021824777126312256e-01 -1.051421165466308594e+00 --4.611891210079193115e-01 -8.538937568664550781e-01 -1.009325683116912842e-01 -2.803907692432403564e-01 -6.447545886039733887e-01 -4.872370958328247070e-01 -3.829936981201171875e-01 -1.415368616580963135e-01 --3.368061780929565430e-01 --5.532017946243286133e-01 -2.696065604686737061e-01 --2.345689535140991211e-01 --2.235712856054306030e-02 --7.332716882228851318e-02 -4.060483723878860474e-02 -5.105115175247192383e-01 --2.351123392581939697e-01 -3.629172444343566895e-01 -1.578218340873718262e-01 -4.879159033298492432e-01 -4.969968199729919434e-01 --1.966212689876556396e-01 --2.432241141796112061e-01 --5.203243494033813477e-01 -5.905023217201232910e-02 --2.562727332115173340e-01 -3.617292940616607666e-01 --3.327385187149047852e-01 --5.969607234001159668e-01 -2.997459769248962402e-01 -4.651669263839721680e-01 -3.281677961349487305e-01 --1.172596812248229980e-01 --5.016624331474304199e-01 --1.489991843700408936e-01 -2.177629172801971436e-01 --4.108846783638000488e-01 -1.440818309783935547e-01 -7.768923044204711914e-02 --4.429140686988830566e-01 -1.292066872119903564e-01 -1.713678538799285889e-01 -6.299359798431396484e-01 --2.199327796697616577e-01 --1.302842378616333008e+00 -1.457566767930984497e-01 --9.617265462875366211e-01 -6.564955711364746094e-01 --1.528875827789306641e-01 --2.014315724372863770e-01 -2.958278059959411621e-01 --2.806325554847717285e-01 -4.258283227682113647e-02 --2.116076499223709106e-01 --6.349673122167587280e-02 --1.495359688997268677e-01 -1.878445446491241455e-01 -2.661544084548950195e-01 -7.779234647750854492e-02 -2.018465101718902588e-01 --4.232980310916900635e-01 --1.106812953948974609e+00 -2.421708554029464722e-01 --6.483934819698333740e-03 --1.134511828422546387e-01 -3.466457724571228027e-01 --5.150250792503356934e-01 --1.294043362140655518e-01 -3.503468632698059082e-01 --5.707724571228027344e+00 --8.727779984474182129e-02 --1.839415878057479858e-01 -5.337589979171752930e-02 --2.609585523605346680e-01 -2.951710224151611328e-01 --8.711181581020355225e-03 -1.908055841922760010e-01 --3.130768239498138428e-01 --4.789467453956604004e-01 -5.236034989356994629e-01 -1.213718801736831665e-01 --2.502877637743949890e-02 -7.159129381179809570e-01 -2.294371724128723145e-01 -2.972486019134521484e-01 -2.519525885581970215e-01 --1.862778216600418091e-01 -9.316504001617431641e-02 --1.539929583668708801e-02 --4.046074450016021729e-01 --2.781559228897094727e-01 -3.671758770942687988e-01 -3.752010464668273926e-01 -4.965055584907531738e-01 -3.661217689514160156e-01 --1.596216410398483276e-01 -1.760518997907638550e-01 --8.603113889694213867e-01 --6.751161217689514160e-01 --1.565371826291084290e-02 --4.972478449344635010e-01 -3.067761361598968506e-01 --4.226627349853515625e-01 -6.397656798362731934e-01 -2.487742155790328979e-02 -2.310360968112945557e-01 -3.255710899829864502e-01 -9.338064491748809814e-02 --6.651074290275573730e-01 -3.171201646327972412e-01 -4.416056871414184570e-01 --1.784701943397521973e-01 --2.381681501865386963e-01 -7.483348846435546875e-01 --5.218355059623718262e-01 --3.730430603027343750e-01 -3.625536859035491943e-01 --4.964668154716491699e-01 -2.348926365375518799e-01 -3.013740777969360352e-01 -3.055275976657867432e-01 -1.480403393507003784e-01 --2.320497930049896240e-01 --4.064535796642303467e-01 -2.263774424791336060e-01 -4.258074164390563965e-01 -4.144503176212310791e-01 --1.770139336585998535e-01 -5.268094688653945923e-02 --2.831856310367584229e-01 --1.477504335343837738e-02 --9.703387320041656494e-02 --4.511838033795356750e-02 -5.333589017391204834e-02 --9.445999562740325928e-02 --2.004902511835098267e-01 -3.365515768527984619e-01 -1.703894585371017456e-01 -6.698106229305267334e-02 --3.738038837909698486e-01 --3.695805668830871582e-01 -2.319071590900421143e-01 --5.826967358589172363e-01 --6.368566155433654785e-01 --8.390385508537292480e-01 --4.107039868831634521e-01 --2.614681124687194824e-01 -2.630363032221794128e-02 -1.726042926311492920e-01 --1.000009536743164062e+00 --1.097534075379371643e-01 --3.697288036346435547e-01 -7.575616985559463501e-02 -2.224939763545989990e-01 --2.521356344223022461e-01 --4.215825796127319336e-01 -4.547260701656341553e-02 -5.952886939048767090e-01 --1.791865825653076172e-01 -9.719451516866683960e-02 --7.582435607910156250e-01 -6.978361606597900391e-01 --5.387004613876342773e-01 --2.391571402549743652e-01 -2.574767768383026123e-01 --1.712000817060470581e-01 --1.907469034194946289e-01 -3.617357611656188965e-01 -6.054838001728057861e-02 -6.030167341232299805e-01 --3.645527362823486328e-01 --7.730015516281127930e-01 --4.504611194133758545e-01 -3.196120858192443848e-01 -3.509167432785034180e-01 -1.879877001047134399e-01 -1.031449794769287109e+00 -9.688516259193420410e-01 --3.409947454929351807e-01 --1.223350688815116882e-01 -1.499477475881576538e-01 --1.039341390132904053e-01 --8.341165781021118164e-01 -6.827871799468994141e-01 --7.014564275741577148e-01 --8.521562218666076660e-01 -9.836302399635314941e-01 -3.324556350708007812e-01 --1.712496727705001831e-01 --3.096389397978782654e-02 -6.746208071708679199e-01 -6.885351985692977905e-02 -1.202857494354248047e-02 --1.899963319301605225e-01 --2.752082422375679016e-02 --6.318244338035583496e-01 -1.289674639701843262e-01 --3.119843006134033203e-01 --5.882817134261131287e-02 -1.642143726348876953e-01 --2.947475574910640717e-02 -5.384861230850219727e-01 --1.071689575910568237e-01 -2.515020370483398438e-01 -2.421672046184539795e-01 -3.118571043014526367e-01 --5.063782930374145508e-01 --1.265437155961990356e-01 --5.859344005584716797e-01 -4.257576763629913330e-01 -7.087614536285400391e-01 -3.908094465732574463e-01 -2.803798019886016846e-01 --1.502375602722167969e-01 -2.499181777238845825e-03 --1.250709593296051025e-01 -2.486710399389266968e-01 --2.422083765268325806e-01 --2.543610632419586182e-01 -6.485615372657775879e-01 -2.218875586986541748e-01 --2.156969308853149414e-01 -1.803071051836013794e-01 --5.259934663772583008e-01 -2.468741685152053833e-01 -5.233973860740661621e-01 -5.828575491905212402e-01 -4.522130191326141357e-01 -6.095971912145614624e-02 -3.063503801822662354e-01 --9.126045703887939453e-01 --6.824910044670104980e-01 --7.844391465187072754e-02 -4.712547659873962402e-01 --3.449836671352386475e-01 --7.073698043823242188e-01 --1.636506170034408569e-01 -3.543359935283660889e-01 --1.519567072391510010e-01 -4.201447069644927979e-01 --2.701852619647979736e-01 --2.194357514381408691e-01 -1.452693790197372437e-01 --2.864643037319183350e-01 -2.220908105373382568e-01 --1.773251444101333618e-01 -1.679011583328247070e-01 -2.730821371078491211e-01 -2.361543774604797363e-01 -2.246947735548019409e-01 --4.980872571468353271e-01 --4.115273356437683105e-01 -1.090010881423950195e+00 -2.047744393348693848e-01 -6.219638586044311523e-01 --9.196864813566207886e-02 -2.323516309261322021e-01 --1.681832969188690186e-01 --9.680019319057464600e-02 -5.585495233535766602e-01 --2.394603192806243896e-01 --3.053095936775207520e-01 -2.141336351633071899e-01 --9.413032978773117065e-02 --8.825856447219848633e-01 -3.839341700077056885e-01 -2.191557884216308594e-01 --5.496608018875122070e-01 -1.054756343364715576e-02 --6.325354427099227905e-02 -5.388532876968383789e-01 --6.009625792503356934e-01 -1.273819208145141602e-01 -6.890402734279632568e-02 --2.428063750267028809e-01 -6.020038127899169922e-01 -2.988198399543762207e-01 -2.759329974651336670e-03 -5.277044698596000671e-02 --1.205244779586791992e+00 --1.197616159915924072e-01 --2.656232416629791260e-01 -6.106294989585876465e-01 --8.197216391563415527e-01 --1.346422731876373291e-02 -3.115884065628051758e-01 --8.700287342071533203e-01 --2.767286598682403564e-01 --1.448835525661706924e-02 -1.055199652910232544e-02 -4.653731882572174072e-01 --8.509911596775054932e-03 --4.799016118049621582e-01 --5.536663532257080078e-02 -6.450237035751342773e-01 -4.408835247159004211e-02 --3.374440670013427734e-01 -1.666690707206726074e-01 --7.715082168579101562e-01 -4.647931754589080811e-01 -1.126632392406463623e-01 -7.722954452037811279e-02 -2.119724154472351074e-01 -1.048572584986686707e-01 --2.917249500751495361e-01 -3.101131021976470947e-01 --5.582486465573310852e-02 --2.201662659645080566e-01 -2.142339795827865601e-01 -7.404654026031494141e-01 -3.509175181388854980e-01 --2.044949978590011597e-01 -3.726385533809661865e-03 -2.923355400562286377e-01 -2.864260673522949219e-01 -2.927254438400268555e-01 --1.243146955966949463e-01 --7.328172922134399414e-01 --1.037245094776153564e-01 --6.129434332251548767e-04 --4.291651248931884766e-01 --6.334857940673828125e-01 --4.308040142059326172e-01 -8.274923563003540039e-01 --4.062857925891876221e-01 -3.142048418521881104e-01 -2.004694566130638123e-02 -4.555304348468780518e-02 --2.909836471080780029e-01 --2.276893407106399536e-01 --6.813959777355194092e-02 --1.444584578275680542e-01 -6.210656762123107910e-01 --3.663198351860046387e-01 --3.821780085563659668e-01 --6.322101354598999023e-01 -1.072372049093246460e-01 --2.692255675792694092e-01 --4.396297335624694824e-01 --1.831341087818145752e-01 -5.499981343746185303e-02 -4.722392857074737549e-01 --3.504121899604797363e-01 --6.826843321323394775e-02 -7.346655130386352539e-01 -2.023862898349761963e-01 -1.132285743951797485e-01 --8.604030311107635498e-02 -2.105165570974349976e-01 --3.782684206962585449e-01 -7.761229574680328369e-02 -1.874015927314758301e-01 --7.811535000801086426e-01 --4.675215110182762146e-02 --5.433402061462402344e-01 --2.123800665140151978e-01 -4.366737008094787598e-01 --5.816888809204101562e-01 -5.904363393783569336e-01 -2.561127394437789917e-02 --8.634641766548156738e-01 --2.721174657344818115e-01 -8.269499242305755615e-02 --2.955511584877967834e-02 -2.693665921688079834e-01 -1.998760402202606201e-01 -7.313628196716308594e-01 -2.924258708953857422e-01 -4.525561258196830750e-02 --7.452881932258605957e-01 -6.597924232482910156e-01 -1.322687715291976929e-01 --7.255443930625915527e-01 -1.634298563003540039e-01 -2.869873046875000000e-01 -2.655473649501800537e-01 --7.671123743057250977e-02 -3.054022490978240967e-01 --3.072836995124816895e-02 -2.726070582866668701e-01 -1.111197844147682190e-02 -5.466554313898086548e-02 -5.278943777084350586e-01 --5.705235004425048828e-01 -5.237748622894287109e-01 -9.901364445686340332e-01 --2.671047449111938477e-01 -2.661453485488891602e-01 -8.456956595182418823e-03 --1.947641819715499878e-01 --8.193356394767761230e-01 -3.731850981712341309e-01 -9.668135084211826324e-03 -1.679916977882385254e-01 -3.195111155509948730e-01 -4.949894547462463379e-01 --4.730733931064605713e-01 --1.908192038536071777e-01 -1.000339165329933167e-01 -3.540372550487518311e-01 -3.500400781631469727e-01 --6.154884099960327148e-01 -3.802800774574279785e-01 --6.426225900650024414e-01 --7.594132423400878906e-02 -3.320287764072418213e-01 -2.728916704654693604e-01 --7.135124802589416504e-01 -1.679833829402923584e-01 -6.725890636444091797e-01 -6.518514752388000488e-01 --4.694243073463439941e-01 -6.193121075630187988e-01 -3.207287192344665527e-01 -1.926315426826477051e-01 -3.013898991048336029e-02 -1.289301961660385132e-01 -3.211455792188644409e-02 --1.606753170490264893e-01 -5.375450253486633301e-01 --3.680217862129211426e-01 --3.480783104896545410e-01 --2.953865230083465576e-01 -1.202267482876777649e-01 --3.626164495944976807e-01 -1.786191165447235107e-01 --1.571892201900482178e-01 -4.322267323732376099e-02 --6.198822706937789917e-02 --1.290416121482849121e-01 --3.064711019396781921e-02 -7.731530070304870605e-02 -2.086163163185119629e-01 --8.336438983678817749e-02 -2.845852375030517578e-01 -2.564371824264526367e-01 --1.314451843500137329e-01 --3.739587068557739258e-01 --1.512291431427001953e-01 -1.246318891644477844e-01 -2.561454474925994873e-01 --1.464029997587203979e-01 --5.625591278076171875e-01 -1.440005004405975342e-01 -7.433188557624816895e-01 --1.764921844005584717e-01 --2.192884683609008789e-03 -4.341214299201965332e-01 -2.523289993405342102e-02 --1.730086803436279297e-01 --3.126349449157714844e-01 --3.779135644435882568e-01 --4.671062529087066650e-01 --5.430517196655273438e-01 --1.429144442081451416e-01 --9.436997771263122559e-02 --5.054178237915039062e-01 --3.180355131626129150e-01 --9.261984378099441528e-02 --1.149611473083496094e-01 --3.742703199386596680e-01 -2.060787677764892578e-01 -5.940990895032882690e-02 --1.843289732933044434e-01 --4.852246940135955811e-01 --3.015697002410888672e-03 -4.264630973339080811e-01 --1.516445726156234741e-01 -1.295473724603652954e-01 -7.629500627517700195e-01 -1.422168910503387451e-01 --2.645798921585083008e-01 -4.269694685935974121e-01 -1.865656301379203796e-02 -6.254476904869079590e-01 --8.332124352455139160e-02 --5.012966990470886230e-01 --4.339874386787414551e-01 -2.945995926856994629e-01 -5.067302584648132324e-01 --4.568411111831665039e-01 --2.528634071350097656e-01 -1.462249904870986938e-01 --1.342212855815887451e-01 -3.591612577438354492e-01 -1.447424143552780151e-01 --4.649496972560882568e-01 -9.344598278403282166e-03 --2.758426070213317871e-01 -2.415580004453659058e-01 --1.285136491060256958e-01 -1.252650767564773560e-01 -7.525369524955749512e-01 -4.123204052448272705e-01 -2.185205221176147461e-01 -7.091249823570251465e-01 -3.200031816959381104e-01 --3.681315779685974121e-01 -3.147734701633453369e-02 --5.254916548728942871e-01 --1.469201296567916870e-01 --5.021519660949707031e-01 -2.662588357925415039e-01 --7.800726294517517090e-01 -6.643526554107666016e-01 -9.518469572067260742e-01 -4.840956032276153564e-01 --4.694586992263793945e-01 --6.441003084182739258e-01 --2.094087004661560059e-01 -1.880166083574295044e-01 -5.539071559906005859e-01 -2.463098913431167603e-01 -3.698300719261169434e-01 -3.008196353912353516e-01 --5.662071704864501953e-01 -3.102169036865234375e-01 --7.623708248138427734e-01 -6.622936129570007324e-01 -2.950800657272338867e-01 -2.162528783082962036e-01 -1.020280838012695312e+00 --5.115104373544454575e-03 -5.375592708587646484e-01 -3.525848686695098877e-01 -2.358348369598388672e-01 --4.117915332317352295e-01 -7.641390562057495117e-01 -1.236370876431465149e-01 diff --git a/test/samples/extensionless_files/docx_file b/test/samples/extensionless_files/docx_file deleted file mode 100644 index 05e64e82f34fd9794319124f9c6c9c02e8bfd3f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11899 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 KHIL@!-Twd@?=$HD diff --git a/test/samples/extensionless_files/gif_file b/test/samples/extensionless_files/gif_file deleted file mode 100644 index 8cf3628fdbf1e910c59b29f729b17f2d63a3d99e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64 zcmZ?wbhEHbWMp7uXkcUjg8%>jEB+I7E=o--Nlj5G&n(GMaQE~LU{L(Y!pH?wr2|p~ NQqI7{ -sample diff --git a/test/samples/extensionless_files/jpg_file b/test/samples/extensionless_files/jpg_file deleted file mode 100644 index f478491eab5ee36eb57d8ccd3c11cb681253b98f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6427 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 ZfZs-FHAM`}tH-V*e_&+LnV`D5`ah36hK~RM diff --git a/test/samples/extensionless_files/pdf_file b/test/samples/extensionless_files/pdf_file deleted file mode 100644 index ff7a0d6e7595ee90e1f09210243aac9d9937683b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1117 zcmah|&u-H&80U!m6uwm3K*LV#I1Q>QHAyo~46RCw1nYJPsn-QcTqO?bxFPWvNL;ue z?F7=eaO(@~zzcBVHTax%UDO?jl-U0H_kF+bUs{7O+P9tv)LMRB{#sryzaSe^tX{uC zoenvY`BYzE21rbzY^G&FqFJJ4C{s0&-7YG1A(MA#@tNJQ(eB?zBRZfrjD8UbkqNK`sV~)o_<6RuCE?mA(>CscCa&2$S9Z%cg$rCIh!yL=-i@WgOW()8XH!O z$e>W^Q0g&(bjV09^jXu$x-%MG&LtTnQ}Zb#IN-(siDjv(B9$dJ0x@|mCt2dF#hAiT zST=S&`-~hEs+vPthGbMEc{w*8(n}HyNhsfEsf-VNa)@Dj)AHm538ZzZYczbPG)La=UuKcM&x)d^Iobm zm5*1h$jetJIIm{2)rW%Xqa>g1%6$LDaIaa<_MQI#+OJj7iTY7QspC@W+LQ_pRt~FU z&fU5{lPZ8%!S$7!nnAv;fRKYE|P2}3-dD$vkww`Bvwje(_t9@Oj94!tPrZ4I(cJ1K)Q- aD`dXQSYT$O)JdW1QoGDUtycdyLjM5b{wS3I diff --git a/test/samples/extensionless_files/png_file b/test/samples/extensionless_files/png_file deleted file mode 100644 index a1016c371b20aab34ff00ca6e9fec4626dfbc947..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4747 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 E0Me20-T(jq diff --git a/test/samples/extensionless_files/pptx_file b/test/samples/extensionless_files/pptx_file deleted file mode 100644 index dfad289cd67d9fc76647cd2d21757a12d8201ad1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32936 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

3q(kEeHIL}j@>1~3Iwh(vpa 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�rh!!6{)+k!5eCD$S3^>-N%iGj8l^J_~~G||;9 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 CWrb0qUSt86SX{=2ek}Pv% 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 Y@)oZm^xFABORDa(SFQ~eg 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⋘+|bi{#r!QwrvPDHuY(o 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%0DR)mh4_ee91|=gv>WJ`tS!l^e|a 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 GxpEDkiR#`;J0F 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

-o$>y-k+n7huCn{3?RS|=zR)+oh)gp& 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

s_0;rm&dp_P|c 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

mL+lb0^~XwYYOCxoHL_ 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�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%0Dks9`^RJYU~#I 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 z�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

5fiJ7)SK&wKOZm?6a9QC$s0R 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�pdRO8IaFh8RRc~ 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'X-yA#uy2aZbt0>MuG#AX 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 CJTsC2 diff --git a/test/samples/images/cat.jpg b/test/samples/images/cat.jpg deleted file mode 100644 index 25c458ac72033bbfba3001d0ebaef14d5d567d8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634756 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 MRX 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%0Dg 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�=sijI%kpjc)!9P; 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℞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%0D$1U>x-@QFjuS;-^ z??!VNOIog}A}WaPpnk8^S#v=V>eWm*gXqLK7*$4iKzZJ< zYTYHk1E{dg8eMoSf&H7yzuT2pV>M@-YIFx9NrGAi0r7Q>HMe7+^u4z9(<}R!#rHcl zK~c0+X3J3#nzM5ahh)!F{UI|0?r?wxrQ&|E0pLsHHL3l~9nQ~V7ftrEnq>%wnNd!b zlJEdPOp5>NqH9jq`(HIaHinFr9)RmS-V9^yX4AxdQQ*+aVaY1hm!SL6RL;MD=&w^Z zwIax5{UCV$4hFzFp=cWi%Na6PXJPk5Q)1qY_pReAGdC@K6+{e<$vRG4f%Tz6F(Fs$ zYj3-s`^e|Mg0YkIo3^*YGhE(K)5&^~)6%w9K5+)e-F1zAKEjNBVeHaG-2qh(ML*o0 zTrId? zB=U}C?+;Lqsbirc&nnaeb{^OHg$(Qp1=%zY0Ukv8bghB=Xk5an6%HT%_~G_FU(@`RO|Fhv|1Lc zHI^C<2yZ)UkkuI$#d*}P@{EW(5G9Ca2_31c5PDSBFAfXtA=fvsktg$ai9-#+we5l$ z6dG{GLbKjkni=0S(QOuw5Y#c+=B$1u zj@JsJlLCAJ&dF@j zfCEZV4I^1g^sPHx+JoAOA`~B=g6!KqU&1zjsR|PHqvS(b*Ka%a;RSvTY0>m3>f<r4Zzk_;lLc*(bV*|zHE)acDMKqIgN9kduyAbo*ws8Rg6GCVzHbPVd~2vGu4 zwSx$glc&A^g4=$e7Q2EhxLC`bi&azspTyRF*+y=aMsw8wwv2!k4L%oQQ4-t=Z%1cFAiJz9um@HP8LR(lDmgnRixv7JI{t z*#(r$DE<*!DLQD2r85ev)nP!ydy9qUzbl#y;39rx9dHK}spSlLuH7#- z?gUG?97#RxHydYbac zURMg3;%FGVbNCfVc_wX-9OoW>!8rFaV;@jn%PD8TE+7@XwCrZ68fpk33qzB2W$E%E z#a=Q%mYeiWo4(o8Xo-MP-H8iZ+r6FqicZLwE^t815-iBSQ$hDXecKIpYi(DWgD>L>d(t5(Iw&0S4L5yf4X!E zw+yTdoZlDxrM`Y4E|<#S!O1vm=8oaV5l$po%^aJ|1gCIYGYM_qAb zKdedMx#o9NsDxjpDI3_r@WK06JpVmbf^M#SwAoIwz2J;vHOA1ruS=j;@e135(gmsX zwK=b_*ZAe$F4_+ia(kk$2%~&A$44Mf9Ei9cOvN?^buV_% zp{MqNyNl{Sw$V{vBxjkwyk6yM-R#A^> z)|~%9@d|Db(um9Qa(MnOnV6>)1sF0*9jFz`Pb+EN7?yvPTPXfYWGf&T(eU$S%phbR-i-QPhsqGgfF^#&+ zo$qiF;2lRzD#Myv5OU*$aKak`*vQS%wQ7sEZfn|U!WHmW zCMx~mqm{fHE|Vb}xg&XCE|R%CdN8KYrI90esan(%o^IUgjm#Ft7>CL)xq!7AcVV^+ z$sHOE0{!sQcG4jg+X6eZ{L#vw+D-}mFAp%8z+DZdZIk_W8xq&w>i5N=m$r}N*MDt zq*Hr4)_K$sZ;Viqw2?*Mv3{OlTSFHVa-hQ+|Ee)=t&JKD8#wmYyg*s8QUo2x?c+^C zQ0njhyk7W9aC)`*7wzcfeXefJd?Yz^DjnPRL@#e%#CqU%p+=dO6lMd=s91U_V*;9=w&*z{Pyt7D>z<60?uEqGbMjc!@ z8pxY}sDzG?Zg~{eHjg^3L1~Dt&SFNUSH_qP2GCwBA6A`Iv!i_Py$KRaZv{HRJ!@|V zS5;KXN7Ry?wB*ehq;gF(g+sF*!2Lzk-N0NDu43d01|Y* z!T-uG7~TfHNhWIApDp3?W}LgV$wDsgBV!2Y)EUy4=gk9S4}gbZ&Xtu()8ETM>k6(G zcHr_=z?JL%!Jpf7MmDC{0RbXLTaH3Hg(@7O*S3?9@kzNNE^0jC@Ji%uL~ea={w@8e z-ASzm;h9LgS5BHFR*NP048bnxNhIHHtxNOss4_#(N`4(3Iqgo~qPfVRI4iSC;J5Bk zo9Zw2PQjO~4itw{G=M$qn`sV)=)A8+|6|f(T@=XTAjXA^5n(bvVdoF^uadk_krC_E z!{PlWKKFrQvKS%ef#CV|d(GftMeH-fcIhxIG4&KPH6v>93v~R`#)og|BUD)lpjO-M zqvR*%q9S(!&*K^xG&K#YroQYl6nOjX)lP3uhm}FRU-C{&)|Pk*+jfeihDeTakUt=- z!t6v0E|Il>)qcLcR!lmmg}(>ortfTJn&A-$=)GJhyqDs~2zl^A0)`#?PpTS!da*{l z32=6xo}wbHa_?qf>h$E=){m61nfX=zWnOdH%OM+4cS77INC63HhpB`+6TVG@QUDfm zYw{L`%kL7>?_*={DPHJHu0>5CvTZ@%_4#NJOFitJsGkoT%iyvm%Rgbu4d4jqNP+p* zI^-QK;nst4$39ZvYp3BTT0%SP=zway4-SWZ0Z)coNafk`&Brk-PdPsZ>S(JjIZ&`x zK{4vbNlBAM9uMs4uG8Xh2`9}&Ig{F)%LQxNnQXMmA9eHPsWt3ySAMqIh@d57YE*Qk zU0(e;BWI~4qi1rXtgBWLD2E6vswT0XbhxRuYj(yF!Xt9+wql+aZG}vSLyxf=gM?@K zaMamjn|~L=iok#rZ>f6$?xhZuoJdJbwc};H2!-ijdr4CF}NcM+7Rvcc~iNF0Z#DifKu4adITa?P;x@*!^f{{Nm{7a&&+}r}ljQ z9AGZLTkBASUb9wq0DN}Pu*7y0vL5LllZJjh!h}%Ss#miVKe6?aPnfx(imDzu&EezI zewgtm&niy(ByT-bNysK0tNEdMh&fUH_3_mY|6|e*Mpt)rrPTZOViiKQ*VVR%8O14_ z=orJ_ju}1i<}9Daien9YrLMfk2MY&XaiSfcz-Jo>;G;&Q-uxbSing(aI<%TJAm2!{ zL@@lgaZGylyc5n#v$*d(wFqK)3URa3XUvHR--A&6*u!n{fqCfaKC89jfGL9JhF#PK z07oqL0FDYQ6Wpc;0mS`z%-85BLc)CehsV6%+EeO#^d2t#z%pba8-;BAHLY#!d)=a|@(I_G#c~RmT#}F8!?cwnVBj+XI zk3gEBpZ;6M5jA#SC`hd$@Dkm*r$2YEn_y{3a`bFZSxf|{;;$6F8`3i)*>gx%>L9+W z3oA(uDe)bDRBh`b(D$~t_$-gMo4Sg|f?}9@IC>M8739aYiPqhf?mx_FWRnI+G+9VB zJhA-|uFSF#Qf$WD-ZxMDvoWk1`h`RmoowuG|QGxCG+SNw8vLCSv7veYFd zJ6waP{iODV(Dpak7whH8ldbAx!eribHwy-V@REEYuiGZe@-j=y;M;ayQ>c`iF)BFy zaGp&fma9ZZbHHVMGjaS|0p3f1#c|0z=K%Hxcu1I6or)K&w@>5N2pE3_$jvS+)gs*L zH|KKU^YwXvK=a^K!SM6a@(qqJhcaDROvhHgIuFQqnku>hTwC5t0LATfzdNEa-TFIG z-sc}{DK&PjRtyI?6am2%dn83m$<2^B6eb_j*oKNL{)z&2X-R+BbpxOYIcIiNov`A7 z;X(x+pm5s~EaCwgS-S^oKKiZovIwQ()IO^sLD;3qbfkl_tT2jS#S{0yB6tqN6ZIw_ z(tYb&^V5SJr@4Q%XB4d@U6Qjd|1yjpVWb?)6mH~HsE;3SgJ4qv3F69YalhV*#68R- zofa*i!Q?pFKNrnR02!NREhfqLIhbCIVRU%V)b8=xp%+gNgzXpX51b|%@EE(g`ZHls zqHjB!QcpU~naUZmU^mEv?RU}}aLzN!e!wSGQKIa+`^aND;lpW&ax~ALUgTY@@+*U6 zbD`47XmK(xi;*M4b{4aTXwY8Ohp%c09FxUdJ;WTkiL2Nx8}q?WE4aBLX8rlfa9MNO zD-``^lT)DTD97rfiWuCA^CjB|*yrZSQQkUL3{8((@LmkxNb9FNcYjxEF^xodDdw$d z3x+@p6(_$+jRLBrFr<4h=`72}8wsJ@kJP@kd`?NO+g*B<9eq^`p}5_zuE7lr#gYC*+Z3@JiorxPVec$>96!)!(^y?!$N=A_8@;zGKE>F5P z84{M5X+>srs!G3iFWFM|`!FvkTIiMF*y3?bzYdzDSqZe!1D!QPb!_y&{xZ zd%ZM%!0PaqHo){%#O*FF?+EZzJm=;L`boxP0WqHM^g1unr@rcsebt3g`IhuU3E~JK zORfr2)pnmU$OOoUMW^ZdpIV&0yg~i_b^FCcYZvAa&=$x0vUF?dln+l#cH{GQ#)PGR zH`kEMqJJFu0P=J!{A~r6`#`pV)|UY~U219hfO6>t3YrWHG)z}R8OQ>O%T8 z%3kP^V@j^+=Kq+=Ye(ZmuD+ghkPwkB++Z{B(fzP(p7XBGFn8a=LxlU*Y~mO5R&gC; zZWXOY0G?;rBFscHL98e!zFO%=>uf$|LbF}FYF2>GoAv48@(_~#NwzLDJXrKII7IaK zi_Alhr&M}!d7r_TlgW`xKapRhTFK=B!`vn&N7%Rx6`7*b{BeFIrPj4BOu{aa5EHo_ zkuXDcBC7ypb%%1{0i$yAR9iAs{j^nbO;&d35UOT*s+Q#U7*2*M(_qgtu-S@I0=-Vn z$iQ&ief6z{eBw0fP{q2Pklg1ox~-cMX}E~)E~xZrLRV+FUqDSedtPuJJ8>RA2+{J1 z{awTmzZP<WoTVeldXrmnRhx9Dg@2xRo5{tzH>3{`(Xa zBD{YTlBw}tpOo0As1Wh;qCAL`Xqn5jV69%7xpw=;{oS)V6fgsD@sGlR{oP>Y&CZV8 z{k+oyW({hUfnREwK2I{1Ky+@~4K2F2hsUmcaPHUfHkZA8qJVcLG_R>^Xr z&5rUd^_BSI|ko~k`s!J21ttse-<#Si!vvcu&tCX}y=XIQNd?T&-Z z#0Jp;SYIKtDj6@Laph&1XU2O1v`j3MrLnlp&OvFGnz3f6!S!mb8NE5^@C!IB>35;kq9dS4gKskekIROL5zkVK$qHoy_RF|b=P$#4?Wkpu5MyygKlhx^ zDF#k=RgLD1uQrjKW1mURvV)m(sMdG*?+rFX%ZnQ}FwCllz3^MgZ2rLy&1U?U6LuLx^LVTyN#=bNqY2HJyA08FzH1 zstp0I55Iwhr6w6gqRS!00T8b0N?5{cyTqhQwsn5Zl?Gnj+NdplXl+@qnHj9vhC>Uh_xWw~s&_B$q--b0?28HVW?vL^$4LOG}(g7Ce z9JE<+6OcF+xt5`oG1~b|64QvZq|d{%CzhCER!jO;%un?Bf~)Td7(DGc?5(OIMbQQ~ zP1?@X-k&ZUW6H*gN1tYu&oEo=uc=QKWv$1Q*1bpatF<02d8g~{d-;H!w=r87?t8Dq z7h8FTF4nMb<%ev&=iP{w(rsxWu?@2Bj3WLLM8s0SK zt0xuv$Y;c?FmkPk(1(*?x^@6Vj`Znc&&~B)4mI3}AzD8$ zW1!9V>8x%`w^uD0`aci94uWp6^D<@cj2o9R4%-kpI4q1@`^5Ft>Gm?}hbej7qopg) z!R^9_@oJxENIhveP4~Op!+`0bqPSm%&0rO~s=K^HX{zlGYlybCputXjq0yWyKsI)& z^mD~%BKjrcI_Hl3s9VIRfSJ%ME4gNtom`;)rKnj(8@&`c3fr_C0UygebL6ZZSd= zw&~Cb3wld;%-h}u(k{WR#V+x>sI1h#JZD~Y~36sjTR88Ucp81|0fbgL)g~5blLs})VJ{P+6 zpt(MEA8Wy8X8#dwYyBvcOCB37qq|Te_{(W7(4)jCmKrTLTPfFRqFhwAJ7r%&Qm7}s}!f8EEjeU4i{k(Y1VUSi~L ziF}e385vQtWz97LvwtRZoGNN209(39R3rpmDRlQk6p#N*GH|lym{_LivbrG$3CD)e zr=675?Vd+u*axl>1H57vrpK{8Q)2&DNqUiYIjw=%wfbz^`oB!r((gx&3gP+7WfZqBGZ{>J!;L)LRJiJU^GJX?euPPfOGRjNqzXHVz zM=|$?+}0(>ZjPI9dmBq%{e-ogGDJ<&{tb|rJ80BW@XNKz`Yz^o^+V5TP66}ly3ZFC zWs~xOu8SY!JE`dn$ojqCc7!dPQ92oT--p+6m~j7Mos96JF*Uq|d?1`@k}0bUKadd> z-{7erE+~9itvoXF^Eo`Zr8PZmC=(D_FG%w1z^rkbw(+FinLfwHWhK2)XYX?7_goY- zB$Mw$P{d}+bx?ZF=$63sGz^g-*#cH*mbl70ZCVpNM1?4}G%fu1V*S-WeT}>JH?OTf zQvQduw7ja44|wW^H`RVTt+n|)A(S-^J=SF`Up44I7}4HE)c{9oun#dsFS_idu6}Se=%jiNY!l z_g79%g`f9D0}zVv(7Ic+8mMC%h7%`!tJZ}~CyWm6Q*gnabo!^|DaqwmOH5DH3X+AZ z5Dqhc9AvIs?0d(gD%_{&m>=qjJyg1Ao;N>pH*cMOoz^_$6}P&1qf0n*oV}J(pnl2y zFwUHn+>mdU{Ayy3@@zgR_A_6YykxcOG~14Q`mTKSV({5!A2DD0%OTJu06rheV)f$soMLB%-Pk5*c1M2GQ!Q)IlCbomcGA z?aK6B()wMfDv)SdlPL23MxatBS%#HrV*zy){*NTvF-WX$?46H&`L=KiSvntW<$PuY zF_y2VrOKo!D-Y-I7=|~DvkUtx=;2v0riM;ke=EbQr@S~->BB5NkX*BBhK%=ICg?2o z!<~NKw7;l^fqmNt>E-XFc+nAMkJE)uuDOitSfBHZ-? zH)O1GIctV!b+Nxy>tKO5aQwGh@&R$Hw;860Nu$L+5bn_thykV`Pi_H&lo87Qqq8L| zJHo?+N;@ni7X?xPYod8y&m0E7Oz|gNA~^IcAh{H|{DOhRB(`Eae)WduHLb;UK%?OI zFJ$YPS4zMCT@+~VZP1?l* zZ#0Ls(G<&K$Nu@miu92nJ{nhRYl>#hi$yiabmUzm4}F=DSmcJ-a)l7=&r6DeL$%%{ zv~hF;@ZosKzh6M`9YHy&*r2&xQY8S}PN{B4wS~IT;Urcn`|XR#Bo>j|8j0viA(zST zltvQIIpUN2+^?qaF0lEDE5)v(b;hPAUmG|N$CNTme=Uj*W~H{d6I>(ZXDx!<5}nrB zlw9y3Dzq}sIpdW?eFFfI$tODxwky-VV++>^iIQ)4V^hOmUN-89cc+}wMM3`iz_gvb z*mMT7>YcN?x-P(>?R>g)!qeGTo>acHayE@1q1h# zl!c+m6;`@1I*aqj@`#cq$(v~ipoD)^xKbqe6q$3KEs_eV{N--xtNm5_3qh{{rJgzS z+8^_pZYK#AA!^h5B8WrY|K5`RY0%!;@-~IG9&gDSU)D0QJVYn0;KhpeHF-38L!W`EO zif@R+KHODwzQ)>ke96p%r#mr|qllOfw%o9aSsIS&zov9S{`Y1DXhJQPJ>SSnq2yiT zrufcPhj>Gznh8QwAOCvJ&qThgtvJxb3yFO{7cEpVjvL1129rz8N#} zZCHG{1-r3d5^6|BNb|u`Kn|mhBCkj9cHJ0{b|)>FOqN5}V-r?ZmZyLObx8H;iII0Y zEc1;PRXoM=Ed5B~E7jAYZ87%^#CThy2B8eA# z+mZvcCV1+LaIX%eSXhvn zUnzT&fI*t`zg^M%CZ}xPR%8AS0}h&ZDp(LDJ}j9v1gUm)4a&PFTfukX$Y=wHqn%aW zVS>*mjNyH?OjN%~QH)|L^$RaEKtpGMR|XO>S}xv`016FLS2n!f4( z3=&8t_=d5U3-AWszUGva_(K_JVX+)m1x_61320%>8RoG*Nmi25&5=KV)dQmp>~MSV zItcZxmXDFcD?iymW9^zZPvT69oojf7T15gQ+rj-17|ydC34y>8(O$x{HahVWnp+&* zzZTs7<<8a!Gqi$DH!j7b(C6G7UL1*Oa9V{mzd*O=#Hhs@OPz&`-!Z@T6w$;zG1A)# zmTZkSK7E>n9oue{G~Fsll`opKveFqxi&WdRezo1T$6Ce30HmeFKF$^X{`h-aM%_~T zeRz0kUqnYn2zW@KUdk#NXx5%$kWHZ^zY^10R)khJ8H{f8<`~GGv$HI5fF&vE{eEsP z>EK^-PFHbrj$Osg=m0k!oTxdBn=D{s_h%1%qsCwqUV0Wmal&nWKFseH_{uhF(^)-M zs4%przl^6UtRCB;PJ?W;>6fFlYs9a_NV24<4Qy2yKL9kZ05Ik^%%su^IhvH8d4K)) zmjSqx3MPPk2&+mHv;mqi-%jE!n))zjSbgKO3B zN8$yGVy5j0wYf0F%SsdOWEZWOduWBoj($}%@TecBFpQV+5jshai3S=(oWS9Ac9Dc) zKfhP%b3uny2SIuU`xID!^m&)?eP$QeMS7peHy2}r9%V@7rK_n)BVU>SBEQjHUMPw|S>UM=%9(LdQ0%sr*&EAG;qvE^5dMIeN6Sw4ZKgw1 z{`P4l_paQN9>GtW@rQg%$+G?R&UrirVA%e`563p}nk-;-#7+2z0iFDjyxd*wcn6PiF%8`45CD z0XTjg{ADfP1ECr=u=!v-H6s0ara3Sqs9k2F92-5gN8j;Hzw0sk@2Zw{nh0_}reQPAmOt55^!H2WiBdK(R#I9{Fv$EorULYm=yJ8r z4|pt|NzPO%jg!%SUF4kMYw3A^wY{{7nk}a&=;qTAE1<}1kU!cvbRD;M7n@I^sgi^y zrh9V9Fyh2d$xd;djq5E;{6uI%Lo4liOj< z{j9gPHI8m$;XJ1?bVrYH#c-l0D-39H{Z;Yz0x?;DZr()6qDkZ0pe)L(rL~nn=ibAB z+{_YJAiT_pU}E8QO`=gK+4eM!;IN@y%qREd?%JZq42s}NYdGd1a1@-~6;U^NV?8O| zjxznQ4;{X9DVg2s*d0W3zTf1;i1-Zy_m#6l4z0x=@U};T(xp15gTi+G~LeUYJ(f zRvb*Zb`m{Yr%=z9yHgcI*HxCS%$1a~)7reGgVkHJXqC?um{T@@MrD)t<*}pTnq3A< zqd6xOEO6Z7e75Ql_IP3%TlP%D9mpnY_B*%LE12MZU004Dz^IGtIzbqxl@TKXGDZckii@yC>{=;(D zldSR+0%A7J6_)lf5$+`3+D~Hod?cl;VQH-LScm7S{zrbL2l*VZH@Gt z>iomQ$C?c~fQ+fDCEnyhy0r`C^u6XxwG$tll(ljru{;z9<0=UHo}mpQp0{A^Dk=A1 zB_`x{Mz@UWY+RNc=nYv~Uyn+neo<3#^opg`HnN_RLW5dr-2zAJTi=yF3+J~M%E+YQ zrOT-)iP_15_G$K>V|?M8B9=i(ZJB@5dedzYqPa<+8dK}eM;6$(oy0ICp7z&Wp2xjo zWUAEvYyuLGaNn9RpSgV))gAO@7gPDj0t3?VT+R@PqIoqlErq}qFjg@;S)&7HB z-o|)vJc_sqXy+(xjy*X#A_Msl5o+Z!3VE#mj(K!4QwJxhZRMYa^HTH=hst+ST25SH zBz&--_bHRFMV_^Yc~cYRkg>M@ZnKTiO%(f9F(95{Ir7YpXpYs#+utTWqhiT@3Ha)cL%3F_m8j5)ptm7trQn z)0$bn?l%q}%x!c9b+zU>ip6N`l z1^1-ewEJ~S_9LpIIQ0>s$)TW#NMwA5spUHrVd2qcYRSR4IQNiFjHHOw)QpFbOl=YP zMc1xJn)Q1|GrJ=|Cz5NCtf?(jCoCG~g1R!lYwDu`n{$cTbS*^sWSOkkI=+fP8#A*P zQ&71yW`~MOmcql|iq)-8Sy|N?i6I>a6{*RJ5(`;sAt}jIag7G=?B{it2O^_m>A>oi zF8 zler-8Q*+!SwJ2Nn&TTB_e4vMB3|;s{Zi4PQ|vri%^kc+}O#iB?J>$ z(E9|Qe7A?->jWb!?LI$=e!@U@Dgkmb&_EyCM}456{Um*Sx&KoB!|pGq?}9E&5S+X4q7)@G8aJ(Z6xXgyZxI}5lMR6GaNu7W2X zxZv&SXp#+aV@z>W%{@`YD=5QstUCuV7J&{=)@juKG9{fh(LZez#II8Bc^^DEJaUK` z9VzO_zPRQQga>~QEf`Q~ASbXb)c+54xVb1pjZ)SdOxK?B(y>X{mKYuZg*IBSN3PNB zy>PT5I@Ehof-cxKd~?gwzwjEaXOZ*O(V!VX2c`ler1&cy#UXT_heuzs*%^cQOxN>_ z6qS}f2JYUP@ zx1l;Z{*1!jonCk-VZGgy?A0)wzLjALt2=s0Qw1c7(M#eeg0b3Nd>QttkM49E9SLYf zjEFBIRGFTWeloIa$%^+6bn%tr>j-T`nYREcEez3MnoRSB8mj3yTtOj_QzBfF;pdMm z7>(sKHglVv<67_tvcz?a>8b{IkC>WNeTUoL#jcS#9Jc5f-=zzSDyb*Z`$o@+_=_HT zIVraXrzSaQ(NBCj!)mnOAcA~`=Zp0Eq5*`;0nuEVCk6PBC954o;eVd(#E29G5*qjT z^$mv{wzUvyY*TM{yWcIZFbdu+&$?5mI-+2w zXJ^sU2Re8ox^x~qy`{d=DCJD=z6t9Yr5n+RK{f(EI-DQ;Z1@g2+0WgUw?V}^-IBe7Ps;W&j|DdLZ|5T%=IygJu4^e<{= zgQEp<@lA-ddBe@LdWBekwJqQ9!62Yeb1c>*1=BH+HyhNRH3zJ4A1Kvgy?c8cs%{l7 z6gv@V*s~#&quP+W#Won^4@y@pT>6O{e4@qeA<1eySuDyNRy}@bcVY=W0l-?Eo4hXB zu3`m%3q@HQC*y~Rv9UPp-5&|TthMWAw!h@9=dUg=Q|msuEu%Ttq0ySSeqQT+(Y5nM zWZl>@S%^Mqt#-1ocGfc)8I!KTI-(hZP_=$#&@t=y7eLpT+A#rylcv#U?wHh+OAPEX z&UT;)o$_k8l!(_mX zc}i`fkJdEoB0Mo$yH2Ge-u?W|0hbEqiF*tP+j8H#zCPJHJV}GuWz-s~IWNT{T$cnB;5NqY8 zAJ(3+t#X7_gE#Ts#OOuGlr~}kOb4vzL_{1wO{%6~7F%TZ#3bfO#A{qO$PYvf$6}J9 zZN)mSI^#_&Z^zs#6NGTBsX?8Jq{b#~DRURC0PCE?MkCFF=rB1DQ6ryR2+4N@h~J+R zvv~CR@P(ee{}b53ia=#hho|4>_EV98C^Q-9a9siXZ-#IadDshk}%cs z*erL3;1iaRz_cY>3AGWe4jb20!8USeK<@7Q3`nY@o~f|}Wo`2e@#k<(G`JL(@CoG$ znc~61K(^hr@)ps>a{LQqui*COMn0?2Ul)sZwes@o8(5zV8r7;wgPC0|-NvWBL=%jb zuD3v1%&!#gWr3mL8F{7`DJ+kIT>;4fI{R1Ov#IJu?S{QzI4aM6%G@d@s90-_I6QvP zTSIR)#$mB0?Pywr4u%ei)9n8&;2uR>NKP}!WUaHSaaXUH+yFQ*BB^uxX&>h80cr>zfMH$`^iKo z-mcH`*M4xS+t?MBF)r|2{#fa0dpTX%;8YH0wG_u_Peguwd$Z!kmv9v;t>e3&_X1N2 z!;>q>r$nrNz55bjm~GHW$AOpo0cow=`GV@jmjoTh**ChQhShAO%T~SXA|hU67yQe9r1#c9Cuteu%D-GKZ++G!s*aRwZQ_>L?M88V49+HE zHB3Op!tuA85#V#wK-SR2<_w&xe6J#RV zII>E~s*JX5(^ykDOsP+q(f7SH@=MR>A~y6D zhNwf4)VoaFjJ5U@s*}k)vB&|I-1X*QhsgrF_mcJP@?=yOtIO-`7O7az!NZrum4OLa zo09INN2LeDfnGxU0(@P{OyvUapMM6EKHqL%xJUpH(IWvVp_nqZ_0*yS;dM-eWa_2D zZ_AxeTPj}=4t;P|y5=!2%){6VZSQRj{7Dq{=l3$4)1GZ_=tP zn6We1;`TAcv|4a#i)KAOU9IMBK}I;^OOS=@VB#U6{5xno;xcUalMdF9X4urUxSc3q zFjIoyd;tZ`N4-tNRb9_Xjx-vuII+2C&-L<>^jV~ zZi#_)0xsV_NJ|7M1kA1r3kV9F*J@d^J11!k=l4=_X>G8+(G`x?l-G}X5voe@(uhYr zDu~<^e0WGkrouD-?Z5g%?3C)n!AA82pzUk2*fnvML?#VgAP*ZRK$PFtJy!p?CYQ?jo?RXZ*EHGop=ExlVY)(xwggU*OTf4PFR`71E&EWOpVx96zNc_YS!k<9A~ zhv}!e;v=a`E(jf;Jg8bo-Ma~*3>%(7H078Cye6I@2#T=+Z1f&TKRp|T!Hh;b$=V29 z29=#!%UsJd$OsMU``hUxJi@i~6rB;Po_Zt#=T@%JH+^-(Ys{8|Q_J&OH+8vi@>ee$iOPkZn%Fu3ZL69eAzy za=<21X$`Akt7s+DNK;o6^v5UdBp|@8)mPl;L0+G*Fm6Cw&x!1$N$j$7y`f)1B z4m!iFHm!@QPBw(axOgP{4ubxARCZu)3)?nfba>Ai~%3U5(>(7$VE9waqfeij-8N%z4 z3$|8EJYh79QuBNmFgWYu=fhdN+_n&_AdQPRr#5(!$=5EC^xHOtJEJ5YXjPsH6wUfV zb^>WnxklA=tv>K|5Pc@vJ>5CLCG-7vtO9boU$fi(Zxv&B{n@P8+1sRwmy>DR2d}X1 zzt{Vx-9kGVTbDvcl=>fw}_7#CR+V>Ljvl5I-6;V79vrsozwnQA&7ng*k3P{UeZ zTq9C9Oa;$)S+!Ye4hsz65{xi05)er*uRw6cb0+zoPPi3LA?mFhU@ZEMaR0n_ZVNU0 zcK=mYh|VNc?2PA7@!7V-Q%se=7kmVxv>U}fE<3zXO^#uMRR@VTopc4_<-LuUmn0wP z>`2yL!^X!)XtX!y0iWqIVtcEM+KKRDF`g}dvPslU@`;$_A**R;lIk^Rh>;-4jkg+l zds14S^Is!ckZy9p@pY@E%6?`vL>YV7hDdE%QkQgfF>IQd9`1$R0e=o0k=>5Dgi~TDBlP zj`PP?t++kurIViX;uM3GlTBn6< zJv;SiW+Z=!jXKV^YKU+^m?^5JCyi?Yg6LR|Lk~=SU5gBUHGSm?x0EU54+>QMsA=jp zeYQ26`rTt{D!6r;)Z*X|$oT+_a#;A{Dh|$s1PD)VGFi|3_ z5GW9x_ zd1x@-RW)6)sXKKGt5M#6nTrj{;49UqLI}qSpR9yb-)YiFJ^TmB#Sw$B5vn%YQ7zlw zye}}$s~feq3u_G;-FY{mMd)a^#eYIJh80A_Da+Ib+@aK)deGPcwFtvHYnohZ$nefP zL_L0^bQc8C>jBp2glMY}W1zL@qT((%{BP3rcpkASnX`gxQY}Ix*jM}>Sj`H_zp9$S zQtjhk%P`%@ZL1k6*6`QZTlMaHovxl|8&1X2;LwWDqg)56frz)BGxW+w?IqeW2k?D!!ZR8?x(~f9F*bDTrpbwWEJ4@I|Z)ddL z|DB)wvQ8@9M*HGDJ=7_h@b)kId5l*IZ z7VPwmU(#WL5s>9HL;Qo|dOqf`spRIpc&t}Qn*C1gar;W>?FCUd-NDx(OIa(M10M;1 z-yuk~L0{PrO}Ln-uXF(ZIZ4be%_6VD`eXG;|0dfk->FJ}(_>j;rXOI~HIBLSEy4kbz( z^ategPU7)S{g)yjyPm-Dx8U=pZDtsIlvXXc=8OgCVsk)U-GEEIfHk!9E|(EqW&*mD zZ83GLDP98D?t(y_nLV`})W}Iz6O7*U{mAXu^R_O% z)%Op&@RGP{+4Yl#{aPcevN49Ll&Lwv7XszCt~x3FjA$==@!0wq0Li2a@DujuQv~c2 z$A?XEN6x!-#=3b=?P7zz`{KfJtz9dgO)+?@&5TE;gND*=xq7Okg#YD*y3I-vu_#YZgWA?g?7-73o1}774q1!sK@r#G_*GJoRLJFx)4woF_$Ip4*NL;u0 zQ)4B2re^&@*7#qdOaEerjoZ)E8y%OupnLJ;{RaC96V!x7U^Y1gtIcYtXXNu^ZVZ3G z|4WU6mCN(t*PmTvbc&IrT{L@3dkSf?PAFq(nHj9f;Cy%T4lr~&HsKo5XD-sCv8<^S z>8<^DS;4J(wa&D2pU-iwUVK2jGJHi(Pj{+-IsfzC&;O2H9~nCS;4h=|qp@Wxw}MXM zqlYaH%59AmN)D0fY*8dD%mHDBS5_C|I*Yk*GGU$@seAJd|BzgN}YO?!~U{@6223{e?)@zpNRtfCY zrIr+=C5J&oklDEQww?o%>{E3iu#Yy8f7bzq0z-vGV)T_rKcniB6b&+SAk1{~wRG z4%=I%KQ_l>*ldtmg!`(j8Wy5k5MlYb)Te=)jEq=Z@d}@Bxz*KZi2nX*5?E1s?U)Sy z^!Ry&4+qolX1u(&jVdL+BVb?zc=zv>?7}10TPxJVm*3G{zCV3mTz6{6Nw|28n1AH_ z>_VfpTM-ku>uXA#_k3^nW&>-MCOY>g8Q-_(_hooUF~(gd=G~uv&n|MV@^E9)t&K;Q zbhdZ@-a9yv4Xn#)X}J~ptN#0I+&@chT^Ikne$fuB$e!VCJ^TNwK`FOs?ElDR_jwz~ zc&p}L_|K0#Xqo#P-s_Ide)s3`%VJxD=WkSG0~Js!uOi>^9un^5y+JtNVt9dhMwdr7 zHZJ8;w@Ft#(N0uRGU2P2;HQr$9wcyYbE>tRjXs@cwj8rcF_AU$}^ zl!^)gMeCwMmVIn=#+GAQ-;T-y7~ih-9A>fr0g{vj1(6+9lEst!lUaqkwSk=(8Ubyq zVpbM4Y3Dg-G6PP>F@IfK)GI!uUdIH`K@?l}JeR#yr3;^Q40i@A@%8VJcUi3<4XGNB z=aP;?WGb2lY+D~u^Df zZK6-Rwb_vtFkML~YOW0=lzn6~DD-g>komUqy3qprGO^*QidyLH!{`X#a&+e4$qHZe zr2@X1afkc13WQ-EUIpDhXs4TrbtQQh^gB-X&&F2&+G&-9Giq4jJMG1;h1(6r&6Q`| z^=YRZe+7|XhJnKMG1SFf$$uBkStEWwmORvpY-q}@Y0t1{ml%t2=vAU@yFCOcLyShsjYZ%DE4jo(cJaw6a~QoToPaC@LmF;~G_DigBzkWH|LDgR!Q zBrooL?#>M(96{of6sqX0B%8MZ~m^jWB@y|AHDxf84|;590@3cx>Z^j@c2-s$Xaj& zJ`{mcGdA@|%~PJt^_(ijz+hnl0lT&q>%3-*ge^T41n$a8k6Uh%$MW`>N z$;t=9L*yn}nLiZXLFjkLsz94oF@)68y~lhYY>OYqGLIAOQO`6l6eqq5$VkW(i@zePW8QyS4gav`w_TER2P!=$=ru0?VT?=jt-I35c;hrWwSm+3k8qc9fy3fvtyDfA7L}Wy(mDeM9jb+ z66my{G7|g>x#$^C-Vc9bQ9s7o!T)!xCtz;lGk!#fZa+p}4=+%EPnQMMS0XLvD)9bU zF3%BeKGk4U)H`f%1jUH}F9%BkD#wyxf&_%Fcg(NmL@tt2Kwn@q5L>5Pr#fd>+E&KU zaP)g+ccLv3eh&l)3V0p%-~klP&QLH7avoH76}xO}PRGZ|{>w;?AT90EnNKpuRPVew zLD%7-BTf?%+rB7U-ZZg28oQ#$Ez3&%Fcg>St}DETV)7RlaY>~-TNeO#5hRh*dJ@CL zu>({^ee8v@MB6|b#X?OOJ-rc4o>Q{u)Z*n-5y`UhEB_OM4vg!@#p7#h1~1pG+x{{I zBV#>al4_D3yHuaym8;uWfD61cyD9JzlNnxB$;Jb1F*FwCSH?nD;!<;B59FLU8s#N0+U<3O6FUq7Cm!i0Sj}l*LRKy#UxURrlhY>?j=AR-2Vw&4iOzM&CmXyy>nE7Jkv+Ewj|AW8hk46V+hVMK zDPN?*Ty9uJyigeq${b{mcaBzsa_L~N-SzbD%rZ}S4xT#d9T&o1zp43bsnaM}yuhab z1sY*fL}-qKI;BT-Ea!#_Zc^XEpn!E4c(QxN+-oAgon1U)asbh$?qWuF8_U1paa|sc zi+^_a{-^0)Wc$sr^iP@xxzvhlwFL_Vil)sS(NWx0#!3=ZZ|A8a&>fYRDLnF_BM4B_2d)vMxIbW zUd07n*6H^?a|}v4&>H-Y=4@CRsD98jx?nS>faKj2bxV^KiLeJvqNC@wH7atM zo#7D1iZShH=u_ljvo~y0V6A)qUq)_f1is@;$_286rkFzs6>R0$T!c;ZcuD?1o9@@Z z|XA* zs3_LQsBy!Pw8i&uzz@+Og{9k>Voqvop9g1;^2avOBbyE5FXV~?`ONul3XcsohDFz( zjrXp$j;&QN3j+=MWLFk+SKlIf#B^5+*t&AbmD%`!wW(X0^&dCZB@<>`DPg+?jJbKb zQ%Aw)gjX`1o#9=5wVA%XB_0&PoJXp6zhBq$Aeso_RDn z#MWFS3UsgQ20CfkCTh15l;Tuup9~2J1EM?A@98c_6ii9^>*V-Hj2wCrIq{`Of5J0j zn%{6&L+6LX*d?md9iU1_pW!woX?{gKz)ib2cWz;@e|z z0z%tR@-Di|U}Moe`XN@+SiONb8_xf{1r4_|Ha2$&c`|fSHtA?5uWd}&x5KS zo;Dem0KT7Mz(b$!>&Wo;4?5;AjqtJbTi>(Q7i3Rl0leHVx?a*sNi9HqnAG8&Hbj_n zfA8|pg$1sdp8dm{ua)ym-!niF{#KU?r8Lw=nwAGJI>l5+!{zzTJOwAPjWz|SAQ94z z4djhyNS2Px`EQ;Tu;Y}Ewt*1%f^Bbf)z0`i=WImbj2176YdY4-TIS07mH0G`gS<%v zMFz=k5%at_!CtGdHfyf#%HCQrDgHUyYjF_wIjFnM_=NSY^kS2$*N;rj$;}hv$MdDl zUybId2uQm4-Z|MP{RMO4Iu>b@BXqbwlpH6qa$JZo>?c@Xt&LIc$gKbeUZz*@7dzXl za!+M2V}<)g9bX6bs=M+TUw#t&XvFrwb3h@yl+fX_Nl<$%CVks$D(;9OziWpm!vqR# z8!cqu*fLXIltt)sshtUnTzPZ{LCW+vNJJ^H&TZXE)H2!3t;~L(Ww3f7pf=XeZ41cD z);O1LL)>dY2L@|XZmc|g>QlWf$6t_*r^c^?*7ur1q{9zB?j}mcP1N00xjWA>|6kUJ zo@;M9cQ-r^C$KoI1xqb*S0jL&WBAjNH{B4?1c(y(>?a46|D##}d7#~Nar)0h4ae4?#ev-1U7<`j zS^V02L^!rDdA5(&XUZ+UG3uy%w`{do2h&Q~T)DoRM{mvuw5Zu9C!zKn3K&cNL=gGZ zc?CZQj1({jqI5~}@u-?WKu5D-6oUjDj}O;G7Ebr^ddGfvR|98CD`?*7UMaxYlByNx zb4ULVzwu%Zi_ELFwT`6n5TA;=U@$08YaXzx@CEDPs}2(`b^ojN=&eZ7FYD`aV^N)ax!mh3+ihQs%feHFvx`oPT5{P# zGM!5a>QWg_>UO7~Ym6n?x!I|0YThR6*oARDbf4B4-QUkEbJP0_iV12-ERpQo=0LBj zpBP;OGoKr^{rVSuyfri0NusIJ?gs!@%^{<&sRr!?->MQ|P>5Y3qBHt1o+bb*vqkZK z7Qttc_112yvNMH&rf$TD&XRhh2!1i!CA${IHD!e*6#OV8Rhk3M$oNuk1e~HX;W7Gq zvtfn#>aS~+N%z)TxBgWT^Y-~DHAiTB8XJ_c|K4*1a4|Vi>W2puK-bkB>qMu669#G= zz9{zYUkFuF&YRv9v(C5HxxI09jo+u;hD-A1&pIj`_6wb~XrI?*ol2SM&R+31d+39f zELW%K%CiD(Rg8mfCQlq|Cj|3=(K^A=^1-Gae?eQ?UrxXHN4A^9I9S98?E}jsRUZDn zYM)wUKN=<6B-y>-XPmFcR96+h)Hq*yv9?cE%Z9AD4=HdybX%gyu#gdFMVR0pl_vW% zAa862cz#M2%%;9BQZ&}&ns z66jjp2Cd-}Dn}7-RZJz{CoN8ofBoGv+a0hIXb|l+V1VIfyGC!Y<@+5nag&Ahopq%S zSr=LN%m1=$FcgoxyX0<|-_z6mSg)s}^>|v$?*6x)XD4j} zkgp1)A$E)}+lN8u6XdGeFKh&$e?+kQama^fyuX*Nn-$hiy5!oMu*nvsBQg62)};ky zJ(by%R6K>!GKu6yrHq3SE(wLwnym#b?yn6ZBMr*-68!jb`kKQN<~hpnCn}`rn}lAG z{%?c7<^x7H?T&Y4n{LR8(pe`VtNiAcCa=0@|6!LwlA0xA;fiI$0ucv*o9vrBQKyad z?X7-|C*|71nY+0Cj`>2iNZiJmuh? zIr`=(NA|M??p%?-!MF0-u4@W$k6f=_pg;*?-|a2wOak)Zw%BSGao_ z+V|Rd<6Tg1+M;V|7=-dzt2`UwQPaS4va@1iYMCykwx${hL{d*-r6h30Wa#rsThk&8 zZbO#JX=uvQw~rTi-kImL%-R%}?G!XErrGe@_T5i32^0-1^zZCo|94DwIHD@U(fW>~ zO1bH7-|B89(H_4yG?D1YJg(3*b@gOWj3mEn$+z)>dhh?i|A+-9-_#cF7tnIK^PKBs z=EPXO`gcce;!7KlTz8Xu5W!^M}-#*E>=e2Ga|J!6{*uN|SL zR2pISl)`KM%sWH0MmZI6F(+0xu6}NIh>|gI;s0tJ_+Zw;_})DcvPS~Y4{ngHo|ty0 zSXECSwEXSW@4BWb{y8^1L^>4-x;J%L`zjeYzyjO( zNkY;g6vvgB*WhmTN||3R$XJ($wSeE;B-kxu_MHpou@h?xo6XI3snH6d)BFiXyfS(7 zWHB2%0$Jvv<(g6NZTj}x^Ypv&Ne|x^?EL(E0FUNg=h#YCE{?tqZXvrJ1ZCR0L*1HqoexAQ-Kt}q5U`{!S>15b5FXO@4o2;f57Q5m6IxxQ-I+}OhR z->A1omcm|38a|cr@!d&OaxbSZIr05WuozIDXC-f@KWXf^f%3L5KD_cKABe}BplC?T z-4xUhe=uQAtg5uI!(XlzzEInX#Md5}*Ae4rpYtBcF=oNvw-C;?vJjUazBY}HDWv(#xr&cuM z?%qj*3_*?B^itC;Zxm>y_U+(hy!yuj-q8W&xVZT)s{xjMZWKMreCs4$JYO34xx>2_ z1MKMP`UQs$5p_Uam*P!W+O`AC;s4d%Y;{a=YwgI>%&D>If%6#$=%$E%@V)bwqSdt%zfmlnoU>;O!WVGJ`vl2;JDw8Z}qX$h4hEDt$O?5 zuswSxs+xZg(So}C&y_M$x02UdjRK~vjx(h_R16;tMk%wE=Siug?I~W95-KJ;wa8eV zfX6o3R4fOMY4Rqvz%lc7#OBtc?vtx!whE2$ug`Ijnn)IP?gS(y{nVrkhzwo=NTFvJ% z)1M<%rXu$Ok|G(u^-Ko(7VQDS#?cvGL3vsa6sf5uzE#JA^{*+of4$MZwY#VODpk_# z?xaCo_O^kGc!Vr1^h40A*+P#Ow&~>nUBFKkl~`{S{o{ zrb+>3Ed_XLk5F1=Ny>LM>dKl1ILEQHh)~9GJUB%;{~ho+8)pzH~gYi=t~?0 zEprx@dl-1=o;egT*4^+RNMsBQ9soB*XA73hO1tr>0aEW@tt$4T^W@ zzg$sf7Ly!$P5Q$%S4$$AU%pKJ=X;mtCr4}3K%Twa^hV~`U*+E*4#B{=1ToDc-^4Uq5GF3@eY1dtX1?8#; z#7GRHN1yB=r}(s*76fE8SI&MC!=JbUG}i zRzoM;jJQ>}%qT4=(pq^jx*8I0R8|C!g%`Ok#pBTMmwB7;%nhEveFNUC8v2g#z-%|f z3j>c6kd-}mcU;xH=w2DNY3+v#(Ml+PxlicwQmq*d7R~7gRIN^~QQ`o^Zi@{6l zRaK8~K1YgX7vR@rZ~gDKF_T8^*;NI_+SyM>L#<*VhcVHw9(z!I7q-Q=UnH;be}9&- zxI&z*ZqIN=#uJT_xK1s5cI_D{x1|eC9rqG&uFZL+KD{{3zusE3s|~o`nd-8^m+Cp= z5PUHDQ!86SUh;3^?<%vcw_q=9%Gib z9ShSDHX@m{^L+Y}s3aER8wF3D`r+sgImhs+gBg6h#<~4!3h5qGNP!o}>Ue~A*rvSn zX~uali8u|1?wMAZ#ZB!$4$%nYhe6sjyDYo>49g>ioIkAkL1fhI0{`-RzdoH}ZFYCj zJ0EGX>~$$^K#a`4AAK&89QsBR_0;DHBJ^X5w|wutIe5Pq?&9kx+^;+Q_+~0RxnXsG zHc&u}O6PIw_Y$kVYm94z3l9yQeSB_NZLTbe6K<_+M6_oxvrv{o%lT3{>+mwwq>ug~X7b^-SZDnf5{}HaOODZyhGC>HP z(t=Wzr!9y=Z=X3XtziQwFE?4>rZ+7*jE-)~%*g%)PXXc}?PN~^Mh1K=uq*S&BkPVd^T zYSLefXJYNSx5*%`Juxyfw{{aIXT`;@wsbw#`Rj7Wv@p-7Es`a2RQlwN z4{0O!LO@KrPVz1%gzP2R+xtd2l(Sm&11qOEIp}V~w<|0YU}pX$gQN4!os|6I?=~~y0>*^;<(&JwPbi9fJoCof{$M%WMzG#VDETVQ znzXo`;l&=37kl$CfAVb{0VqDC_*QBpf}S}#HDt)P+{U%Uc)Jod9m<`Zhkge>y3p0d zvjf(sxQY-A1z)IH{L0AI5Iet;UNqX;DZm}3!p8rEi{xz9lLE)Fe=Qn`%LHZbC-ox- zv>tb8&(bZXFHq_N-96I=LkIP8b;V$TahrubG%sZCE#8Qy5DV5traiw4^~m+KRqrYK z%g`)OY!epk!?L@nEHfPs+VAs&+L6PI9&42l9joiR1GTRk5;K^e8!fD&h_psh4y(XM zn`#+%jxY!yT*ShiaAut&8})ki|2C9xAg6-%s9%5oX|440%d#jj6-@)qtG_?`*ccOp zezMCk+8=hip#&tGY=P9z6d9Lq|50t7j`+UO?)GHNB=>#(Mx~^luDf7FvkGxvq=81Z z|F@}*Q(u?#Ki{NaZD|L0qpuvTQNo}X{a?%9}H&}?@7Iaoq=Wh4$kgI14Wkhi~eJu*_}H4I9)`RgRHOUNUyLQRd9 zX&Q!XOo&7WS5a|7bpEz-9d<%{@VQ1AHsQhaZ-~(Vm(@JjwtJX`$B80y!Lk+$=MFX7 zZ9h0F?cyRMH*}iqR4wi=*U7?bGuF)QsmV&mWw5G=x|&*}MEeQ|`PxFb+@ma=HIZdB z+{^&0C7@;gZ#$`~Ooa#qByH`phf&5kS*jQxJN4Nsk2AUj?}cC`e=-OqFTl>qoMyI} zLza;62@9NrH3a%}%#B~kxX@A83sAjRebx}{5f)M6Lb?4Cf1$;tv@(p4o3aw?!mXm| zxO3&=H5XY1;`Ju3jJ35&j9e+v$+psIfm+hNekp!oXMHCIyBPM-h)K@H;1UfkPgsPl zx-ZK|y<--Ru6p(DWq)~Fdl*)C+i=lv2p5%_qeT;;{`cvrF#ffS( zj}RHUzt<{~byz&==h)L zDA^#HwW4s{ zNdhbTo3o~7p;_j@v;8#eRffi!`g}322pPXy4R=JrqJB=TX~F-_;B%oH7NIph@2hTE zfd=tQ(4oexc5c%lL3*^sS#$N?vHU427)&fec}ArFx|ZWkAi5WMeX++f;)K4~6Yp;p zIfOOWm=kPmN%|#|?<=-zu!I~d_K1geVGMk>>46+NPQGAfB<9+7c}pQAI{m#-T7lk; z2Lwe}F?-~ZzpsJBimHIQ@x44lBj6G>s4{PrJgo9V4JzSFnlSgO=}}HQf&d;a`xzr_ z!I@c(68E?J3Lp9x(!K>dy6lv8b*}ZPW)<*tTT{|C67A!m zWu47Fs;|v2-!2H9=DnBiUNw3>L3`3gv0J0o$}ycfW;4I2BQc(ci?=N97b$3cWz`-= zNG!5Tid!i4z^$|=*5`W?VjkQn8CQl>ke8IIs0C4T zhSj07YV(%skVmz3L88UMgU7NDk!tQ$elTCR^=9(CO)>0fYBrYjuG>D2bT8;{5E+Ry9~i;Agz}8J=z3 zyBoIuDRur*vQY@Mp_Ag5cUXZO?lEJPirYs`~DtOUXIXfzRO zEorK-)0b6tPzn_KU{-aT-qJ1HdH%cTp&`UJw?wz{A~%%JJMW-WT&Og=>?umXxY6r# zc43BO+v-)VUh+sVdic(<)~mvO4SSM==VNO=DF<@L6b3tf%1&<6DX~AHXhKj28PtBX zx{8@=azER{FO?6OP{;H3(SuEoeVA^(FKgShxu5jmV4K%%P+TrI&|psPG3U5c^ziOi zoQo?=z_7(4m!tplvb87_alH|fd`9cm+O&QFT%f8*0bwp|u$=Pb zsTS}k4fDItT)-xGWj-Xixuzg%F52_tL*FWt8uQ#j6}r3oHRH0^bNuSusfH6Sm(G%i ze_6zA7FXo)dm+aXbiar63QcW{)8l84cmNpf`8*QK4Qi)$t#@3qY|kRRq33L|=6Irm z&%(*bF7?()i9Yn7Hoy!Fhy}VEn;KgW`%sSU$TVk@E9*ssD`DwMD!~?wVGP=L9SYC zlK#2RypB|3{9uH6sOw@^R^vdt1kWj2e^t~NdSu<9iJ6pGU0ph)Z@nr+yXE)a5QWUQ z2ZEJy3M`&E|54NLDm9Fmz2b9JS!+3(I+E)uaU2{cnoA=xMbFMVnOBIdJA1E(Gy;}D;)DfuaEhJ$B#rpMNuN*}TkOn$5M=azPfu zh7aCUqI=z}Ngw68$nX;*%$Yo_=%bypx6zvPikB7kN#~kyW}4?!zpqbwd@%r;@BW%) zns9%Fg2<5M#O}ENS#lQ`P;yl_D4r<83;8bWoc||5$tQIvWU;+zEg7gFc9fozuiEtt zIk)Ze>X~7&-sm~F+LQE5oV8$~8(8ymEl77%fD_*NLcFTEjDUR+U+)W`3P&k*Ieo4T zQ{GY%#@a;~P;`t=sbfn&$dEn^W-8`+0gLixAX_MPHPQ>y-)7jR52m>hSHMdKN$m~< z&`qSfHZMyUmg$VJ$1^nAz6$*?Yimh&8Gh|gc8g7GhIv~2ohM`pXJ2K7d{7ZoN28 zS22t>uU0|R(o*MB$lkgopY!!2asbS|#zBrRyGQEy+}tL?-3^%MH!qO=HepWIrNGf) zuZXNVpqMp6_;~!0+Dl^Ev+CwafTB#yV`0CG^ctXJK+Fm3C;_dq?tHN*n`7eD8AD6fbqhfW@`sVk!;OCKKuyY(uC8} z)6<<_X>Chlde3)>jE5ii=f&lW47YU`X5|^t%#Hn2W5Gl&Ocg z%d6y;@r(>zV>++JTi#Xge^U#)3_Z&w8SK|0)7p9nah#a%#dCyX>Y1zjXClFq8fci@ zEx#2r>6BdxPZ4IsSL^3U#g80mP-bk)t2VPZ!*RyZ#*Lz(q?Rd14<81EH^@VGt3 zjhC2m1^KqQ$f1<+EWj-h#dmkMWLiS*)RmGRxJDLvBZW2(p;V@#4i`g*OXo_EVtg%` zws9FALf-2PIa;wapKSU^Hbr|L7Jhvlttsy-w z4{$TtqvIkZ-O@rs112X9!vloHTg=k^;ve(SCk;wrGA8OONcq&dEy~|HS-c%5LDbCo8=5E! z2mx3s{BDu%X&3fjZPQu10Qcg7l)761-6p}ef@zmnn(~Vm47}oLo%9DH86BJ7(uzUlPVn}>$PDMu=AxF9=RdE3Tv~sU9+v0+|&MSWzG|p zjB{8LIjarG)0;!i1tK9d5z~;(U%kcSx*DB zVl{0Sl#Hc1pu3i0WO>_h@&)dv!^O9r$|rS+g%}P*NJq$O!n4}_bp*9JNoqcF0g~lv zZG5e#xl)av$Iz%Sp}K@`K9EUnu9nQty0li@7p2~o3E8K6Vq$I(F@9Nwv%b@$SL;*d zICQ+$1|Dp|m)!}i8!oZxPIgLjR37}a3j<(JHKp#?2#dcRg;&yXr99Po)|zDu@I-a1 zdNORcr@+2?^qel@*A~gj!Av64w%8giYFJi?rObRKgJCW|t@^DImW2h^&qX|U-OM$b z;eO%rI`-D#Fuw4;!yG!BH?cwAtuuTl88DAY=S&E*=W%LRAwzvWIb0V9fzFo=M0D&% z&NC(KiE@U?`4wUW&7;aXektbX%tZQtVOmI1UWX|V$L7a|*fiGR>)$6-ak4@sf33*d zNg<`Qni$D^<|t`%lCQmLT}!T#6ecsP9ZJO-J~w}VQO(DGw{_d!)*kfwp88WdO`o_5 zF-Y<@M<6OVN(h*FowsAc&W>;?Qv%1j>f%rfGS|AcWFc}u;nV?$^jY$|bw?|pQuUr9 z%aZwEqzXlolsn_-augIq$TiNNaMYc%9T74zWywSURGD&(i`)%@T`MfEnJ_U8Kx0Ev zs&78$1An{ojyTf)y1Q3&j!#(s9p`s2&a%(8mJB3UaPg(~rxL4?_bC^ltw-TV__0J2 zK$B~K76`^9&M_*EQNfQUL- zD$`o6*xJSXdsuUn-CRdM&IYA&B)p<|pzNY6s#`%|;=~c6w1S;jh=D2g-3XXO6s(cT zPXo{WY>iX^%p0*Kgm=b1QWqFMbSBu6TS`+Oi!es{=D^dtaUD z2Gcx@mPp>hGnL->LTPDXiaNSMb7$GlUEoKSU(UzN!Mo2?E{z);`IMaH0#+L@T)tQ{ z7X2Zx!08+yHG5P7bXfyL)-+OV+R3`SF(~&(XDO567aq>uT(imXT_SL_2G49jgcw zPZ)jG=);mV6V?y5is-%?@Rk7!uWl*(W$n)Tbh`z>-&~`K9FS0&2X-@6eUrz5CBT-2 zam_I~VJ9s4gQl8?nH2Tzq;r~Kb1dO>CR9AzjH@AwnYMyTVBAgl8X>7ka$K>I=gKg| zHj+yw&HYfM9U03goLpYxkk*#uoxP-5T?c|r3x5q8>gShYk^hGwrC49YepNKXD><00 zT)gFk{x{o8-OBKSPyj~sGzBMBu4X4igM8~hjwdlDao{Kgb2S=I9ym12{*sG%6zcAs zDTzuLqLiCOwO;@$_O~h_X!)%X{dZ<2O>BmZ#9?u2xdmsV2kBM!Z?74{gxQ$ws7jtAQo`i|=hK9%% zQ`)l2V5dZ8IxM5I5{!Un2fuhFsvXl_UX6xePEU7;)z_a2z%L97$P+XGc(AE(kqad# zM7Fo_!S@IKg{~78ZG|I(^cMiaZA}p5S-=p4pp(n@rg&T({Fn!lEY})S|H%PIRQPKD zq*CGQ+nVN@@t&UdeWQUpnu4KE)v4yM4I%D;a5ZC2<*H1^Fc~GHC#}j_F;E>j*9KjEe2&)X_27ehOS02;kml2E>y|9O zmrvyMQkItFV-S$ccl}2Vlw9;oGXhL1(Xm5@9@H~Tg88#=Ivd(){-5=s^E9P@- zJo~;{zvh%Tr@^%C@vX7KT9XT)cvqqvvRTi1mn2W+)ek4$-*7F&f{clJevGNw_Hp}3 znm#-n8wc_vtR?vruf|7gjzoSesxQo#jzB$d-V>Dwc5HlFAhrR$lgTLyPzIW|r#o7a zzqA_*|6#~#?_3{P!&2Yw&ie)x-naJCxId)fuWkmpg_$P3ulR7}O3Ie)3muWQ3=!@< z;n=45Pev^(LwE7&oo8xk+*v*ii*?nZauK1gU+)1(Ph1DP71Gez6eEiBX-f+9-ObtP zw-{=gf7;q((Wt?sTjOW=-$wCv5D0zyByVx`Geotc^oxB>TU(t%v;6^R6ajabs#dHF zJfhw{Xb?9?CZD2?II8e~DdD!rj;eX05TnS>bJbc0_JJG&M-Ukk)4=c4fu)Q*+S*;= z@>}C?*LULX#>vMg38a==#`^0g$}ODPbBBeyu7A%KeLQ*QHyhp0Yc4XYj1EyQ)gA#4 z8LIXJ4KnCKQSoS5_(=onEJ$brOgV}F7g|$$<;y+g4wq&sT_xJjq+JQR=;hd=Y9{oJ zb8102CG?JT6q$!f&ZpIw?9Wv zDo1E0+&Mk0dV7U2nJmK2lrhOyglldpTCp6C<{hO`*D7Nx`=kP6&ynhQ#ob-Tr&mA#$D`*4qfv*qm~vUw$hPYwitRs ztT#NsH6^b-_Zft_rZw1@8AE_BO}M$4D3CI{;$Ff#v0Fi$;YLdIL@&XkhtF~5yBl>J z|2$m-!mBX`A=m@~W{2gVA}dCIxdJy|4sFzAR6So@o5%Ggv_q8Ye#5~&1rQL|RP zjacZf;u-uJPmlA^?dOki@D*#{DaUy_9>M)U)t*8%$Vy+U_%zGhh4qZ|Y0aF%aVC3+ zw0VSU;9U0ikNiN`928sb#Nn9a@p5hL#uObL^}jd)1tVGdjqhLAuXQs+y`G-oHZjjg zYA4K_io9eBn4&T6Lm_$s*50I@n+uZ*u&YIVG9|}S?z}7iktghvTh6$xeKVEy9ouP_ z8z!5>hoA_g6ka{|F1y1>%J_zg4xOy&0GLGxc0z z$Y~PpeQ58l9kw?Ro3g@1sI+2H;gO&1v$TrJmd|p7-KT+8qjjq~AO;9g{k0ppZ@92$ zA5`#wsTCuvS(54AU}>RDjjt&F@hhj@>UJTSrLCWIe68`>5T2l?Ec`q@zVpC|3z%j$ z-MjlD|2X=CbnL%l;vmNC^(#TwbZn-RRIX1&er+03e(_r~Iy=sm_42tHtl|P6vg4rN z06L|lY3Ej6=@b_Qutlv*nO?=8jBCZmB`%^lE<3IF^C~#mR%oFK=$<)7K&guFL0nwB za=bm-8`|)0$G?CB+2;6o3q@~&=knOs_RPz^Zgs2UUD@r%FI2G)<|@7Y4wa2>G>;&SGU3IWJJe?=l8SN z=9+^RAv3jzI0bp7YzXxkjm$byY19bu3t%nUH)) zhwv;H_q`fn(PuA)Wa?6)TMMLn)N}6%W@m-)y3ZS-!%$(@7Bq(1r^G}QspwhoC2Yjs zicN*ql1q)I@&t?Q`R#sQi{O3rza;Gyd*6;27iA2M62EyW7b2l|tc^#3d$$7?tTWgT z+cpv~x$yqXCyk?!m?8Nkk#?-*5m<<|ac1{Eg1=MxGlj z`$ajLn!vVHt0{OvDAqk_ypl_?XU^QJQkM`GScX_9pu^dt=QKGxhcrM@xgyhGXr;jO zmo|CEPPv)(CbNGQnt2=`X*jrKNfb>~x|!Y77u`pjayv@poT5btmDp2SghXn?q6EwU z_&Mk=TbWK-Y2a}{5>r3!O|K~n<2GcXWGyx(p0;+WZ)(DWDcnRsTCU#|4`$l?-UU#V zm-Di3<({wU@_2{s)5{2JJwH%LSdvVvdp9U@QXmZ@KZizNs%74*Z>bHPJZM;)XDZCg zL9&Ft&u{r&oNxJe98S5*lpLp&TT?)e6b@KZs#yFGu-Q^Q6-fyD<>7dwK`ce8Ibi_{ z>$LVjM4^Kapy(s%nT`RmbVO*WT2D!#P#LQx6BU5`X8H{>EY%WaL>d{QX5|g z#Yo?kV$Is7(z+}2QM|1qp}C;2u#n)KI#o(M8d zfpA=SiT$?h^LD&!=9xs<<7y*=&9ONZK5~glr?>-vJ!J1p}(H3>*15*I`%1vx4hCMcCCsj-r^6Q$CeC z);t$&=32qR%HmcY`qiwWuOn7w)=nE>QEU-q;YFRC!u5J?xU!O-(!gS883D~kAe<*% z(mLm3aPC3~rC_IUrgTuDOSx@ZP+l5N_4erufvnb%;R4B4(?{Hh?mpq(YR(Cdwbr2C zOhnY-qsK4+TR2(1?*`GH5k zUeT=t(R3e_&!gPCoJUz3zTP&A2hVgD_wuFzr-<3$!3+ko+n!R>PX+4r*%wq>6eH}c z)g7%U<=_bdGCZLM6D23c6oJF4fkBiPfM=0Eag2j#juq{4M+D*^=SATWV=uVjsHh(W zP})BtocBP^j8wSnHEMvsatoY9Tm{zzyW0UJv5Z^0H3IHg>$y}KV9&Mfm1549CEJv{ zq}{${kez+OL=$vob3zB^iBb{Y^}Fn+V+a#RKWgwfXccC2^AyfT#ZgQCja@fS)T8Ym zWY?)vg16GY%L1sK8IMkxTKBe}9nuxJIA@2bqK($hdTx2uFUEkXU~md&Xt3O3IT=h6 z42N4OPMYKb*;XDP7p00F@{ao4&sP(OdmV#=Q_>xew>uB{D-OmjAo#8gLHe7&#V5A; z)c9Il{?uMMGn)(tETo=EKiPK%BNyY&uFD4t|FKPlxYOe2xubvbOyAc@|irV6`+ z9CJs}r$eVtG$pIudCdwJ_pwa^ooTPJd;2#KafF|hiyLtE|>p&OsV z)dUO#o^Lx?oDCTsZc8`X6P*8aS)=jWQNyZL=^`rB-95#14!FqF(`o+`@| zTgxvei_3IgTsG~D#jc(vd4Ky+y%NwPoRKMa?n!0p6GZRIWr^@&v3FtBfMxEnf;}A6 z3sh|mrs~-}s5mP#9AS7y=hD+s{XF*;RT{3^hGcQUoO;{eI_xR^Nr3}esQifWmEULL zu(y`0?^x!#?es8*D_u@i+6Xd24uE>eYe-)X!+Dh5Qh&bmMg9o%J&X$xZ@;a)9Pi*r z2CW$s7!;;vuZtYvt9HxSxYWId0%vjbqFZV``c5)~zdtWHJV#%R+M>Mwi`t1UrqbGVRv$4N{60X$Tor3?@T+ztg$zHMuK;^Qd ziG#enEnV!Bp~iulMM0xFRP#WPmR|MbFH|#6#` zOqfld2j3j(avlyj>2@~uSDvS!Y>yC_lh^x}|MJPF?iy9L@7>>ZWctyQU~3~7-x8F{ z-8N@RhvOMtM?o%RV+TwE9&-mu70wr0MbS12CRT&BCk&ZrsgO$(BY@Pg2q`>dGId(6 zW$|@FjXBTu*-&rQNgC~=W$ch8_{dx||LBD*6a1G}A`Co1P=k1x+jA!6rF+U$v0oez z7**%UO@~?$n%*>J79cEoB(Hu>Sr#4>nz{l6?`&Fmz;=p|_x9aqg8b?W7d@_Bo0s~N zL|vHWKAqRwIM>lmNsOJl=)O2~A!kFMn@_FR2s)oo0g~m1Te&2qH>~R+fvxcws1k?& zjyWi=UG`CbDK(e`LB(aa;*yf%^iyc;Aqd+ooN(Y6S&jN>ndw`hH+%&Erwgw zBoEq&u)4cQdTL4zFI1@BbpBTtt3)AKS8@+ww(j{>`}S{M>N# zyp3*lIkCu-x0os0#F?-+5$742&yras{rGqz?6`mH{RY;Z0@y9`V>u-$@DQI$j;=a| zi_c6zEU(9Cj2-W!Ym7+xVqXeoX&%V&I&4t+>=}0*;28x;D~qRXN;Gh;!Uc&PYXss# zA!;sw5Eetcv{>krh%4Bzw4d>vF!psMOA;jWp6j02#QxfWIS7bNiv*ClMY+YI^!!!u zb7VFD=xo+6q>0xTY1}dL=k=91gdyeZ2@T%E>geTA^>c6WL!kHq92|#u+E^_?2yI8RiWFR|;HuSj`G!^!Dnv+Ce-WU3+aFOw zTLf%vu{S>C?I${#xGe>h?ZZZ!u^Wb>sp3muY%hkBpZo76bFtu_)mn~vv3 z{C6xyWX@qKOT|o_7LpOLv@gC>iX7u<0o-g^CQ94TVPZ0iCr-RgI#O@kysaAGHWU`@ zfIXo*A?OXMm3$gIo|lpAG_*hr`H6Y5h8w?ROnKmr*>!jCJo*?zKsfYmpYu;6nPMs( z<32f|Bw+=lx1(1fkPTY)<+3I@I9ASls_s{-=&JkFZTJ&3Q|_u&r3YC5SgzZTtSdhs z@FD-!*XV6YB}E!=nC;G_xoyT)Tl#$cAiJV#zj$zKHGwAeVnYZf;kYMDxW!Z&*#IfJ z+5lr1Jnko4(09nolt<4~haU^`r^R+YmNxd0c}fn&GEPreoDzb>z|K|eNeCFuCTagu z>Kjn#Cw4VIc<2<~x3iyY;e^GD`rZpYt<7r4donQUD7LE7d)CWvE8%3bLwwTipRu>hd8`N?Pv6Ig-0xH2x~f z>4>xI?_4)WsrWgZ5!#h|Txo9a1h7m!YO}{!v3d`DT@rm}i!z*7lIC&qWQ(3NFbP@v z6+Pi0NWRCLWIy+1E^v_Jr_ek9xTel?^t`qDm*&xL(m#ZiY%otYj zd@?=d=Zwygr1FwL5WcM=%5$f^HsthiUZ!KK&Ps+)} zwS8*&XJ&*+I)?oQQi!Tp*_B3(j%EC0;;d$Ow?bx3nJQV zAgT!sy7QkdD8v9t?rEEwtDihk8*pKfDeXMy#CE+o02a1B6K;KFy}No)&j2P~bKrN7 zA#f9Lr=}WHb^O$$Ha)p2XDkGeK!Uc-YojSaXWh9h0ad@cvxurI521`>ht_~ z>#j9h30UhIv~Fs25PIPn_u2K0mvS%Pyczpq69>4Hz6CYwJ^|~-KDu_@Gy2DywWw0( z@)MOIash|EXU-~w-tIj9L*Y~?v`>yNXE9AVE3dfiRP@&QaA^M|eo{j?FiOg2G6%O> zmRwg)_-B1>dHBUpB$0AZ_M$8%tTTFUuJ!))FA8Xt`fci#CP*grQycSl_L=+oKR3S) zQZ~d_CtL2_iyGLR?F#tw;8nzz0{8|>@ok@G-8`NCT7wwrdf32Oa)l{GZjVq8nV1$2 zMhI;t_qEk4ZaA(^c=}tob}94CL8gmC_v67;%o%4TDLWo~=7kZg&&Bf=hTq@ew?CAM zqjih$1gO;UlAB_i{TiA7tYPs^AY_5H{Q=m>{33$55cjIGle$es^s8mGLhPD2?TuCI z1j3iduj5g!F7=+TJX&_%Exn$7aq>o%)Fi2)()B+q8M1`Djma`AoBj7n&ECtS z1N_fo4pgcW4u7vt;?`E)@GLejbey6aPmiqcaYWYC$1N97MwV z@=WB8xD(1DEsg!W$vpYb7$9HgZAkWANviOQZ-{&;b9)>9yuwkFl2x2n<*jk0$D|o5z&~EY7Q)*X* z2)(z5-T-Y#;#e48;Dml$_iTxZ$F1)K0skJaoq6wM9X=hurA` zpL_g^?!jcawK}w*h2kObxmBUD=$>g%+HtI=uiG#gI?X?vY~;LVWca|u0Ji@a;>0&@ z?&QN7-0cH#^=TUp3^VM9pLOQ&H?;x+ZL!L53>DmfrKR;uCcBb^1H<-%=2q0s)9oL| zb2VFM)IDo1=h}rwF2{Ub+@*e1suT|TMdv~W|x zq-w?`+qT)eceE`}ypIc4i^KtK=)KScM&-G3Iyu|jl_en170K$K+g{867j~C44B2G? zlKHGtY~O*P#e|!mR8DWr-g22R$VlB@U3zI5!l#n#egE^eEbMe6d^ZW`F?3MD&--+S zp~IWteRz%ZBSOag~ZgHu5ut_WAOszfkFAZMOw}}kJ zR!`fP@ATUegLFn9%2$Gr6kq+EjEYimYxN-KYS$slSH7(MjAm-=s|95EcuQ5Nm|CsAZ_7&f7XpO;{46WMOf2F$280eNF+vGF%v4* zL7(WkkS}OD3{1N+=wR+2ttV6Qx7>dUO>ya*e+x*wadrEmDa#eM$H)JYFzy{-2fo65 zGAeD>P}4`ND6MjVMF#Q0vGn!?bEA`ZL6wB|Im~y7B^tm9qBP}IBSB?2T{}Pv^_3 zpRqePx{ne*dFn4aCC=`e=Ra|cfJq~v0A&%&Btf=htbY!=PL|8`yFgCxo)91p_3vm+ zDtEGZGPhmtyriQF@f8V9&vBTx4s5Q8*FoAZ>lrr-l_Q<+x$j~*TzWNr1?(`oec7yf z1|bHm*cY%e`HPXe`l?B}>=_~sqauBt{peBOxn`zQo|&H7>)aO0O0tGf$hD!k01>m{ zFlfF9FHQDtgS7Wa7^YS$ht!&lN!mIVqVH&22ec|zuJ+gLe^22zyEOfB z&l1`%5_i`sXYS4L0PESd&vN1Ml*#5$R<6JZMxK0E(niTZbACry#6d|Sbx9WC7P;jE z&FodLIh%b^+ob26EiuHC{;F8V5nim1iNV3Ay?N;Vu6t1mNN_P24OgBD3=hpN)iWO| z*l(VUv5tlXa02Svg`cDz`_Z{yx4+^8JT>KO~z>&I(` zarx$Zy>Wb~j^0f>?uhLb(U2XIET_a>XqNw0nXbKlQ9Bhd|`;@s;Y+x^39kogB3bDlhwj{6Xeu z1(3&P?4;W+mHOG`ON?->O}_5?ZLz+A6pbN z0w@{GQRW1>1RUwQI)3F|b)(Fo8eKOh-8_vi5zijD!}q{Vl9sh`LJvM}bMrMwn?rpf zmwJ8M6Fl5_1>f8y*_KEIVOEH;1d z_W_wmAW=iLSVc(Wy5k__{F~!qwn8!nUus$f-wLt;c6AMAQ6ZAXt{15eDsuVGqAoHP z1v+gg7v)u#?D9)_&JMz^4uWA=<-ut!BdTiwWpe^2kq$40=~~~@yYA^+rMRa%JULr1 zF|p7X$kY;-Co{E4&DNlby2YMbdsjKH@}R(uSYp{|1=N&=SL!sgHif6ko(9ORMG`wP zXNohkQ0wdaD|#D=P;WI0DRQ^oM%t2QTmC8EDb`uS7FW1oN>13E5Zgy^4mfEOb7_9T zXdV2<8d93ZO9{)40Nmv%UxdR_t1`8-Pbg08@OvG)Qhw>^ocr(C)d)3$Am6zLk&l!t zNW?8d9TK28ra2-hYoIOlUBy12&g{xvPo5}n&3G1_=nXjfaWe5(4#L5{j-+S}wygvP zYK%^mO`^K&i(mYy*=*)js=X%L9Pi<3phTR!yv{tO-FW+I9_xFR+D+=2LrU@o@bK`< zyp_xMd!M~ZdQ;=QxqZo({TqcZix9_sw8#1E0qz2@9=nI{*WH)XO{oz$nnzt-1%t4w ziS;n|yr8BbO+Ot23&Awj_Itw;y8rcM_!d}r8HEeNl-F=;@h4=7m)>dM_l-nPdnJ1Z z;4eAn`hkZVJIHs7%mj)9x^t@G4xq^_pu~e2t14rMK*mJI+LPMrvGPRFB+5vhc%P&! zC$g>Vh6-mg7d_^khCl}LxnQd~)cuho>>>my$`79qJ#i)t_$Jdh>Gj|R^7Vk-y2r;t zIdT9Tm#0$O>85$WeEx23qL#D$#lihX?u0zpaydRR=NHLs=+vq++r7W9f-IT8Bl#=X zb8$LGvmw|v{d40H7=H;xSvvpjk;--lph$UvDV3VS9|EcIDHe^uTBxiMRQYow8hc(1 za{Wmi4%7cRtvi(iFQmfsF;X*0N{X&!9hG(kQVrPqWpshp%@qt_8P;AeC*FWjy9lz_ zs*GOz5%_Do>c{;MT&G=mkUr*#_qn2b4%@iS69?Odc`KdvEh*eykt=PH`V-Ir&Jbp%b!;-gGtwokq z!%KGlHV*!(5Mg%MQ+%&$f_pmBhv=>1ge(@~z&~RiurNuL5{SqTO-X`P)y)zQSkM|o z`jJe#&-05}JXJI({8tCvbNk9K&1dUQVCT0Q`6 zw%FWE`QAN2DzQ=Lc;FKlfV*-;oK)Vpj2+)YHDK1s(w7}U`J*MRC#F>T3*6dvTq@fy zil&GGGlr5^?v$7SuYz#bFA)vjnp54DBY)KoQYF?kBZQ*AxsvCCDGQb% ziW@_BS`FMGSrE+A&>w|pQRwW?fbwaTyDiO~jH~;bQ^L^Ip6B*R9H14%V@2Qg@qORn zYa~^a+=Z{bWcV56g{R}^<5E3*GM!`MykZwDW%Cwu@1`$-vWFDDj~F{WT)|WJ^9Z9T>yB%!1g6^X&I-tG_6e&}eG1;Je0;t#-vZNbrmo`D`$G>eVVG zG`&89n>N;-I5_A4MU^T+=EQ!68?05y421f|FbldA6}T;5+>CXdzU}Sutt+*iTAxhy zP#(?&Kw_$W4!^2YhUFC|3wV6nO4fHv}P z?nCcurCrdeqNBw+X+aP+VcD9z=;bNlsAER+BIqV8EPmoIsAy&j9dOwk)OsL za;DBmvv$=NE8ySo+aLHY#XhduF za>NfR`RDt&5kXOb>)lo9pFSl93}KYyd?^mL-jX`y$E?qxgL-}`Sa#*u@PFv_{4SsT zt0x}w?%ca!#3c&OU6E8gRbsr8(C8#ydcBf@A`}}rlc0B^PdLjxHk{pMt3z+50-!_v z$<6~g3fkG^BCM_dLJq#IWi?7vh*Xg7UOSCbJhF()b$hae z7LXC)M3rCGU=Uz>q64NwYai3u5*4%&!f&pqL!B2_3lyTfsKPH3($Z^mcxo&~ZaxQ< zSO1fKLvfo_Ns_XV*!cB`DFv=~G?$DvKb7?2cW3Uxb4BY2$F5ejc^YX!;3#dJ1QTaj zHm@zEr}te{GgKQ=e|fB)i`^Vd&zOTy5<(ceB^E%}D4c!vtc{TOy^H2O9bcPXf~T4p$!Qw2N>;0j3UU%7U%_{gqfb5curlB2($MmDIvjs=0+IGIPIrv7;J%?VAU%&f) z7L|1ewbl6^nsw$E|7lxsQSPkT{UUKi`4L}O5+d8=XP3~osDDeV2Cm_n-#k*!NKHJ* z2v7K`cIlp)G@Nx&;0=lGb1V5b`2%!<{_48oj2=y5Vrt~5RcM!&9OsMRZQwWeSd}^6 z1F{qMdW-lg);5#$$%NmA7t~F;n@$t=DwSvk6zdpj*4mPRcQ-&&G-I(&NDZ6^Y%lDf zAu%mqQ7*(09g3_(RlR)?t!!3Rtw3S8;#Sx>uKyJ8C${^hkS>>=o^ldB!W0dJ@nxJP zdL`9;?`a54wx<{&dYX<6iJz(etgZhwh0eR^_`#asy!Bz!#lyMI=+|2a`qXmSIW2mI z>|;sjH&g1%I^+1P{tKz?t-Y@#-|UBdVgu_+gy{s`9lBdc!w`tPG`}4Y7#_Eiys$a5 z3s;^Ix%pxj1;s# zBcdh|WuGbKl3I%W@V_BL@k{Ij&ezn{8G5u$!1dmdRq#l%cnq?)QM}1 zi>$`l8}iq%n-I)|>AI$*v0ActLVJzo1Sx=FWK7&J^Asj}l`FROM-ZHdGy~nyKiN_8 z^lR;gO$GMLSA5nF?cPNHM^>O}oBQvTBBH!}P&?tg>n|XFFN=(dB z0_riP+0gjW_-3-axwk#hk=Sur)zpUizm%ExeW}?0v@@A~3Tfx~w4v!NGd#9B1 ze{z3hWH+d^OvDWjTJ;+Hb|uR1uD?jTet8oY^zbjW3izs=35c;0q+rRdNcedDf5+6_ zJ#MgdUhm|F3k=&ssk56EGe2np{NDciZW#uBDLT7JdCmAFXcIbypvPtFcEW>-_fl(_ z5$+PGt9I&}dXe(vZ9llO5t&g0)Lu59tvM*w;<3Iyq4vvL@=(XzR#yWY7DkeYI`GvI zS*LPUl$DR1))H$~?CZLH-Yij^!kP#L7!IaKqD$FBzFMzpQkBspXSbW)d&C2LzVFZuX;r;{lK!0AQ+Mg+ zP^;Y8x4)G~NoDiy9~OG#J|6*NHi*3(?%jOHJ91EJ&awIK2I>5Yv_%ftCHK=`!MDG! zS1zaSpnn4HhpDU|`hL>M)|w*pPrUs=C&t=Zb8M$t>ZE^V)WemDL%awjL}M$S2p$2sTydA*)b zAw5Muk(2cpyF~{=*DZ)+KHw5E^9@7Ie5S04R`~a6MAeSEq4N#Xn^=)rW1{ufe!Ob6 zucoy8s&sT-a*uMr-+Au1A`cQb-oAGmL8zb}N%wZ|Ev{6a`h0GZkua00KzkI+4z6Ci zw9XCh0HkY5XWudW+=Y>K95h z&usj+?#}~+8uS}~KBKX|8|+!K{e{LNxBg~|Yw$6Vn;ApAbI|!6<07kj@6Mwe0%XN* zg!(91)X>rzVArLBXX#hPW^Gxma?F>Yo)EX|F&cF6mx53)VLxE6;%>`?tld2_bMGEM(< zC*`+W;MG4>=|UqW1;4!BzZd+_v9b{jFTDY@%UX+l|&8r*PCxY)DiaFB(cRYmS?0>Cue^*1Lvg3#(S}U$fnXy>I%ukz=X7%!EzXL(eROP~)NC4}q8ZGZyGW zECcLHil=dSMqK?{DYST~io;;@gK=N3`-{Cizkw8K>4#9={p=en2uovQI zG{(Y4FvwJqR;{iRK*ONyVcMVwLX&@K(W-WO_;-ivxPyk_eu_-3fEN#?bqL3eWq39+ z4s;IblPUDf8o|Dx^vSbDT3`+p*^al^vSsMP7OB$`Uz}H5X3#|QyEjwvH|M8*WyzQQ zFU>K{a$c1hr?oO;tUNA@Ph)cV8KEu@$$hR?W56-!Y3-uwGLb?rjn%GWCOh(EvmOGs zR~pKc!0L-n<9N?Sa;_SAaY-6{5or8e>Wa7*H)kWN6%G;zDe5mQDw_m%Sie3As4G?B z40Av1#vtJh2zYwYz4An9S_QD^+_v9)xjUeHsU)x+ZXDs-p*rrDL1oxSoAv=WT>@Q93>OsNo!HBBA!KU;`OaNBaO3~nm~ z>trbBhcRp`RSDY)KvwTp3q-0*a^n(!GU(#tC`70XZukPj6Gtkw2 zD%TkBXj3YCRJ>IbUyoo0Pzhf5Jir*R9@%J^>fZN#ls9ngkLlv7zkd+_aHjN7DkkC` zgh`hPxEfg}xe6K|z1DUVOE0Lje)hYj4yCPX2&iQ24}ww8O`E! z(T%LP`!@f@zvQ6=>>DF1zvAQ$jBRw>$012qB#Ly4J2m#buu~nasZU2o2vFvop~lV24MO#FmYArM&*AD{(EZhRi{nnk0#TXDJ{Jn zf{(J_X_bx3c(Lgno|=2^Ci+!WYw>W~7>?~+MY6}!3hSu%J#)6VQwy;<_@Y;v%LI)f z$t0UfRX~iiD%1GjaX}&8iDui!ons2$+V*p-UHNg3J#$@-P`;-XH(!hKSetyJW>x*3 zF%kiM#1V1=1)MbA#s@}8$Q{3e7MHmcPX2ROY3H3Xcwz8Y$R2Dv|KlILk@#xe<~c?r zIzn6XlBgHBH{OtV-~EG|PmR;~&C+tmm7)3L3D@V(*^4Q`j6jX-XGZSROv^?ZHV9bM zPI4iPcskw_f9*s}{)$%r@Oy6e*k@v4zO%}=w>pPqv?CL;t+d_IGZp+ZL@}Y}f=bhn z!m2ro7&<%q}uui7Mi+c1hW=}zxF z=iXaYO2c{qti!!D2LF*4z#*%pD>XFVsWZ1DbYA-@A__NuN#I_P_l83aRiQvU=ISKh z*f~gIeZL8Iu`B1jq$uAfsaE{BBO*y$Dp8+koOpFCh=+&GqW+Z#;{$3w|9Nl)*u%_V z#?!3E)BmXw3Sq~|mr|~5c$S#&?$wvExCIcLWH z?iY01Su1yCi{jKF!p3Pbo6o6=^v=Q{#v-a@3RGL89#i4%-Kk%YFD6s{H5t9a+VEnH^fOI=`SNIl!1GhVUOO4O;!AO+ z8#8fIl^F(lG^Nq_F<`1Kfme5%*PGDZU61iFyRhN=wr8&f7ISqEFYrDYPhHjXLCs6^ z1otYoVF4D0ndHf8`*U?Tppk=SrQ*h2dqVhKApjvL_Hr|oC0jNQ+qB%`*h8W&^g+ec z<@bPF;rv9-53mjCS!-MN6GgaX>ev`qj%`6|hRM z4=Dv9t1YY-i*`VK0CG{bZEspZy2^IOQ3SXIhb@+jIl1Vxr+kFgYOhq4WH|p*(EGDr z5YgYIY?9cp4m)PRFn=2 zpzI{R8XFdh{uLZdmivo?Ju7<5rT~dGS{o`d+Y}qKY>p(Vq4Me;C9$WPJz@+rWE=N3 zEMF7LlATVm(*okki27UUWbUn~o7Mix+>X*muXb+Qs>2uYj+Bwcr~l=G#KJhc_F2vy>n=AX)13?X1s{`l689N z<4grzqWcti;4aJT8VmmWd=3FRbH>%cLLb7>0<7vRA~$hKeTTxoci(keZwK#&)wyro zBJ0tg#80hDX1Cu#620%!nT`2+VtUw#lPHm* z9!2#nMT>LDFWVj-{PtRR@=`glIExmawN9ymO{9qHh#EXd7&owDyJW+8AFRRt?2Xos zJ`0|1_ZoOkf~2(Zq7k_Cu8^Us6b-v3I9mskc|Te_q(*68xr$z=)hWz)W@G=4Lgre#evp zU+J)9Xo>fb)R>a9I{VVQ6O_Td0XEAvwS}iz;qkAwgbm>*CzXP|R5K{5u9HVIIxyw8 zX6W5|z8ikAE%MHaI=()fE25d0z6_mrOxe|Tbn$1IwFvhe*@w)#zy38x_#uz{e(~|H z+K<^VBs49oKLysHB%)zCn7Qu zhf$@RV~)&_RW4lL5hJau%YRZSUsqIGsN2zXz~+hP&z1JUG`%u+kY`G9vX{{Q!!@%5 z{YmJ_%tJAS47=%vSi0 zSo8hjee}!NpR=_ivLhIci@kF4uS!*|&~`d;DcCRMe;Rvp1%4`X>P%|uvxwG^p1vn? zPdv~2x2RDy7v!VFG1CX-LxxAZuH5GP|1tEf ze9@+7oe#TPwpwxTt$C*xa|!wqXV(G52dPabWA51=jDdsNuEEbtBNR@r_TwIc+Ft+O zhE49PkzJCOmLO;%1UAa}piPyEWS znEY$AJ}h3^3`@4M|1dQieVsWV0@PqKv~eMk;O|=mPlm$?+ta0BJqE!><(KV4 zNYhGb8^W65?94*96-J%u6wy)*(ALlkT+T?9E3dn*F)VG^C5P4^tuI2UD5txNTd?2u zy$9bu!u*=g-EW*=;3^{$C&!{!omG+VugER`sI+EazS=o@w|!8tJr5vjfY37f7TM!w zzj-+loBr0Y|1y||&EDdeg@QQ6LBR*E!=<8*Z zE7Y6ydU5O2u0!#GZ2Wun#1(@aqrvSEkUV%qFp`+r9%Sxtrpzd4v^dlJQ6>M-yU?n; zs~zp8j;sQJu5QN-ii$8zHP>Bvt-#opmXd9PoJu{z*IK2|dLb0aWJ5#iG^~3;JuNXO z1Pd|Z*iPH>Crsnjb7j21Ik}%5o71pGUXy$zr_%n()@{E}1L?wXVe=84uNzC_R8Bu| z>2sJ&Z*{UZJAP2SP=<^NATvU9q^!8q>=fU{N2}D0i$SZ12kuZk$7n2e%8pOd+tY0u zEaU0M^(bC*EW`AtSp)Cl;JNcxlM$XQX3xm*65cy9xO^LL&)|GsL)XvR52+^^rhm0{ zW943miq@Ku14F#ZuI<-lWKG2-t;@KZPib?>Wd5) zcZVW5^`>9DPL*~uEt?~`bG5P1^fV#eM^4{~wl~EVbTYYsRHY?jN#X^<&<5q@d(4Hi zH}OojDXOvi`%mac)QaB;Oz`dyr^BatFVwlN1ztrI_FzGRRCRt%#Lxa*q+;9LyJX|KU%ZC=Rov~;MUZdcbx!gBW=6|kwa zX@ffWV_LeYpMas&nFS&oJX&JyJMLW9PVb}>_E+ef_n(eU29=QSlP%2?p!v$X!ymhD zTn1PI)J8*fj)$gO#Keg%(m71WRFQ7I+Qe*6!cx@Ur=!5z70GQEW?rt@;31spkJ43b zxhG!Pxf8_%>v)Gp!P|!Z1uy?qX&#hq;ELT74pmB$5NAM(T23@W#y)i0EV+%#sRa_# zf9EWJ@XM-UdNRlMIcmXaBNfQ@YHgM`TUn^k(=~fMDaomhRFDd{d#PcSAdV2Ggl%Zf z*ZD5`aiu#$$8CN|vIJBFAo{_<7~=vR%1xG7+D^D;kq4!m*4ICD;MsI|vda?M; zn$Ciih4O}SK~!+Yoqia0(Up&~?Gwn8y62*1iN3IpPA7WPL>D;?k}zDkc8UAjh_nO| zB%|xSzDkR3XBIT=MAHGjIs4lx;t+usGFE1a?B~dL^BQaH%;sptIVH z{RS`XChXPf71@|-xOnbC4E4(UnoNs82%FNDT7J|jc0;SE8D611ezHnz6l$*y51S(r z9cQ4`6)qFY0YA51yeTo}nLfSuN#!`Mijjzxurp8?1tJJo(gXWkqs(BvNxBiU?wl!7yjsJs%4oD%TBlxYUMNAX`$);AHr)^1r~qJp(aWx-hSO&;$q*0QoA`ZlB*Hg@c6FL;? zv0IC7fDTsyOY-p3%B68tsU3=XYOGil!FwLuc zzk^;FLtnc5ta(&`RW-v-XYeCKCS)9Zga*v%r`75aKD}00u%`+QJeoiIWXsj|L1fD- zRwt6fd@Dib7axa;?}5zqFloSx=yZ8=Ey7l}S=2r1^@3?VceoZr1s2iVIHKR|;f-l( zX3QDgGSP$DTi4mpsw%*iMP5k>0h{Z!v%^;59s;-!{Dy|4K&lXa%MVVFUR6ec(H}|| zZ04-tR>;kr^!1fl>u^6mIeFB6k+s)Enu&zThVkP5F_qO!^I?Iw#Q%u;&oY4NSL$m; zZnor$g<}ptLuO)Q*-qL##%R%Wb2)1JS`Wu^>>vtL!QKW3i*s@IDTyk!z+_1um&KL} zpInN}a1m!nf{GWXJdf=bnS4J?$lt`7MGgJXG7G-viEuKfAEpAShK=+OSrqoeRA|yz z$pcQcZYX79Td`$@hbF-|nV$i=|3t+J+zvjO4UYYh3$(6;+qa~`!#RtkJ9eZh1rVvV z(w@60;1b%mVv>JqYKn%jD(NFH_nc6Wk@?SK?yg;fNC}vH$lhGeBJsOwY|6Srz53Np<=hkPT?OO(=c*eJ$NIs5O222pnM}vIMijy{IboOEIbk@#|{q z6)oZ0(z`3Pm`9(Y=S+(?C_jUpH(g76n!@m)9)fD;4fI`7uoI~x%P2mI^ZjH2fZmTf z;77tmywO`qW4}zE=O-trBy;)}){WP@9CVoR3@s4VIRWOr-q$`)n$j# zz&`HoY(}#)7rki}s;s4x18bp~-JxtiV?)8VLg9w6TTa;6hZYHAEJZXjl)WJQqCaQ}zIhE53-(zK)M8%lM!=o}oc{uy(`(6!m*-Wkp(nPC*uRH7ErL zG&m@2pvw<|{Z>0#Q16cS`2d)5oc2@OhIK!*&v_{ZM{Yk>%Lz@d!lhb(mrm~KtqX3K zEUvHIpB+3gALc&~1%4g7rxyV9DNrcCntpJj=s8jO4K?QKqH(H2^1Av1S#pwpG;*#i z>=uVNYGEB2^co6C7gqiJ4kdPj=7Ku+m#z0+U!U2Bu$q)@n=tY-y)xwQMv)lb3%u)o zrTi?BsU(7;6~;UD3o7oY`t1}*yrnTRoPBAPZIVMwZ3egS`I2F1D}x)xCzH6l+yAkJE`xnfz}_*z|6`W;|d(|u(QU%%{VjcW~oRjucw zwsxDM#X52R@ua~l2ZvE^aBp6DORf8Gb;`Ocy={^N{G#H|c^$XH$9XJU*(E+4kcrZ&^})SUTI>Av z;Ho>2BH9^SVUS&4$70Ai#L>t(F3~Clyh7>F7uprCS)}zAYVt0CIPhKRMM@*htoe5N zT66|>)t*IWx9#U@_{i?b`wC8QJ}T#rC(kIS)>*B{>*A1kz1iK1+y@uWDgU3sAYPhRrZBz#FHqk z;;_~EBAndSowo1tZR=1#S}x7NiNgluE>6!rt{J#Pb!s_S-aCAF^fcICD6mWKKL(#J zLw$@;D(+6Z_8^S}1qax96^q)f+BFPN1>cLvCsQlWp$w?C#A=XPIR*6~Ndv@@5SF?c zlA5E$YUiP7loGrHlqP{CmJvBMe+U5UO2I*$(=zyA2%&uUv|Vb1U;<7bQR%O=?<6XP z?!XWa2?HpngNY5ndv;R8&Ifc%t<(CN;DDh@wtEi6J?d+CBFEncr!`+huZdon_`YqZ zGqOtznO2^JPsX?=fQ+at6`g_oeHhdG}J+c zaT3(c>%p+3r?QBQN6Mj|srjL|m?pqA^{y9!*+>~?RSj4xQ)RX)sz$0bb5>QGnkrWF zpY)o-X5MsRn%AC5923u8b2R6z^f9Z?kV9>po3~9 z7M@H9ZP_0W-7-I|kGuYva^>u0s;GZZ`9f9tOfc(NinE*ip%+1dtAac(rXQBdQ|#64 z9n~H~O&ah|BzW3%btZS_awjG{$0>FEc<>>HEglkU|)+$_tshTaarqHpkWUtR2J>b21{CFH# zneKIoAdeA_s?Ly_`YxC)&7hUHiLDcRad|S31;7eSFbo!&>Csn$Dk8>xwj4%7!46B} zQUzw2N~p>HalIP%qHBrHfh}1x$s{!6@aL9q?_DdMx0d6|zh3oL1ZGBLkve9ez|Sct zop0sc?(q^2)s~c>(ndGZsw6v{mVNY*|;7tHQZ!{cO zQ@$?L_oWw#LCL9Wjc`<&`4c3masO;XfYW`4YJbY5D&ke1%8F;dTFV9UxF({COtJfs zFg6*gl~!&svJz2HRjhFl;PpY;h!Wf&7d8Gd5o$#G`l>?SubS~sQE^PIq*Qfu=qYe3 z4sZ1z16QQqGFfW{1PpoTDUV!xTby;b1$g{2r95>JDj-NG^v^@(1LM^*W6XrIL_Gcb z>vFs*?CTGNLMXq~6&IsB+!2$$NAv{C3fNHDWTsAK%ICs_^F2WEM$4O5%l5jU@-`fp zx;260eqS%Tzz`-=VxQ|yWi>e=jGT~o?RQA|9(D;4zam~6s_>qJkZ1p{&s(~tMtd%v z$V?CG{DO%!m2QjaRRT|L_KlORs|94=c)_hpRd*zrK4e=Z_=U__H5^-1E}iu?6AY=+ zJq4ke-TY4XoSZ(1St#`oHh{ApS1WQb)&8fyh|2npzt^CapzR{@4!hl9X%W<7f|4wJf(NK0>dLgV(ycn=aeA;H< zk%|&e8*dyq`Ns@ACZU+WP|gg%c|X`Y^5?8KH`>lvBkV*~oRCuOUVt&_6HR_)uR1ae z33EPzK~T^^j#P_T*ZCR>D6s$U~_Bk*41%r#SB zt{1sSo`qI*NWQQwDOzx!$kLm>PyJ}8g~``V_SF6_tSWF+{p*V7JpVCdb59$F z#b(~KYZUhiJE`ok)5%}YIFwHCHooK2nW}%$M(L-eem2 zV{ow3tFEMFqvoR??<~kTFuVSBUpiP`I;Nq;;hK3%N0IuN~j?O;L=OK9`xyi#UJdYWloVsVn0zB!423FQVm7iBx&3t>wj~ zZnWCKQu3nhNgr*q%#Ld3q%`6%-Z01&M$-pRdRIl!uU2Srd6!Li>g1s($3u3b6qL0Q zABFBKZkJ?%r;;|b-Nj)Y-{)$zIErS%z2I|2h%_vZwx;gP8%b#}_wr_$q;K0N6$B1G zADC~?tm^;e3j*m#mV5XzgGlI^I4?g8x(rhiy(SoDFp*ki?OWxt zGAha{#?Dq@Xj&;?Sp*)e2eAbBLEq`N-}id?qC%^YT8+#r!XdPKd-FI zP^m&UQ9`6!ie{D#!DK#4f?g)LqM$}HT|JG(9+)%Kli2_uiWB{0s*rR_RNz6ChXUh$+`fQd#N>PHhRsEQ;xPyyKhb3382fV4=MQkE5Hq zs;rGkm%VL7rqYvN;E1icMMdIdwfo_Bql~|Rdhr5(H;CDz9Q%n6oMXeL%B>ptd~E3u zv-Ve>IWf%oMgBEqa}(y$l8<-FrYhSE3yFAwMi!$!9wdn`J5Oi-h^j8z>WkfKC!PSUv5-Ou_Mabv!3mW z`_c`0**Q~fcT@|a^$gHr)KT&C`dTrgy(y9gnA=@aJ(7>(K{~r2X5KoCtu-D*m|w^u z17DLn3woI^QCqcef{$AeRXOwuUI0PL$}$*7E;xH^Rph0qyGpVuNDahsgktF=np`!q z&a~r+AGGpFT3faid)HnsoS$tgOEpQs(i zmUiM`9$Ui>Kt?-E-jcQwd;suxs{QL(UaOd=&Sm`@?Fav}PBlvle*lES_PNGy^nDu} zPqF7q4aWm7>_NFwF9=9{W9Q8CUGAx+{gLx`k>h`r-N4J*YnGO) z96P_Rnq>^IeJbsB_4SW}azVQxVyok%yCVD5zmJlk%>{~5bQPRGWW@W%R#FG}u&%?< zAE7mRc}e&2K-`eh@&|!Inxk3xo%}HGbfO|#@Pu)pj5!NTkfe|)-J!05L=T-Tt0bwN z$ilPo8_t%XLTblJge;iO^On6b7yn5qF(cb-GcGUwk)R=D5y+~f(sv3M8d9^SIbuQD ziDa_SS*As0_`Z8*VI!xoZBLo@Q%Y>>L73%B%ePfP916}_diyd;Ry~4!YMACOrIfe# zWN@*kTGrie8EFtrF+kkTc{_H(oh<0(op;1#%#)_t$3kKS1c>3uWRqb|eT~TUfHJ!Q zIyK6D%4sw7c5fdDo05VK!5jp*GP8bOemkoSNjWP22qlhG&B64y_k>& zjaj<~=@+is@)K*y?dyx)5|%h;g=CprX7wqG8@RUu z8kJ(3Zm%lJ@Ajwud$)zsnJS{Hf+~zQ<}mD;oF`~NXNpxRh2h{6P5OjYXvuUJ1(GNT zj`-#1(1v(9SX2Oq8+m?&hJxM)W*o%U$nnS?N)RW#7vJ$zX57+I60yA0_0r$Odg55c z$iye!2&*T%CSrO#EWWD1RUvjGn;-i~-;H22^xR$t_=v&dvq6D(p%-H(m-=E=s+}zI zkGs{Q2L3$9?B+S($utt3UlE;V)&V=b>Oofq>aw@L2%FI&J+~Y>9=qD@KrAK^S1n&( zlRBmjJQ!4Au|oS1c=s$wvpzP4Qq+an0*jzh&|=M+Z2>vVMm>7uhGpz@u~-4IWV0<8 zT76h+|EmWbGBUr7mh%}~!njbTZ&9E_k;=@p7Q*{ z-@vW0gU2c>+&zXk^2I~AZc^BM726=ZUd#V6NL!EQ8CC9ke@s~~Qc<@U6jvH5<^tD99`}7LNEPTo4hvIw)q%9BV~TF$lK=<5P1-}`CzPaDN7JG0T&)fi z`zV|4DnOV9_u+vAZ^P_LLz_#NL{Z7-@Ud8ehfYn4cCrzFI(fu*$$uo-!&@K6lXuSs zWqsZKYtp3YkDFd-RONDxf|#0qr=QTfwzXS_QLD|h*FCW8;!h>+uG&F?gwKSmkv*oY ziXO7i0fBUqw<)5XC(TSKfcFNVjldl602Mqwyf*}Ed*r=!)Fm}CGmmJ+QB0x!(a`o7 z7n}0`@qFqpx33H7-R-}=%F#JsC&d&IV7-u-iN56IPR$z^`H}EimIxT;Zy6_~t{Paf zZ;>(>sy$j>QAMsAX^LnF4$z-JLQhg~B4>ZyB45h9OB!T*!Pt@@+VfJ-29+Y(LF4`F z>XZI)pAD#F6wDS7?U`=DdPz%7h@t*Uvj|SLW(Q$r5ow`FXo#4#7TcM(O4zLi9T_39 zl@g^=dh@pSN8wR>|N7q+c!~~%NcyXtw^kb(etz&sxs2nrJa@9ukH=Sto;KpQ_2P|J z$z~8`lS?uT$UD6ZZ1J`M3~cOm7=R|Yd&S;}!P731>lskSnmiVdNG*G|YIpER!86_Z zwT34A>Y$8^SnLp1MD`8Us(rfSD*>p?4J5D_Sy)WJKtRpb>@^@G_81>Zk!P+dz8II| zCu@&v+ds$D1!8!Q=f7j@`-z?XNA4-G71|XDpM?Ovc<_4ZFC zjmNF+zgH8Hw-q!r8Put5L>E(Al<3U8$v&>YmVITktpq#TAfnN1ltBaTp6x4b>2f) zPeLF@N@m1=4HxcWR?ki_i%a)9Opn6ju5n;v{+9k7Xv0^(!2T82I1{g4gMPdFw>a)U z29^<1*>RBfIj8Aa2<y$e?RXCpTHiVj4h0vo-^}@ zgwSi~k(ii+lh8-q7;VM&3TVVMhW2mM6g2K_^zIS%pV98GKEE#*N>-mSgv6b``)B;; zADFbbFN145^loU@H7zy|z!k|O;bLhmVP>5;g~v}yn}W0uEeNy)zT$#zb%aQDt&Au< z`SW$QFd_tjb<{*y=*2l5E%XPL!``R{EcO1=0ylp0^o~750tff|kAZuxR4F3fzPIy> znW6KPcE-QGbZ{d~xZ&Txr|SKKsZur53vK)V*dA4`6FZ^3@@D_Ey!tFBQ94?cfwztdJ>yC;`ZrK&6c*fftK#RZ=OUpxQnXNwn=M+4OD%kgMh;4M~45!s@Ff6xj~rYIGi_tS^N$9jA8-nj8V zN_8DQN(jalmACaEpByZGia5&WF1u$hdh>@4l{*CQ#nu#X+0=~3(&N!Jx}LnJJz1a*`uF4Ixu

A^Sq6BU?aOMF|6{?@8z4*BM zsR3Lv&uoMB(U{vwE8^j^2zODPiLbP%)m4WXF0tKtrKTRG`w8M>Yu^sYgmozejD( zpUIKOVmm)m8vJO7AB_WdT4id(UQP*z^e!Ic^$ELT$R)8YkY-V=#b?d~yZI8xuQ@ll z$6S8t-QO=vv=j)yUGfyT(5m0UH-?FpmR89ub>IC2ANRREMzT|`XbQYLN?Ses$?%Ph6AF^k0kz)7kk_Nap1erBC(d=KU#RvMJcN2YJmr^`kuG2 zt&2Elfv8at1fO{MWLhl4if3}No%C^OGSW-C1}Bv0TYs=X;=AM>4i9Zpl0S^VM20_J zO{>uA`?*{T4^Wl-ttuRz98B8NjL}l;6Nft^;^}p+$Z?~oU=qG~vA1Q5w*1N8VMNYx za&fm?s_vwU*f1l~n=}uoQWlLroaTgU8ESt}?BQ@o$bqmOKRNsEckRM}tB>;t)iu-7 z%`92$6D?ONGn2MkR_dO@LzAjbDQ7cy5-`#cs&UW!tR;ErSAA3d70P^C#4pIri(bJz z%FxlaAsWa5Fy-dVeKtf>gtFl_1F{Kv8I2B^`A`29ur0o$}0Tl_455%(ZPS&R^M zumY&`X5Nt*$1&=N->ElOz~MX(eS9yVQsbK7FmhwGRU$eA zk-jF$TbP5#bEcu~9m%GXq;}j>o_$;d{U*22m-%QM*x9n!ULVMu1!ah_^D^j3=^VP0 zrQwy$>ohGRFO%aI7S_?#LG-U>X%qS2z1LEzHSea;k%UT?%4U6yrLl?Y2}YPYUbp}F z;K%rlp-x%$jF|YpQ8+&9XWd>n5jHq?0YypD_KH;ObD@yYVnHvvwbZR`HS=BfajqV! z)Twt@SE|M$reXpO>h6>cO5>tO3k8h)k<4MJ5ppq1qfk*z!JczHlnwdO;xJ3 z+BESwSP%#Xt5z$7IT^0h-7myOKp&m?mo^l>fxMc}y@O66qKaDHdbXOl_?y&5{Ls`+ zhKPfPa`Kf!9WEhl+{;c8g^a?sx-ExGt7L}6`0(1WF05U z0W+i*rPvPmWCtFRTHaqVT627DXoIu`F*lv%(;Z#4T6jM&!AWAzLQVxdbA~I9Ry`2% zI1n9&*UqGy%!XKQMOBB#sC)560;D<){7+G`fe=h&*y?7-fsB%UQKljrtS#5KBJSXn zPgaB;^sMjAop3KSt-E5iU}yX^tXFsyB^E8#?xITYzA(rh5?`zlC8A%`lqd#%&z`L% z-R>B4yEx0CW+hi%;=qm}RShFn9kqE8`!@tWvRQ!Z1})1v3at6=eODj0A=5I)>#}uZST?xFs zpOeR|XeKb2qsyuTr$UB#-)0j|=6Uoym;myyf$_5R!!$cxVA`V@#VncW_O`u~AxgbR zfwagyt3(_~mW{*>)~uVZMIzFy5_zQ6wQ$>MVPDrbkc#*?tmu7zfubw|=$>z*-8j^r zg+|)bAS2H3WQ1Q(qJ^^;KvNH8;fI?aZK@y>6*)dY)VY)efvLUgACdw$^rtz zwf)ob4jQ*JSQX?!`T#TExwWq1(2L})wksToH`=S7J5sI#MnY0U37RlkXri2N`yC&P zkBh=IQ&`PnRU@smt&T_i3gb#)PJg9Dk(wVIYS`OGYLb5%<3#FyhhFT4JMUymkMzP|LOex-*Z2krH3Y^-cQsOu=U$ies?S1(k1XN^l2 zv+(C1`q*tpv%uIau;e`>?!jh-t7$#~o56ar6;`T?=aN&m7&43u+y?HfR@r-r;FFDV zNJA7a_xIZwlxR743dfk0sJmBG9^~3ki_gu>*8kmMvCeM8vUJJfeiORl_oQ#(&OTt? zXi8ZsGm7Rj%1SIN*Den{LT`zvqGs?mCMOGne#Kfkdw4vs$X9cCb`$R+15*2B%Oj{K zZ+B`mF0Im$p0i5p*==2&-y-zS&b7CVwxbp`C7446cvCGAaM5c{^{AZ56sUVcz;J3Z zwP_jA+CSI!z!)rJbuAqwy8t?^K#RMYdC?)wt-U4#4mIv5)Vx*`Bhf*2!)4W2B-Jb@ z2x|~h7IyL@8TlyDL|G(IIkf(v0#hxU`X}|Ex3AAX!DLcXKZrxmV!~FxCcR`1GBDEQ z*iamMTdHNf>4UJjqY8eQZ=G5VGksAr6Hzs1A55@;Lq?tL@69Zn)@oCfyGZqwVWgjt zeO~;Pk&==A)iGv-PC<~DcZ>9e^~p+748NRyn=+F}7Biqo$Na)F8lkpra}&U%IEH2Y ze-xdCLzC^>hEYK&m2Q<7vC*SLRD{7cMhr%S(v0p9EJUP+Y-}JfKwzUmVsxnV=tf2; zEl3EwFUX7f`}X}2_j5njeVylV`kz`N2|{6E>*rJjaX$%ajz=jN+~hGVw|m?48$ zDW+3K!LMhYd1@|rG&2*0)1?ua>9ude2+rhJfHXgY7rqePn3Pt~~DcyEIREmAXb z6AhSG-x)SUqvQan6+x7H`ssvXfesxg75Nd)*;!qoLmu#jvLQM$XQ*qpqR% zQzcx?;HEvch$fn_tdN>P@&GjU);cUbJR!I%BmA)jB8A{<6sO;r>l0vZhEoSkYPcS9vxdJYYd zuVhzgei{}(gktBK`EOnc#5r~kZWg)|P=MDK#CB!xNp~|vA6>seyZOa`%8Ss73bxvC zA=T=DX@hCd5-09Q7w?KQ;Ksg|qkrtJit-wv;!0CZtMcxgYFN1Ruuu~zqo6*19o4TO ze_=b*84WeE58GEKc(+hticoz8Gn-*w$=lDoop%Cqe-xPxo534r_OF;-@3w4d}(@r9z1@TUlUYf;@@3Aur1geX&x17H^nt>-)3Bm{9WY0rd5Q(=xduQRO5D} zea%N=Umh2Ri|HN-gV(-0i+0s_C6AlsUvA4G1(vosm?}scll;GRWbi60r@vyN= z%WoK&>QdHG8hh(9Lr6T%lrKP|l(|o8Ik!7@X_8QsCFj0hiFaC?%R+}bbYUZ4bGB@2 z?bY0-?X@Wv+GdSP3FsQ}#L-*DFll3h1Qg93r}==eo}p*puI!EVeb;fsZQsub%BavD zJmEY|IC0I?x|MyZ{+%HH7~AD0Kdc(!KQ6IO=!luaX(?nzxvhv(mHVqV_8_)2Q4s=z z?u+xZ!eZL{t7P&I?eOA+sNeha!#2C}*R?Ax2K_T%)#lR3N9KC#WZKQM-_EyEx=Xi=**;lUSMdz=3c%ehp z1iIWC(Z?%FM+enG)xmzwqFyIgu6c=TjxXJ}mh8pG)>TLt-u?y^5cn_UTk`H5UZVt6 znHqn|{I!E=cow{a>GpC-t4%LXyTd}?WL&4t+Ph;5>ktL_y~+Qo=tym8Vx0Z-3_Py3 z6v6zAs!>Zy~wg><6QFnHL58w zfn1;el$Q3CjO(VuJtFEM0f^q(#Sv>@asG<2RI=bif9&@~K*8|10J)>y2VQ13aH~4r z*NuI5bK#piDrNK`y9{o>dy{iUCUz*K^3i)|v0vNk1sLt?#Zhm2?cZXu9@fTP2`}@x z{#-t<920Ndz8S%?ajp=d48rzP3zq9Xr2Uona)*m;F~#A_wy`~5rltW7sFXUuH-Y7q z6T!vyMbd_{85w-v^h^-wsMy3}Uel^a4P`%I!FfWIU3FpxU3N)*xS)j?`a7gM0q)Vp zRq{IZTZU40^}+OKnc`?PnNF97=M;Bj;38U2{Xbh%K=}4IBSw9|c zM_V(&FqH|H^hlGxx!k7QXZNL=nsWZg?H|a`$S4Yqct+So@<6zU5-+Fg53*q5WY4n_ z_S{;!rvFv1ZEkC9$l;ywQ`kPf@_^?X1+4#`D&lele61gq+>aU4TdtegK5|8yqn~k4 z?NM3+R?}9xhr^C_rFhM1-+2F~rs!69a@A#8V?wZPj76ADB+r~Vo8Ju-_@#Ust`#Ux{`v1_o5>j;3%g5AalTS5q_&}6TSA?& zefD=LC{q2ulj}C!Z2?Jv?CO&};U~lLy^{l*0s=*~-s?J(A`N*P_0*Oj^?}-Jdwnk3 zyaL^->#*FY#85lL=nyBKN1jDHVC6VVUW3^!&@K$vY9Vk5WsTj-KUuLo2RT7w&97O_7p>^0*Wy{oa<D@8qf)_x>sMdv#`*l0eBTVrse-@9+J$eNsOE z-p!IuJ+8T{7rK{b3;g=<=*tqn38Y;O{(7_Lr%C(q!3egb+}`am1w=_%m-TD0lIU!EVbn!V_bT_ z6{IqSl(+I^^wq>oWR6^a<2z9cUfHVe@ZM)n8z7!0z z@gJ^$*`x}i)rQP-?%`N#m`#E#bmr_C@@3kR?3|eo8-OT{k=Wp@^?7C&%CnJqJ{=4h9Wa1Xh;@~RQ zW-FfN$Ct7RJ$=;-VgL!cKYerKP}H85{IB18+#Z951mv?Tb|&}DCwD^|FI|SOpuv{_ zGcA3t7$4W@b(z)`mXimnWG01Zi1WZoJd!+q1A%w+(t@Dm=0(sl`kb2qp~04IzJ!<$ zMQC}2Mw@z{sjuqXe;T7BeM6u8_ryTAqy_Vmi)37_y?1&A@+91N=6R3@w2O>kl49POqp&g2~nI+!F)? zZmWgaQn5KswfzoZ?{(9v7K|G@C+b#GMt@B>I`7!rMrQ8?$RF5yOPny)VR`!(I5l9X z;uH5FRd>0!TkD&sKtVu#JFj(WdruSZtn#i?Ngn#;C!n%Bd@3q`>8b zPN2SGZgEDc6~3511{yf>jbd#PTZgz9dBjlUD-_h(N`DjU1eDvc|WRMTK z1mm@Ck*n}~zn<$Se1iIy!>{naG^|g$T!-DCUE!5_fD=dm+`F)w{PJ{3BrkNetHdpC zjj1jFL0O>-pDQH_OD79hmHhLl!I39gVokHxOw7~pc5d~roBitQdLr}W>5>?oMSLb( zuKP*Ax96G5fR04DbW&uHGr_Q%g1&t&Zo93&TtZQc3j2=Nr$gUfpRkpAA1Fv>1Gru| z^@4ErvL>#~Q+!PN5JMNCS&;sRdVg(|G;!0gwIv|6yB@zZg%aJuyO|PYEq(GoWZU13 z9paTiAk<_~CF|F`VI(08u51R6SyY31I%4l{w=U@#@%3%`v1x#$ah(&k0m%q~!SBCOO}q3REDZN|fbN}VDS z$u?Ozlkw4jEgZhJvOhSBf)cjIFT$*59KCoCfU(fM97MVL-rxC~if>d^ia(cr-Kiff z`)ZtTGSQI4_&1c%dm)6Qh_Ey!ap{UW&j984ztV0k3d_I3J7Ss3jJ`bA<)+TL5MT<6Of`%)`iOk1aD5w5aUe*AVC> zF4mg&IpDCbOW=(~eF~(>Mda*;b-zw&y739gg=T{#@bX~lNw3^Q4QU+8w0vH(n_5;x zG{iiaem@k*6*G^Ko|0&E%pA%H2+v!FsQ8Z&o#CqgHA!)#=Cl)i#tsP&TC`;PG@{C; zVX&o+&Zje3+xz+C^`|yAY0G;>bo$Daup$^BF8dYqSV0VMe^j{tJBIDP1bXReIs|J% zIPBs&db*EkDn@e&hivgsk_vCQFAIGJOge~(1JDEbDQ$7VD{Zyil)I|V4B8Jnt9$+Z z4kLlaMJLH599`!YRDT}4JUEX8_WVCQz8x;XiK*U^Fz#q*nc|A+b{Ou+kv!ovi8CfB zvfgkthikP%TMOyK* z_}$6g6$PRdfQWYsu%5;k;K^ac9N!$9ln}ft(b0aFqR8QVFAo5e^|`rC8^5-&nUtw6 zX*&!~uNKL*g&dvx@c0ii-B67+{5g&)=pL=I|IBkT^fydNZr=GBbq2br*3jbF{D~EE zPhl*FN2B4@{J+d-0Z*()KW)1s% zuU7l6Ooo`wKleSpu&bSoRf*=Y-+Eb&p4SLY;)1^u=!II!$?%>&6ngpUPUh4#cE%7L z*|PbcdnL>z+;(r3pdxWQ1XO%I9l86|pk__n#PNmQ3E%9WJHN=}rQgWrse{H}VFS%S z_X%BDyyF>sdBNeOi;7uyh!f?OF(M553hvRKwwW^XA)reqUMbH6zt}E(ee}JL{BsHI zJsciz^ym-aH$m~%@-KIewpI_?QDsLFDi!i+o!YbN3t}bvP*Ap3jwkI1Na?+gtc~7N zWb2UNRQq@>7du%~1;v7yOgH^vjG~8j>{3dO?iiSmIadJo|B3^jby771O4d3moB|;C zJlhhs9E?})fuIu5)YLwSz`QGn^p8EtpKMlMZ7p@huL!n0zfN6)>y+9Ws0=W@s%I-d zc=&Fu;U<{G*|6%Y9u3pSB}CZVYdaCXtKJx0RSJ*X%sxR-uY4( z5+vyM!RKf2#G+A4U5Cn_2Fs7l>eJ_Dr?!clpRmSBvVNIRk{%l6_)tT0;iA*~9vXOp z%Bf^UiIZ77GD_Crw9?_dO+D`u2uI1rTrFV@HBj%!`@2%RYVk;cjV=_O zN&ZDot0m4~X38~mq&cO;O%WS(42A@=^;@KW+~kVYY@cz>vF$5b_@W1sr>kq|UFHrxK*x)N< zz&Fm()SPPk{j};LzEUWmF?tR1DZPL0MCtA3rH<5A6wP$}#qVc-1v=;V_WH;(<9>6S zLSJ59J&jt=aBaD|`{kOk^Fsg=pSp4Y%008U^WS6VB?#`m+gCY;%{9dvSClccsXhW# zK8qdWgk-K78&=bNaSiiVu%c3-y0VR#LT&T*)N@==F#g**GBnwFV{?>6p6J1%z8lh~ zuP}BLn5X5lmNDs&Gx20-zU%GvYI`Ut@v>Xo(<9@c1k2N)ZwJgyaaHeVrQ4is+gsS1 zlV5LcO;!C%8vY?&kN*PnV7Z6C86{#~gzGc~i9U?gy zJU)?MLU7fr1PIO{4iY>rtsBR!vwylOX;NNyrYD{$Q~l3H;_{x~=>T&E3vWjX-A}Hf zorwSafe|juhvJO08)J{r4=F`*ouYwMn{E8JB^ye$VBhDG840!ldxD7K&*3cMcJ&>9 zW(b!lP<6%<(ahX3c3lVBjNbboFNBMb{gp|(=w1QL$a|@4u*vrxKZy2_<7DH@&x9zjWKQDb1?#Av0- zQcI33UGy9>9%zY?(a(*qn9lQVr$Z?Orz(ZiZo=7Kmm`%o37S@~w?P?s+CWV}$-M5; zCUD5HB2SgH?^(*P+VQb>-MOXyZ(jrM>_YSb8=E@*e9{48JF+jf{M!0n=l#N!yD#<} zGa6Uv$tG(((d2cjmaw{1hpOiRbaX=`D7nu-`DN$9%`A?L$Jt6hHZrBvYD5b>W-0Sy zZrA`b8cXU@k=XI;4nZ+en$p9#BYx3JaN9R++K=rXb2jfo!~N7u9PV*C+@HHg_;pO# z8s=J_aO@@@c%)+JmEdBJsqS(3Em=blYt^o{Pqk*KzC}XHiq-i{HNrX`P|y%ut|dW^ zaYnI*AigfAMrSs`LOP2N>2Qy-4~mo=Yez?Ir#VbyxF7EBa>kN0ZLNc~j*k+4+s!zF zs(dUFul-XZQ`N)2$NN;^cK?al+hGbk>d}>PV`c>aBK_PJ5325;zABK!9fZxgA~AT- zfhyV6Q0lM*kVt-iL!sPvhx|%(?4_%J->gZdkFw9ZtmU~oh%#Um zq!XfgdOts~eICjK_vLXnZcp2=#CfWD2sCQ0fgn}VfoT4{Rcmm3mRxHAz(-3qM$b54 zZ5@=3oNEL%Y!W*cDxF7V`^riWO1%J$XN~Z%skXyA54+mmjyFo(-AG&q2~;T~K!CtT z0K~vE*^ZlStMJ+Zu2{#SOZ~PbRHdK%x^c8HDn}>s*se&yaztJv1Tu-Fo0_#pynl#?Pb&eD z>ALkxh(J+DaIOX2&l2vv-V!q6Ds0Ep0qb)2dPb04omtm^Gv|RsmQ-48JsZONKyoo~ z()4!7W)Q*7WmalavoA(4d%D{u_%tI`;^q^pZ_}1^kk{3!d1pgOAYi$u=q!omL{b@l z3K}_Mxx3upSOFQ8>{T)3Xk`L~fsW6)$^nmIla$m$37sc%AAUxzZoi=%GWm1~&2!s) zoRxET3WOQtpr#Ir(`b*hjk4(v1RvaHTx60`P>u11sz1l119{)9T~AG%T--r0zLn!l zi7R`E*hq*Hmnp2dJZOT0RMeKGIsK?N7zvIwoKYLK8V=YA^yM7x?AT?z$qi=o?ssPL z6OK#n=R0}$yzDKnNCg-fPb94oK+p&J6)2(bJ33i9K33bRyV~h6WJpka(W8cH<`&A% zKn^G*)FyfJEvOz*u1YGJYVW|KNVtCx2*14#)wek10m)iOqeMYb8Wtj*v}&khcfBp% z!+#(wt!nu8=LY|>@6e*o(;cRfEKcKkQp}t{X==unRJR}i8^O-!Dc|^aEn!FRCR&f- z*UPdcTGWqz`PEJkoA9xkPI!WrrA>1a)+G}DPRaqxJ}}BxyNCNV+{Cg!xIQ#DwP?}S zGQD5&+Ir=CG0h=6chpwF_8eF1vQ<&_ICFuJ!K_YMZj4wXn`Tfkw1HRj;lb@o3UC!3zL zu{oRh?xjKg4gWab#EpfE!EBEttffmt2%N_?==XNs%s+o%!lU;ef_UVg_=~sL{a&kU z2U8MLQ!UcPlA3vq!iHjZ`F+gT&=v@RRa1s0dHD6wM}ZDYt%Gwf7K5bmrPfGatu_C9VW6-VDag;Bq3$#seS>M{L! zqxxIYw`sSZf9qoY6oxA|xAH&oRt#WClL?rb5qw7VZ7ppeEUYy%e?RIy3bj`+C_$fc zt}N^Q*vbrNF9A>A#K&jXu&OM+wu(Bf;Kd}THfj8Ooot`I+4|=PwUPbj2tc{}==xt5 z%xA+$^LY4+%T)pQb?V;6&~eezk1qQ!6ldy~55JV<%6GW+o*BPqxQyv-+go}?H!Fp; z=D{dOH!!S}@A~a1{B$+TO!>a#umFrVEH1?-93(pw8h5{Nj0o&|NJCi?(GM3+OrdJU z$biG_140I&IAUbM1i71eVi*&AY9ULiyP83D{FXQJLXg+k1~T@&|1f)E_0Qp_f;;so-lgKjPVvbE5z1Sn_(^UwvjL%6cia}8fqS#H)Efw^=$T^w+6M=<;-)AT|>G* zLtx72yTTn@k(pzo-wV{U?&|b?Kt6$kS7+Jy_M1qiQA+w@Q(J;g>GF05SBJDG+vS7YB1XslzIyHwt$Sw2fl0;)sTi-jHX&_iQ^4_}3P6Ro zB~C^>bLqoAI9<<}a6{L=h`7bIP=M*KkQPhOYgcjohultg+l;~zYkL4yV@G4sHp!xw zna_TIzA^hLjF20#=dXi;kJ0^7%IVMF>$@}bZN}|hIrmpKzj}ye!aVfRJT z5%I*F+?-@o>E5p5B37<9zRqf@+GP70baAHXa_iQ+*cZMc+odBXgPritT>i@gE2%- zv;|ip&@qN%Az3P<#j`sgyiaGeBgIp> zdV{P0iI>&}acbs8=BunD)dWwh#fDt!=cWd2L%`&VX4jty1$vlUD+G2SOp)VdSaibf zkmeP&j*LN0aZYeR__K&2X7Y35E4=&33S9W#7mq$wM3|Zky147O+vo_c)1Xhu{9@C> zmv{?TJ2jkJ^1t@1aL4q|sR3G=Ucu|23M;$NrT+S-$)eJJ1Dx)OqRpUJpyA=iOUt(9 zlb8)!ISeXiaPA`TK+6hggEU7;2u@cNvnW1+8SjSC;(V%#_oim4ZT@P}&~^=8p2HEs z#_v4hj$c4`pAb#|aUzJc^^m9Vewyn2vWl0H*9*0hBB?E9Oi%fH@~<@4B}ToqfNP24 zfW`PhUFtR5>E013xS#Ms_%%2$y2m? z?O#(}YJ8lUIVy0Wi^EG6e?DHf8xx15-}4BRzi6Co{Fb(|yYCT&qpf0yDq#8;tm|rp zaa4^mbZNLj;tM`L`&P=Ui7JQLlv>`jRxZP9-O=S&UDbr8I=Uc`_@_HivRXK=V33>D zd%X8t@)iPxk9G(<W@~Ih4Bi=t17pUReDQ(H2dGGIUq(W8Nq8Cy% z!_d05ljU3op2=qNkXZdQ^Oqk=x>}4D19j&T=SDn}idxl4OG-)IOsT3VT}Fm)W0R{d zW-%A?k>*`#t8(%vk5=4lVH9ssWK=_DzFP7FaV&#Xn&%?d1|Tt22(tMPM%*_k_=&X| zc4Hx=uD8m??aqG^ar0ct$=0kx$>nzlidn>S%p?Y-%xS8eTHcl(m&ya|Cw|woLiAak z(Nk`%q0PeG7FhrZ!Gzm6g@WpPyALW$qiOaFAAc@;<4F{{b&J+{QX{w89tX`uVBeX@ z^ZqVNHFxL;L7axUdqf+!g`I#l-*f6TAlR3FP)o>FpYgn{n7-A2{p+OTP5R^vyF z`e4$$ENWL9<%5uBT;h#F`dH@1`x*kri{h<{w#dB9Wyhqix;Qk{uKJuPKCimZ^I=%Q zyPsLEcdoJ|m+ua(4gol!z(o%B>IZxjhz)H^eT->!MFXE&FH17OY0H(wz>@=w_# zB1I;cFqtf;`_0YK5u-d7q##O&iJK))oRP{N+crY<_S@1WL+`qwAD5V^O%DX9c9Jjm zORkz6gi7Pvi)oh!OOy&nr1i%!s(&XZHE3zw=K!j&S&P|~IZkVSwZ4jIsfE7yWb!)A%OxgllSR&Lq^0-GkR zW7G7yK2*b^y8u8#kp6r*-UqA-kk)TM;-CDjcRH4?ay8=*XrImg+hWgkT6eOWF$(qx z*P8*m)S9Wn7^<)PbLXFezQY%Pd46j2m@)ra>*;%9`mrKvh3b_Bug#QdnMNGsc|Fzb zGOQSu@0bf24fY5r@Qj+<8V#WH#i1R93+}ao-`pvuNxz~mlz;i2W;)#fb_xC}>i%k- zaiO<1wQbk<21yW`{5$I*Z1~jQx6JtSYWBA%{Yp3hBQi<(n#;MovYVsZR6iECZOT0u zM*q)@jHvW;BtrI%hSXv5cP^35hd+i!PrS{hwxr08?|j_bJ?XWyI`=Upv$jOCnkrSs zSIW53Kkmhto{#>o`ddsB6q%4}KmYZGfGhrH>8zRzhzFE-P=&C>@A{fPEq*4F$vsx_ z%3pkDm8N_$6&0#wCi=cDp8g{Xg>-5{+he!G&Xfn!`el7Ris90#6Iy~QzN>@aU~Y*`zh;bQGJv8=I0LLR)NXGbTXU+y!sT5Yci+hwz%A35Dy;=Z@R8j@EIC1&{!S~B z>eHhElYLFsLe++$tiSu^e@lAEV8W0 zy1wL(aeN?bw9RK;&YpY6btLQB*h{8AcjZNv5)y=MSB)iu=sj|7WxM=c7BChZE!O}I z7YM>^b;L*K{;24P8#FR9Wv+nc%O9;7n;dU zCMNL|`BuU&HZ3n@mt@YV-Mlru++UHLnH3V^uFoC_u;G-GRo!YTSAbqXwPFOzpkv(O z(iVmg`F^6rs3{lGAtl~(;~X&K<1{cHlv`3XQ%sfSuaBJa35_jp%Gf%KMxuwnA&wt% zTc)>i;Mwjm^cbS_b)GuIz^mtLdFz1o4n+>*hsO1WLM%1@eGBiRr5ahc(4`9%v*&8fT$sY+eUd8SXOfalBa&HbD_gERTxMb#zxF9UJP9`@fU31H?RRlQY;4bEAqp&JB`Z zqJB>di`1PX>pK+kgsXxE*nMTQ-L3sf>^5+BD>#k4-y6ObXLZM{MP#ZoE&Of|PSwo< z`<)cpxwV)nShoNG!Mb$#93X-n2kK4ZG>6m7+&&DR4J7MF^V>;kWpciaH-Jps9GGAZ0HW$at(=J!o`?_|D%X#Zd-=^XM z36ea;M_>7!C%bckhPxzABnwNS;eZ6@BJcMXDvl4g{^TQ?j*SoUW4$q7!a(cA<8Cl61R_sIf zsTBrUn=BHKwHjDSLZg+lM`(NQ8O$aFSz3 zyaRwM@a6J)-Ulwp$cOUNq>v%@h$)|-!vgEmY^@mWHK+q9<0 zxNFJ{o(Uf3Ls?Hn;CqC1b&BXa-S6>dk!jPzf@xav3hqrFON%(!P?38b?pV8#VAXfW zL~!{#BQBlQymP8w-w1SDU?FFJL#Fm#`ek^q@S>?kgWB-oh+C3lOKZI9kIO?6YRI>B z@#XyrHuNwl4GqzqDf(dwYGf$~TBYLMMrbHNGilX6q>MQ%^?@<;fUA(RXEBu{lYz>Fi2qH-zKah3+&;7 zrN*Li^E#6#^Y`#zP2(Dem|^+ZjY-v=ZRXeAjEV6{KRl1;{>NaU-asBd5ON@6g)~V} zf8nuc`5M71RdoJhQ})fn1SHbvb}U^!E%5ZC`Pz^{r{ z1H+;v!^J~JU?P+`(>z9CH7xl^gW+V?M9y#!?C!q&itC- zMk8j3sYTA&)D{wxk^2^8?bzg4hjwai`uV> zod+db2JmQC)t}NJ1ax$yoTa0YU$^L$@lcsK4KTSE7jWC&Y#XW>^!-?ug~tMvBxIDL zeiy79C|~jgU?*6T2S7~9_)iEnwGm?C<1{5R&0Et4PlOXr7=0ZZ3r)H6WUNf{p4phL zZ2APnWdw(Ap<3M#NQ~JkjYOtHY6{D`eX zvU}S7M}x}$RG?(~iIPL*V?0M3^ac*Tq*SV?0uqlGnZ_6T_D#VQ$XXEdxb5xj$);)r zR9lMAaE|;!BhapCg-Es6&{B_yeCs!1AdQ=)$-I)=o9^aKEgm*my)2=kD_L|?i2B*e z`N`?xh2iRodswsF%Z;}oJ;BN`Ko=H4!%WS$|1EG@yeH7^DZ8O9bPDRJnlVwE86)rr zw3{`MMsS03$LIFoaBNi`C68s79WD@6$Lp`pOy8Fuc~(uLV}AbHD=FvFz=ztp}^|AsA4VNlseG9LTi zH+_Px=v^@?1C*;q1l_G`yij^PF`#k~p8>F>ZjRzH`sY$#5M2h3J8h@@rIU?e=avZz zLO0d83<)GR@mtBlL&mq<5R<)Aw8OSaLhpJ7!#vjp4Lv7Om)5eZ&H7|$As%vhikTIxCGyDT+J z^HFcCT3ZThdh3jO{>%&|D|Nov=x7##$$rHcVZI~i>An8N>d>iMQSufcf`J(X+lOg9 zahFsbBx9s=IHc&)k4GZKLRF5tHX@TqVt{o)r-|`a^c5!D2#peN-3aN9Up;Ap3|KOKFb0} zM%vr;?>7o+@ML{D&!9NiotXJ421vJXvDiz38PjhWFPM z+)pPQjI(6Dw!nh!k24M*dR=lI-L`LlGS)fjdVKO~;!-K^-nadCuUedFlEpr4sI4|j zs%nRGFj_(zCx%hq#A33(1qYIIUP(%klYp{80kN zkLZ&Q|GA(OFgwEH9^<`t;1_!c@~!>qg_B^wczr1utpT_N>bme5p(QXLOMFm)0{p|L zZjY;0Jn}lGRVQF)Xg%E{z{XI(oaCP=9EQhYAWJ9j_*YVvv#f7!;0iow%HFPmT>nrA z+<|jc;qqTrSFLNkVV4*g2#ilK9+tZMZ|Yf{<2&bNGCzN$zgU9t25vS2FhP;4)H{1; zQg@!p5Ehud{ubt0^I z@69Kf!6LBoWxmaCZo0odagF&{zuw`Y#DIhh+9M*pB8d?S0_(<~*S_mksfg>eswK@e zO)P5JRm-jCtZ;6c`G-saLi})oML128%~cJPJG%N}(qlmsYNOqHU2`&X>_w(G?mz?O z-kP(;i~S<#84>;aM9giAl$s;~>eq+llux|!33qfE7I=iS#G}-NSN8=V$eci$Ms&y! zEF_%Q*4DHFzH(-trJ-WoIAi&-J7=N2T|MK8Q>fyWVlJIGIdKc;s4FQXl_Tjr=f4V% zT_hR|S!ii71U{|Er z-Pk|zZVUffddMCJHq_^-R2#NVrMF!9d0CM7(nv(v5Ggk|cx$87!e{{~Rm`F(lSa(h zN)F2Ca9x*emmD6KTKluLPvtF2PHt8km7H{|pLdyR)ESPN7@BL&=#zl5zZKSwzrIBws+M8xvT`qS{4%)1S1sS0bv-bg z(b(m(3~g;o#%55tAm7*{s$aogJ^7xxW{x+RS(tyQXctCpU9G$qK`d`Hbncur(a-$_ zgmGXr+pr-)CtdK^i&YR z$M(4gORFit=%OnI0c`1l1)m00CuZbs)9H0*z64V7NGsmK2lRJ8FRy0*ptSu{(*E4O z|EjV43vU;^kqA6!zA|7Rt$FbvG#Bk05z66dWjsSV9cvJ38o!pI>DkWbYURB~H1_aF zeNZ2>qYfVIo10q_za(OTh~ko4EN<%BXp47j%vvZ-`!`U!wWT?#Srl@-X>KbI%3}oed zdfM#gIEHoP=H|9os!=Hnbq|=6JaTqd9v>xg)DosbP`Y)(eLOEG+KrxD)Ysu0d{Z1e z2nscbo&j{*8e3MJjQsLS_ZPXT#RnGyA$OiEw^~xhS|$>V)X&s2^yfYSR$>fw4;u}p zv|;m{H2F5pAO)0L8sw_iSRXd=HbxT?mF=>7jKm0_f;%L&X15FVIjxRv6v&B?VU0Ex zjfR%^VpHzqxJs3_xQ6zO%_jf?A!oC55f1k~RGnTH*{d74lPd=d4GwD#ROYy&E}THP zh4_TcG>#YTO*cb}G$)AH)giE&IOhD3@mL%cEwOmcS2q;9sGbbuHGvAt1^1_HP#P$Q z+>nY}d>aN2h3gj`mK~{b{Lj6R6I3+o&=k+{!Fz0JxbjeX(^ga}LTJP`H&}_wIDwN# zd1vD5=fKjDE+1+nM^oJ6^PsYM^@9^RvCFIP8P7w(CMj&PRk2??OOe4Tr0>%`L*zdd z<M&=RQWKIfMuht%ot1sPLPh)I2f>@i>`}i7bhQ(hdn%N&hxU7qTPST zXuBGQ&CyKnY+7t6C$VMSaOs?;Z&V2*S!zcd%H&L*8&G1YP5SH9M{X~6gm|Py`y-Vm zm=GVm8hzi9lS(6VJmf_V@hx0>8&-7zP0hERvf)}a;+as13ssY&rKg!%k_m=QMomm| z^Op#s9c&7HVNG<|@j4R9Cz%qaG9Z^&UB+}F(wth80q0y9N}CYm^q1cb1mCaO*f-=V zDt|Dh=2~pApdlb*O5)WHM_VFGHK9|bGSkJZ$WmBoS7W@Tyh2A?|Ilf$#f3&(+EGS| zHDUV6?nKpmJ?C_KzuLStb`l1f?>UyI1+dr{Vcv6gSme1ehB`YTMIzoyQFta2?h8y3i!mu04B`HI>AxQp^)Vq|`fOjB$+;?7 zfkhR9P$-)L!!r1!R0eZUSN^VE5>=ARhJqWZx4 zufp-3f2izTjQ@q#7UTVFC^=`Arixg_h}`l+NxD3RFAZmb>{yTKEY`ZNdeQ3SlQ+NM z{Pfn|Y}KME0-XKQByBRwyfi`Pb=I}e7dKR1j09a>J^r(5b)l~3K^4_uuzlRXWhDGS zaFK}V-Db?03&OS;3ra=O$d9rv*&2iST?@zNA(B0^*VAf9tbuP%(oiTzf0N6jnZspQ z0PorIL(fis3V4iXf_6>0L-UCfKKl^=N4Yp4WWUbfqMU0tzU|gZljVzVrUEGdr`h_sq`h%Q>L`10Sk{d-!OSH zx&Qm|;j;o6O(AcY_h~+6&a%H+TTY#JTO;kh>`ZH~b}buGsgcx&VZ9$p^e$ia0$M(W zO=-%tv|lJF^4CIz{L68*@YC%6AZVm7wL6Sob4sg0L*nh$(|<1a2#DftDF@67Y)WztGDV4WEUD25JHq$^QWy&!=X}=ytPaaerJ011d^-y_M|81wc z*LyaZAr#NW_ce?aXbMOa0e*|B=)FW8(Pz^lX(|khb0wlb0`l{12fvcl!0$6XzEt|6{HNEv?yn{nFb0TjcZE z4K=8{zhBlpJ;SIes@i=qLi0w&1d1o4#oOYPr&D$M8Q{p0Y=Ifg-wh1?-BH7d48BY0 zT@j5n2d+@%%eg+h1CeeRRF^sPB$wD@hXR?chtCDX$uNohROPWQ+k|%?rhpBDyd%z_ zMiD+$4&MC0IxIibWO>7otR0&Q`-=7TR2mmP`!f~S;-9?{?e0SP<$W><_a|&W|_VG-V@Aoh~PXskAc)l%pNv(byr^-MkGFoeg zg_VtYEQYyFzXC2rjwi&VDwCOb9Am(WrP8Qg2TTdag?s`6*N*zu{%k0G`g&6AxRXnR5#=evq|7-@QZ_YAF8PEyUz2cr9g>0`csflq!046%{j+AoA7Yy5z} z`HnfCUF^KoG_hejTA(S+jJ6n0RQ@3T9}`RZ>x@K$F6relrGZE-;fAe1ip?^z6xxFz zB@3G03#>rvpG9$$U#P<2Wnbh?Z-WXUCG&0M1f$W{>IsP zRqVvaky>VDV}>aZO?5LX>zmk7Hy~p?O@;d^8?j#w%w&?3OGhmeZqy*ip#J!acXN#*E=t{`UK7OT=jC(g$+EW&5cPk?0w**YV;jf$)XMd)@-4k0DOXNUO%n6qtA`>xd)DDCgx z=BR~-4OZzgV-Rn6r$v?7`k$Jr%e&Rq=IkqH1^n2TVowtc5=lg35St9X(r;F-v>~(lvSZW<+qm4pJVLqSYl)p zYuMiAeV$Szl`@xa|B0wSN(>09G0C7=F^>IM`*M?#f;W?}+T}CWO>K!|TikAlfV&k*z>Ni;L~k*3Z?=a3Y8(*L&}H7? zRMVNe2bbe5F_P%@{F1ZQDL2cwfUsNmO55kHN)dg#EHae1q3b9A5o3`Qt7;ucK=7>e z{QG9H9m=zg$on*kdOX$~^GQp|-)|X#ifWpL2_>#;V9mIW-?RromVKjbS) z6-$x!Ab}TOlX#|Sga_A+w$2*Na+BEc`>5$s*#J|LZG`f z6_fml1T-WHoonV29hD&7XkkoV{M`T#kf0vgF9Bmx7;^b}Q2Th}Y~J>zb0l{xCL+{0 zYB5B=@zwD4T!{yE$B!T6JP4pP!-~hJD zEGKNkIgokpm1N5j#u`Q;!Q7Q~xbN~9kI8`&{^|?fu>Qi>gHM-4-;$T5v}aRenp3Bn z^lr@YeV6D)t-__-5`5Y25KR~>=GeKY*P>H)h~ni}Gmr(6LXhRq3(si6g~VHngq5Dp?N)Y5QmboN0d54x7{o5x+uf3xFOt~fB1(n50fGdLaxy`%`u#c`(uR2aNuK2-$ z2YX?5FLR|xjbpQr1Qnz6vLI)0ouk_bXSFE?Rgxkv82rVe7@;b5cHW#`J(pz8jY^_= zCkNz#^i+AT%iB&$vB;iMfgoT=q>o3g`FrO{Tp`5nZic2j=L&=qlHHCjA>+z#&Bo?L z*sUzrYI7(6WJIv5D=feZ!BmhID!<&yCRqqwqI}1od8F3eCNPzEAkj6@u-2Z#l9#xq z81N0ZMFLf{C)>YNMdCKv(st5hjWxJ>x@W|TpZrKD!v;k+wIoP9(3e|j+2+AN-wmyp z^xE_>n^-4{zCH6QxRKe(WQhyX+^=eT-C#|M_k0mlMDVK27s_g$_gSgdcDi&|n8IHp z+sc1vW={E1=iP{J3D^q7j_peMNClV7wN4KnqHjUEW;UrAQNNZ}G3|WU)sDtYOs7ql z5+x*g=fJhqhb-9!EPF)`V-*wlutulx@C`;#8{`W65Xu@qe4ci%YZN`N31IGHk8twR zh8+UT*#=u#eCtHkag&XwT1L!@BTdE<0uxgQ95l7nNMEwnO4uQ>l~Mso>pFZMaH6Pr({((I4@tL zPcbnkrdVS&=<(+zr7wFQWUw@xz>plpoeG?o30*txnJdJUW9K_xWU@sOO@unqDYQrX zC#75e_XDIH`teZlHtz=+)nzaU;p*Ctqonh$WbshE>4seHSwcCOO54 zKjmL80}f{$eHF0Jn%6k8*AFX(8^(FYDcxAV?#Gw({Fp4X=o*?B&Bb% z=t+f4Y<`ohVC}`C5B*w~;PxASo}QsQyJM?s+w5tcMyv6CR^{Fx&B5l>xDY+V?A%p^%K6l4i?86Q+|Wqb7{)@!4ujXoCAEsB$D(ln1A7pCi6S=={@ zSBgaJafS+8m9Ed0buA`}n*No1=DFS_i^a@)kfg}GiEA?~7__xvM9g&cgKWoR#XQQ4 z$}X`KJ2A)~WY+?a*w8y8?+p_vkBsI^%ToW@at_MlRjU_8SZichFrgc`7`~}^LW)Qb(jpsMN@#sor56+(bHBno>x*zHOHdns#l~x- znu|c7pwnb$`b{a7Tn2vKBEwa*l*K?@*IrXf+KCh8i_kqdc3mx0@m5$34YTRVF)r+B zOhG393zC;e8|j0f3EfRwzK)~`Vrl9)*j+-~@O5$Eg_}k%1_EvEjFajCIsv&wU$4oY zOqbNK^xCH=dMc>_H2O6}Gky8~{j2RBz8UL6zM!kqlFYr!dGUPLD0pnWX_1JsSuxS; z5_N8%&H7Ps;@x*;T)2%@hDK(29L7>~^v1#V=qwT<(Al+dsl!#K)1D%j)lvPSw}uT_ zz6!Irm+qT$l=f-HX)IsUD-#HZ;UrsoK4uPvfgA^)fYU9*&Oo1)O9xm#@A*u-chAQm zjs2q8c@BGc2e837NJ#s-hlk+@S>v1JyaII7A@ux1 z{jEFGveo8@;E#EqYQCS;k!qlA45)KUh^DW^F4IwKo)48-s1 z;x^wQd-yt+u>^Q%)i97S23z@PN*r*%(rqMZ((s|(e>I`@7wVsDwqG9-deX%pzpS;t z=5D*LVF+735j$ghXW~E8%n_?}Lv=v&Fh{=6cqFh394|(&wo=a8L}Om*o63oD*z!3H zJk4_->9xJ$6!?K#;``RacXjo`0UvZ4Va+vqqTPnio`vVBT%n5n*^0?ZGR|C` zj<*f3(n_wOP_Z+(DT>ByOl6-=qVmkO#Kc60Zw08l3Lzp?)!XtToS{rK;r-L-_Owe5$Jw3>ywlG3~Hz$GNZ=rgq#1S@QBZTKLf*LUc?E#|`W zd~|(1=_*&O>d5AGFUy(j;l`;RjUiQ@ zj5O3IxvXMT(#>tofz(%1&Qn4|$mb6ZUP%PG@Hbo>mjFhTHy4FB_m2lIITHSK zPv^g<3QZ<(!Gp0k#}_V1NRL%aqRxpv=nwxA=rDt~vLCuR7+8V8&c>9U>1Fv5A_v|g z|2lMPOesAsQ(TC0x2Qt*7m|hF26P4lI5gqQmb>lD){ucw?axu3yQ_uqwU1@ImNFAR zzKpx_c$LaMCGGNJr)g0?fo*%bIDE4`d89_X^Uk1wVVtrZTH^2<&u>U~B)cE?nZ1tl)D8oh~P&9n*z&3gsi=4-F`rrE_DCaJ2EMa^6qCh zE<(6UgwgMglisgLUl6z_ArR`JM~sg7-6gadUUy_Gnz*C^Iei7a2WWSjT4jJy5x{$- zfv!uhR_?468UOfa(1P+I{P|tEqlMrFR|VBR7z>9^hpAbc#=K=(Kb(kUu3TiMO0m?Wyz|3~mI~kmUG-*Ya1W_GH!y`3b7bj1MYWapZpf=TG+D3m(QYlf zF%yu;=yqQYSaP^d_?_PTxBpr2as(jjg8JeiB=fn9)1$o+ivT9L(4|28>)L{DLC z-7fCOf?q{jhHKUX5zjrKb;P-_ggp^6eA$HrHO#aG_k)X%REDlA>IEDTtRt8bmO!R6 z5vi4M{_}>)3MK9gibKMy zy(T4dlE_V&5{WGozLL4(X%V>JI#qnxskLWia2~Cbo4rM{w*^M975)g9@L{S;9!o>m z8Oib}j(qZwn&t*{lF2!oWS09R4RLI`J>0b%@I*7Kv|Br8ozF0Q1~)4)3NVoX=>~1c z{j+n;IrqAlT(Pn!ZSh4&$~i~pNhVeU^=zTxj&u2yQ^T}hNabH~OJ9WIDaj@nvb_Od zem^6e$PGGg@FJBrB5s`p$^H1mVk+X&90jxivOrb|Sl|5z;UBZBDcko>2KC7zs$dF2 zo3o5?ps4as_u6KkCS4PtnfwC;l+DpB5b)PsfjxrQ(Tc}8gTqB$FBfxSmfV|j@!%)k zwDa(oFvMGkiSW~S6dKOP&Fp#670++VHskgyN9d1`^I5IdgkbhD!Lx@z6({lG`MXQT z4CCKNk@_^%RED>p|9ms>ZehH)qqUnvAl*rknK|od3FG*uuI-7xjKSRC+y>Y7u}hhw zq+5h!ZHIlxYkHi!y4ZNPg^@5Tz>C;Gy1=1*^_b19lXDq!)!p;rIm^}CHFGt9tu=A@ zSXW+oNm&K|p?>gA>8Jn{d9TGjZU!rT>fL&B%&3UaYguAUchM04F|nhP((RFnbX?cb ze@s_(kbi2bzXYtEF#&w+?|!!unGdPefVLVyir=}hS`VQ0pOwVgx*3(*S+gvZn5MYczpQV8Ib(l*a`wGLubFri z*%0QxiXe1$IdYjq?qvw@sC+v#p9f!CYI*diHKu*GZV%IyArv*!5u4!zL{0JpfeKIn zPsbtH7BK1h_?6D}eTx_?4OO)s5=GZLswrk?&QTLIR4CW8Jy)S&box`%eKyGEB7E!` zBfus_C*-+#A>hGQo+WK(7J&@xL|Bl*UcJ*XsW;k)6xalU>r!Lm7IWxqon{F)C&yHL zy?)OnWVju?o5!5LRWOQi0S={ls+^4bPXZ1iL{N=1BToWSO(I2!Xq7tR@YF1;2BuF9?|@SXU}uBCxPDTe8F3*J+Z}W=SQEN3EX;r zUY%GLt(G-30Y|}4?T62Wx&NbLEV!d5{%^|DZk%7$FEannu5)Sx%2H>ok;icEKUqwP ziWB8hQAYBi`O{+({>e@MR7KsUYy(Gp5U1eO} zod}C*1(ef4XYF;*ivnx1AGYxJzQ3#NK&rrrsNH~%&Ix~SeqWvpDeo5aHl077U0uHD zW571d&?5GRcfSNHau90+nqyAFKp#VHbA+$`px_1dhqh!V#S*gJ;%rS1oAkM%!>M5! zfQukmO{VjO)HRL{+P-{C)XlANs-w?QrpV1iP@N!i@?OAEB-}mpV1vX%!y=1w)SeyV zECg)#Tn`iyZ?ktBeFWqhx4zg36Q9Qv*cZu5h7xR7;Xcx&J5j?n$&j@#DKh1|(<9J@ z6%n`eTi%$EF$w?bu7g`s-$wP+zjyIE`_=NK-X5L%{@H}zYxU?QkVo@ee zjDN}i+VkdU_o#WpNA}Sz)A{;f_v;2*&%j&lad&}BA4@uAWO-KT=ahM1b~^1zzd~Bg ztm#y17D|^%yybF4(6Dlv((}C?1<*?2=L7NGyi%sGoZM1xJJp~2wfs4!;MrbaCg*GI z66AB47}#haG|_SBkX@oYDp(!ip_mHCgL~~s`QAr_h}+dx79{Mc6%v|8(7Kl?QBJDB z$Pjbz*dbn-APtbtK9ARI%nzs8#cJz^(p9q6jpg4Yzs+x(6lP{SvAX=C)~a3!9f!@z z?}eBwO28@zlBUBDQn$-QH7PbN^u#SSDoNVP*an^W(@vpp87F_l-c|E;oLn$3y*A`O z-OtN7v0@vLOyeAhdY|St5@yuR9M334*p@Cepbd&xB^ctq8_Ic{iaBB*i?vM$0?T&7#H( zt!v|X{Stjo-b&lf+-&v6WI<}7Te48@s0%x@|7uL9G!X#a$^HFaSsdyiaKQ5HDOdvb z`r%e>h&@jIULib(-U>$<*&D0d=YtpHV~HHdfw#}47Pm5P3K)sF;U;mbi|C9_GhO$& z%@3-RbAdYVIqg#$N1GN&$TlO)Qe(596x+fA{QD!5K|54JsaE*Qt_-Is=_TcI5U2K~ z$c)(1g!ANuuoffTa60aD)0_8vyn*_e?{28GN}&StEKgkj_66i&bZyKLD&A#VRTQ4e zVZm^_)(UO-T)T`zo5j}irlY)rWAZVI)U7(>(ESp2^W4`0g=yc9Gp#opzNr0+*TvP= z+?b?HaKm1eQNjDRLq;vA5shnIVguUHo5NAKu*zRrvVJe#HyGVW$|P-gx#lK_1h0P5 zW=@3PD}zF~s!+u0aeALx|Hn5;f^E;LsSWP!aST4NTZflxdy04Uph8~5NnoQ<{{>mZ z#5HL(W

zmosNWXYRdI%l7N~LfP&PxkgY7n6jEODs%~@JoxP7C@k9Ws(8;xGtnVQu0ZXmUn&8 zp*hU^%0X8_NJThmihcW4!e&DMicp-09jUZNhGo&<8wx#F$)pHO9{U`eD+Dj;Z0wQL zC=DTBj(-L)A?#{(hzaOdiRJEmz}KG~U)!zLd*^PEAd0-Ssf?BQnV>#8O%G29OrDTd99OF7!i7z<9)thWLWg$!e9STqolqc)l}GqPw&)yjO^h) zI(8;)*#7N1B30Q-bBlpVkb3c6t7uoqxu`bR?%TUI`^JdW%=GhMIIcK*t7SO*%bkWB67 z#Xa_QPf&-4H{Y6wE$SOV@vjrzg#@hm!WDVT0>oP=Pe(O(so1u#P%ZtnzJGg0pZW1| z0kGWmyyu07)+}Xpx93!vAsDLv$B3u?OUL-1lUitSt-Mw3LM7SjDZjEKOd_`bd~vDr zkdzEb0vgl6+^EsN<8d&x4DV0~+~4WS(G$@(WsMH?l$hemk3WzdaaCr$aJA;}?~?A& zZOfzzM+B-yFf$#6z!@EA4h8x0@z;3)r7gSx_tC(<4Tv+etUHv3@MznyK z$cdP#oyiQF?+QUoS@pCL)2!#Emh9l}a-uei=N^rB^i}pchJ>kI*TTeDcwY?xZNX-z zo+0Hh9Z%#pKDp{7-Vct0o4f$0PSp}=$$mQF1#LNx7^N;1>_EJdeO!kTzOuk}z=vm= zIdkmb`9=AIT5fTT3`UNsDsR4*UXVFgjh*seRVxu2RB%=0kWcR7xY5moAr#&dE0Z_% z8OlwM+rGCDJ|%}E&<3x?~u z(`|6;R!HIb{^}14@>NxX72C@|Zm0I80(+xY$3`Q1*7W+bvO6XB8N3RNP6#`sKYd^Q z1@8X7;`hHvf3vSpC*Ft@W3Nr>QaH$`z*vutCVTAeR=WOQi*a91H6L+VKmc6Qs`;PF z_3iOAG67vHe{*pvz1pVAPI$ipp=xEs(o(HoA!ldqt(1l+4SZx-jHoRu&&_32Zf$Lv zE929URe+xX>BS|_1Cs&*lE3CO77iQ>t|+$W23&lVwb)5n9&cev5qcGxwdL+^`(2pl z>Xtah`el6Ww;$PJ(XyDj+EdA7MJ+26yd!Z2m=zL!^(Jlzid0bWI z$RB0k5`vS`Ug}Pgyi~d`nYMBJ`WwlvdheUQ1qUWJ z9oe|)qH`|E8q^BwmSlDoKF9%?g(;fZmZTh~Y87j7HKVXS7Hw`pDlgX2E|u0iqlC>z zHH9W-AY|9KNR@x)AJAs;G%<7TBtmYwBqPtxTSliobmJTU7{Y`oxfS*8Wl+BWoYALT zT_!y)axP?I2rA0WuSo)64PG~n`ek|yO&h#nwo$fUS=L$`)>@IRaWLU03y8&zNnfFt znvzCE`q_=7())~rCX23!L@>Hibsp3od5v#CVwwl`)lRx!5d=?=;4F!t5}r`h;#Y1H z?+{}`X~9`OC4y5KIB;G945B%XWQ*pT<|Z@ljHoHfsl5xhTD!UPdB`GG)jR}aeJ?Sl znE$jc0B@P+31ve)oIO)02AC@rnm#C@gH(A{Z%EXZ|D2z60y&zj;xrc9Ypjb~45QaJ z7(ZKOGZ+r8Y8+IVSXlo!f3QzNzP02!CikKVVIi<32cM~ymUaXiUK}7!(#K|3vXQPt zn6Z&u%XyLu<3R_K1JiVI!)`@6Tb`NZ>vccnxc;E#4JQ-K7F=L|ncH(K?4Hd8(@#F@ z-HZ6}x!>ZP&B;G<6?*^N>Fqrjh9?gVEV|-5-9WBlBe5Wz4x&F0mI_DF{9h z$_+}9l6e83m8JVwT12OpcyG{s9N~3dYB}`xCibg1b@yHO)~G3U(dL?(-1d*8E4qy3yJQV2)je#Y(O$*)&`)ib z#j%L?XNSDAjyCHAUFLY@z-N81^dA$ZZ2Tg<&-iFM1FbtYPz<7ZF7)wb%%})uNrYI9 zp0gf4iqZmh8AWpWI2YH^E+v5F`BsC^?F?&z%gRMWo)s6` z3a?fPtvSi%=Xa3pVVrP5lfV-3hLNQ9H^dkDhtTe8k{{U!1yqVz$*cEHX64(y(@U$Q zbL?twtLrctE1nsSXPi^dA*MBAKo zF#Pk@QA(CHY|9sv74RnRBEPw>?z|E~y3QU^QochY1yuNHUpK!}1#(2l9aIy`3uSHW z4#qRqj(u|W>0!QR`)v<#D^*VCG_Tb*2 zLg2en|4NrT+4?NjeNd_>M{oW2uj|8u^@6{GhIA#rd%p1f2B~LRSovainjn#2y(X*u z2Wk@A9I@Ha6D=zwl>4>cD-GD%A_p8zQL0U|7cyYkc2(m2OEKq;j`{kof`2YQ0-7&l zna;?ow#v7x(zggA{Sy1u_319F{WXC;!fo$4DNv*a!VH>stL)SF!Bc6Ar1Tbg3@Xrj zV$=-iC$h&%*A14b<;Z4Nxz?Im6wnd36yK%B$FFnfP)GCQ;TmT%5N=zxHRF#rme})P zI>9uJ39}q@NMP?PPsp&g-UvO|_T3X#)bZCL*_AZGNZ`{jocl$hP3UR`S@tPwXx)Bt(3-V z<3)3oqrAg=DRR{sMjE51aO2#90zS*?Hw7hTKD>OH&6zS`IPaB^NMNLPS&IC7Rf!^R zKcQ>q!K30yatvtpjDfH;lV^7F$KoXw=|=;>K&p|e!td-)P;^~3O4{&wu=z{rWHUVC z`$p15OWWV1pNLzop zA3`xCZ$*7RLvC?B<#b8q6ug@r>r=Jyb=ARyuO|e!3G5s8osJ+b>xmhVxnh#}U#A?y zxi6avs8#P>d>D?~X_dt!@?`ob!NhFG$3@etTVgmkD=&>k&8SIeJuMZl{knEVZKk#@ z^ey@|j(cTnI(6gEJ?1c%PW6P0Y@GqX)6Z(YglE1#%2s$m($Yh+3w@As3jdsy(3u+9 zp?DkwLio1k-Bgfh+!|91dOWZDb88*>=mqap_x!z+y;A9+vD3D+HVkza-%ecYe^6#j z+x;YVPCqb>Pw2cNaPGd+{l$CLO^hyrbN_tl-RPh9li_5R0{y8;)(lptEYAem{H^)h zz~ZdVR9O9urqI9d$U`f|o$*qOiDT1QH-^6bq%k$R9Y%M!TCj`ED?bbtk?hV{giLyy z&Frv-gj@AarOH&N?y@AzTfUZ)ZA9%D#x!sFnQ#eG)sb_FxT!0rs)#01QOPG1GVusk zU9;J8E6=rO5h@(sealEjxpc2Xg9iEY$!N(Yz?zXxoy`EO)<@MiIV?E-h)M3vUBRyOI!_CuP1ObhVL~cof??;#_jWMPPGs}C0`J~ehQpeOgSE# zIC!aWeXLR-f5fCfY__E&ZP2AQce@O}U~eFp(t#HbASk4K=yJi#`y0IYhZ3o+yZAh6A9t(UXc*dLUZqBw>ZF)gDZ+py-U3Ubx5H z@8LM+R=8X0GW|w@KF}Js>8;vbY-M@TGsAY+sp9*KVa_PkecVx9FfmAF`(T?q8Q@#u zqshCGA&)CRDCab%o|noIWQ`UOWOcpL*`wXxD-y?k3wkkm_2=!T)&ZLl3F~NvCcj23 zyULAyNw;L_c$8I+C7Ve&UppT)qITE|KueHkkfzY`yN=~pCX8WAtF^Q0Yo*e0k^h)L z0`RfllV2j?Z>vjj*zUmeQ*P9`8z7t2pg`6R`;&Cs{em<1 zivW6Tny-wSul$sqrY2m~oy0h*+2wx1=hNVQx1RDlr^qClxH1TlmtRM#ImG|2qCTD| z*Y@usb`Ow5?My}KKW}L)J3G9lj|%gFUFW{Vg~rz@lV|u#)b9$rSnDKV-5*hVRqwdk zJvV&%Su3>A)2C)Eb1A@n`9%I>IOC8Qb>jNxpjqhFSp2;cVwor@d!cpr0Q=rA1@wEDO1KBhYFix zuxluiw{n$`=AbdrG9B{`>L1mSBa@u2ns86pM&kNLkXr~=JPB*Le8+$HfhWl`VJ##%bb2jyJ_$A%Rv^VBYQ`e~DiL|KC17&rezXTHyT?VT`t7J;Aq z3T~a5BJPD=(drm1*)wLa38JLGb3G8jDyeGqCd(_#=3o2qhx1otbJK9bfp9fB;S*dh zNSs@gZ1jwSbWy~h0UT51@_2b+mTLa8xyHIF`tjD|hC)?Zz89QkrWFvFDdW(XexLeJ zn6&Y-h7F!>?rY){qOoXXr}PQwpJb6ksGSMybXfb3>7Dw2Oic2b>tQdt-8SrHvs!xW z*4Jmij9A-0<&-l`))qMO#4Bij+e zGNR z2x*qa!QAC|rXB8Niko-^WRcfym5C97`%k!kRojnJusHW?29P`KuK+~RSVWgfbP5E= zMAleg`gq;r{&=VSiRG&y{3AR@;5ScRQ5)W?Gs6m6v~G@@Qml|imov&cEg4T7(u+#I zNC!$usb81J$VTpm`69*~b|cs5%MV3xb>T>=SZ5-8ZpI?kpM0o)x!`FxLHK2_;X!&Q zNRfx_V2Ep2)oDT*FiiGahwekDol$%vw{|m)n3#D`es82)P6gQzw>Mql_06^M zep6YjT_~&s&GCe`QWU>X`?2(no;7hGlH5JE|9Z~40>xJLv1+VL2CdhJELPts)kL6T z+&B5nuktYR(UoKH@%OK->(4M~@iEI4K-H_=-xD)5p=MIN0zePSL`LyM4)zab2_S>K)CvzpBu_2ISeo34E( zN)qE>zxheGDpD;iI5WjZ_O8nEV3_dXh&;p7sNl=}uMv_TeiTDwxnOaUX_FpnN;^ww zNq?Y`^w!qI+bS}jKbHvq1JbokJEj<%M{}0p>t-a;ZjUAZvSV8{MCg*I%A>d-fVjp4 z3S#=U4c#y;tzBlzXI8^;O~yRp+VjNqHXm|+Y0}O<3x|bX7IFm3)lGAIaTQq{59bQ+5w!2oEOTKzKY!<= zKCeJ}2}9A9Fb5-c{?qKCzT&vaE50wAoL`S8?}iNiQhZ*;U!?~!st|B2 z+xq5pYcHeKFS}Lldd~!)K(LjhxzXN5{v#%7PkXnKXB6PWAuD=N0%LNFwpJR2kkUY0 zZKEXw%^LbMJDW(f9qgPsLFl4fnGMrv{D*?uZ^!z;i z*h*V`#3Slva09hEBb&jVk{SiD?`@1Vjqw^2{=vCjj-&4>GCKRl^QGlI`WfCr+bU|sm$LMt_ws+$$acIYzLi;Ns;-saPk0s~Uxt*3 z7?&O57#mvOw9QZRdBHU*Ht`Pf)pFrD08-l&_iT69euOZuZ^wzJ@`;Aq0S`^>sYkVD zVrhy$aTU3hVy$Q8h%iyOL36G(@p`EGz^9#U`mnNQSooeT%UsRhJ=vNKRUrg-bEopo5vNl+z0*(>eijZKm$!;sr0%Tb?+OX~47z}?`&Af0JVzr+)5|K$ z?m}EO93~+F)jJ!^D&lX1!Qu)k_(O}eZpLbCr7a_CND_~zVeca%;u|YIs9&{m66fPE zk%9Nz5KWt(9MGbC%dA9~b6;#fyqtMWQsiFSSiBpSTXuuC9_g5HEt(-9bT)FaU~;~fCH=W?1|s+* zLW=DjsCuRbHBA9&Om98@L4oU>R8=AJih&q`wO!~;Vizh6i32jz(ruJ|GS-IkC*}7U zdZNgK+B3CHtxgeJ%Y%t%$z<3#bd*J?`saaQY?e*%PM6k6f78fLh}geUW$|NIyUHq~!ZO z20pK57Hgb&Z4{cJO{-2+SX?W6RJ%pjysAt`A}Jb!Lw{%Bj_3+N-i@ssy#2%0QU01T zyi)mxM)Z#bb6c=iL-Xy78$YVf>s>J9Ai=0o`8ekKggU89aztY`<4eV*-fGQ4SSPPK zYFV5~?CBZQ!4J~*+B0>OxkS={IlfY*$){>PVgNM^K?Q#kx7QyPqRtusawRQfCuM1b z5?p`q_xLb7Xm(_pK+FhdH}b6ik9^q+Fc-nPod^E;C3lTC*$czYosG%hZ$YlYl>%Ma z8?<6y*r48F$9m9kZL7qXdO=WCul=C8Vr9OJjQkluGWIqWm4~f-odx8hs0PpFVpr7) z#RKTL(X+{(8FgQ6IpD-sq?559_%1|oxu5kJki^^(aZX`q1;9i3u!aKRp*P?_)pS!*8ia7u5!lRPCGVmh zFDzzBc1@ENYwy6(Gn`mU&T4OPP6sVQKpx3GdbbKzpbVM#m5YtsXYB9flD!Zrs2 zX>QynuIQwJCU@Bu5S9PKwd(?tk!i>t2P3$Agg)YmwL_~-i^E*W_K)_mCwM`LBcmF_>%!dyK zPO&L(%sxNzK1jspxoNzPROfG*Tk)&a9h-)ujSf{rhGtlciEbHtCDE!8`FKCkyD}JA zo$&{C1f1}e^c06;<-MC?T0mNR>vZi%7a`=V%E+Hz%(uT}A|r99>|$tVBC{uEu~olc zFuuqDs6kzluJeqQOg~ZZpI(L)naE8{ln5|mL_55ezxcONS7f7 zw1fZjfKbR-bdYzcW(2GA<$hP5Ay=+08$S>PJ0fxJ^C>Wa z8^9yJcAqarkbmj-UE>&)s8a4%!eY{gg_W9W^loObg3FDS?i4kZjyP4_0w1i>~(v$z~%D)?sAZwT}jDV@)*!G4Xs*u0b))HIC3K zQ6JYEjlQC@{C_vGZMP387{~JJU&xng%P%(N zRjNpr@=ZuiCn=Z?GV2(d^(zQUN-s9jJ6I~SVP2_r%4tgXO`~HUWjhYNF{W2PEO$4i z0JsfB+tjxGeS7CDxW~BxHj>xV0tL>Y^W+9wVEcUfpU2$1cY^)Sdy4=X=M*GZgZ~va zt8AHZK=*U%U27eUnkaD-`L$KR>{&R;P78(3^gGEir9PK?O8y zF}He^^F7U4$Muz8v}M4jkrkR#7J2u3sOqRM2WR@ftDcTfl^uogQQ6TblrPE`KG-FB zlGD^|XJnjXXPjePu(ExucJM{Hm}cO|4#r+P2`FJs@iBf-T{a}@5f@mkSP^R#-^kD% z=wntXgUih|mwElVijpQfE5=FND7COks0DU4G|7xQ5rZ36&PV{p;k`ksZ^%}qPbK2B zrxi(JQ9Fl=Ca@}=XDkUO0cmnwTdYNCbx#_Z5E(zrSMsRJJT}rU9mtZr0&7;em=rGW%t%Iv>Zs z(gI1AQ&0rYi@%}yj9p#tpe;Xy)9bz#l1;itI*;&M627d$OpC-wuJ)Zo50ll~mtM-4 zNj;i1`)-11+$7sK^V{4Nv#bHAIOt1&Ykx)b8<4$TCEqI31#qnMTJ}Fa0NkYM$vi68 zw5*D|LHBUC)^#^@Ft0u*N8`-nWc#779WJifo~*WJy(-TtD}0xEWIw*UVFn?#@H#z3 z%xdE`2fv4D-98-PVkfP{vsVtcHVHwq|E?V4#w?3iT!^wy0CQz~qkX!5mE(*8fX&hwwm|NY+`v{qYtQzKUFJ*#FUu|sTX z6U3g?YO6LeB8g3j*jsGX+Qew>nzfap#k*S7_Vdl}5BS~4t?Thft~=M2^E_YY^Eh6! zGB*eFSWBd((C#(Atj8$$6PJ6xxCn@G0xYMTA zTFKF+vS98ng((qF+kac6vaTI`tx5_khz)83o4^?>=2w8oC+o(~ph^f8;^`0nvpxT# z(+OKi*`3aA*@8j3@TRTu4Le32S9Q93G#RRYCQ*&K;e~a6y8I@A7?e=7z4zKgnBp4Z zGD`0IvL14s6qXwr@$eM%xy}}bt7x#PJ$~cfH$*&0h>f-*h zfnhCA7vA@>){V#f#RqP~5@6hHb-Izz(ES{Gs!hWPvooC(hvb|n=To7TT6%ShVsVx! z9kWVcNlzunoap{FWTeQ{!%CLG{`KMWbIACUym4(ojzRQ?f*p$t>E)Cn0vGYBEjz{k zqyjI#F}Y)&tId1dg^fQ8JytI{W8cbJVIOcc4(X=4|~s;Uv6 zuFHo$0+*6jaSmlb`0|<{A~gE08z50TnS;X{me=1 zq+;7hjmhxXBg0OOsyw_$6eNZ9?=gL?fkG`-Ry0MiGo1ROAPMh@Rz#I&^nDDa^}Vj% z@m*@eaYX^5K0R!mVm)Ili1K$ygIW&r!6A%#6pR{enLIC!ky4M_?F-A^qlY~+9#zL0 zR(gSRP8jS*pJAxSF~_2|5Vp1e3$q zm}gfJkYW8qO#_W)HM)*I(dxZSo67Rn0$s@ks4IW@^CINNBNOj zm={f0wMj&ri)h>3OkI{lc-A9=E~Oiu(pKsNPvgU&ard}IEAVVTz=tx%{`4| zq4m*@#3~P<7FgvFP7%J=zh|;IyDeT_=W)L28{QuKeuBR1fg}O*AkZZcZ!UGq% zef~xZ8kNCl@E|uX*+DnZ(?0i>nocq$Dd$Vsjm`;&?+6|yWCi`t%^W0ai3y?Fq909cJgIH93yhb(Pm+ksDUA0h+V_4J@|Q(E`;c=hiV#1ieAn zm#mpX=O8H|)CRvq;NMc|1GA5I#(a#W7R=|Q_KaY&)AL=Av?%kD_6g<>EX1r)&o>Iq z)D3P)SLd{$Xkpxu#}#sRdaEdA8n@vbxk3B#I8hlW#HfHSdcz#!xpoM{Scxo;kkbTg zQ*blQgb~-c5JU zEI1zJF8i%A9x=q)Tq{^Je5+=8$fH*i+L?qe_k?VVbL+28tr@lS&H(%AiriM#A#&4p z>uxwMrSy<}dq)HA4n_mIppm|Coi5ad>XWg!76p4IAkfD!$QK|xWJ|ybA$3&TqwJUh zo7Zxc%AhX|Y2|?SdHAr;H09cZOLto;O$vqA;o>64ZXYcw{ zE#I2PC&7a9gY83<*5H>2Wk5smwVk6~3#`>)Io-YFSl=IcN^gQ(*@;#dk%7PZRK6){ zR91InfUEmPf8QOqZGaLqlBe~|iZvF5Ni$;dk+GD4TnO`n|G~q31GT0kLRgC` z;sMSV3B2yAk++i{x}N}MW!%`cnQMl5%@d=%aH9NRyAXdb+6Yvw1X?6VBgV$&#FL@C z*so>nRBpPI$HV2IjsY^(90F|=vKc50D?GA_a|FNhG670S4llHA|HVAQU%u##H8J6I z(pW^S>yKYgkz>`8Tt7WpT3WL)_Qv9{l&MOT7i1<}TTVkS*Ons2f+Wic;uNzS?*NuA zv-3OFIQ3|&*Y!CKO+xrPv-#tK%Xn&qd9dZu9PFaG7)^Kw{MyhxGtLS;h`r^JuTlY7 z5fsf-`Y)CA;HL3xwXpK@tgDuRHnUY@T2pRD>T)no!;4pf>({XwBS}!w*(4QR`_G#j zip45Q$xLj?ml!-&oYoh*28Y9oXVY7?D+IAQX!U@|)f1h=hgx;Tqsk1U@I-2f#j3QA9IVn3 zV5TrEEeByNq>HOj`Kq4EL6ySDtOylRpK?uj}G_r<%&r zJ5^?1m#77qkPrDe$hCWRL0W!XlptwshlaRXup660beJN9afpWm6Ib`1s*G4c#)$;U zS>w)eb>hx_*L{v$R>rasx}bY+CV8e0WUpTT>_q0J$<-=tohQ)MI;jj0wM|$p5gZ*4 zH%OpyHX1HQRysUt6EkKh&bOHVnPC(-%K83TD7aq%`SnqDtwjDMrx6kLaLnfAfwu?6V_!CNb>GNN68zDjh^PsT)c815 zK10Dpsq~(`2}C80Y5%p|26P1kA+XgKv=uB@3)PTe{}weRLgpS;5wv1_0uav3q0Aa? z$XlcMHIEl4D5auCu>Fv5<|=hzPe6uG%%Qz1mYxH$S+%Bv8>kYsemx#`;~~-D{@*V3 zyf-Und1wzUmR)x^#?#~mDjY9O+RF%i`Jia?g3EmwMX>Zh8z64WO2&Ws@>vZxJy18~ z2%Iu4SVvtU)j|IEkCtAi5fr%`?WFB15yI3WZROa8lNYJ*$&<20@#irUK1xx+x;TWk zc_*-n!dZ+T+Y)&b^bx{wJ!$<=)j6#j|7PXx*c+9Q^Z4BxgW-$(9qwffy6#rxi)WR& zjl)@Pa+I+;?80s+lZCtAT4S60K1*}uYBjAG3Uj*onA_=J&^IGw`t$Y129@bF z-X6tKc&*U21;SANCf*laRobf8Dkd=E_Ek;rwW3Jxktk>y2(dx*_ z3%R+&s~~M3L`k#ZX^k@qgo+bMb)gz$yW@}c4~?~L*#F(AP1a|&GC5iI$v$scUyUGS z|1flkXErysJNXZKxwuY@KF#r8SA4wr!v23ZoXG4u*s51WvB`@1@o}T?<4H1+uKNE$ z>i$0;vGUax@+EN-ec!Ne2mhR&R8caUo0W>pZoDBA?1b~LUOZXayh#S?8J`lDD))T9 z&i+)6m1kjX%^nTaa$>ch z!XM8c=j8yZ%qE(B21wI$L*J?EvcW)}h#YrVGFoKNmxSwCT70#F{ ztypBaKUN>Vt!%>}7KY6ULNJ1wEZhYc5*PKiNNJBZavUPWl)O$L{fC+}-?KBoN;-Yp zK#G^wHC8m(;%3!rqpL1S*$fiRkP!ZS)wm4qOhX`3rmf+DPmkW%!7Y6&znEt>dF*ZL z$DRV5%E@R|9=MZ;?c=9BS@<=$J1W~>dr*QktvD38#c4|hbKn$m%VYv%L;(!1EB8k!OLfRKvRBsclueJ0uFwt9k1i)Dt+;^uKdMP&V{;MM1jF z3e`u&>?$npy(Ni$+bw6iL-rPIzy=Zy{7CUZE^}2$b6f*wW~cyBU+qNP@Gja|;e)Pe{CdA@X zR(q9#X-oK`BS1kS&rTfi@N)zS-+og~>_?)JVXu%~zc4j;? z9OF-9;(-8W=WuUi{#wBKo?C>5K6bk;6Z0Ge?4&6b49sJcTDTBI4i#}(+FQp@Hp`DP z1*oS4poBgL@YFdcy{=1-zw>}}PCv?@XqnSer1^9@l;1@0FF~!B_)r63OAaF)h)h;| z)nVaLp9zesuB!1f56KWWH|`u67n%?eV&70EmwGGG)=1vBl11g=v<1Podd=C=d9+3z z7a>e#xg<4F$?KN*DAD&jk}bCs+bUMk{sMhBOZHR5vZUxP0zA?Rlj{YumVzmeXrQPY z$9~-gZDp2?!>AY2u*P>MU@pNvv}i4N0E=p;7Q(Jl$}*@XQACHobE9lH#wxF^Pg~I@ zPONDMb}&pg*-y!R3u90cvXt%A4|h(G`yD(IY3GmPlr5_^J|_`s#>F1FP?{G1nL*@|P<^SWc@@h(C7zu*p-y}N_N zFaW#jPD~Mw=f3O0#0_L=^Usl{t)U0E&6I`LF7gvg%(f+I+Jf z&&zV1e%Tv1<*{!k@iBM51Dx)#8r6Qt#7s>DcLYc;|H=KSG0tTm&|TZ1jUNpO5ERLl zm>opYI5=v0W#v_%^}!R$V7E+ah-e)kMU;GwKwfuVD56powFvYntE6P#s_Aa?)-BFQ zSsq2JEL78^{}5DJsqBK~XOK61F+4J(H9}S$qib_q=b{wl~ ztuYSO=OdV|Eg1dlYPC+>J|RLaC2eoAQna7wxNKNdQP=3XyJ}~rgk7w)YDd~0C2Ena z1@jF5e(4AKSDXr^J*u0{l4zKa7_NA(sn{#4zh{_B5GvlDp(t=ay3cw(*4AF2_QG2y zbG^J4fLo+-wV8dm!4-P_s8?Pe5I|pS#Taw?M7Wl?XnrI|5jTb&m&kP7x8=9Vos_oP z17A?ctT+HtlIhXfLQ?}q@h2oC0=HuMvEwrI@*9Pz0M$1EoDIH+^3z7v2YwHs3ZlnK z&0HN&5W9YQBjv2_>%gzJqw1^EANL>>+V6Kg_XhB)Sig@-ZpX@?{CKU!|ZHS7`^ zI~P}K$49rbvwzvOq+!~!18izT+S!;KjOCW=KlXISO$3P>)2i9anu;9n;bb}ne7(zQ zSoX3Q{7+_d6Y3?Ipf4X|=C0&dB$PZ)=f{jE$rc#Y0w6E%hT2a=z-i6=bFIS zOu`q%q`H$61~($=ePn$jACm#so4j&x0IM7Ac7k4$8Z`#{O z#?2TiluG&YhxMdTEpDxV@{K=xw`bLN5GR=4K!nVJQFAIQ@7gd2_GlytX7-x=+YW29 z4w=21$!@rcu*ez_g(=Gytr_p7RhKC$RP z#l~5$!^*I_uI*NJ;Gy*NJNJIsJ&m!C-%2Ked`)_z@b`jKS_}dADC)AoKN(GZj+~e= zx%j-kQNDW`v@`+T;n*GfWT7dg^9fp~)P$%)Q_j9Tt`8D9!3p#9z%@N)ez0TAOyK3L z!eaaP!YRMH)mJkDZ7c5`4KzO5llVLJm4ov<5rlY;)IEmL$R(uWfUeN{P87fcb9WmX zq1pu{dH}Jk!j+F7OL|DJlMPEyhS>6ovTUbCf{@j;BG;nXvwD4fV?v!h#J2Xhi<=qw z4Qg83{WN>c1_j*`>JIxi{Stti;I4s10&M-I{5`NuFlG;MHf|CjPIJykwpFZ+LWnjal>LhJlI*Z_S!-0-u4tVH=NO(Fc#t!QupS6 z>sdG$?&<~}WesT|oGd#F!g{491p_`)?IKclSCjAjxVR zwescB8;2A|F!$v8v1APS6&Xav+!pfdkK7}%2%3w*@aD=?*9JVoha{+fNHv=kl!aL} zBn7owepLw1k1yH_-C@2eNMmYG`RORgntfzU6adS6Pfa(HIBF)q<+UHUD=5 z7*Qkx+r+hHjDfK5ZRk7Sn1K3@!ww6(+PgB9I9BD7+f%Q{Jt7By(pk-bPVD3>Y@q~n z4OcIfCucYM2C>8dz@1;UKq3?<{VCLY4*}@yZSTGN=O94DszQvrFHO^0e*VK%0`BXF z^jSkg%H+imJ~sJ+M)4CUb3n>N(JGrg{cDK#E~@xWinYU|*8RYeYaOzjc=HHU=y?FG zSNb{^=ehut8oyQ{!Lltv_h6(wsGUli>NBVFlxL`6_0er)M`VM|hxKfSX^pRQ#ArmD zZQU{dwORByKPu15Ff>+YLSX2BH#EGf1l>5|gZH&@a?m%8@Sv?CUA+f%i)ciLEG5>Z z7!rUi&us-~aE&E0cG)V`y`qU4>J3864%mL~D*>)8+l{lnDYk^3s~Oo2x{BCN){WJ3 z2aTnjHV}p=s<^}nrYy$Q6A~+F=RV(vL~G^X@)liYMv#-ln&gl_t7VZ^eD6T|7%TG-U0slQRp-o8A_nsVq*nOPrH<=F$qgF7Ezh*} ztl@>!#&Hov8lO5LF*pV>wGxrjMQLuZ@&so^mgNK?A>-+m4O?Dyc)}@WwRIWNj*mdt zjz&MadVbr1I1``{9bFJzYw6+P=Ej!U=uZHcD!(X__@gjG>QAzkE=sv6`Ton2*~ZZ} zJKY3v3K60acvp&5`DJ4Jdp`wdl>sU|1-izJ=3}DioV4WW;>ov4^cRD$Fz)xD_J0mp zRV&Zt&woC9soQRRUYHX~XLX6kKTdF;lfDtfX7tC;5iwBt3^T!9aPJU48 z$)P&(Gv=pwwl8*FxZ!e<*xEWXXn^4KdFb1t4(N=_-OOys!#3|lNpo^&IulrSU{%ed zxF0WQNm*+BER*I}7hpWeOjpze(5$paXOKHY$u|aJmzYX9n|f%x=-+_e_Kizli6-Dw z%xx_uGdES_YN_TK1R6=Yu{vE0g}=?_t@UhmSeS+n)Q{l^=uVW`xr^EHavyk}?j30; z!TF0-O6U<(QEZOj9ip^nQeGk+#{bQDIQR+9VxNd)`vyI+gk@tDSr3#aXH&5RkqO@q zde!CFvi#mgJW?vh{!FUA67s@V^0kA05S<$sCx%t30jO!*E!eUt88 z3~^0+TV;Gg)*qR!n=0+16>ljbWOVspwe3dv|4nhyB41zI&1(w}%juvw@Byuz@*0}% zK{p&#=w{yN8_DB1sz%`iMJTy!M3`7Mil18)t`MLEZ&6ZB2t-sxnSHn#lt1$gDql9g z#jgB)N`z$!XtjsvB41mFns*EXva{#9e+6xx@NRrMVqELrmz<0Myu{r64xurP7okr@7& z7hAVdem%#Htu%w*v}T8P7-@Rbeb>Jj?Tt-2l4oZxd<}>RcxCqo9Nm*t|KI;^+;h5W z->}p67l!a!g`qx8A2%zorzyO`GdUxX{XsU?h1C{#s0`WqBZIMYQv?`i-vUg3I#M}590bbK1#M- zFXa88-bpdbp&#UbrM2O9Ee>|HWggxKoqgwlX`}mt6={u`tW9Mcbh6Y2gEZu#s2HS# z`ma@mddJ;7VIO6kl}{dbTUr%tEv5S%c>UX$ss9n(BdK}P@E^(*0rQ4g+UgG%5E)Ce zSUCVm$Vef&8Ks3x{Iip@JKIMW4om;LvBmQ?)xcQSyr{1JWY@)){5Q|_id+4kPLoar zKR<(783Pf>%;gj(GgF_K_El_yx%#3zIE;^skjKo6m>3pSnH0hs$RxltHw&CX%>Z$S zOoD~&Ush}C?M;Zbk!Q+W!ENpf*$CySsf_I&>3b_jv)(Hj+OEF4gEqZ7e`)ZZ5r#IH z+f1yflh5eiNo`oEZEc+ieT#htQN&z0=@NX7&?`c%Mi&ry-ApSzcMm_o)?}`U@C};8 zm4otMQ{PiQZ+RtX2<^PRI~o#M_bbD+qiX@5q9R}{Z5eH^{xw$^%{2u!^kvyyQp#H6 zN`>gP&*k|^`fGe~{Z3oL;lnF5hpb?eor>`3bJ}HsP@(x621LSuLe7)Bxr5*%o4d{- zd#=?B1UsgB5bs9dCDu(RR3vm=Ei1LKVyy@mw*5B0cmAvXJi4lq?Y~HN31b#3My!## zNdeqNv@iPn+J0QQ4%d;=lGuaLbemz?-YAOtI{Jw?1OT1gkhC1%k+(;AE z4D%>=OPst+r?c_1txc-1iEnJWE(B=1^3x(>lSWRgDPYt;eXQx-Z==Q_B~C?Y&Yl3X zILe)>v&z9$l+>V15>$bOe7@xJE(>95z{+eHdOd!MJKQzV8ZVf6P4@A;CLN4V403EZ&Nd8b)J9*Cy z%a8zfgrJSq`F9@cXzBc4PlmexCD!Eb%`cwcnRhg6dX*-HB#pp6fyn(JLrr;RS*G=* zqzqj4!yBJDTidTelIM!oS1W|!uc?Q0XwC6l;{%m8r(35s3xeWFc{j5xG8g}-DwS{t zua48Tv@*0w?OF(oRh{=Pcj83%o+$(bFsIdlezeCABz!?B!y=>9vJ0K7EeYlWL71gB z7>1d^0oC}^obO-gCaSID@clB=ex&F=G!tDZJ~fvkQL41AA|w(%7YkdQep+5|7;_C@ z`k}P2H6Qx*ihSI_GeXU>&_L(0zLy3P$sSvAJ>O-}Du4OVQ?{1dxTeQ2NN~U(`$+?g z+>l9UFc&m172@caNY&y;D>bDY~=OfwDu%@{E0hTO6YH(W;0dT5yr0XGKRr??Uq*zgC0UPLTbt~KNkxFZ_w0gYo7b4X0E*R(9PFPE zjRC=W`*O{%yi4`co^`Pld1}!os;?qkQ)0ZXX*ZW%KlXUc@{H$f_+aRswdMEEL%uu$ zKi+hu?7Ll7)2xm9NbIz>^-gv79X7jX0uAp-KE{6hU3$9da0V7(N#~e2bcV*i(^*0vA=h8ncOa+@hvrxT>GoHIon1A+J#2%5sV?l74Jk@%8DLGr>k zwHQPcnDX5hs~$>*kcrROM41&v{VgMqg{-C5oi!mpx$V-V@QboN(0jzN7>NbV`?_Zj z;omdjC3rs@lvv=VCoJQ2uW+@Y-+Y;P>R3+8B4@plm(AV1%Rlp9z0iI}`@Nd@?!h4_ ziuhMx);@fmh*a!=R2xfw!e`kiNcK_fNi|C_il>_O`DFs+B>bQoi;wyAaYl{b!yEv=KU|hvkSXlsO=Lb{k}6O0=Jlr zd~H`8#V*+k&Ilk}`3c&JpxG%r+})asIk>w$ObM?hz3gR%bsAX7X4Cq_Yyx#vrz_H= zo-?$XL_PPqNYlHY+^dlv4q2zUoXJrSOYhC^7pSMxcsvZwT`gj)AKfMdd#Y+YBBl?L zHPz>sI+XtOF79#bgVY~9FHFU@0vNnIe%D#4UFKE$us(EaZ=3t3v!P!-{^)&D=Rm(= zlALI+Lu|qDq><+Pzon18o;--Wey=v4Zyo>4I;`eP{@Y$QC;qoH!qKZmhR;7N|Cd`} z67M&#=Fn0fk)_PqR=#KJ$$wqyCvN1WK99jjz1$*`Bmil)4P zd%ap%N!2KT>;9&64)1O{AJ-)}?R(ci1-wouvxg4z*J#nInxMEs-|oyppO9@aXpxOY z;Z-TeAQYF4`QHu2p4pTirxDlkfXT3qkuTXV!pBT2`m_9B0dhzus*H-s)4}hU|>(wHk^-|c{D2l%rLV$A%50pCSVQb;mXzLlm$b*JK6Jc; z*FN}vH+Y{}Y(9VTe&tT~R{d?Gk6}e@$4y6^3vX=v8~k%6%eVIQ4T_(ecppUK_QQN_ z8Q!$L!h^N0E(V&9SoQOF%QL&>4Hc4x2`LtI)xh36kfP;V|4uh#xS_G83R(`KPneJ0 z-Y$l|y4_d&&O1R8Iv^DP#x@UTXqXUh)FLW>ntX~|b0VFCn%N2WOs2-hokUC9G9*6s`Y zwveGL4~q>x2#!T3mYU?3CRXg1&o{!%kmJJ&U0!04>gyFn=H0TrJ4JJtHVH+-+!l6= z`Z?v!9og3Amx;D?J{g>9V1l;e>b$1X8$aco1I~Zwu-%@Xlo3(9{U`n1TYUZ7@b~v8 zKjGH7=x@qvtoE-=R=tTv_9eSitl6(P+ELXLIV$@Ortm{%54J&gfI zt6CKLVfCpSpHC~HRG^iDP+0lyem2Iv>+1ti9UrsTm#v9v5!nz>xrJG4Dze(PM+`JR zuDbEhemnX2P5zX7cE+)PjE<&Q)A-Ld^~kBfmGq z>e&>^+aub(%_+5pxP?o`A%#jxcqb4%_ylWDOJLHiKDee=_*M8V`V?aWv$;)#RNr*_ z1Q#*=<(`nA0e7}S9sHK7av(dp`T`A_v-#bJms}{@Xd`2m%5H29p;xM(kJ3zrvyTIs zJpPXD@F!`SU%sP1ikLlYIw=-U^-BLb{l6O)oMVKDI;|>Xyt(@rfSPK>E}v#VY2TxJH^!g2wMny8caBL z5?T81O0r(ROxK^4YGXU{z^p|st2m;?xKobBjeq52qMbSY{x|F5f7{bz3BJ!kJS`5- zOLyhg^wO!Uo)6_|nf5YyOVq_`X*78BDpyaQ+?$jyw^@;zmwolD>kiKnmz4op3B~de zbb}8$VBq+?GO=Ojnj5@2$siyaZL@6!;!4VVoP&j(o^>~eQ_0X&O#>BbEPA=Z;{-)@ z3Lh1OSE?1x#l78wLrw0pnUEv&Q>@)~l_oPi7)*h6@Y~}q;lGy!se8Q&K?{lzA<_LY z6q@`6W}V%yPTgC)@iv6>QiCY3TZiUJ9ysPSj$3D)qx5M9k~}@qRKG(0F|LN@36rho z_2t?pX=ehU^YT>j#B^%G`;yz@yZ}^hh75-t!>2DRdn2#5KD2`Pz4?@DgA^oO@}|bU z2d2UvVh+_b2Y3ZmGe^5Em_fZurtbHdrKR7vcbnj6(jo~$bHeV7AiL8|ecEOS+-}_2K>WILP1Ha?4>`b-=x%B;J2e~7@b-Sh| z@n?{H14O1L6i`f%5T(!Y3hG}cdTOKFm_9i;)Guu8**n)&b(#u*)7m#2Qd;mY&05N{ zdZFfQHL?bTqmFJ5TmgXLaL&FiTc_b{Xkg>6fn~a36t4wyvzk!%TJEg(!X5;lR%t(? zI#+?GeCWKz8)mFH#ZHo`HSsA3`Y9qLjZm?ZviRu&%+~njA_PSa;P>l&vNPmjPTtHS zmPJl$0sD>ajUvph_K~JWhQ777C(ijt;t2>T*Nr)Sff3gzy|F+?oQ}KMuqUvkM4o?< z_VeAt%Q?i7nH|^I%8CEIfjq$T56sQlJd;M*O`jPxI_}%(xtnD+2;+pl^v&D3NKQKw zi&=oK){NzP59B=3ZOs^yKK8_WM66A8(Z|Zii2l+3{@c6TKWA$(-B{POGhNckTNo0% zQlA%1przZjAFnd1GGB7HYGHmrS3q0ISaVcunc`pP#=?Fv3_LF)eA6BYs%6DOF6J)- zp;AGiI}okIY7qW&QEl{W#^cu4`zbNArxs~-v*yO*c50BZix(`Bh9*H#4TmACB%E0j znuIu+d=TY-+M%i6oWx$9Amky=h8YV=`WMJH*!GZNcuz9U{CSa}u%cmO@JtKkUDzCJf?y-X3}gQP|$B!<=}DKQZwL3uE(*erwfw zudkY7aZYWN)qX6(KK?vB`~FYBE%y%Rv;;8|PAwbpXZQ~XMJFeF?Oj=k%QJS9>>Y+d z!CFH(;@t?Vxk(p^V8#Ykk(IP0k!-|&Un>)wV?JIG8P)8EHLS*{{aE8l8I0eClez|C zhcAb_LGp*cfwUgzmBl095p^jfYBI*}pG9oP-Ovd}ENl;ut~K@H8%2XsD5(suQv&d* zCfyI?%uuh{;k4WXl_M+)Yg9!zEbK^7ITM!c%DZpXl|?2Cqwo{7<@hNCWSF#wl(Ii3 zo4}*%gK$fpsB!J=KJb-a})?`9KE(*3JLHo3bcfj8 zr42YeOA_pI5f|z+vIZzXl6E}eJ%BIuJl10co`wF*e^Q)fFVU=3H#Ym8SRfYWg<`<0;>^^v>dJ>#QFo_EWh-V?+ixmqB_9!)Qaf4~&Zni!Tm2;= zq$zb<$T4Ap*H#EH|M^pgDR=OwsPuG5FN-_ zn^WlWe8q0#=(46ykASB$>UuIBwiHHI=OASppE9|`u4@TdvL&v|StOBAy2 zMc>WryYlA`=U+6J@)(M4qR3*B`Sj@S;0DhezhSg*TRfpy92^kQn>BVhqj!^G6&s$9 zfZojyQkS{dU%BYw5~zntGnl|Cs%yxZ)7i43ZzufF`$Y%R8y||z!yNLlz$PEL{7Z$V z{c29+fX2~T8eq)|hpZM~?>w6KJKj8Dubh%DaRtvZ(2?=o*BS+Pa}=x}^a*lTO`S_1 z80!ct$hsB-#$!`Sxca>ZPD|2%?KlIFYM>6opV8Vt>ag72+YBPySoY~c5 zI|)!T^NNl)voR!Sp34G$M%bn#v5RX;Nr-C&*#`|#k`;~~5KD8cz1vg4_)rb!$gxc*@l?>4vB&eL3aeO3XHev?aDT+friu(`@uM zwAp|)=VCNG$!}e#0_~Ll&V0c2vwbPK{|k7uqtCF8SWJ!lJ{pi*3U@@^!h>78#E9iV zOnf7^Sw*|9x{B|omSgo#s_S$sVOX$b)%KxwztfpH3f!Uj6m?Dtuc~C9YLgqfCP%@` z2r2_|sj$Fbg#nZkwR7YL& zLRo}51KOq%ec;YGB23XjVc<=(HLma0X7c_F7a%>;N4>I<_-^4FLue9mFDrC6MK>Do zK||JlT_Tk~4c`KtQO}u`XdtH7&M_imfAOJv$A`fy&;DDj zret1F+Fkx&z>=8eUpW=y5yoL?wVfm3BK_33R#AamWS{vyDcJxwGgZmnZi9&Yw3VWFFTdn{;2M+JViMvV_xYHH8_Ex=OHBQ^{y%l^NS5Szi`fd20_f`sz+C427 z{}V6P%R^>a1*^;PP6NTrh@J_Bc;(3*>UcoMMrhfAs>p}yORTCk2u@a{24|;XZN~Mx zMi@eWq;*ly@7ef6T1>C5y$VR|=bsVKi(pJ_c^5q3hfww%Ih&Te9aSr? zS8h!*zYDCs6ZR%GBU`N_Io#fLKp3!pz6j<~>pi$`l$@ueoWFC38d{#!c>HGE<6hAZ z%&qeXw7Q4)vIm4y_2HyjZ=B8h`(KWzJO;i|RR45I2=tMO<5vkGDSS1tCLhfg7Nd+W z#4Lgw&=?m42!KjcnE7{zZ&j8djx!k7Ihye-<^$hUnMtH4;XfrvzX--=$lxNE>#Et1Gi0 z1b3g%MbexR8L7tW{kZg6s(>1PhQi->~?t_t{N@?~*wup=i}ZbloM4%j_PXb5AM zf;*?uPa*Fu9$0~eQCWClHt?d=)tJgCu1q3q{_IIoqtkTQ#}g-#eaj3jc;8v##EX_w zBRKv6myV|EjU*0^RB?(st%{Abk*?Dl@4fAcPV1|Dtg`PRzOhW`%VgP!xxJ7{=GgJ% zBDaI^ZF$Z4Lah#}t%JBr%mVwu;9_b)!17e3*pp?8pv!D@Apz#Ed66hlB4L*uQVoZ{ zE<6IUSe6}DU4wf>JMIdJ>yTv4e_`i-7Poi25UMXO@T#(Jt8bef6zXbcOxhETj|=wq zbj^~hNkl=#s7{mHZuoy2=woO(n?_ZBy)W5llKouz(*5$GR}0oFT~vw_)Y+wUl>!P& z9+K;Ax<3_G04iBnQ`}k!;@%6SnwwglyZ71~6b}B_REn^zJINuJLF3nr zpLzojoArXmvzx?umNr07cSr9+Z?cmvGO|S%U=5M*C-?uIJyP8CZ{B=nuP!^fWDReU zOi$!~>d~@VzoVC)rKaPy-m4-IIOq z<;kx0JQVGU1YBSq%E>t?($(mBbo4Ft3!VQ+ost_N`TCN*h|!;JkF}rN`LqEZF*mC@ z_8zhKb$d#oQM&fr#K?q=fph)~Y(Qm&KJ<&IwEMgZN3gX?Fu^HwzWF{I4jtESd{xt? zMqE(s&P~{TTTW1#Cq#~SovU;~^RYRPd#EAj%RbT8$r}3K@%G<`oO9~Dtv4*S= zne-NuzM|*)#n&gEHn@jhP!0jn#MRw%w`4)^KmIeipY%Q*S?s0MyXBNF9$s16TFQ0) zqcMA`Pb9!Yo0^M0YiDwyw7^161&pP{h3A9R&qy>c!w?Zq%uPG4#=zXiKIqV>(Y?EnUNFo4Y_TW{~Fv%mC^7mLy} zIhc5m%<-qqXjIKnB?^Ew(h=Q}I3GLNCl+jbbBbxYW7$h#w5_+a^%3g#pViU z&ufufRdd10v!ry=JvDu=l^3Te8dzblp z{zi?D;wTR+Uv21P>reJw-rC)8y*3nJrEL-hGOGc)< zkNAX4QAYh<8rRr*pIYNGk}KU^^>FX^m}D7cuATDNJ5nKhLU*E@rrhGQY1VX&!6-3u zAnRlQVML-eziZ^kU~;4|gT@dMh~K>VjctTanJ>Yt2qLZbWmS-$7G4N2-_T!QS!dq# zaF9r)m)5er9d1_2XxsDJicu=pYpOM@?otxhCZO@!nC!8}JgQOG@vtHv^Zmq_blUJ2 zJ5Q7227ix<+|1evvVbyFIgplLuwD$^A7uIJfXq`d{}f#5=%W-roilB-je1x@d(sIg zsw?ZvvT5=syyK}Jk%Ii_)R=yVX)ju_6dU^{&r>YkLJ!S%Q)*L~I&NOZ4s5HcG!waB zg$9z00KXZ1b>*gw^{kT^^Lr*maetOqwU1xrTqE2xDVDqHs!{yj!7Y!Cp9YUl&-U{; zu^Ldj-zQrh5NyX2MZMz&S7~Lr ze}?y0^c^D^PR4IWXBM+sRe{h^QZj#!TdK_|_TInF52gS*A^8&qi>NBA-;9bg`bu>@oQ{eZNoYD>)UIVY0S~PQx4LW+!=aV7q%wm{6 zmc()~69gc9wVufzwMQ(7tXwbNGPc@L{luptE1k9u@90c&;SiT#HncY8(-r&qPD($` z^~~=rAkzZ9W-Ts85B`MmUNExWA$u&th<~*Bh74zk@~? zYi-Ufnj{T|SIRjV)gj3n6o;N{eG`!Ot3j3>sS38WtSqm_igM zT;#`j0NwWr@X1g`3KcM&Y~KDf65Tgc<#Tmn&#$;#qmyJ@0p8ce`5zyZJ#Xv{_md_d z>mzETtRcJmMV&AfQ>U2Mj9omYaMSr8S^+qAS~W zUf?gUT}uibS*%8t1!afhQD^h2%Ys7*DETi#J|{0y*z`%ZrQ(U)>;n>p*HE6l#u)h7 z<5_=3h^%2M$`5Pp6e|IF^-*uIDcJF#d(2EJ7Qus{Og4xv! zg8R3}ZaAlafr5sQ`ya;+*2qe1IHB6+<;0n*1dWyP*Y{=8G_9LQLnAgq;RvRO`AKhN z_%G)ab!gL3{nbr{#(Y`>cQNkOu+)3>G8iDJ?&SC(m8#d+vtE~dM<U}Y;!n-fW*D8y zZ0esx>ZlBxf8kZmmNc1i5MU(U(@|w76$(*S+{ag3J6+l9DebTcG?{X?6Plwrzs-eT=I2CSHBC(IX}t4AcdH8?{#)5Q z&piTRmq-cIHLTzE3wUYwmRoCFXx8-{4owaz5Q81)wX8I6!?Lt@p}ZGUubQ{;EI|tc z7S`oepNuL`I>(?aG8%6MwN~^}C!)SW`0U(AfL+KXvt5xT^U#V0lUR@`z=F%9i835l z6ZsfgZ6vF~$=N-38rJC8^FwZGNzfw?-q$BS8r>YaWh7CR!9KLLxKtwnYN`k5UyXki z@7GfH8@gmNwzT$1bw&ju zc#|%eNC%pJO|F0{)JkyIW~Kzgu$}OH6ky3tB6S+!s0o~HmA@;`GhyC7CEk?zIAMSO z?97Jv((Hp5-sr?bo{a&({ArV)J>d>{z!AA@F5Q*titA}k6mSrWlrMj-v~TF#cu^Rm zmt4>8Gv3WdAhz?64+{ZOzCHW0Jn^Hl7<{A;S*U4P4Cm(H8Yv+yZqmg6*G8UP>`_2U zdpL4p)>I9MV=fO4FuoPpklpEU*Z5PK5;8G+{2S@EzanacHFztoc<-X1cwf9&Ae57k z-CADC-@S6P;7w+MBn_zboA0juADA`G`~*2EN^03k>{F9&_Yg1A8VBCe{aDi}_7KOdf-p`q??@HiaNq#VP_0{EEU6lY zHv$S42e!>M3t+b1=+Ax*o4CwqS9RdB+hzVjTwc&=Dx_~=t+K1Bz|Gp+2C5p{6%S2y zun4s44p`8FRBZ*O6uuScnQTt)=GXt+Y(6NjHnr7k_ddJJiQ}c`$%p2RlZvb2ln?Jv zo9G5ImsoOHg-0#SlSQu;_|jygey4@~Ti*VAI;taRSHSyXMm4(=;s$GKv5}4#xzy{R zaJ?llEV6qd$3U?Y4SL;z+HbJ#y<8DunVomF3l2!VhpEt+eY4E- zj$)HnYMd8ZrSCFTioI3AKT8^8Q9mHuT^OHrnmw(zE-J7z-#%f zHk8KyF5P@LgpD>(D1I&kHYJ8J^im^A`v8d3=B@^R89eh%6Q?Z%frdv37^v2@5iyUQ zMbvLDl_gweF%a(ISg0A2VDY$Rk??d-AI_t~qlUN1!kT*cU*!7a;lgBeYM6zF`66v< z2q%|A;47j_H61J)=j@eE)7w!UTf9mW8s{bbnNHvr1HT)_Vl-6&MZP6%TrD`2EYEg_ z%PrfEyx3}+0%7fAa&KznfVxieYqeSM8mu5MRcl!%Bjq$WT@6ntmI`J55NNK?8S=|I z&#K8sGlg&%lI2|BKzT@YLXJp#WXV?=5@+?=7In@)TE64s!PdNZx&9G%YGN^&H@%oR zw?PXy;VwdX=<^Zpdh{prwaw&t&logFC#YvXy576@ZiFKFSRA;h+u7-H;-NA^!yn%Q zb&HP?a6BeI3Q9e`2!L0PBiYP&fNMs|xnT(KWoB8hovg%3iCK zpzXNz>52(535GQQre5mlOPQ&#@D$aUzE zCByFQ8kWnNm>E>kfs%Nx;!v8(RX)Y-cu9HiG{+syD5r9fC%v)*Fzf(#pvvNh4n_yH z$}_HB3qa&p2*q%75FE9ksqG0|1OmcAK#gEq{UK+whveXn;*TCn5qQBT>0spr%q6CH z&Id{s1IOxfC7fiwVL8n ziwrra>Z(`Ss$tPrJtL7}`&Cfo0ISWjx;wzIx4hB=&J++?T|U!1s3n);3}NM;Ap381 zOB_DeYl*-Suh}l1D5<>Y06Mf|Ko9Dl?GCb(;nB&HR5_K`&7xV|Oa4saX?Lc`0^o*G z3JGSC1@7+IafrH(kX9RcDcX#3W8ds4`1pIdBpJ-HJ*HBnY;qOpT5j=Ca}8jv*KE?x z=Nl;B-7k^Kp@25f!(|G(LJV{Vi-)P)&TK+2^0Pn|*-{duXYdI=edXp>Xwj513EryU zT^-PUmPL{-A@M;$a^=*zIgsBdyMZB77jO3n*(6!G8J{`e=O+g0sh4a z`Z;$xnKX*RxU8jLkC`;?kWeZ7+7kiHP1xvQanv?VV6G;{J@3l6%mr%#nYqFdsiqVO z`{j1M!0M}gjVn(4TyH77RWI#`;^pxF}(>!_b zIE7xS?7brE02v|FdsiG(P-+)3kSa*q7+QbCU?tD6V0)N6-j zTC-(X0LZ)v+2P=zMy#IDu;=V%K>&ki7$I%3jYl7)AFjmqG>|X9V>nn@i6~FlndJ^^ zX+n-QeIu*+iiTx~dq7JWN|hC+G#jzto;_m9O*}tr9cij>3(;#VtpZt(|Co>f*s=d< zIyaAxIVIvo}W}TlPM z%Nl+}*#{_pqAjUf-dbYb|A@o-z{~s&?Sd61WwY+uMn~3KiLnQvWU5Y}Gg-E-TQe7A z7^G#!t~C{kk1YfRgm1zuY6ylt`y+d^^=0|9&L>Fxn9uYFO|`sks8v{y@0Z)Xce$tZ zq>IF-F@NXl7e|CNn)xeCujYQKO^{|Yp-Cj+HX-R0iQbwEQryG4-*sv4Ai}OuNls5I z<@Tjl+#ju(nF=s`%IZxPQK?MRyy@8e)WD|4T+7}$G7v@9?$FrXt)oG1MIKDB-PTsJ z&NblRR~Y!~B;q(>(ng&|Q4TTs;3kz?WgXMZ+xg0wqkXkeebsW0_9B^K<=ugN37sfd zyw1&Hey}YlcoJ{9FbJ0bmta(V?v9hTS*vDzLS{%JW|gqKOnSIL9%i8sj7Ok#)iTdK zbc0$ejEXI;(;W|z9i8ka=SLSs+H(+iSOT07&|m~85tB{)H_0JJ=6dYd!&*dJJImb* zvJn1l7ANWrud1G>QJTKEU3m73O@8sT`yV+@em;q>4QnK8b!6_}#GU%WLp9kOn_h*7 zWbojua_u3*R)Q1$}V0s+yqe-=B)XSN6eymi>k>C6Hc-gyO=mIvblI?QYVon@qG8KRxy9u{=K9ns-2u|Q z$h%1Ok?Jhq@KWY%%M{H#@@KnBB^vbK{kq`bQxmteo&EZ`T^2$ATwhLbGjQ)Jgk=!` zV+ezqv}b*D@~JBOmh@(2Cn?gyH}teq-QIBePGgZ_nu8mIq?bFvDA#@!`NCQ}0nWP6 z{?^$vsuB_+O5m#5CrU7C3^(i16%#KN6R!-DqZT|ReXFah`VVnRb`wPm{_4XjbCd#m0nkNmivDx{Y3fw-kOpy7$i^G?n>tdRuj8<;Zm-9imTxAU+6&1zBF#qOUbU zCy4Ya(`GwV8q6Gqoq2>0GB10rSMW0^Ik|9|6wajWSRtqVm}_6b(y4Wd`rp5(OdpOR z35fPT-fe;Vd3&Q-U{aUNbr*Y-${`&huUE z^mB@*XOaRoIH73$n8`$n$&s_FO?or4apvrm1J8wW@b%thwW(ac4W;`fx0@G+P`;s@ zlq6;&;`+*E^gk;xriiQW-+Frx9matt{2T4>O*WCaJ(WEFX_ad1x##(dR%!gWs469t zwRPH^=rtHkSCVSV2|m#jf+jewW){;G!ignuO97c!T16bjwDkE}rB9B;@>2hpLkSAm!9n)vSqH8#dK|b8wQV0aqWY z-aw<1`$#_8|iuU|I$?a^l-1F)Zdyg`No#)RzP?O6yv~k|;DmcEH`DEO3;n^I& z)8PBZFFD$@0vZQ1#NwKoYD^A{$;eD9Lk#+eETQm=fY9tp)DZAW_f^V%h2T){?#NOG z9v4e~{-YZD)+g*g&s>kd$Vg2hdTwg`J{o{xFz9qZNS6`UQijkf{t$;oq7sh$t2(oP zyb$OC3*RIudeTFJJClJJL~`*MpOH3|bF2E?2VvdHGM!vGgN!wIQO*YSxG$Ibc6681 z;SI+tJ3UCWv~ju1*JZLEmVci*D6|CGlx5;gTQ|}bF3jFLU^Er($cVAb7U5EIvJ{UT z{$4@oOa(^F={{e+|30`y@+svZ`Npk)46@J|8+hvSLz92A*SJqpQB|LS@Al_vm}=cd zlDC*oO&SE>q(@2@Nd!u~WMFnvX*=~TNmb&Ao@F(-DiE<>v_$5-iuVU3XJC+Ns+zvK%+Cv;Lf{5%H z(&kv6KLyq{Dv$}en1rd%Ic6SS<|kwRZPMsRsh-_YNq+kZB36OQFYAkw!<0KXR`e1i z@gWM6bjGM$HWR5-zFz^uO^e~0wpL!pooI4%1#py6ZF{ifR-h(brsR5PQy z;0hqDU`5i2d>q9B#%>lmu8c*E+q8nRPhH3^ubl#pf(q9Q#Iwp5Q4@rLLEEkR^`*|v zdeV^vM>LhMK~8Wq{CdFLXQ)ZSob>4Mq5sWgRFywd?KR`HmPWbK$7D|1B4Yk4L+vqI^z^_$-gKYx4Tg-aa?2doLMTF3|NXn^VbDmdQ6) z0hp$3PhEgqABgRro0d8(F2rymTGLF?ClJ2lBEG|VK>JgT)56l_-E^g*^{>{vXX5=2 zYX?~l9Cg2};Y9OTMB92=+f9?UBkIv5d8W=8AG1w}--WEZF{DTTCwwo!TQhbWxxV?QCN(Pj+dou_P zasMu$I}&^+m9YLbUlq`P3v~nuPD!ar(eg@$%;;r|Z38CQau3Sdlh%GaP3v&@$0`(@ zF)W-VWbYk=#oJr5mhKF`fyxC{5t%n5MIdO;JnlzCS|+btzTIbxV%^V8o&ZY#FYn>a zSs}5G2AtohmtTgn%h2`F?Cik7BE#c^j^kg*vu^*kr)kagYwt3s>YMXCgHv2-gUlyP zbp;KMeYc+0%LoqV9qdf4UpJzgQ0*k8i?oI1BzEnqZ&giL-nt8&E?+DuPQ-d&pkX1a zvp!+isv$ORpiDdL)xo36snCs>cHsK7bEoPGq3S79QwY5!7Sq=j+2J+~V6M{f4-uj$uKTaC^Gr zm)&IFUzK~gNFjU2TFSPMh^!R)m)G*jhB6EvtC?lPoT^ihPisHPt-j2g+eLIhm_}9o z-M`E=@k!wyHcu-xxyX-*5yb?^da9TrY0os&_0c*mpF<%P=c@@Cnn3rc4}dI$hkcrO zf!kj7%qtx%-PSxdOK%vo&8lww=NST9Dq{Hr1jG1%ShdO0WEpKuMemX_5(@$|6_h%= ztnpUL8!BJ39JCNTFME@dLTAlacf@Zfh=<#kCBA?fvR)BQzGf%L;RaKc7}c<&^r_v5 zZ;!)b=)U7ol+(WL_89Ay*22P{-VPkW7HyFTZa;@gZ{e`-J1&t%%e-JsCiqP_}d~++WPC?WWud$~qgu zi+F!=s=vB9UPqz!yP{VaEOi%(v7MspoD>bL=n{q`V%i$XQ@i9C_x|?tJi9R4)ul+g zZkZ~VnO}IPYD7?Hp?Vv)9xW+XJktIXfZf2v)GwP%e4xB?Wzc$10uK7BiqIQ0bQ4Nc zR$4L4s5NBZ-8LUSF28?YL`4&u;9T4PlY`n@WR_Nz`#4QZyvbP2Vg+e2<(S&!)bEOj zQ3l|QxzdH|SKQdQl;S;DfoZZiB=4TXbI;Fcb{9i_(5EKsxS=7gkHLPTJzdR%pDgo< zJWcZnNY|9(diO?46hr3n`jqgw2%BUC#y?0z}?PH$Nsq67i*YN`WDOb@34=1Hbz^$fWPWp~f-35&9 ziAzin0Qy6imhDKAaDJe^M%yU2)g*hhzW}AAXMVBT=~Npf)XmSB5%+P7R@9=o;DX$ z=0y4>Q*1#^=ZPv)9{gF2ecEnJd5p@N2-@^Mh{I5ib$G95s7bM7Mf)N^Cy5q|TodL(b{grrqpv1V3l%-|joB?-{m>V050!Q30$#^k}<+hdm<`LS380?+e` zl_dj2ahDf6KZ}p}QvbD}!PU0>womArHFtagyo~k?&dbXk5j1H1`W-Kej5rOT zZfUYT$yPj^q`kr*WNtgGGtQ_AgH!{TY(FA|dE1 z_}~g3=nL?8q$QIK=NF86iH87!u_(}#=|V5WXi#QQ2CM)}y&Ep?`0r}rbW>L3R65iY z<D;h{1zA8O z3sXCPUBVS8iDq7CB)9V6*`GEO&4{Lan|*spvM?#C^?{3fFlT0ZS_2Q89J(eO9D zsPUKA=|)xl{@MNe^x+SNlH(<7BknL$k4LQ1CCvpPXjGH$`;YVqo^;Hj)&Do(MhpM#>|8uY{=fMR zbS&e2`mmP%3jeT0pM{8uF8cc8f0t-yFRYEYqO&*tKA-(ch<#$e+NB7H>aVO5N-!x& z9HYY+NTv4ftlf{(1g-fEw)BbuFXx>5qyXM58r{nQa!3)`!FNtt-x#|46GSAoJlYBV zik{!bX=-a7SrlMK%?puxI`(HtP6rvWAAB`)AmGqNaX^X$4aa1{X_`2(Wb}#|y#Z=2 z3p?U39QEnMYlh+aNofn3w~hV;=^x}#2Cr=Mg3^*TCLwipp{3^D*|G=}DPlPWnABUG0}+J&1B6;KycCq8@A&DX zYtJIGw_qb!WOE}*th*i0maaRJ9C6uXov|u3)L;4E)Ilz2UH2&SfFSDXa%)K@&B80y zwX@l(-q9E(vhe=P3#l>g_f}b14PzbXa!1m3rYwR2;nbJ!S3c*US+n)TXoTGJ zgtJdK_M&k8C;5gh5SB_d}*qEDpv_VvZJ>9g)KiqOy{=l$BKyH(But(Y+j_H9c(~ zZ;c(lxTe|z^JzMd+2U5I5~rFH*~P(j$_LCflIt%|v5nLwrhhUjUSIC%!rJozA@xWK z9K7`HBcD4*L%&`ZG~>X4gRIc~W%tWRJaW0S{rdK&&Dh3veb3;n#QW`R7*YyoIB`v5 zB3`*o*g9@^%qk)tCUg+$N`oolQ?&-b=2ey88wJJ8GZwGq*0djVv(-u1gr_Rev*=*in+#Ul-dMEz-7<=-IXgs zi9-}cO*WGzUE^{#Q%MN`E1G^TH+K$yd!rkUHjKRv=eg%eRAn732QHkxdJy0k*y65d z58_e!hK(ixOGL8)^1Ua}QQ{;LqUN8=8Cj;1c^Nwt)ChJ|k5e|fypVDzw!Rws4kSX! z+IGo19iwCg{JbbzTD0Db^YB6tK)yv*XK%{a_7!0>>($oXaV1o20cLZ`-&D4)AV2V5 zOvz6~AUf@zAPFEv0WJn=W1FMYe^iEP+Ztt*Qzt%TVOzoovAe1Mr>}lE%@{2?HLeK9pK!M zOM{bd^pCmhP5^$_ln)&k*3wwIxis;z#vYgL#c<_axR;Tfnjs6LwG85GC$yUL94kBN zG~LMR$v(1_+Ujc6bTMRhz^VdaE(7YB3QnnFQRkKJ3LzMc&(L%*D5#RlZeVgO{tRwd zyCDPgooTHDbar;y_{?jz6tjqJ!h7QDN;(tF=rH=1!eudhfR98Ec$?kL^9SdgAH%QN zd=Py2j(p2$=%2#QWbtd)MIMiQYAxfCMdlV~@ZP?A&Lh_SL`6%;!cAZYB%U4iBD#ZzB`n3Mrvr;8S6B3 zTClB!BQj8O2EQVC;(l?Mi{-{UFeh;=Zt2cZ-NnONA#v>J)c&}b387sH{buU$+`QPs z!x(f%8IAEq^;ApYQM|?lJz`W&gM9#MNsaAC;;o;}=W##gm5S)-b%d6=?tW5NDcl%d zL^>Y9S|T@m)qc)`$Cu_1c94?Uy4lhl%83zk0voXPp3hCvw-dCBx{*-?cby~Ex$@KE zz97v=#T=wvG}X(TiLM|3|D!Ocsh+BkEB<$>6cEl#=LK3}gyROiOHHGac=^DK%8kD0 z8#}pWV*~Gcps8wsDUdpe5Tfd(iy4^Y&RT-I-Aj|U=Fl|Bh(BX&n#ZNBCwNIhX;h@` zfWJ>OfE5QmHnbKtYT`IGnY?R~K0bURm$)-sgQyjy(ci}Pl`4z5nVl_IqD%&ZgR_=5 zcgEGKKFK)#0%QfwIy0*n7X-MdQPl)Dl5N^PiL$Y$%N%Di1EKSlb zdEF9NJ&oNEd4kLGuqXgMuqkw?8PBT_fWrN%J{|wofwW~6Wng5?WgX2muQewpe>=}i z?*8ia)QMC2UH^XoO~>fEs4U-NGScdP*RYq17=qU}l-*+0 z;LYpLwwOZ2_-fUo9d%Q3nL9PUexs~PfQNrv@x3!5d#BVgSiMUwO1LE7#s(5itG?Za~X+^j*g5_$g4-AlE!#=6Mt|SUD9s zjZg0!gTV;@c;nxqqNKPL!~UzcEm`7Too=NcWHLd=9o^kalNT31kSR6I!Bt=5dy2w~ z*3J49_QyCnh_-DSlgmSlx}-pS?PoFwCqh8I_;HyJ%QI(3N(7yN zx2(8ydGPMz(t{|d?YnA{3?=J)TY6wXzW^j{J_Fv>QGiEARqHrT20D=?OO_8SzVyZH@l%>cZapNnwlI^B&;M}#`Hz*6nlAodyWKTlB(vn(&ikJgUjP??nESV-; zBFZ$v;*JN~XFYy$N6LuTs{E^#$+r^=tm~_gz>!E03k?hPNU$$S)$78RE2 zz7ewVD`zI8K)f2-OhVWYn6>pmg*wsADXI2a6ydh;T zyc`bdJ$bRteJT)MqKL0U8G)8}EuCDXQqDZuFqm_aRd&lHAu6#XSH?B$ma-}!>Uk8} zUj@nJeT$Nc$+gT@B=`$zX3U+jyS}(Tf8+OBTJg+&$-Cy8)x%TE4iKTX5j9S8@8kVc zQ^oxE;^c^bsKE5ilo4->jU>3qxJuSHW8yQaHR%CZ>GVfjBu#Sbf0x2_!d^85+J1;2 zDY}+acq8&5oq#0|sW4h3as}UnPj;%R()1cBbL`$lv%_-B+QUq9H@uQo?MX2Yb*#Q* zB?;RfpcKL-hjDuCMxdkYA}`rU-z$39a@wDtFWZW}H}EEGIPKp6HbB&-Adj|3f@g>G zsJq(FFK!&B{!BfJ+^Ib`Df0^C_ug@7-x+tMi0*NKLzeqElcI-Ny>}*!iWF{}%!)_K zjXVfedq9v}iKi(@* zfBN2RQW-XOGeZabGR2HGCB09{6q+hg_9lxt+6X^+)%Tp4`tV<@=~LixQMzZ-ge-N5 zYL?gE2m*}=&r&FE2z}3GAv-C*AOP--Qw0_Yurtf{U=NrO8nxy2>~wnF+esj?ue=+Nfx+gE5g^8?^#a!)6%A`A+Eq9MnMs(==jtK*Z5cy3u9{69lBza z;Az`|${!Wt{##Ko@RX^W1C#vYeE5f@+-J@bErpkv-oahkUqjNqc2W066C~^G4_ym| zs(u^fz*dmC*17v}SNZMxf7F8E4)%H;m#o>0xJ0^ITGUioTNj#;bsF;vHF;TK@qBj? z+km|JfA+;}a>>CDw0doz=GxM`Yg)R}-|$q$m7YwWhlaa|BEA^Pkj;$f`K$q<9{)rtWNNum`#zo&N0|{|cUt9XYX+WVqDp+(t#Uk zhJbTJPzkx z$x7&ty2B2NLRcm&PNs6EaG#|e6ufy_G;ST#6If+Yr<0N=)SPVH1-T<3>=a@bYZ_&W z3^K@VeNb2SW7EXH&(4`H zh6XDWqDyKy{vp0%)r^Fl`@YM*VZg}?ym;gNq^(naysr9AH{YCl`)^fdiC1L9S7(&~ z*r&Eq*?oK3qb5+ULDx}mgzXM-{=oHwak_OcVav|T4Ui8>)_348{pdt))59{d#QVJ6 z2dRS#NYFxU$$|};_a+v1$E~BkFN_UN$Ix|gW>ccf(zmi1&dQ53pdj_{Nw)m@wE6MC z%D&n`-Xvh$)UYAR-|v_8712({yE7(*8(D4Q1=YjsOKl4dIj6dlzEcvfz%%=s_Ki$q z-F$9&-kY}9KW3C(FEJ7~!*a=i0b)tqDW#~lq%Q`-BPPcqmE>T0m?F~pqa^2G?QK3+ zr+8KbFy2m=udwYGTEe!gp^GP;%Zbc)`~c(;*QA=Wg>9}udulIt+9~v3?elWv=Ca)| z?~Ky!q!tjM4U-Rk8*7183XKKQ%ugJn$H#ZATC)2~*`zC%jga|8bMMycyd7Llo#yqv z+x|%14F4y*e3=|Td^t|OltrwW!C_^+m8_bp*1XZrxbRCA^u9WM}!JGtD1M` zI1lK3za$eHki zSW6Sh;)AS(xjswB%QSd2*Wl3k^VSv0bL5NuMTaGI{^x6HkTI6#a- z!XP4d+gHS14;(Ga5B#w!Uy+F9kLweD*HwK^PrKLBanj<6l;RN?CMdg|!TJU3?s?sY zd*}O(58Y{7-bZRd27a+4xWv@3L*Rme!dIoc+r1gS?UQmvr+=M~$n0&wgQQkye=d5}k}*4`m_O`-;2xyZ#9&VmQ5Iznx++^_ zU9d9;-JkJ!{Xv@w!*Avjw8xBdPjv4>dhc#dr*!LFbXPbQpr+#r#6)c0&GOwfy5Z%; zOWBxQ(bXi;P89nSe?=`bY|V}TJupSeH$r^*QulFUR-&B3JAw`324Wn;N3>Xz_^fuy zdyymggV-l>TLx`s@n7~>77-16&4t^Y3rCeKG{}pb)NP4 zx`aA@MGtLbVo*U9RIg>dlr)q1Z`tw^CV$~=C|O$X-g=>m1Y^Kr$p{}Spz|@Pca=xP zL~s+uj(rH+z;cHg5$|RF79m8H?;_^r1ycJvOt!)Z4A+SI$wvh0nT(ur45!Lz;#%_M z7U4cxin4$C4(GDDUcgdWvIG;=*Zn0Su6F*uNp4mZ>^GklYuYNOTYjHT-AZc&okdZ3 zL~38yw5N$qaO$tBSq%aFs#Ux0ycpY(l}Wari4`7@T)H5sYgI$Q`0@&#oq?{9)k1!{ z#RLk&)Oz@2LXTptbOO1Y={t%MDpDN=B}Yv;HCBbq;3sv1CTB%JdR`8EuGDou*a?5b@AKRvif7@pE@Uk9}`CgB+$lPBEn>R%cdCC(nbGxR7 zs}%+!SLCJ@4(IMTQm!WNh!4zAFeT`Zm=pOqHAwl5{Lut0S|WB#2sdbUt*Fk6LeuB1 zdlHd6dHPEjGF^4e;uifw9Vgi9WWv%3Dv_qa{6$pfW(Z0s*vWKzDe}eNH8C5F zqmFvEjh$y4=9U(bp%JtW<1bW)W+h7xw3u__mxh2$vRs6Nvck4!xYZbqsY+np@_j<2 zR}nHQ@qSy*`SeARRK_Ji-{H&J{y9+S12F*SmnT!N28O_`$%AuaZ^3gfM!15OYhGQW z;BqN?C|U6i;=0EDb6Ek5gYabkI(LLl9ry=9*QOn4;%jFQ@=>v>EG#wGf(8cH?UzlL zzQYlJt83D# z*CXRhp_s+!IH_^wFgZ`cEH2zmxbEMp4_Uv@3xsvi6DL~U=>2+*$>H?y12@o7UC)R_ zHzs39$i-sm{jvLhf~y7*rQkVr%l#bxdcOlKjOsMtw@F9qi#XTZ0+2T;VTo(0$JqQ{ zB@gJ&d)W5^Gp$vAm|rHG8+I**?QP8jua-Qm{>3*j_H30Ik674kxNU=`b+VRxr%8Yx zl<29@9f}VqziM~}Wd3_MKQ>!^!!uhQnzajcs`k$wt#Yw#Bn12-i9nN8gUYi!F!ox< z;P9AaRB)AA-ZSgWa|x4%E?;Ej-u{cfpL65ruC41_^?@{#8~w6@w0%Ebc4jbWReB=b zSHSSEP}lo}Aaurv;sUpA%zlVrcUi>R7s7pTOP&ejK3) zV$Tf{)4d!j@|ZPx`0>=Uxu2ylg6|OZ!Na_u3JdzJX!cFD)IKn>eQ(*M8du@^kr?z}PKl>Ry{juwBHcyfVN?_#rmo99}{LOz4MJ0~w$%6^eEbr+9(wN@;u(h!qW-&DINyHm+jn2O~B9GK2Dpi;R4z; zN9SbM`4oU{*M;y#VLKJQUI}2=Z%r+iUBs(9l0I2!s{B41dd|DEqS4vf{NtxQ+W(Dg zzq)DI@^-IVl762MDRb{r30>(UEQtV&WHEZoJC5iX9lwSTIIgs}(fxeO6{$-7G4^1% zM23tQYqn)B(sy3n=VqVFtwK5D*&3Z)OCqRTT*c{E)gVu(V~sVq`D|XUkhBkQ)9+~v zd9!P?3BN-PA@N+KYAt5wQqIsuQFkhMOA%1TU!`m5N$l@$xAw&B?{CYZ1N{NCmxZO? zMV<(K5mO>AOk(iOU~QR}l+?HHmMK4c!n=5~tG)$%H7)(JQ_H-d*ReOH^*D#WFgk})Rxi8>i|+US5iDpm z?e{BZFWP`H-K`qAl;gnBMm|MJI1IDb#$~X?uOYC^r(3D6BFg1S$-r4bkMvJbkwNF0ac%6JZB#OQ|xK zE1wIHFik+84A$sXTIP1}WDM7OVkHLnyo)pt5lbd-fl>Z1d-$urckM4ZYTz_TWyJqo zvb?!ugvl}R*%<4A{~d2UDOO=5MjB0enMsEw>zw0P>@gz8vi6S><`gxw>MIBwv1I>N zRmmS`inksgEW6!2bS|=ivbN6@-9GwR#L+hOc)B$vD zBHqQt@H@9aRvkTiUxD%BuhIg~(Y69VxWGr$+TYdUpSAur`u4i{F!ueeh`3K{-v#d_ z&Qpz2+X^4CXKMzI8oldwG6>~6zCKzB#+G zHQwx&Q-$IlhX3d&_ZP%*?I;yQr*AUU4ea^5>?-yt8`5@W; zcj*=JA)ETdW$&)^L}=an%nj$e2deUgT@Q)wJ#BdD#F>ov*1WwjKb(OeAme+>^rkH3sAUQvO|WM zZG7q)uSH|qpJ8DC)G)WJ46V_up|{KXf0x=c84EELK>(Xu=-iy<>V2i+RJ~!E$MGqk zhx4^~=R*aqol1nuGPK28lbc_Az+Af0#;H{dA)B9v?%d&8lTviE%zjT`h84J1O1qFY zmw*^&2@w~s5$*%TyC*FX2y;n&m8&&hZ_^h!^%dxGXTfbo9!bd)TbU6^1L`60el*IW@c zTURy>clV1%;R0rq#CLcJU&p+7J3Y9KPUJ!?=B1X48> z6KlIkr+0UfMz^&{V}e7orIt5lp^X){eO5bZ%tjWaTd_{lXbMyl;#&>*O58uq6CnhL z5$9^Ft6^G8rYDhLv#W3-i~}Z@ds#PwQ~8CHUH7;DUHT_ltPJH?UlktZ^O7j*jjk_R zu84?h=ypmnFb34Sv+oWw3|6~Ex5TFxdJFjYYRr$l8~Zi(A>03&JjY6yhWPmH00y-o zW`5iDVWTIux3BAsAiuTNq+F<5RZH_%Bn5}LX8b(ZewZE4>~9XK9aP^yWS+pC0m^aD?BD3`sbknTn2hDV$!L5 z*ORW{X?o_ht8D)GIfa`B|t45Buhdy2VOa)RbX^u;-V+$~K zcd%fQS16k*ls&N4EeGD#_J#z1cTXC-vN4c}q(%xxi_4)BV=l2Ka-2A~gH|KD3->>KE@whHCa;@nv zKaY<*Zdp*W7Ym9z6Nk07+AR@F#d^qxSx1_wRFG0%ZHU3*_As?<(TQbs?Uc}U0V$7m7{edw z%u;9nz$+~1n2C-%51PlLvG=PbdO1e8!HSLNnKc=b>J>(8Plsds?I!*xe)qH9PpAzH zJ#-ZQuS|Pfk|$?PmDVl4jQxSQ`F@?M2zD*L!dHdTpj&-35Mf0j5Z{$+{VE2t9Ph#J zAMuEt*tFfNYYd?DRQV>E&Q3FK&wbT!T`c#=iY$q}`Mvk1*7uh5hmzac&2>&bk(a#Y z1hv%%F3o%=6?lKR)ae$6*~p|kBSRyco}*N-H35n|41{&jHJ`s-rmn?QpzXsU)bG9r zHP*Vc;vz77{V66C`VLaMvv2bSL0r;wwh+MadijAI+f2Soa;b|>(hLH zBak?;QVyWN7{S-Pv09UVnv&{NyWA1{U-jMI2MIj1Az;3jSTuGmCL!%r{a=1(oWB%>cHCRZ6WK9`Vz4>}HQ8NY1_%xrU_;Ps6^1H2H*- zYRuGn(TI)@N>)2L9jRVfnj_qZQOT5O<$0w9!Tqy5hJAd`i1HA%Ixu2KO3}%m8Bu@@ zRr;gVJQOb0QSw$9$WwRqzFlTxZD4D{qNCShTEEW6z_PD5IcGX=6*;+Rprr2t%mG+1 zQoZU6|6-<`4etf#iRg5#2KHrJDP+SR37WHC(DJ)WOoL{;PCn%3+!L3(Pj6%`I6=fG z%Pv;|FOL(`wVvd_} zthdeO`vwSnsil`~+nj_H5i}XuHk9qUV>zJaxUI9nA|5C2fRCWS$R8+>ugH$J# zh}=BA`gg~ueCh8`gIjkhFuzk4O>R;G17(t>n#l6KvSy2+e4Z z=Cm`@T0q%}>-WsjA67R|ak&{h`t+ z?pXQH8(pc?3nQ(jvL2jODfPzA|DOE{UZvJD9X|MtAl+KI-)R6y?daT7lo9N=uzJ&B z?xuH~IoK)=r2+#i%tqj5pjWBD$dWK9q+BnZN*9u2hujHaQWM0=vf5E7qMOexPcTHA zV>$~-l#-K!8Q`6&AzB+TZSUYD^Cbw~^9Q;5`?%R;kz<_l?}Od{7NXoD^K>SqGEGFt zz~ErEzzFF)ri!OM-6SNI_F*T=+?r5&rM!ij9}prPNPfuAH4of|0@<^m4=`l&GsEfDo3wrDex*i^As=M7G!Zj>3j3Ctu* zuilil$J{*i%AB`*b-;Q`)7hb)VOQT#P=vi1P7p5GjcwDSq2tdJgorQnbXK5~g2tTb<|&Y0a|uUO>%S(59LByoU0N-u6RKpgr9ESaIs_)%3DwVF~YmRXGsLohmOB_O1KT zR`Nel4CY)f(__*^oLnDQ=c#HScv$`8#>m2Ivua>!RbniAub>n1{r5F4 zC;P8_!kd%3v6Ym=ru03QLnr`Hkaw1okRh6kcMybQKCzy+6I&$L!rOp)Hkk50D^&Nx zmAiS3{0d7BHql*ly>thd`eEoH9*H%UXsooVyjTv?1n!NgVVgvp%NV953lCx#1&s@{ zEu)`*J5QL}4xex3y`Be8`%-_iKaIPRZ(}GlpD$WC zg+8wD&<%!|AzmoY_;%TcI|mh_|2djp@DM8AH1$sW^Q+oTf5o(=vl>tj@DR*2NT^HO zZ{-Mq5}LYK6+y%=QwbWZ%?um&YZas26avY?GJu+zZ{3#NQtkou8!r z6FrPda9gaXeL$lEuX-?3QA9g%P1DjH?cvbhBYLE?iKkZ6h5Au}7kfhR^~orM``jjE zqh|qkKz3mLY=Xq}`gF0X8c|C`iAdOeLwiL%rTRkjvDq2lz};t7L!Ra2imj%hSQ%YbKS9 z9J~)J^I$)1%lU!LJ&3JSR=GrsztSp|NC;l96u!RH9$RZYL)R%cFE_M=zQ#amtQ&jp zV^+Tp7uasoW=&`43P4c)M8jd=Qp3XXn=S!wkGL+nUwgo_(np@vGm#vTaq9FxCAtCk ztvwe5JXE6}pW`{cBwl)dP=3=aJ-*-K^4I-wfdoN|P}h(a6C@rV=WS0uyfrYipkm~)*5>K1D6gA8^`cU&U)Lg_w|v?_R;7lV zzAEKATO&(Q7>!nZOg+cWRFD~pc6M=K4Hw5kvyjjqkT!?Qs0?u6gTVR9&r8c+E!xAg zyhF&$^As+1rv;PEH1oyoQL$vefrm5wISU_$GKsiptw_3E@loej?YnQ_7D~X5l6_-q z&^we<&GxCKAIY&J+_;x#d!Gb1e!jET>N+(>I|A2Rh#J@L>8m}a3ZnjG3JVy*lbm}_ zyIXBJ9HoGN`qT(=tUG4bn{eUxcyi+($9^k7vRZYa1nPMes7#Ccfa`uERg*JxE9g+i z*M>JJvAkPji@kEFhtxI}(s6{U5As&Nmr!e5^}Y+i)XPd}3m`4DXjWDG0R5a#TGGbg zJ^!w@268(w&O-F<>mdekz9Eq&IbPV74n9+mvo|s5$thi~f4QE;pYy~P7lEn1(mT%b z($Y>)8CTApw7PgG&mM|@Pf9F6k@B6t+2LHle=UI$vtvbJwSW@i%TqD|J`~bDAW`1A z2=?E?56>=l=xi9JP03c#_IkKJRn@7FXHmc%AZ&9dQy{MXC6XYao|rEoJRCby>ADm% z@OL%eT7J1&=Uo}l``pFQrZ~!0YACU}-;R=B9>dX3bQL}^9V)j8PT5M^JGRr@VJ<6l z%mcStmd~`lxel0k7xY~(+DnTsv#Mk51LMc$Y3ULun}C8`?o-MG@1A-0W^#Bk8he51 z>DC8G6EwUB>RHGBkpb=DZB~0EPF{Buo~*F+ulGAyyoB_b26!Y!J6nneYhI*R=C}aa9~+e@i#R zYJRuba9S53S9QP0D=)qB-fQY*XNICI6+EVSl*u)&Y@Wk)Pw4{FZvosv(3LNUAB{=_1Sf?98M^7qUw5V!B$G`ek|WND-l*5V z^fbNN$A+$#!Ce8Td|BSRT7Ao{92E9}rt>cqE?*GW7^c%)SrUY$-*C zYK~;#yr$CDuKSb}3GDpuRI<->Ub|&NDS`*9m)xGi9s%EvEJJt9F)QmBz*OBKXigjv#(4ZSTsdave=O=~Ya@h>a-bD9Rsk6++7>VrpD zc<4VDQ4W^N)|Uf@+(p2u^j)<;%mnWvhPetBX*%d{G^7 z;Y~;D0zs(v;O(hO>JZpV!8KTvm67^n+Pf7$8@|Ap_|EKjcXm;@LRKT024owrS#Lb3xFh7Sseb?)68E@8{kdF3!-=}q6C3d8C| zA4HP~ihk9X#P2C;St)$Suoyw3Q5Cg6BDh(ME}$Ziaghb(noJ0%P4r8QSXmH3)cm9XgEg9whc>>(v^E|wxywq2@ z)DHZd0(!z94!4EePj@feQ&YW=bGd5=iWMO{^>xCAEOZfu@Yp!cfJrOaaBW}hyy znv>T?hV!QqJIa?>in5m75UndmBS^YEWQ|foN@%{5ule|=?KkSg;^MaGXxenv!~guJ zH!wraOIihmqZ*i=ReS%v;*@CGnM3z$FO(Q2-0f}hulDru?rC_VBom*WamfW??*u#N z@?ZGUsp=i9V7HEpT~{lIqAEeme#sN3D+!3UQB@dPMj|PUp6^WSTRy$odwe@B?|B~2 z{qIy)V10*S{eTAc2e7+({*+pyr3MsKl~p3u)%4f| z1iZ!iGkF4^a4t346O}5SDg|K(ps!a|(~^0x8|0W)hZW_KqSI*Q+a|4Qx#CawUdHyc z@#>n%8zmQNDZv&;gRuGI?9DCD%pJq~Xg`LczS~pbVhQOh%dX%$fe+-vS56A9A^1E| zCuSFO(aC8%6oUmwNjJ1YWmwPtRLeOFnI8Rjeg?L6ruDbe@#8T%?vd-v<4FrK(Vx*i zQUyHYLPZcHed)V*$zv)r@32c=Yn|MQU5!oA!QWEXCVbp z>OC#ETkyxqc?n>Mk!mqY|2mSi3TRXQDpR~6lM-=py-cfr9bB#v6Up9i4?c@^o!;3C zEKTDZ!J9sZM(w+RTdY!DffY`gvm;lw6cY(1nDevw1v?#j*nVnMJ=jfA%FpvuD@HQ? z_7waaOJYveZ@GNOFQ)Wh6RmYVZR_p>vq%ITh$5C%kZv}Z5A&~FeF!ytp$(`2Bd(?? z^uerP)vSR;_j|gqruncgj1T8gD$L}A4lQZ4y{r{1A4XvTtZzN+8yG?Heg}ObXO_70NRgwJ{|KL`NRaMfJ zM3h`S+Y3X2ioG$UHAZ^{snBBS-F0#z(B?-msHjL$y;!^QS;=2Q;0j%ju#pDy6$+0& zwkEyYw#rxf8LkU;2qx)-{FvFSys=j0cI=kjC!3eX42gUY-t`_ zXUBeWtF0Aq;D}uj=3i-rZlB=;*qN6SOE#w zGiT%NOgS(dD-$j2d2TJ28Yx64}DJ$gqshA9O3 z^({!^PC599BWN372XV*m;wBs$D>odOTKV4-M`yf@pN+Eza0TZUCz&$eD@;~$?gdo_ zdX#FFPd5n(w?RxnX?B;`)|xSt*0RUWKQ??=4yy9w@L?pjK3X!8O{U`4NKPFV*>Jyd+@{Z# z+PlG^@58jt?LhFfqRdd6`@Nh*d~9z2&n2{MU+*`5(Z^&lkH)CgqzLlrri{U;UT@u) zfURQo!Ti+Voe0C;qf6pfB&$Sc_t>^iPSB!EpRHE%@vy9JG9#*1o=LF51Hl|TdVyQX>i zg5h2XCc@|v&VIDi<16|*gA%cGi6dWXIUB#G-sr_QPB^JMRMjtZLJy8+>sMFs{&-AiS;_WPXes(6JtDg?!{AG(o((MR?+Xp5+L7sJZ-62p%-ymtRqsJ9AOhA{>E4SB ze>1EpNDY`dNY8BZVt0`IR6zi6u5kPSJoiV+@Xr#Mvd!@M0Ha~2UZn)y-g=3Y@8-F4 z(i;>8fK9c^KUh@~H2Zq$`Yu<*QKs?xK(9*oP#&nuJ@D0Z2-0o|zu`>+^^-mfKchX%X zcaqMm;|3|QE$P>9W%c#-cdOJ@m{bM_8Z=L6BpN-mB%C>~9j)3hTs9(hKYN$0?z2-O zuQHr{b9zpvDBVKK79^Xlt39Bo=J_(jF3G8EDJ#EHo!1_JW3;UWFKAu3VWjX{9=|w0 z#2zW_E}o#&o}sLz%md#*I7km0H*R;^_{QAB>;xU9<{=aH@WJaucUWNI!2_#O-SY1I zy$udPj1D3qKv{WI+2~^%Fvhu5uw`eOfa-umUo@A?t&>UPwG2t0-r)f?#L{J~gm2?x zUvkS}a*m&2FBN~?wcS?RIp!O;mhTr7d&t6lgq{g*300o+{G_~uu})MQx;lPSfUW#) z65d*uDU5@$QD%14swn#nzSF$(qL9o@32MlvQ;+36*uQMt2Hjz95qd78DdAzmu?OM) zZLA4fLrNGOs3XsuG&jjpurTcp3698DQhsP+4y)}@IOyL;MZCD)NrA7nXLT)fAP}R9 z^wdKcfsRYxKva$brsb=b3Y+30XSjDLWQa1XqFzSzjzsYPPI-BF7uxVT^r}ITnDDR7Y(r-YD0SeJ5_Z@6;&^tJ)i9@_ z;IX=R^L0alno|1+|H1{FqT#6|&3nq~go+RLbsK~chubx6UQA%Cl>xUY-uN3RKyA!$ zP(V#0U%=G*T(YxAhBEr`xy8*UT#=`kj_hKkalWT+Yri^fWi%Svua=dC%((IGvS&r% z#X@DL8uMY;c&^T9xij=#pU#q87$sobgQ8nZm7QrfeV6xDNfIrS=%6mpW^C()PBk^l z;(IIz;B32iX(?@V5LbDZm$tgP3J*$Okh?!JC_)^1GdA*kZ`i|K(hA_372?P~+)7k) zG8)F+zWZ8jzv_|J++NUreZ{fsAo#rR2pNlYWou4WTpW^{A6DCx5iRRc>woDk<`J2> zBjcl=lb}4TvBeoe;?#Ia?0VWcBQ7H#WPuO;0Vi;jDm{7z^cgL`vjl^wMFwLI=3DmW z8(*|B6yU4>TmpQC%|luQPftS1;P0eORPCkGH4fPPQNTh7&){Qlp}R&RPrgL?J0a%s zg(TAnI%QO#H&Q+O2MQgrG7sbua5yJ&UG$aA!;Phu8vq7dy!;0S8#GY5(LbwE#YyKQ zxYcreqdu({EB5MEgz%>=XsF8Lh2`Gji2ydG*LO`$bF>cH57O~Z(pBD_w=S;XxDj+1 zwsi%g!P+Ydb;1*!=!m`0{Jcs8!bY&ZTyXZ~R1isBet<-0uv~)0jcu;VP~bPXkK^BKO^n4{E-dVEq~ zP_ch2E;NvB^`iXux_!|eKusc|e;IxHwwTw12d7yUVO=cZH;Z`T(Zp%F05baGnM`+V z?p53*DS;D4c?pcGZd{3}uIJ>MJBB+6(lCa|)iBjw=%SDZ;@9H7Y3u!`qX_ul#hNIu zwIrO9C?5C4ni5Xys?U~52`#YxYOKZ@eQsu7Hy~J-3MeOAhgRCsir1q04Tgyr7vv;^ zz#>;NJ3V%5>It8{nyNdixsv!>Ggn;1g7%QMK-B!18}Ej$$&_)0h)gEgChit=Zc9!t zDFI|uj3>bHQ-%rA579m&zAyAxLp)Ek&5LNv>CfQm!qpAbmpyy(qDDH`ll99L2R%GC zr1K-Sc`#G^1c(!Cz&GltMbfGtdWUNovYuO-$Ce^o!{zvTqE=k%E&04#xf;%wliWnP(egnpff6jMUsW6?7=PCJuoy}bz70pA9ndX)B zbF>GT!>a5;*u!^1BoHOp+h)K~jZKCzsq5OG7pcc=}@ zQMXW*{#pIrs(JiFj|*q8%2A9SjWup(+IA43QPx!H<7NuPs1aur0m>O6a6AkTmgdH9 z*10Uv1sI?pf^FE0_?AMbZfgZ01I(J*jpYYE2!L58!t}P|2qBTFLFNa|ZTYC!u^~un zmuF@3=S>gyxYO~bOqmB0P(0U^*<|;LfE;R2I-FZ$g;=F1hA7rf5b<1J9=D&qISS0} zAa4g0lWa&L{JTaGobJ)c#2g9nF(Ld9!s=v!t&Kc)*I_cJ0g>bg8?MPB z3j+&Iu{)f@e?xI{qSmD%Cm4qiqKznNLj*eG%U>~uK$2h~;iVAE$}1QV9hkycp&e!j zVvVHWq}x2G7>%|q`GX;S9ZbwnZFFCyi5?chGxgWIE@u9|sl)E3sgeVlR1nDezaSVV zFB-kS60D-Y^@e2_ZUDO%M0t?+pw+qV7_2QSvDzES9$}kl&NkWA`zkSg^X~mhzTQ_O zgwfYurmj96&(l_ECXVb%J1mTYfApOF^HrdGQE4&BF%jdP2lRNd)f(?pREY8B#a4<# zJ*46fHY3mM?@4z=7AhDdqzlA&bWXYA8sHKK3GSCFbQ4|HcC`*_JZ%n}WJcD6SKh0; z%tiU~e~}YFxXdZ@`i==T5NDwZ@6$|UoNlPTtArbGT#y^W%xen%ojK-9iJc0?K>86J zbfD-1NJ2(voIJG5?T-btI<-m)Iw?&Vu_ZG8Tu3Atv;o7<4>O|LUwgmf zzGw0QVSo!ikc*Xq#BB>qWVn*zyRJw|I}QbxEgma0Iy;&8d)c^3_tO@JU93P5aSIN( zA3C8Qt{63E&~cYbG>z2+UZ|CQ^GYE&?5nC*Cxl?so~|Rz?qQ*}%3ahm!YYT=%NTB& z4{1c@&CPw;WVO|D9U@``94Sy`=Ef7_e6X=`dn0ATD6F8k-hJ~L$f!;H<}%5_WqRI_ z1-Ua_ZlnsYEIlxXS>l=!JTC|sXKlTh-4M182MSx1SP(4Z^Sz2!1gY%M&=^fwLP{hm z<2snq?nj0WE6EPkIyJr*3O1BWk#{vUTRj^bR2Lo0P-4_S_iV?&pYH+4R-$h`BO);8YsB`V6lI9)b^B0Y213`3&(U=0Y{rOs~e=b(q zqn_*&Aj?=B1<|Vg6bH%EMkiA%tR!8u=mp#4lp)Qz-NyHX&-M1B55Z)Smx8||ew-%N zDg#>Z4p1c<*(apj&H*hRKnUa?@!(X}@rSB49vE-w&lHkx&lP8@p5*OCZ-e5)O>jwkF8QLA@`j9H#i_)C}c9GnQ6B4%(!#z<#c05 zoUFjiRjoL!C8J0V731e!BMm*_|8N1OV?%kzPo9uO=kq+A^i$!r7k-h7Qbxg=9h&4D z#+!ZO(R_o_!ag4Dt%66ppvFF~DHcZsoql`lK_JH$(b~kk!w=8F;ch3#14r za>x3?tTiOyIS?b^5iPtkR-;!9MONF!=NH|(lth%_nC+XOC#GqqE))GM`$9rMi$8-7 zkkzPk3A=nnTWUsK5OMp&#iw;>`8_U+&_p0^3|1|)XxJ%|K5AGk&%BoT`pA7oBXtPa z7H5?FQ=v(~`v-ZSJFXtO*1q5d2e=7q-N3z$TQGkuP|MpEB^!?4wNnHWHq|+ayUF2yRfN3EK@yioMmf~S(PWOsNVV9Yv%96Ip z(vLKvsZaT=u05;Vsf>Xkt14`0b-wm_Ir-X+sfk+5*tt@jVOV9Up{CS0iUuIrbaC4I zphA#o>&2z=eXuIGMfXwRAKG5C#qIrC7^W%QqrR;=FD;!(|>Pech9_W zm{x%hj+&w?w5?Rseq_l^OcG#-MA7hTnh(RDSLy}waFqXb$uFBC$tA?jtd|d4meFk> zF3MTHRZ`mW6~VZ&Zr1G{A)qi*4*h}1uN{RdRQWwsqH#Q&pnRsOIZ~1u>Jq&Qu(Zbu z3q#UhGOI!cq@j_AJ_K|PF6DKY+NMFA?P~Wo;~0h_t3kB43Yj)2+p|InPB<+7t%+uu zG{4SVHkF1)rg<(%b>_w4(Dp-!2U`5qx@{cYe74 zIM>U@wq@oe$+>f0GEJs=N+~h_JA;29Jg?Hkzxi-PW1ICuJy^V>)EjxH#vwS8D_eQ* zKy#=qY0**q`>*F?;VQd!FTiv#SPIT(%m1|^h~zM{cmp>p`iJxpsPjIu3yLgT8@+V1 zTEUXYT#wI>E)oq6sT4fko<&eoiBwc+gA?K2&OQ#P)0~@z#g^PD>#Yg!r~Z)gDeX!w znK2yTV(~|L9RZxRfdEID+|@#Ob{l)D_^ZXcva#f}i1!(Rm|*@(snFf(+3ew__SS+O zmQ1THhMc~+=C3F)^0rDXM+&E7Z|P^&zyxlzoq*Fo!csr}e1Mxs%vODF z`R)QoE{Wci%W2~&tIoI{8*!8e9tsUrs`=_?l0Hw3KaKT2Nc!QOG6@q}o*dGzr`-qk z>>%b>U0u>Hz!I-UE4(kaS{S%ug&(8qS=NsK-+qSqk;ZU0H=6a;>B=HuSS!Z-r z?szF>&(}`qPH)y-E;Zp^=%ude))dJj&Y)3#S8bL7IG0yHOxVyRy894XTH)ucn!PRNgc7 zjG~{&|L}r-x~Ij<;13dhJql8Rpk;Wf@K~-fv&)`JM;F}%Bdf#a=AKXA^@@i-QR;DANZ+!H5{k%!)gZ9Omoqh}Asy)^PQ!S9AzK4$ewImg^fLdOWzOIw_7%!WZfQ~fn>jmGGddI((BG%IHAg!+3o^XbjW( zZZ_ZDhn1y^@eK(FY_EcDKCmR&?aB!_@NZ5ftT8xY+H#}9^4877+43PEQsEs!p+7j= zK$^4y1R*e19U&bf`TZ_72mC#p)x{jto5t%Sxi*G4%5y0htGAzo|9NQzXmr?*HkOCH z@wVj%7BvCXn}oUO+A2&%%M1hjO>%BU7(uKHwl(lh4&#vl9n~~K)cCxob3^%4NmyWC zJOAQ-A4!EAq1u1&q>)<@d;XhJxZ=eYZu;WF;wULu)aey~`%9%F;g}P8x05q3WFtYe zQUu|2K$5$l1pc(4M`*6Mt-c_5T(xi%NAs*I-ntA6A?X_L(PVCgTWvhkH2u-n!r=eH zqP9k+c7jX_6xAI;z?q=FKrx1*PILg=R65i6J9tvSfB1RLf>aO#K#($Kk5^ExUL`mJ zo9o)^TTV3g0sZ%Xd>j{vCa-9pc{Qq_Y64IVOjke~G|5*89H}TZ6_>T9uiC?4nY$c^ zF^Qzr1k+p`?|zorV8nggf?U0#XWZFZ$Q+fi-%PsDj#rK5N3QaFEP)mDIh;4q zg6D|5uTABtCFyFx6`!^z%0-(#Km7XTSM)3;feNyA)rS3dJTs%Hu`<%;Zewn2I-Hl_ zbmPChFLLrr!&L>G!SRVA{Yr?uBlqhYsdiaN%4p%#)`>2li)T1x6wBoXaqPJ59u0$@ zGKxl~&$G431o^0mWMMBRvnRz#2OF<2#aKlF1BSK$ zd~e0_z0aPnac*od?f5_ziPsqh%WB#Ik=c7D$>Li|B(coq^O*Z^&lHvi2>O?CM;Od& ze1ADAQ<=TjB7F`@Yp5^>O5TLcUUaymyuIIXt^5psF5 zE~i<@3%0d6Xo@b#lv%pBaicphV5L zm^W~xa9I0)3tO+>D7|)tTz&m<>jezt;1?d){=ZWPbeN@(T3u^n-r zSfB9|3g3KF$)auw+-AKy#d>*adOytgeV=uNDEPSeW<>Mfi$7QHZEwH2A2n$k^xf+M zS+WXkBR-fyxV9W^2sQJSbE5^S>fDbs@vMwQl zLYo>B7EL{UZj*Ii>QAnbm(jGeiwg_aGQl*NzSp`o&NQ-pXCFg|Yper15m?RJ9FoWa z{h3-C;9mQCdYF%VDlYElA-OB#1a*!o9o6yw{q#d*-w?Gd=M45`(f3QAKOCL1{@NyQ zn0;f$XSx(opo2=Y5wch~QDBV6);o=Ut!b{eyLYkUSD5(_!%>!EPFAiJAJ@oi9}tHW zE*WZrzDb@A7A@!qxaL}rd~uUM;s<-o#L$_<)|Td|JRiDEEaZbLOh5R;D>mAEdH9hzY>{^9sOic;BMn> z&gpXnRf**VozKp3rN6=01KN|NQch(S6H=--8mmyZa?~rK{NYm$pIfxG7-yLSfo#)q z1TCkmjebgTRE-id?tP>JKVHy>CmE9mb$t#y|BKFPQ#o)Hz5*FW^%{rEnNL+4^OPIg z(8{go@^krA(dsel&DEld6(p&=BkZ@3k_AG$xlSV`;0rQhqbu)0*D*3<%Qy0tFY`0* z1f47<0wH7ceP_ke9~2ql*!qJa>GVL{?5dg-Ggs?#0lj-ynE0&T|ryR zr&~*$>>fN@98-NwjjHtC5aS7^><3Ya{jw`cZ%_CZ8?OV(Wp+&q&HHa@l;*+CXMP@0 zlCfv>g=@~F%9G)yyR_$b*?gxQRkgbPlTHIsgXsC*UaVo8EnUZwP~b&<9-r^&LjN)_ zKSu;Ao3NJwHOgTat8(4RJd&O=uT6N$QBy~xoo#(n@holq(2i)Qv>QR0tw@M5!WJ;cm;;ed-4SMcZG4&I!e+Iinh8Au#D}S|oelTJ~a?j%x zu;X+a$YY0q`2|60uLl|T8<-<(<{;={R4>xvj6vXG2@l7bEd&Z10%V;!xWExGQVc5; zv{M~*d*fw~EsB=zQpPX4IJBj0oY&D_fXP^1MK*2eKfKdubi^^+!wNS~;pjUuyEjO} zL)Hn4EN%;exCn|N#9Ni+7l~%$Ja^?_){B6G1yWX{?O}%Un~S9E_JZ1o+1*ISZ0Gmr z!;d~KggJRmm=QAdc|wCh%0cxzv~aIMy(s?*kt2DLVsXdM%_HhxA5YGCH8Q)1=xO1^ z?qmNVl%~(2c%qshxPH@EoM?9h2P37Ll)%1o7=HY+qlHqpc(V7wTFx=3x{Vs+0dlu> zZWEYi)==5tWe|6beRF`Xtg*+F0{7dK8WlUP>lCszB&fRGSdCY)nYUE&;r2M0CgD4g zHl094e8(x2tgv>Ofma_Ge9N<8Y3pTfViZGas(ogrQ&Nyw(1?IXWICD8macFoG{iE#8(zPJLL=cNV_RM57Mog?6Rkk8dZf z^U1pblihN6rAZO5x5XcVD$OC(Tov@!0if2bJcekC>6{Tlxmlz|;{uTH?>ds-WE+A#Pq$HgUhFS(CN1Qwazi1iQQ8%>zTj zL~k|FdlB%rGU@#ya*5^O$JjUm~h!6jb zSLrhYVK4Q~)u5dnCEr_4`;`fnj~twqJ~H{9t!3ppp+7wplp;JTA&L1 z!|5Ra#R~VO+zMA@h^x>+TGKUk5na%mz9h$#O`=~r}VG}F%)x(a*DdZsgcr+bvbmB3S-?@O)sm+@40l)XCtezI zQCL-<2to6O)%D`0>P@5v#FJF{Zo6D)B`_7A15ZQ^cU#*g3s#Kw$dKl$rX^F!$gk|ASw#Y;#>`zMr_NGTcOYjs7N*4>2bGu!s zHd0X;G?L}iCk*k3pMARoPC48#3WcBae-tWUL&>Mx{GFW7)u`RsB+MQ7^xlyn!H-qp zQnqO|C|7nbzhoIQ$9mGL?33Y-rDRB_c1|j=aR)1#Byx(o=fQLA$a`~OFF9-B7~bi4 zP0b`ltu|y*eSqyXT4m%fK+n9Z>VKy^$c%s z1(pIcb69FEiwKmzV`WX}%%7RD0YX;=AVL;L6QPN|d#Fl`PK)RRU1QaXe~LN`uNR=D ze#UZrQ=5BZTh~0Kgf0XWKNm?EY3?K_1e}R`dF;A|k@1<`Kg`gQR$is-x;SR1hPfEM zXlD$*rc)u}w##AoLA>zQ$qACxjdvtq;eIhszsnp($u-AGc*DA}(716Bb2jAn!z{P? zmiXbrnW4=KDfVfzZwi2&lbsz?ya%%P)1)aE1HtMXw1P?52Yde5k>~sKh0CeiGeI`_Zw4}CO9B(=I^5@LUXTq zVlC@`nXfvVu(V@d1*^%L)ygrBySJ=zY0Y_xW#r|bHXDt%;-t|4+k{0ZZ{79NXf7w6 z@>L(#3Tt}yNvxUIEV$`}TnaSnxvMZ8=2>%912jh$ZK5aQ z^3q`Sxb@Z9d{4$j1k!<3fZv%;-3+*inwt~#+Ha6_B*Yue1bn?Uj{`bu^Sh*M z!LY`go119wba>lpuqS^9Q}T$n6AxoZ>)(;fdjqyNO)yq_ZRX$IX*;|$d=cpB87?%RCuVYe~B>Ml?KRqza@KQF}u*T0VH1*Nf2NIDPjmCnYz z8FdNHpwP{bL+k1Fu;$qGP@G3TU5FP|n9d8Qn7V{uhe~GLt7yw(G)GxSvWMpRz2gawqOSQXlcb(`?uDKW5MU7r1-TQJpLInhy@f%BRk;do2!Z zcxILp0kkU5jbnRl#cAneiL}Zj%vtDZ3U9?L<48PAx}ObKx!KPdjkA*5STq+s?BCq~ zH|x#QnjOOs?N?VD*wmx8;XBI=8Al9)>@971bnO45=sf({dfx`zp{*Ki?O8PvBUTYx z2PGsbh#9N3g~pymhoZI$iLE6fVvpFPwIx=?ssybSrKLqneLH@y_kTF&e4gjr_jO(L z%!2CLal#Y=Mhmw7G)wBgJ!FyYH783;d#zjKeTj`S6G6OPq=WrozI58nB8O_;5mdxntYCvi|;T(kD*PfoV~nCz!oXi1~yHY-5z-6kOqcYrS5=kRw~R@bQ0 zdBOC%qcQGIiYD)KM#?pV% z3VzvT^Q-zci>bBZ=%)xH9S9wf6XXd2Uc?KOo%gGGS$uBT}l7 zPn1p#INSi;jaQzw+Skz)hhBMQr{0{4D}w(#&Qw#FvR)ka|DlK8zElE>lnT2TS5m-s z{BQEFk8*)&sfkwNKG=KD%4|Z^Dz5Y+ly&EJOaApazX><_GmGHE|NRd%C0st1h?11j zUizreC3*otY_%vH(CSxV7J&}t(gLW=CE;L8tC+g#7tPEKyEG5HS)GxbGc0By{>@rp z1SSR1?Ozn-+~LxB(4`(4q_MzL=ot0W6qVC5`KwNBDQV+cmZW&LdsKjOw*080ugayW zp@T5XWyAIqV~FWHTMeK^>A|{ZdQroNk17gJliEQM##8yXo2xVmkFJu(BKW#xN86&G z%;K`m1E-tMy)jnoY?l{}xv35meRCXWu_uvw<|Qg8hGDxoGB|dNO|W)_JztnoyAj7+9=FQ3EWS4)=4StoD&(A% zu|AsaEG+qgdJlP4vadSA>XWK1gv^acU6RH_BgUZbe2O;r6dOB z;pmGgamZcUr`Y;G?rUgwi#WPrQ<}?1Js)7nl49rG1Mw(AM;6dRNCWJfP>dJM9FIW7 z$`3u|$xKryIM{cH!Y3JX&Q6P?gaR8uBiw@&wc!YzUV|bsKE&hC?;9D4dRNy>r5C^_ z<&8Z!J|)Y1H-;4TIn196ucpSDjJ&oN#p{SayEVq=P=gS?)cN`V}Jc+%=KeZ#KL^A8$6}eJ?fsdDvv&9LqVCOo_d^nMiRKA;7PIc;(k7 z^SdqVL{q4H7V#pD>UU!2jtf6NO0nBy*sB#l#wd2XepDG!SE^n}x1Z0E5Vi^~!-C*ulVt?i z)Ag#B=1icrReTxV2rf#Zy$&<6!IU-ZfeMROwPs&rA7QdnVwUQS#;VOtPiYLON#Uv? z|9`*95y>HF_0q$bMSxL?mC~%tsDX2@J4ZkeFM#S|vUrX-h2KAqynTKF59ufo+&rTf zC+Kk{w}?IRh&Mp1sva}p$K~m1bJ66Vi`u8XYSL%=UTG|mj{5ISioJVthpS#NQeu#n z96xzr&UIy~7iIU?19m-o3;9p=<-Tndy>@P#f`0V9)84tp#b8t)TY%g}L?>K?gd1~H z8}j*OoV!wD2Vd2oJaBXZ5hMwWMp~&?-tf*No$`Yqxzx4C?0VmI( z&efEkLnyIzXxpJ8K0aS;-OY%3A!(w6BmViL@aBu$Zoo7>$_yeM)jwN$2Q4%)6IMA3 z0~Hmd_=8sk5tXGfT9wkv&|qVFJN0$3DUX5L(J7~i)arw{9EN$ymhVn^-*Of6>v*t2 zqsmnN5!ydR8^I#7p(ih#9Pddkk8rLH-6GedhPu?x^h3YAH2m8bKSK+(BVER4t_O~+^<_aQ1 zZ0u|HLfZ$kr?`=KDS+@4v%&Y(fTlA2Ey3b5W|_igdWTJ22n`KbpVN~xIkwq4V8X^2 zX+;tQ`Gc2i>iGmN<~TTwpN#M1HVrN?%U4}mHV816KcT7qL4gI#AhU{%6NPmd-SS@b z{rZ=g@p{HlXeMw&l6e|eN)$*kznb51-7-$saI`c|Nw0~GMZx)HLgdJBrk~E;ab<~z z!t$t1@1%rRl$(?bBEGWuhM1ezaO+q6b{?eL(Y=VIF|f|-55PwsQ16GXjI~(+Ll1fR z*|vr2>F(%3xojVc75kGrjt$ehd{%>5JwwgO7TIO0Sfsy8K*w8=j2`z|N38V|9Xe-iJzocBw%xm6he0F*q0$ zT-bxlD){n!?B4SkfBzQwOw|>w@-}FBH%6-=rbEaXz%BUUd^gqljDXKWyv z6JnzZ9NtRzR>aX)Q!b1?5@*;A|E^P)Zfa@usoi7Zc2D(QNfVR8#u*TLnfN`vWCNWj zN34nL+?x57O|4;ATPq2%m*zI>wN{vV)Eu1APz_`YlexG)PfPfhdKF2G>Mwe@4QBpC zX(NAkwJsB5!y*u7nu><|4By9hjMRygPXJaFY(!LOcdG~ac1)>RWp&1t{9X@D6z zGf*C^9Ztn0@jk1gNh69plZkw=kj)~}WJ*y~73^9jh*)m@X-8|AdkgVYbXArZmSj1w zT5Q8-MmlWcU%It{r4@8L6&#n<;Ufw1(iuFTGTsLEO4zSo$u)>h-hA!Zcj8ry+s%`q zB7d=k3*2>bXHWTiwXwbTHMBY9))(O{g;xPNM%-uiAxI&cgDaAk=Zy18DRwfGcG+_qw2R;e!Hq<- ze-0Fd<~KGN$XQ`S&j>&q_suzf1(*LO(li>J7Q0npYhKAuBOAvgkSR>bhCw0tf)K}z z36_)kmZ&wy@*N16Ndh8xcXTFU30nQHZ<(XCri-HJK?I<7t&O+(E^v%3v{YM*0#~dY zqOvK8PPptKx?d|iVvwB+{IFjpxBn?6ihN$VRAA!jLqx7+tQiV$cHGsp6j}>VFjA2} zZ}MIyTSO4(7x}uob=Jj}GbFsK%w%P@?EcU)(9_#$OZ(bu@(cbY`TAmE{mssT{V#?3 z1PAD&v#lvX;5S%%oU|^#8apgM{+?_i#26zRp9!AiTi)-FtY7o^@75TyFEHE5rG~nZ z_%?+PijT;Q;S}!oCr0`^T<~nqa(uSpRMGvhW|pANN`m&yrBza$s`U2C5r3C9VXE21 zf)i$%2!At!D_o|XIDV~ESdk}n6R;)Qeo#57oPRh3bI_Cl6luFhQXmttFV^qyN8WLm z3msea)WECPVUOg$AZgc19^;o4M^&SSKN$#FU;cD3e^oM6%|zwKyZ@cxe&qka5<7*% zA^sf!+4+^qgZJDIHphma;~{6(P{7P5qYHj*Pgm1J92aVyHf|i;r<0;w=MLPsSoNA3 z?|YuzNCC8CSn&yl(|aNEh*!dklxd zxYBGkg&bGrsd7eeM2KZ)4<@3gki-|S$}ndxMO_tzu!MVLj};zg@|J0!*l|}Jk6(tn zo>M)yzqH+^!0e)OUUUZ4V#YZ;KJ9N#Z_mz}Tbup36(YOiv!w%!30i8drT0 z5P0lWabsXU9&k8bUdvp|1a@&F%ajx28*}&$?_TJ8W#_&xVD{YyrJyH0Z8+tJ3KE5R zdZZ=bfc6_0l)bUI#(}8_jONklv1{qnOMBgFgPL3HFGkAs>CYrUVc%g&d$)fU*I>*5 zWf?0bl?JaBYPCAE(&}btY(IgDR@mGwKlSJqz|7$d9+$E3?++aH9P(mBxE_PM<+D)-QLCdg%mag4%a_7E=96Ht1WQcN4{;C-Gi>p!XM#QCuV7T&%ysH?V!ENPAZBFOJpL^^v-$nE80b^J zCL;wa^8k5LhEVIv6uV?W&lGVZ=%Lt}lPpU^ir?C;V%W7b?WzOqAs}id2k;kP^i76O z7K}BLGYAUKZC@3xZ6A&YO$Mhat;1ECa@Dd^;$20Swf`T$vE6*!MKK=xBjfuYUtM|? z)Xy^_qWo5OI&oZY$Q2EO^FLBkekFYZQ_E?$*j%`f{GZI4OlCK7Kh94Pa(w^&50e$T ztfBDrrbP#byG?rE2Uz@9LO}U~QQ79wOD`0%V`z8IlUh>f6A=~kq}q9zl<1CEkQ!R+ zhjQ6o>xa!Gwg?(UAFWw1LoiIfRAENs6>PF$g5}ZY@ai%s*8B4BJl;vC*D7Ve zv-Qxw#ob(iN3@{`Jz-w79PT0tcRnPXa#q4M{8{spFTT~g(%P4DIcomkdenD z4t5Ey3kr|)RQwc+C*N#lFN@_W58CGl!ZuEx(8FC0MH7oK>2>{iOS>Ge-nx!b*_G3DIvsIb z>j%|xrX2hgSw}0zgj9X*_!u`A3k;@>0>#4#w6q({D6e%s!E4pv10sX&kwTOz(cHw=~pf5~+T*f?!nM3yKnL!~>cX zm!biOdGDy_#+WyF-g-X}L~6&Qephs}vud;k_o^j15 znA&Ck^jCM?C5}Z=Vpi&fQD>9_K0c2Y<<(kZj5*zWMj9A1TQ7cKY;s+A6+5?%K0oMi z_2rMZNspNc05O4i^1dIDQguUV!0Pv19^>oe?8|&F@X4^GxxyF(>pK(bF^v#cFfw-4 z_C`n0QK*efyQre*P8PF2|3_TrtKtXJ4lLZ&Te^W6z$VW|hcw?rsa<&|9of+B@$SpX=9*yNBcw z&YgeY{A9^R^ZR6Zfd~H)l(5V|)ivcwA%zM;7kNqX#zhLsEvZCs? zE)ODosXKe`krPic70186(i!GQF{y8J#z{e` zLxbC2t)|-#4ukPB)-#*4XaX5GANBB6SAU!3Xqk)DxiE9B@!hisAv>ypP4|dLWYWs_ zm;EBU=ctE>x9<_kyHcJZ?twE##33zjPE2|*P^q!4C|MXC=BhVZj#n=GW3^8lh}HQ= z{Wx$)2Vaf=sA6`b(CX87Bami-Qsd5P4z8?8=YHqgU&_@Sydx6&`%C1HW$wO~FKCSw z^*Htcfbx063b~+-%CrHHpsmJTyJ!{erjtxDIjVI|sf*V3Z=j6&*JV&9l!`Ba)wl|p zW6?k*B;d`uI%rC|1OC-{bvGQKw)mgU-uxyzc|Z ztCb_83KrsLJX4?jOc@;d^C5w>|zYrnMT}xT$IjFZU%GgvnK9 z#XBKRH80DXLe{Y29zxh<1T)pLm;n#A2*CMS)eDRvUIZWGc~8Zbd*t#q3)+8OsIalU zFJGSA{O*Nazr*SHVLSJ+(GqTgx7pr_^`YyPn6c4W9o_0@{p#30>}$coU_*foMf1Mf zlJE5b+`ju>MfnkTY^NOy*>iDPEGH$Zj9%nX)LlRb*zmS^|{2J`baD5=7svS zYNCtD`tPfGn;-V$fR0J$&V7G_ND2`ik>Hl^036=nQ~cw;-nA=zJRs~(@GH$PQ>B~( zPlc#;Mp*^qcjqzNkjA)I$#Z9L55I4;?^GuxJb_gegZMtJ8(36se)YU!5B$3JhR8Y$ zC5Rd!$#mbGJ%U#MbbUPH&CW-5m!A^S>p-Cur9gBmQ9GEioWe|f^85Hr?6+0qomJkM znu%6oK!gVIY=$$G2`%gNSs$$W!UUC%JB{wLWJ7W}Z(!E6KG~f_AJvx(=_wLdwwtyE zLY9}8^rHbK4{^-x+QG&Z!^S0(aekBXGzv%t=Nt!d!R(~8 zLA}fiLrd&9k@B|08#)I2qa4o}AaQ$}RLaMn1vWlaN{P~72O=NhX-8`ChGl}b8QdIe zL_`Fpz%6q;ElCD3*589m)9jPod?tNuWI&v-&adK&CN!!t73a9=6 zusueH+~TASYuR+;UzRW7MS?@jf?ePmU6#HYF?+Ya*rFijtzt^8?@N~K?_A5U{MtX$d%;xAlAg+t^#Vp{8ro%_Q8XaYA|S*YAyXrv{PkIet<|r)pv7QV+31 z{hKy?ADeB~9}!cXy$)LatWUWU`}=M8ObHD3r?naCXdFtYW;WwWFf*}lZ4MRg_uf}| zS#*Eo_7gU8;gzjCorcUP`$6|Bg8XLnou;)K_805fYHO*Ec_!i9`b>Ts44ln1>xq~4 zgP!M2q{sk7lTtsw#r+WDAT_<0K`WE)jOpveNC-Q*in=-q(D?daaY=0euU(tUD0*HN zFJ^zi{j{SfIO?h2z40tc20IZ-gLXKesY=0_lJTTIqiUiEU{j=Jv_rH?UQVlG;WbiA zYh;l!1i4vR{I|>*C{(dl7?3aB+8OjKt!v^O{qHF>8zm|0nn{)68figd6KU_x-D|#H zsL~be@m8RAn<7|1Gdeid?;3xoT3ysu0AO@C`->Pn6A+|ZukR@@X0B=`+*bZoXLiYH zK`GSK)EQ)2?O5o_ZWa=_$-V5Rs#BT1Sfo&{vE7=O_D$rr&9B$1*0dO_wYOIoJ8~rB za$g>M!RI(UXQ0e**jv$;yhrkBht%vUwNG8oO!t zxDrGS4w~920kmX9Zp4>kMr&+5vT%Byri1kdy=&*NqaTH_6hW4UjGlzKSxa+ON0aZ| zNw_Zxwc@(^!;8YV26>SeKm3`fVmyI3bv;+rL$PD7ZzSu-lhNdAa$S?2?_|}WNAp7- zGIzP)X;D$=cNDB-?|Zs5og^r$Ii&@G+W@I}t>4=1mDQx+;bpCkd$?tAmt}XsJY0vo z_OYMQY-hHt8~#LXE3m*dDct3HqL>7w}Q9nmr=<(3QP|QMF>&2%y z+8|Iio%!ta4<|<${`z!)#eF3~id>gNvo7N)x`Npp8)VErkNgun+8fJg8%)I_>_d`V# z;@kplfcN5Zg-Y@b=EG`klIm78NQXb4*Pqci`SZKtC4|Ww03%yw<82==HJY;K9f8E! zYPw2=^f2$n?6;4OaJrOwS2?0a0k*BGd3>vFZO^I(-OYx*6<}h#>8Zk!v3~^f?fr~Z za*Ax$K_v3_Yz`>;wu}A1BJ^O!A{{zR!)nk{U#l{c2OKZ6p@|m&bF0*nIx|hVt`522 z+HW4%Y_w=*in{K^ZQZW_oss-+5Jo-eO5`;#@qpYDy|?RjTZ{*AO6Pf}`e;3pzacPD zjciHpNmEf^n<=M#OCCMBdv4Q%66F!W@kI#mwA%UvpRzT0RmdR{_XS>PIT%iVd=l)~ zuOixPLcpi9Pe_h;l{={z#@Qc()H+E~WItWCRYvv5^IBpCFig>}K`)-kqVc(3O&mnE z-d%jlDX5)XXCMD%jSrNaqYYShs9A;k$F+EM$T-x<(W<|hjeJDw4-}}rZJD;TB$&-s zbSz;uou)7j28vqkBr+LlbZm#{VyY`bqDr=<{Jc{Z+m;QS0`i$5+%*~RDS@d6FQi@p zR$c(l8+xpM+iRgz{5Isd{4`w3!%NGCt;5D5SCTHtln|{K?MmWGw6)85e0^=)i8??3 zo{<{G?mnfm7wVA&nV+t{$dTe{vRpiT=EBQwdi~+Eb!cy4KUI|hSTYN|8WfeS&cFz2evOh!gGnJ1zdMe{ z4}XGPdAOi1)FOb}+_>g+svbHg3dzXoh9`H5m*2-gytrhIo`T!+w6nrypuMe0%gY}e zmzQ4N3)8#Muvwfx9&9SYI(QBu&&nyd4EEtGYHSH13_TWxFm4qNF^9iPIpV8j3RMu) z!%OXpqDF#MV1=_`X^q#fG09(M%a{ElVdb8Pa$%>VR3aiI!673kHNk;Ai?DjJm1gZX z`eXt|G0w%Iphl+`{@<-;<=MWL2xu3W4CgvzOgJ!^dr@qx5qDFsz1X^Zosx8uV^C7c zz{UXm0DR^h)Mt2FMjU@_Yd1l+FRuR8@UI&|e7lPg>N(4G`vYsygWx1@}EZP)9*=(lUlV~~24O&jn6}`zK5Tsa^ z3gR~FO^5=2!lZO&YJz;tjO~d6(hRf83cU2kF2JP0qOcs^CinpEouhEk&zOG@a*`d8 z*Aah#tGep~`+2@gQ5jGTrv#%=O_gV2+%?lvTv33|`~~I+?kuJM(!o31D_<{g-go-2 zqnV#^S+RC4MGK$ql@X+;x+L;4(<4sqxW5ZFDzdAe*3@pEGew*T+JbIeY76In*OtAT zM6aG)amqTA&QT>MknSGLz^VERD4myeuUxBW2t`p}Dn5Qy1QgOb(59;7$c`;)PJonZ zwW%;Hf6<*E0LuxTygGxefxX=A@S8q0r2wfW#_CWB$YSyU` z{q#EDZ?$g5T^M_HiLkskDb{3c0XqaJ>- zOVBcVpQaL6YR4zsTxyQFNzk@ERqhky=1auNE9YtQ{NIr-pSmj5#EJXqbG2`m?xOS4*(~n%pnEFFvBjI*h`% zb2+?u7pMKLPEolmW0*EYdE4AA(2%5Lww|zpyB#V{=z=!-3$b-GR_XEmO-e^ufCzeC zdzTM*?724zM0Zwm^5y=}bbp^epAfm1&y2588U6-}EwC$C6*J7Zor0FW?lnH>nIX8Q zyurv@Eb(k>PpCt84|>U~C8$ZZx~5nw7zPLqxo$$LBU2EydW!d5q+3KqWsDia;6^gY zHMWLCD^<81e%Sib%D%h>Wm)6z?HG@<^Rwf=$6+17*;|SToWjjH` z0*LqAS_6VaQLXY_K3`XpYc{nyBU%z3#&Nzej(meZQM>4)@Vc>!26PUlM@PQ`m?%9| zIk6f(7P#@S&4f$X(`1OOfvy|_JyMauWK65I6|@F`9e?0HjR>20tC~#k4NUnfPHZux z53_3bxHe2ZuxyK!&{D{-TI2;H=TF}vM z1);5$tZtpN_!)_Y5*}2ndk|lLY)cm3Jr=AO-8M4yU8y&26`;w{!z{cteuTqpH;wjt zwnn+k>za(2xks@GWEqQQe6`FMs^H?Yx-c}L4_2TyPB%`QJ%0wTIfLAz$!@v_9{w$u zb8VMX{LLeqqUQg~i4qau+iO}^dMQ5{`~#&(Ue?$q$lq)!*ck9_-IZpTnp8A9IzH97 z?A;!6%KUz(H+CXZYjQQ37-J3(OO$dx&kTb=sspyfB`U8Bl&JCf&s&PfxS^|y@gtAEW7{ypOgVZioN3b%Zzy4lSrud2l^APmA9a}h zIg8^GJ+5@i)+^HwED7er%sRf+JvAa9<1j!%c~E}s;wP05Papw9SHQtLZLsT9x28Dy zHFSae#GNsWP#VHG;CkVYCghe$SZcBH{TX6MiP`ady#6NqSd%{@m?E3?WO(7Gu_&jg zgln50%FD!t_GHT?O!jvehvwWq_o;O_wyOUlOl{C?p;iE4Ek6^#39k^#snV2vkTr?B zadogV*d|@0yrQgp3H#GQ#^c2LBPf1$xvrOn2q<}N*-`RC@>#A%xMTgE1>?cH*4^+i zJyqbu3T`Iqjz_^(SdB|;%TP_i{R0Y^^XcGYqpuCEuggEWInE)`Yo1|=A{`hAs^vVp zaZq6MSuWFn=57oeV46q0_I`6&Bq>1ht)K4aniaoPd(T8mzw5Q{JZE-+k!ItXCb^Va z-{Z{6a!MDx_4x#m;i3x#fBoiibVqeQ_&so9Hu;E>=d9{v3=kKpO`D%4(l0Ew-(1`Q zPK$>Z=)NY~>rcQfT6_gRLwbC-DYF$@F!J}9EFx$+p46XHH9r6^{{ph!x%Zm$vK7%- zfE7XX=Sg$5EwCgK6|Aibif0i;Ggdw8dqgbZ0&G|sfTHA=e8Flh+<*4t=T8F8>9xE~V6@4+pY(90Z?>WlDG?DjCM$#xpK87ZEK z_)c}l{BV*>&3E)hE`HsutC^pByXN(=vt3fUtNXX}Qqlqs1(-fGk+bJ0>UlC52hG9S*LZ$gV*1jR%s?rm+U6D864IgDk+ z8b2REM`|8IjpO^k$WFtAdu2=U*ZGe-6&OdyJlC)iZE60S`TQYAZ&jM6vv`5Z-U$yg zq9X~HBbFGziCio|wu#6X%@Q~6u;P0kB=M1F6gOaA;KOXEXS0W;>`kiD&R!1@p2n=1 zl=XCBPU?Z(y^heW?AVNwqhkboVZOOfv~jypwGhf}_~7Q$DU0iJ!Zo+vaXRy5o0B6= zlZ>Y8H4*B*wnNqflR3U-*4d}MdpPV`I!rYMR_@pLsS1&_%1`9a&bgrm2PrB+3UQ5{ zIo4QugntZWIH);MBKq`{VSwJidP&Oe14=wJLXy@pn5&ALDRTL{8{TcdHS>M#7g-7N z>I@`p%{zs*W!Pq0(*q|4u!GEVhE@)G zLOFUaYG6_zmr&bXCGpB}K)p+ZL@cCufu_1aee-?M!jbeJ#0h;!k-NeTu#IqYQ58Jh zp@9Ue*|te%!<52mZ+lJ|^T5F-If`uQ)Et|2>PhzNo-hvvY*Mc=Cx=bH#zCUH9&TnTNQ^`<3P35~76e*nOao_XKQdfPpbt~tPq62`ozC`2 zcbl96z($2Nltu6kn2ih(KBSujYa6=(Ut^0b)tZ-HbX|*f^rI&(yXNy47sA&+$bzJ2 zqh5y9n&b|KIYNpaC=|~+#w>N$R&?Z8+wS7M`t?bp4~wND>wwp8jZH{)!up&>8Pft^ z50v-1=L#n**c5z`FQ!~qFDuupM$)d>ol(#x`wb&ZRw9KmdUoEz{iD zQh7|T%2JDDbi%Z=3lg+-uy{o1H>FI#k_1r1$jTxmm{}AS;*?=|Dh5QLb${2*TV>NU znD3!}jUKHf3MB4|UmR|-4a4F>(DM)P4hV5n)+Jmxh2{-Z8DpXb-1`C{0L05zAi2Y5 z7UgGq+N#wqiv+T;P379E_RnljJ3)hdZLcfOS7cQd)HRXBV2&z$aJ*Zx zc*$Zng?`Uxn+aPGIK%GB-E~6==$%PjVwA^zKt$}SWIQIVm5#1La)825CLbV=R9kdH zm}%NUqL{Q#`@FR-nL43sr8=0j8w!Eg%k35GybSbo4j}@JK@b0@Ef?Jb{62gzi=6Rj zU{4ym`(1z=LZH5-vL;V1Fr9z14UeV^c?Y)J)du1Y^bovIE}QUtM^?#fS5-c#;<~dG zUBlG3THC(V2kL-Mq-Hs7i5+RBlx-k+#^@*qg_E5NQSdiJOE0}VNtD~+KCihb)xiJ` z`e%&~YbLHXimRAPR*!0AlfjRGQ0?>Q`HCIhc`}cj&-=@YlSy6h1t0Z1R4Iqu4cO?XqOVsOxF~5_95neuTdl9pnK8e zRVl`R=6~^_36K?$)fmt#;=A?Im#Z(tRXXQiOt9lp`C8=Gf$EihT>9^3(Z=)ahO4Yg z*I%jXwrie>EiM?iN^^6$ir*R4x3Cz#G5)cS1KAck$HH;m;OpDH`RJ&!W=j!jp>;bj z-%Uk(St6N`p)IYNUU@cf$fK{w$yGtLL=sah1F|7#hZrF&VC5j4?&%}2jW;|@#%o#2 z8R7CHn{XLXB$Bf(r|w0ci%#xy%&%BKa!e;Gf{;Qalo#J8=>6k>01lGi!zRg5RiRPw zQfVkxUh=u#%WmadyuzW6_8T3`lj(*Jz+=BDE>f~M1DZm;_eqb`E$O15`ML>SR1wInF97+zd{KrFZCrR%{bk zcB~WR22wUKrBLFpXq$SOQsdMF)PhL6DMhS#o0O8nvx=+=NX|l{jUGxR59n^eawl)S0jsT zlQD3#bBQH6Swc=kN6~+O>Z%S2M9V=<*j8-A3UaLF)_iAt@xBDXKC5&XxvC2M5v;vE zK{3{;M=K}o~g(g$OaZn#x<6_#tzTrXFlYan@uttkKBt(@An2{8iTsav~E z%EitUSY%T5?hvmZ1+^vZab=t+#y| z>|<$sv(iD!sT#Ab zs__b_K{xf_Jm(~PQQSOsW#Lc6JCZj)=B+C#X9Jp9=WSU3Jxne$_$G1a?AiXP+PKA2 z_nXhqLmzkS?L`0}8!!{4u}>;a>sJdBNi5Q5Jp{;%2kyIKS>qWF!~2wONVc)&w^gGP zE7u1rH&^;)?Z)#eRl1BNUwxh7Mf|#=X$G z8HMcoi4trzrV^|oAtsY7Fv+vc9zOh5TSIcK7qS8X5{6UKwm10*S@?%MN~hr$&*TDt z(nz$}mN{)`R?N`uYW`gA<9A!KgxckG)C1X9kT#Vw22lz4b5@e0Ud*3u1aq#q(ePRSO+;t$5P+5UItOKOK|{UiCg1Xf$J_cuABfRHhlI%N!wwtX^H zV8z6A!FjMnCqcSThfU?160OTRIN^Q7MEO!SA&;<^n;CMF zuY~4h0TOT22H!PG+Pk&Ur?{b_6K&zK!@1Y1h&fHMq%o5NM>NVSH0*FUrGaZaJF0U0 zOr&K#(ml>fwBZ|y5}cLi@!R1d_Am$x4GG}pK9gLY{^1_xItM0zjMZqmES0dyuXLd( zSL5iWIg2LuAfV)e#fv{kX>Od zzE{Zm%~i9j28bf3eLj#8l`Bmy`p=x}>A>Ql|H&$lzlSJ^ZV4|6b=s5Dm93rI49#&& z4Sy1)QBdQow9#gD$`w<*&JkM1f8U-`GOU%2oz~Ht-#zbCwUl;R_*eD z6TGg&Qfn$1(^D(vZ;h`=EiVj0WDS{BsFx~pPGHBUN8Qeu_H~K?EYX}pl{PWs`<=?lTY>4iCszC%GPDWQq&s$rt&^h>dJzU%h54 zoJO+1`nb}|mXU7iN3R_bMXs!t^*Yu*kYaDpe!Q&|$39k5%)v69mW^JVMYov+w=Mu& zsv(;ZEFHy5gu}2O2iwiH<9@e)S0k61Gmiv3W*l3KnP?pSGH7m-wSvl)MNd4T;f)>jA1i<1%%21U+qTiM5x=BwFt)VE>289Uj&e9m{geX&?5 zQBITkvFqz!teg=QOOz2nD1ukDDCB)`bhO+jP0ieE4)of=%7%QYE{rX9L$!SV`-;2+ zsKJ8Uv;qQ+r;)SBjz2ZTY5wJ!WuMDm#r8<6ED^>NH85JzJ)TWt;75HLv7O7pKo0w6 zU7J~nm*xlRBGH27DM-b#?m2Wla>1f4PB35Mqc-O7KDUQ*R;$!`qjSTwBysips32lD zzrcBuYsUUF@_ivs!yBD0=kcQW)j#se=iW5EKB%lml4_|;?=`vm{Op+nu6+->s@2fGen2wzu2wcMxC9$ZKk?rehRB^e3Ya*3qEIYtXO93 z9I@-V^ImkzBAMc03udO(8|@mox%{p5kCY!4`=9N>iMw?<8aK2(m0s#@)V=4=7QzhHO`~I7Tsf04~ z05n?8uaI=!Wrab=?`>m*L}o$8bSF0b&B+EIG^Z!C7$e-L)i^wRQ{*Er`AhI}KjX{7 zp$EhhUea>D0L!*U#D9?m&^vAXpYI=M6;_Jdv%Gh77*Wt@!$6hunU99LWhT>K z?^;4dE^b{+XGvHZ$rT`S*fW!R?X?7iD=Q?}8 z0FSmWgcT%Xj04vQ<)lJ;r6SH?CIxq0$$i9OQyK-i8n2x4 zTFDXSVXjS^W!;LL<@KS8)BJLZ_vM8cy!;Ki)Gq#~>QRk(scs$f0z4ejJnUwh?GXy5 zM|m+YX4q%YFFQD_W@k-JK-*%#DjhmcV$0yiti+`dMW7_JgIUZ*j#am{RUqu+z@|el zO4qtgEvWvHzZ-7&k7=|-9NkB8^uWI~bC)AgcF&`u%lo6=0yNwMchNMri~GqT=A?7@ zMUZEe(5?&GXcsGuQI?FfEbENGEGnH^ND76N(6}JsVJQJFU#_mDW}~CW^IiX@8xn^< zJrJqZ^=h|{+oJ+ACgzkjKa}|X``;N$)YTHP6>Zx|qYt_A!z)uJ3*cRa9S4u}Dbu;mhXlcPS`yV+t;m5x0k7rX=O!c;%Scy zfkJHO*Wj_zqdoZ?Z4z_r%T9|=@cfSJr#iGM1UN`l+Xw6^0Rn{5x1XZB*CV3rdUpDG*m@cYRN?po+ z7adUhJ^>cozYxi%HC$}RAzyso5NO5ob<64t*H$RqM!r8(4pH{`-Umyk{RHc>9FRkx z6->o0WHa7%kBUfh*BZ&SCXFoTY67rk=EgXY>RnkfNwEi49OBZqM24IZ% z_qY$7UtE!<(DXBcPA*8m75SG%`G0E7cWd`v22|fzTz^i4v`adw+fU#fR1#(HjZ^$x zloh}1yr)!-cvp>F$a8F8Ptpk8w04H-9-shajFgz$UzQEzg986^#%xBz6%9ezpvBFC7o zgG1e)(=d)pf-%*#GFzHF%W4!I)AQ975R@fZ-dI%)%ncdiZ2k1_Q81V*f6^VWpf;kA z>!n*9w|{%;2vus3D3h-wIM_WH^R`L7+Au%14!Ph_;`U>1T!jy0XY=KbU-E!4XL^oY z->~HXgby`YRQZ1_oo6_k@BjXFquSbyStIr)wrVLMiIs>EL2C6^YxN@LQsPj>Xx`LP;;V7#i#1% zk+BIe+7=}a-2Oo>>fYZupx%|qlfM4Bg(7hCJTim^;=A|0;G2J+tXo!{Jx{n5+lZ^w zWuqa%OTwJHs?5zjFTHB_mspjW9U5RA5F>w^FA9tEeScy)C)4~S!Huq)YNlNZoH1)YD=jc6 z(p3NAS<&fJuL%^3Gja53k@&&LV6qGq9gErX%tGi0H}$uuh}VgeV`jrP#Aiw7ERrYX zY6HlyQYeS--#7bT?*Mcv70NBO2fFChPi6=J1XP~j?jNoOwYW1#m>&ya=_@>!>PGojvUx(XC3;7-pBuA*(rlo89?Z~IidF_j+ zhhNxRZ?;?4z%r~$Ivwa!^(8LJI0@$A$%EfS!M5l)7o?s1+OmnvF5%i6{4jG8G1|V{ z-xe*N{YAdRJdhS;?0L~YmC+dEF46yBd9Gp~S*j5nqplyW{WQ=6G81E2Os^gwK87z; zX0R-$d0ljEm+|}B)|F6JU*zTn2R+hsL8s1*OW#hSjijeAuAn86z9^Eb8IL-(1nWJ{v%8`gw2BzR(C3IUWT&M}%$($x0754z4IVLPA^l)TMU`awE| zqiK2Q@=|pH)*bto7zK-hJ>nhK%23(h;>rWar`Z7$WnsDG1hyijqRO7~nGLlSb$9_8 z=^^=as+h;5)FPZJ>s@1|9j-x4^mLz0+T5Z?;w?CCwwk7A--Z?di$}^wLB&!~e?RY0 z$dKwsk^a63gTP~(n!l+A9u27Y@80>W6ALBOB4t%JZDHWSN(QIJxHG|H!>zI8Z26rl!yL-@Blc$yMd# zEsG>Wr<5`JJnp~~9aR2f>DXiczh(NkW!)Cz>kDo;7o{-~*2=j41~@N*Z&Hgvu$9M; zcM2<#qtCeoA7d|;Y|DC1);0-V&oda7i%lvW)m6@}LKth?_y#WL7CuT-ALDIIF4i$8 z6mw1^rz3MM3@+aL!)>P!gyNy=AA5Z#7key4)4vVcO&s(!JSfl@ATc>|xG$J+KL)w( z1$5$AFN0KBGKE`l>RMl9H?oi25A58IolwA-M}w6=di`rB3sLwXwxU5gl(3VlW(U$q zlj>~&RJD?Bf?WL$%=h@nE!?*$>g=OJtM@VAS!pW3sdQjuW|E0bT=|ny;T?c)qkSy; z${+Io+gx<_ve}$KIraH<^#V((K6(at1C{8D?J6XVEkfgv<>I>D96UkzeadttNxVa+ zve7>(1PAZZH>N5^*H)8AlK3wb5Pgwrhn1Dy3=5-U_PY&2wfX?Wy_5t{$} z;R?V#0q<9@j<0u`>gKk$!<@E;sI1IMwXkbD?P% zcp_#?IbaJ^7LrL!5CV=b6yg3+y&^G|SJe}>ofD%D&S#nYd$w0s%>z~OvEVW`Pv)#H z`j?)bj(6d*L3jXsSX{G~Z%tPB2{Q;;%Ob$3;05|9gA|5r(6wIaiORZcfC0iV_bNd0 zUhv?8;fmn7^}vUiC;UJwk<{Y9h1SBB)5N=el8<5RiRD@cmzS3YSQUUch-$j0|Nfx; zaxuHeJnbB(_iAdFRXzg{9+Oeq6x3gl0f@BB9>BHlx@fuf+cDbut0-^>@PdKgWI)Y?jF0PoyPzGjK{ z+mxh7OpG8C2jM_}w)Ws#_jnd2oT3zjUBE->5u_cWJN{dcOut)dTW`c@+DYKRj0E|b zrZqF$-Un}m!R{JZVgS|!kS$;X5zgjfylNF|_)7RyvuNs*HZKA&Zk~9JZcLKN0iI>T z-03wBjvQ?+R$HXT_3b1a-0p{oyFIH+sUw#&;=AzwlEsE-eDHC|#uqC7zu{a@IC5Xt zMADp~w_c90or2?_f0u`bfSXfRjVC_nt^?1KpMqK(0xTbdg8{t0hJ$pZC%*Ioky9O4 ziPK|9#d^U^x-mNGoSC@pm2O0#^_Dn{!>lUCI@UnoO4Mz`K|Wu4^{f2ruX3H{R7G?1 zO2_hBZ8~huFe*hW&57@2YQm+uoMcp*i3PFQRbK+rTRMK}%#r?{tkwOG&K{R>`CCfh5 z^xyl9cSp3#WRpK=m-eO!k#C}80mVYC$-YT zT#&^a*Ul}(t^1aE^);X;der@w!*B7x;(*-RpDsM7ZGkR=$CoaLCuRWwc{i7jQjR67 zo4hO$llgWNa0Dn#je1o(d4tx9@mC(*%N&gx`@}In zaCfQCM6r%BkYZ<#0@DP~Mv`!vNwcAM4ChZP6k7b9}_&2zU75m2)}gZyIW zvEzu&AyoOu67*p4)*ycGp#p!;$ zm-$ttW${^S7>1v*wph4V3qgN^Wg0ndytLED>4ZJSi%fZ{rLZf!6mDD|@zU>Z11DHy ziD?J2yp-wLV6jyiY#OoD%X2Llw#pJo1~LdeT6qK@ZMtY_1;J|!&hUHM*6PqV@3{&0 z3z}0n1Gh9PU*)OwtB)Z(7EH3S0bp6EjXv#H5=q@d%Ap7?l z>GTJ+6ZKDiLkr4O;-%g${A-Wi`f-Y`=p*GbUZ!Ctw&B~yo@wNl}P$5d{m5l9cX!WTJ*)J zF|q~1Vl7#6myLs2(ukKssR_a$t;8kSQ}v}xludc3!_+Nc=OB(iw00t_OpCWa$@elk z9QB$Alfeo=tnrwwd?~4U!46olcZ(8?FIQzkred16ZT0w^hGO^YseI=&SjQF5Rcuzt ze<}CNqFEI;W}>=`7EVF#sl$^5O&6(M=OiSOROgN(aoC%%R4i8_%P5YxBr8y{%M1l0 z=I&442pa7on+##dEfvOnv%AVJ$03irCK}P?cxH@uwh*&@Jo}3y&P!Gi612vh?$P)7 zUwj-Qjk)^aKA~y4OZ*1`#R+2BgS*|O}>GN;uK^z z!5MemRqeP;ion8(zPYF{TJ*a}-Zg4|sH#$`?2S#Y$;| zG7q;~lY#kjBgwe~)Lx81f*7mHOs)2sfeK>Hdel{Rcd8`p+oB+rZ)e2h@`z*p>QPv# zW(S&l^D5^mtPhvkPYADiz-kkn2*C~R_BgB5HW@ITHX60wHD)x7802EFuG5Gs4cku3 zH~{AL+SBIcmHv|$*d5psGPlx{4IuV3F>Q#_!t`N?-|wgTSDsv$$e=`LTTQ;| z)lJ-I^B$GZly%HFwVha|KwMm6MJ*Ec4Yx6}e9NZNO#u5%&8W8Zp>3dI+>;i4)HPL0 z@&)MoRnFaA%hZFLvI~~hw_OPMFnDQ)0Ki-jhaJ5^3^5#<^2knH?Z2AA-~~jQHg_c>R`1JBduuLPVr`+lQ~@0+=Qn&w^Uk|HjUZ%A;Swj3N)x(s{TYzQUfs{>^Oj8hQGV;9mU&Q0%@Gobmt zY{HMYfyq4A(i}`R^c0i~L{~m>6%l!ob`7Tx5Wze__vx6>#nnmL8oKkgaLgXWNJb(> z&DHG@AugViVdG?=$7R4TcqcmsYVvclTtrO51YQm(Rn?FL+hXSpDQynujq|aTU>C-;+xJC z?1h08>hc8K@x_1c#@GIp`Pam9)J^2!@;d1MK*%af8rp`?;K^^9wPK~6 z;o=71Be2fb*{wq%%N8&#E~nI&1{!*|;DEUKN^U4x(&`i{nGK<)`}yL_4j{U9z}!8+ zn13n9;V3v)eS6>7BGKC{s&hKmyfeHs1hAHN(2iNCIze@9tuA`nM2tr=ou1fASDaun zSV}w!sSs9>zrK{#Go)ev4$*>fYMi@XR3@_}R_)N49IL*QAQHPhygi=fLcR)4s&97% zQ9=(@24i@s1ID<4*f#MXo0JtZH2{jE(>T5x@_ ziZ7h;;T213`r5-lQ$^3vgKhWWz66%o1)()o`pvA;@Zb=G*35bq&DRH#v-r2wyL+0- zfV$P*`QB9o>EgoT-wc;z{)CRcdAZ!`G`^!pE+^|Gf>B~Y95uXY+2Ju8;&C=dxK`Mv zdZs$gYqo^$mwc-1L^|-;1g|_{U>rV@04Dv&6`yXr{38j>{%%wuIKlPrSF+-t&>qdedPCq?b=F+ zNuCLG4v(f4hCOB`YVag@xyi5liLYX8a8bLyB#9Ycf;qmcoNOW=?NDugR$Cxtvr-`e z4uPKKq)&k2K$i|hG?<*?13sZ+Y7Y`6E zGl9PkWO>ZsSU=#XLi*U7f7~j*3vkA!Awjc5Vfs(BuBQl}#=>5Z_`X0Cq9G?(b2BZu z!n#)MGFY+1@lFu#Zh0=$4cnd@F9}?>wypvy-6ek|LC9(xXQ= z+`ejj@wfW+GppByaAacA{W3wd+3lRbuah3+JepNVmUl+Pq+AmNRf9oKWfZnsUZylPTgQdmZuv1JMQ*497YYTZ z!W2+0W=i#WUw4NWDjSk!pn;pk%7{*05#^(4(qK+b5}rcSbb{~>05DYM4@h#M$LzI| zafjG#!_`T0PD%q*fv}W>>&%@(XxIOK?i5z--tNrOF{}lLw)!n&wQV>qV9yR8USjTN z$6gdUEb+LcWvU-KPt*k_Ll-qWViV*?e)LV!^)+Q!CY>h%v|?t1G!x?b(1b_P8}In2 zvLHZa*r!n+ZmwF= zZot1JCWjJi;&#u5D{auxLn9NfRAX0Y0FqB-8z%NE;^1`JOF1XI9DwY?J8yA&_`QNB zLzV9@9X}r2rMU(Xj1HHvKal};i}Nc_nm^3 zwFRk-=O60$LZM^B{i`=;U4K|51W9EH{LoTbBpZ7c50|g3pl)ei*z|wfXl|~b(OwD* zP3?a+@I^+}s3jwV+pU~n7As3G)*x?y6>)eM^jS($Dd%EL`NfbrE%HrJ=7OD_nc)j^ zvYa?sS?Wa85pQI6OeEonP((nww}vk7m|vp5pVb?X_u9!uT`1H}$p#P66;{IF&11UlgE4$YFXD9lufHmkOGUX8R-6?x)9irgr z-aAmU13uXK`_ccv=s)=HxGbBSIvO9j7;9OT8O-8(m zxh_yGa-}l2F>t%^zX>qgcGbNViuh!eRLituMtiv%Tho>JScmA+gi?k9W!X6`AGk)q zw&kujyvewYd~Rh~wAra-2l*dev#bMz^Up2^5oY}%#oF1>!Fn+H&3FdU?0Fb#CAG5Z znD;?0tTZ$Ok#%q_W68BW8*o7L)2$7q-bi}HJtVp&ViP8umUr~d@(WEFov|YHi9E4s z?IZASy5-YDxFFXHE3#x_bxb{LCnxF4Q^&;2ssoBTE% zxi$V>43Bs&?$Tr4e4Cf9XSdxX=LoO7S|KfbjeB2ngH#e(VSUerA@(0s)XAJ~dG zbO=3!%7@QwK@a+7q|hHTzN)h!&{g3rI6ETS1T&bTL7fsYGQw zWi7Qt;>zz~P{;3S+FJTq{BpTuePW)J4ryT^gZyk3T9nHtyQuajz_&^qTAc7~1!}pQ zn2>M^fpiQQn+%;av)584GrBb*ze-zHT^l)Y@c|@UbLT*%SrEfRj#WSWVB_^Ke4@y) z3Z_SLpBQ_cU6oEbyX#Pfn^_P%-p<+zX1pq%qGvd1EO@)2I>r{t2^oK06(QGrL_T9# z7~-#T@wr-Wy)W?b0nw!uvJE5EtlI6ajp(7xj)5%F3Y~9-ff3JRJEcNI%YCz}&>zkz zFJ%N_9h60t6bRkQ^=p(+c7@l@RVQ~uSt!2~B_7i1Sa{ zBuVJNaEKuBQLudHdePR`$(q+yRx79R19%USZ_B*tO?U(Xm-EUuU^^Q#geu7?z|hix zu_vLplY@rG7!}Kkx!ds}Oml9dtUb0|rA&>sB{wA{qKB@~rl#KUS~7Nh{I}<1BXk4b z-yA68;-vT9MWQ_=ZVE*fxxX9b>_a&nr{&r~m~JxY$CO;5ZV7tkN!uy6=4@cKlJs1T zX=LQ`yJU`g)sB*4v87LI@i@e;2RB9SME?ucZS=0_|LE{j89l6_SGDtet{v8pJUT?e z4KtTwS1VtL^i}N+CX@`01K;p~3;7a1rtfjjomL-rCH?WVdkl_-d1~mLSZ{JC%m}kqmP`o5SgLHI0N2^Lid`8L z)GK5^NkBoMdzrX2TWmd6+{)BcdVMfH82{MRZI2WBTfD zlATzX@_pOtIIjq+BQ+xCgfsg~HVnbS)~9iG-K{#lC; zhY=iGB1bdtJuLO+9 zyqi3n=w&z8YFt(_5FVG*q*n5NyMH+zfTt#%r(|rqzZ1eOA*Qyc$xFv$tt=+T!&t$< zSakg218HfM&lmh|^wqBVx7w9a8hK&rv^0@l@9}Dl999ySthThMY~xW}AZ=k_qO8tm zZ*Tp;V-nxF!x+@nxy7KYl1u6r6A?ew>|GRJG^72;+@@jGB`SvG%zs0w=fC&8OaAsw`Of>HZwJ^$s7Pp%4^?<~n)fN)7F<(YO zdCFYo+f^o138d|i=D_NtKOQ^m(j7O)+`w|0l5K2~ODSiN5Pyd%7jr*Rt!;r3|8dmu z=12`5{JM$R{BPbfCu_&biik3rOy>cGUJ??>?CI&T=dEJ*k{jcH5K^F@Zu&BH%?Gth zw$A2a>FlB7_b*VGS8BzNGP}>6z24^fW2O7bgc7xf!s>o&OE!{GO9AJh^5%Ocb2)CY z7PSL2PgE6*u+Q)Q7|0W!7Reu}CRz#F*{|#K4O-CvXl^v10=t0~1Eu9MV}Yzvo{NU( zBDmVk1eOgq|My*}R75g&qPp~Hdb_XRZZwCsy*p?Y&!?(vG8*Y&oU;$ki&`m6DhQ@oDpyY0(0ZA#?AZheGGUin#0dwwF*ndF%t zh*_`fk+dw1zU(+dUQ&vasFsGOJX~g9V;;K};3Rh_7%M0spm*0_3f*x@INmRwOWRT$ z9O840J*DeL+*{muulp2QJ`cN>&)PEh!+1{*a79o*o$l{a-YY+TiB_{)1v?ufCk{0bR&a9O1IVJ}kc4dyLrMEN@^NQYw3zR1+#B6(LfC*Z}iH<1-z&Tw7THKBV{MO&>zzD_KN z8rNZW+eU39Y1g<;9KX|}(oOw3-3xIP`j=-5D%C)e;5Bj>M&EQlxb2JxS9j|HMqmF# ze1I9xYqD(5nlJiu4@eqg>Ey+$KL+t_0qeNqm+UQQMfR?x2iB(jGTfX04cj%M(I}rC zPmByvLNMFY6D5RXd!zpMyTaeSi-!s7DjnN7Pi*(sR<%h%%FC8TV_byb50hc9BO1bblh0J{bQSKuF>8zA-CU6TY*VGxz=(46ISZW_c|AdzH~Ddl@p-x)>3wZ?Nj$| zXti?#|4a|=w4rK90$6TY!l!Oux)(|U+cGHm!gD)({tJu_VwuFyjE=QbOhM7wKHnigo3L1 z+cu(Y{%|B+p7C%}+8x^9>OQAA^~CDAJln>qybtG?SH5zn%%rbN_M~SZQ8fN#JRCT- z6)m-M7fDM;E$|T_yvEX66$1nYW8FN%=?tyhLI9AUQnFi2-C# zH?3Mu^1O=8lq~_dUZoQrI@>qed^nlQTef3a`K*65Ae_-09+gW2Q45E#&Cxn9M_SYx zF+_lGNlxz4sb`+QjwVFJb3x_j?tA4tpX+5AN1E16?UbW|tlB}#aLd+Ct9bH~j*p)^ zi6H0ccV+3?(%y&tH$E2!X##6I|D$8;)GQ1wuz$?zUVn>w+&YFhOC2G9;>p}=m-CeF zWo_d03r=7h;ETFkPXh>Zmv$YNSHmK!SG3EytIcgpdB=g?77>&k9~E%wT?IWeO)Z3; z|Axs!sz6QGONDVB%sZE<%iS%|FD**9+5%ca7U-N^0jU+(51NWZrG;rc#=KMqiI+T4 zy(xmSRr&65zIV&hUC^QM4Y2f)fZYvYQw zjQkUCIDW~e{*zX~M&0Y@ceHfYS&BbmuQxp#-93ysJeut{8vA+d}-eeUFZSJ#KZtirarN)>fRpFpN;p&F|TAPd}m(Zkj7 zo2kUL&*_a>JdBgECxB}6Yqy$TT_-r-VFUb@$NQ$&h^SkYf=hDp45xMrWT517iT?0| z0SgXQ8D|P5dj}4;`?Wt;ZX(N8uCY&5NcT_JdG#uJ+18>kh=7E$VE8jQtpg`QDui4*08RNN_#g5LG&UL;5QgP_ppR$BDH3eqnaeM{(f_ zPq=fh!O4MhaQv1O<#H0`X4fE(RzbhL@O1Mi+OSdHZmGF6_q}_Y`|JG4+J2)<>yD4o zFH4X00)+UsJH(f#>=)KbW@%;oy3~3}yQQ~j{JYAFtU~O#u#my^q|4u)J+ja;m6ghV z^PMzxifK>7=s!CwwRZ_37mJDaJm~$m?Ih=yb)h~}&S2p|fb>&zWk97@r!7_}Xw#gm z#baDMoMy||TrG5RD_ujO?sql6Uo1lhuwRI|$Zp=m-9{Haw7%>F?>S^L7;br|I*nty z)|{KZjOvX24dr*ExSurvw&FVL2RO9$7)za4-lV}_*1p<|EKg8oaPu@2&0I3t1>EXO zst?0yMG3R$Hre`l+nhxl9-Sn8!GJabF<^)Oa^epo>_&4`0nHMi0{ z&xWy1j#l^P_QyZj8`aX+giMtJzlLl0TDS~Jg{LPHWZl)ZY_}`gLqlQNyeAba(=Gsn zv3@|m%7$Fy%FJY9!Y=&Zn}37|w)G3Ss5>{_h#tL;(}Gow{>#E%ue(-T9_e{C_`Orw zq$`G&yvArR$O;{^sui~?Dka7_zS;TC@$BP&+*8WmSv@pl`r2j2ndSE{8 zXW|38*9UhpsMa3>6M&*ZjW=AiT{e8~+SrVSk(MBVr_UVibfiOkm@L25zQcA3in$(d zu5sxZ4txOfoaO$TI;z^TFNh3m)s~yMhs*{X_E*aNF&YHodvIjg9af3K|ItCx&k7Mb zJbl}WcUpV48olh5Je0qdW5HDY*STutu}*&y5#b z#y3o-BcxmuJwg_}|45+!(a}ZdHoi-= zJo>v>Ov|GwC*8c4AxfMW4Pb}&19c)w(5Lv?Nv>?QE%S!{i1DM7?*GwoJ$FsEdiW!x zcjfWHA1~G5?BtKHf3;>{QaIFF-^*v7T&*9Hd7tOygp+?uf}B#{3+7Db-{3R971M8m z6w_^CW6_dI43z)n(aZ$OmFS*MhM44#;0q$$X}Lw`_;=;fA0vGjxZ6hV12!vWVvO!< z>90tb$Xixao~Tbn!~=6}c5@L)#5KCVk3Y$Q8~8F3Yvcm|L3zS?G&6sNbFCg3y8$PA zZz}JDyZJ4HU7nzNdalzsJ=O@l=(X`ZN+!2h4f7WT8PcYE+sS5nU!~pm3)9lJ%y~fW z^XZpdHLq~|3;)-wt^K@Lcj0qJGHt$aJ2b?8@@Gz-;-Bw&2@Cv(n;Tol%~I#vZ$|Rn z*&^h%k5uT*qMg#uZ*D%m^w|2#Q|~OlT@P${Z6C2`Oph&H>)_Pe?)Hhu)FLE!%9PdS zka{w@XsB%88jNEx%bCc7I;cAoOnz~DO7YRH>Keea zU`@&!{{eb_zYnb8<+1N>|Lz^Q=SZ2hgkh@15*B2>(PhtEE`B&Eoxrz+NF4$(;@VaE zT+P^(B44ljy!dk`X3I_ptN2KIcGbDg7d@VUf>KNNcJJ%beMVS{WZVdn2L50z=C^&+ zM|$8h4)2~y^!RFUV`Ry%`MX*N1$qJ*d%zN1j_TF{Lypx%&vV{L`eWar4cZY_Pgh~4 zw|_raH)g%)le&>CFv~x-<>ao=zjN453DFT9ECoau2t16*>Xuyai>_$o! z?9T(erG3tmt|nOdib$W|P~+xIi(vu_QN7T&TmfLsb%XS5_Bm_NofQ82Z8H&aScl@p zQBRNd>8D{GEFP-C6D8)LMBtR>$max{5*4*_Nz~}?3R&EQwT8RRef*XN0>%cF&)rIh zs9H@bmzpxew)MbIy+^x2p@bjM&J9GqkZ;xX>54Ja`JSXO$LgtwCY+5*^|znoy#LV& zYfJqOM|4I}H4R6}%t9A%KJ$SVBxsKc+qs=ENBVf%_>?+WnqWOhui@7d`y_^1F6gUO>T6U7t zy{Dh+_13*xp&@oZB<;Jkbbo5nAFgguaqd}BV}>EIR0w}*1%f-yB&>pDN-?$vV384km8<-t9!i^g653@P&o<*+jHjGW@Djh~DB9p!7w z^Mm7VVN8k4BW3#G{t1c=SSzW#6n2%phrxS}?>EtW2bsmG75hDsvKfs<4h1!0LNL(AH>JGSu<9@C9F0aVpG2O!HwsNLOML+MAw1Ml!|d~={U1PA@kk5^uXzIL^L}`cx6M3 zN9Qswsr<)4b_Kaqe1-(jfR0iFcO?Cc^?z)9ZU0rQZjiA6MixpvcwJ4AUX!$)^oBIE zAATowe}2coM#`LvcUrf7t7H1R+jAL#QA!)p zK=(|sN5su~S%F#DXMs1Svk|GzQ~!$~nwp&y@Z7nWL4Tq3HSQQXX%uzcqMJ>(NuCD9 zb4)$B!bn2FvrGPEN8=LG>+ZQo;>$KHzrYid)zma~e*_O||!ZTw!gA2NG7C&4e`85>iatt-65o_48O(V9x% z%^H8n#ZBleG2%Yf!zq7q!zT!nX&iJlN-;(xvz59REE*`tOy>(@F28!q?#9Epnr{Nx zf0x;D_nN@Y1g*iHn3+UxeUzvInmOtFF+K@5K~DOJpO*dpyoH~o0(gvWIbn#&1iVfC z*svr0V?DW?KIHPaC>S}1u442nJs|l*OJN!~nvz+qA4x{wC4oDlgrcRybU)+rdy2B9 z(3+lVSCRp`ADM^`bGj=7teJ!yFH(;o{490W9!-2Y-~z?ViHf)yrDdQwxUobVWn3o6 z#gq@znhYyqEwpJYnG!aZomG3=7Cqo>D2(=h_Y}&x=M~=?W)VVPrZ`f~GwMRW9w`_i zv^?MxCD&q7->)c<%+yi#I8|KRZ2oJ;2^fm~K<8je@K{8QMyln>uIq{Fx3G1-xr~lw zYS~0ktQZ~LoXGktX1Yyb6euz~i3BA`ku+-gw<}3h?Me0n)!UCT#yS+L)>O2G<)pWL zjQVtSu4}f3m6a6)rCieWxuoP5tUY;6VlxCHLT>c9{SxbJ&KvqLnL$_^nJye3d|qkM z)7ut1J`(5m`H%951Y=hpt1ay@S#rYN1yXdsH%I(}aO$NQrPS7@)ZV2(+<$%70yk0K z5+y#2ezaZC)Knnk0=a>!_-rqhSueRs=Niul{osulXB$gyob{3T{#Nnh)jK=A?hS9U zaGUzc_zh@djLS7HtA>FME_7USNuoZan%%Y9DdcQsG$ejG|`q-bQV^{+Nly5&r-CVK2YLv8)BZF?H9d+(zSftaV9*n z>~?*Z)XeBxiUH>a1Vkm36p>2Jkz4Mo5U9kEzPeq>Y9r$5N!aq!m2U-J(bi}i zeX-0Ml`l4~m@AS^u&ew?T#H$ja4?G?&$b1>;oO^kjl5`>>(#1zxKHOq9Z{yk7kvO2 zMjE$Rd;^`KIFNWuQIxo4|JrjSPNuM>DZ>aOD)i{IqK0@f&N4)X+ICJcTfY=YeGzv> zAyCS8wQ&6+9!L;Qo>Vp*u~HE5CAGb7V{TvcmVdXi;yr0nv2eRvWp>`(AAFnOf!{k& zM`nnT32XOD-fr%0=C?+RLrD5PCS!0*%*x^|wJNnCYIaAG#WX&r!x(g4g0ops*A_Dk zONY1Oq*ULh?GRjA0t5{{V6?WG7+N2ibtWaHc_m$vPOfjYyS7?fIe4lOM1BEqWeX!# zUX_PdvIzO9fyLLGnsi?cM>r(nWIn6hB|gCLTXc1YCfyP$5+*#!nK8Vtli60 zZ94FJRa3t37{$@92yi4MD7Q!Efk(%fzDohk4dfA8^E=CZRP|KVOj+M#Nx!6Gghw4k z&W%xKqgV_q>zhZ3tn0XI(bhT&ht0z_14hb4Wc6?+3OQJk=1?=WmJ)=66*pp0;_pq4 zlK&%J{j{>2l`#~Ppev-S_^7WDuxgQu$5qI~ZMVY?` zqjG;EUX&Ebf>s@+yJ;C^0WT4T+W&Yu)M~x3(r&mLX<56tU_kPv<%hlWCqqaB|A-Ir zPm8=f6tbjwHFy%;0>!C@Pd?xnqDyS9^}TBc zVkRL;>J~J5(p2D_l!ta;IYOyx+Ho0eqF}*lA~~G>W7k9G3w81Q@u1ARdzjN%{-=<= zai#J5%g>y{y%nKK?UlfWOkuhKXLIRt0nL}h5AP<|V98=GQOE>dkt&M&QaCK;gXX$y zZ6%VT;Pmeak7w&_t#YUho5v5$qRTh3HJzVCr{>MpaUrY8H|EmAXo9Op-C4VArrNu-g<{ArK0JO=EX&)((v}#vggGAj^g&pBxb_bv z#G5Z$(;#0oE#7)B-Z_xvFNqzy3wiN3ol5w&)jO>ciup}g7!60VVE+&a!3;#VF-Jl^u`Be%n>K zADiP?hN5s-$L*yI82s&``yR+PjpWZz;7Dwh2$E^R8djvvUvJPlWiri1JGY+ULga@&ZC{ zZBOcnea!p;b!j6?)58Vy6N00|a))!Gr$@7pGQpZ(lApg+!>u^vpS1=1f@mvK-z(ub9im>Rx~ z7EZr4lNjBs&1_Q%e&-Yp{R9zl+21bN-rn9^N@`P& zz8k{n3gb-KI%wj#Z;YK2;&JJ)Y|J6b%;?uOQ2*NLKGKt;(u zZ*PY-jLnV9tM0;*w%wA-9qdl(NJK+P?1rYXc~7g^xZI+{OMX|2yLYrI8itkI(WV@o zrJU9a)0&c1EDZ#OhAI`~+h1V3lBqUCKa6%)TTQf)%BQr8X=N8plz;^>Nt~e zX)$ve`O%7Hn1f00e{_o;h=e^Pfg7q+4iN{d#aq1H*JU*^QQm@<)aViz_6~%mu{;%3 zU@fWy6oD;US+xI`4Now)-+z_kH#Gqo#%#U(#gpS1N}dbPv^UK1ammW(`&PbVnYY!J z#`w`|6@_!|W|~Mzw417~*=v2|SGHnj2W@q>AqBD!@`~e~(`1PV?Q!Y5tR@vX5W~Ne z%&n;A#z^J7*gS>o)uotrH*{ua2j;E9`2=}l14zk2(HyvSLU$BUGoKf4fw2fwVOw}8 zxAo3@W|T;;(XfyAq(GP~H_wwJ^_G$S1Mbl-!E2n(Ny8e{Hf%JorDw;I-kB`J4Rhdat*17YjBFi*$oPQF zj2vS(zu-1`xb3<2%=k$(3*dq!KS_RcgBEDDmhPwTJ}js^viDY5cHo(B%-Jr%>N(3GIO4yA_Ak z*@-(D(hjmAcfbFYSOORAqevoyD@St8SFqCIHP`x!hHlk-Gsd!@1L%l44YE#Va*hPr zNXb!E(LlNK!!gW-XVhCpe+!-S^%bLF%9``+(O~@w(A}j?V9CyIUjg;6cKcr@Ssqnn z%u51RCWeVQJcw_3IhZgfOPbDWC{AMcNM&#iL5Q<(dmA(vEg*@j^ZGnd@W z{eB5ugj`0pY)}`^tol ze-qR?*Mq-OgM>V$k`lnROVMUOdJ#x?p|zHZs=rcf$xP?Cg}nq+0C+Br7y)b3g!c0zQA*KA zO+za6!4i&Wl=MJOpEnOv!Pm&yerY9YyZzrpvPg=|*^m(B@h_2wR-&W-;N5pu-N>NH zaH+O*6<3Dnhq`jUq%?JbWKvIMlASJmTpc;h`Grg?Jm0Ff;IO@PX6s zcl?S)=JC&x4gwt)kwRlYp1UF?Sr_|v&gRyu23KUz`Q_?`e^`-qG-;`YETv2ZcF?ps zuHnG9tAoO|&wq{0NP9^jtJs$zZ&P-gM9uc(;82{ctk501W;0r)?93KUgzS*`P+0^T0JbgspP8``(zQe*sCzJx{9T(R?!loVG|l%`M2bzVf;{0p3HRa zMLZ65v6!-^wH!0we4@7d!Ns+2W;EU3V4b76HWSj))nQE?G*A`RDG@E28DIn{SGVALOZ*KeyG+z~e8T0X; z$g&8okRgNFyVR}$Xv0%oKCZqOZBz<48fI+TULh$(&qS`fTP;oZutll;sM`0JO?$Y& z?sf%|rKH97dH`1C#>H^CPz!BrB?)6|43uLPa<{hYpD|U)Xn!+WM9n>#DJ;v;4mBDY zS`>+y!E=Q=wce~k8GPdTecg6iy5rwc(w2+!yNj(aQj{OkFs@piHQo{tTCH^+`Z*uo zwN%ssd=RCsN{D_=0n5natPnu%dtW6Teo73NA#OW?I{Hlxe@RuSWG&L0tEB}xNLo&? z+rAJ{-&Y zlKF*@%1!T3X9ZEG25F7F4PcHd8(At@Z0Q` zM5(b}W;c&=4@MPBkpXgpGJ$PBK9P7-1ncl=L2I#hJ(BDDx{mYhn=Qj{w4~01=t&U< zVGkLY!0Lm3OC`R7V5a#J~f<~P&_Uyib_lwkXO3p1V>S^-wta` zixpJ^pmp-oCEmi=fnB}a7Ib1oFqLZk^zALJ7@-Iqp+PM<(n`%?javq}B*go5Pu2zn zL)8j0q4PA4T%?wp1nz40MpB0_kRpov0Rg8KN2yCb@uYy|sSB6z7JE_y!7 z*xFbptUruU;{Q8F)F`sbLA_o<_52hh*?;!W%em@9XmgdY?ZC#3z0(J=PH_3zd26Ds zsSP&II=?H1&y)>P0ZVAI-41r{p2Dj;H*goh5Y|p#+T>Z9Fbk*p`_mJ;-AWGOW1Wc= z+gx`tz5ta4X-gbZWB)tj7?SB2%vf8#SVEi`OFTDldf?s>cRgrXnMbVLanbI{X?yxI z5w{dPy%MYW`XZguj3ow9^n=XVRWJPZ9&0d)aSM z2Sa-U=fC@)$3p*i#y@=>8NNCE#4{3ufGo9uxp97I)V8Kw=rqx459{ywZR~PtXj%He zy~Tdo`zuZawc{#={Q8N4ZD^H{X^K-*I1aSXKRCOSFd4pm6zOl&l3AGC^SJ>&ULPe- z37|YQZha0YQk?*PS1{89VA8jeScCdbLc%muF)X+jinY2K2(_zh!w6mm#M(t7>$*+h z=OXr}7mgd8RyK>9QfV=u_1G=T>~ol@vv&8C0!92vnTHyBc6%Ro!x!Icb(w~!%FrZX zwY9FS(I+eo1AP_~9p$jGmhk4ed9BOj>^&LkR~gAgfNztPAwtcLk+G^aEHhSuF1Lnb z_0txG;=OIz?TIlQlf~bDn|{7~s?c7nh0tNEall>L+JoVR%wF>BZ|ViNvS|_ZCTk%o zHbhwy(&6Y;4ZH0Itgp9~^}mSVy2>K-9J;#q4vEeyDL z@T)6Nl875jt+?QGFUG(;JWtB(&HPV=z*OmU_?&xR#X(&9a`NY1p5jkT!(qz!+O_0$|w6Xog***{T2IAh2nwzks zDpQOVE371Dild{mAxfs$->Nh=mRjsFSL~?+pCPfx#lMbrnAZ|{-UI!PojDdpI%V!p zdE~QeEGthH4-m($X|gIn?ALjL&2-Nd>X+ZS}S1inCVjnnt^%W9=1 z&ER~l@J_#QCf^T^E8tW)vgZovEd!%29F@Xz)P@wN2(e;w&l^TX6nWJ%>}Wbb!>ojx1KN!jP~y;g%GCQJlo(XnO3a8Om=NS6oB6 z+*3p^F2)4UTbk%(8&jQoy6FVfVAp$F#$IYo5zQVJcNd1e)1dHkb(+Aci5EiZUmt~2 z(zkAn+xrIx15%CgUlVk6Aj%bLr2IqU)4nO`mUEKtV(wpy3kcF&rMbG4#S4{Vv~zQu zmeIpEuuf)jS;oH9BKvx?)G0?|zSfC6w0U^7OvhmHM~w5wv}^NG$Z^wlP^{Y+x% zft%Jk=l{-B)NgSvzaX|fe)r?sxRcyBa?}mqq=3{CrpVY%;EAx~I@VQiO?%z^#GZ(g zOj>dBImcL2@2Ylqj=~7ZmKfV_e>A%?8^iTfC?ozkStK>hZOPpKvprv)!l7l*HJW7P zM-Tau*nK8P^Kzk2z>^C>lFQ4qI2%`|JF35whC(jPH!1El1F23gWz36!_&Ag9CQlB} zs+4SgqMlkGECu0CG=fVjsHgbb{e9b#1qmYwp!1q5?6m^oofL?U3nh;Ay#5gi4MDA= zThvbl@(74pa7jf-3~q6y*Gc`YuKtL4NsvTmSPhbl{sTUw1`sr~7g7N1z}Kk(@m`J< z+?wXx#@P&BuJ4or#fxuiroFTGprJ(NTO{?d_04lI=%YVyqw~U%cQb?bL zFW8L4C&oo8FMfbF8P^LGM0>TSZ?v2OdzrK!^2brws?mq#TKzV=#jJo?(k~%P>-u}w zQja3Pd>F5lTVIEv<)*mc9_p`CW$bnv-RAfw;tTh17>D(zve2I_Qg3I>Qdlu3m89&(=>6Sd^@^Pr?VIaail zf~8QGi$qa){3Fkj<>fKHWJR$7mNxv9f6{!MXFS5Y4IIo38w0p{50Y5u7Y{Df0K6Xb ze{K@f7`>%wl{%!`7%UFL-~72N2?`=)sd!RXHvkz3$w==0on_F`D=U>Ry4;EnA1qn^ zh#a2G52+dBrKp)HkM0}gmxI2F*t9MS5rraA{31r4X$>D;#oqV?t@jZ8hzhoU-p;G# zRy-SWC)r2zzZcy#A_UCfRZ`^aDh%$CY*~#;{LUV2IZTXT-a}t-@9L18I0?yTjqpT@EOK>s3x>ipHh= z$iI@?6OozeQpwIBKHM`S*QD*r z&zpRD5n28%DS;w`wq^IOaD<#%)XtIi6>1E8TVBy{3fc9dMj5u~fWwZ}D?nnDR|T+# zK&X)w2l<~ky8&JP&QGb#0*4K*#{~qYaRa>b_80gCnuo`Pr8^;>%{_&zo+%vX);;+1 z*Kq{zLWQy`sow$r zn&QlIM7DNsuMTa(@W4FVZgO{Il4EYEKsNl+-g~nR^|Zgr*o1r zvYEauxZStd1WS3?pM43-=@O9p4`J7tD;&21Eo0L9>5Uu}4Kl3|$FzP27+YSA;%sqn z$Id9zC~WpA?73nJ(<|Encjzw62+iG~h+l8Z*rWdM3<$#>PlDM~9XSHT=%i-g{ETx? z@()XOjE&cjJ~-wR$Rky5OT(zm>e(+5kxa*x*$IJpYeyH{lV}5>~^4VzuwtKSgLS%@63RQ1T^+RTmPD` z)fdznJq`aMO8Vvu4%DXs3$JDleaVD|S&yxrDye60ii;UzV}9apIz>mi_J1ZF1Kr21 zQOC66hJ1^by6Eq_+Xu9`S9#FGzUJ~?B`fZZXqczq!a0--|AXw>`_Hz!xmH?NzLN`* zm)7v$pm~%m`{}qcnG@=5YM+DaYy{0D=)W4NwTdwK;fi{DKP3pQ2XrbLss_6U=Pa#i zq{(3H+FST@hg77;=?Cft&i^};2K;MC`%kD9-p|^h z!+t8xNj(bzg+~)%g~jC+Ix4Q-(yXKYR=G>~Fw)mArz34IH8X++<N zcAD_^fUx?cyqs!Nk-=yNgsvKsLaAn4v1}&8gKZaP0vY9n^T@OV9_y|GM#fX#LvrJl zp27aX;CX+N*x*1`h*baO|Khm--`{F0ez~&N^pDD0JJ)Aq9Vx45THa`O%|P}whU63# z7DY-78f}xkX4J}-TTFyOifga9(ag;Fd}Vb;Y!)F2)3t@DyQ)4IG(B>D!T*0}j#A4) zzl1ypA!JiGHc-G{T|9^-6=HZQ`|kpofLN8P!ar;M=a51dXT9fF040^k=!Zhr7k3-S z9&wuh-g>pSahKm3%o|wHH1}`Fl5)1ZRh`yguyJTQDrw?ZF_n7xZEK0(lvYn`vHgsO z(XiIJsfbJYaXe(*PRx?^IcY9-I3BKHN;5^i4C^Xx zs3;y1(It0%EQ|B#o>dNZl2FPS)2g3c;Fty+bMZMcl(up&*mhs51&60>gN(G^7>&hM znkRa5c3JL={nrjq8?9Eg0kG9dDoY|nobz= z47#|CUq83Fw|BJvEyzdj;pYm>NP|>IUJw%(m|{evs01JUQat&Uu5!Rp3e61=S^QhV zXjo;pJ`PoS10T@*TY9tM6$Ugd)rKBy10x98t^Mv{c1=G&e;{#Ol{%Z5iRBZvw%eO~ z*VmwDH^<>B&Q%4w>1ULsr3bCIu;dedUC&Uo2NZ7#$lo0tf^EYRrtm#FP@Zi9HLJw@ z@RXVn%rIZsE?|6uw#_=&c4eDQ6H;mVu(~F8lw>!Cb`VA%?ps}T*S{-PY;#Q+0x}Nt zn(DIDFemw~1|TZx*gO+<*=6d_}h)YGUR&FHnx9qN-`)IV6Zl^!|V_B`bq zDg&x23FO=F9^KEQ6~$Ztp1sc#tSDs=ps!#evY-rcMD$Yo?1^aXj;RU`OUEjrv|~`}%i5e?hncIl%77Ypj4wsDi3z^~?#5s!#(;I%5*Zf5!lHAs3Q1 zjUG(iHA(7-*IjbJzSHIjiod*A9-<-tCX(~t5i88hu>d)lH6(7#<#EY92z*CX-t1|kQk=&}ZO*e*o#=B$csLhUYm?-GE@?eM3I??CH{YV@7mZ@Xl&E8d&A8(-I=F`_*1V z6LbH0wcaoQSTr=wR-*t;SMM7Ud4`uu%Rtz1j!%d=t_sPBLiknPGsf=Q# zkR=K31{;CEB_Y{pUj$si(3Ib% zR=K06fesUGb{>%NeFvTAme{xwQ5T@^nc?;#{Z$v`66LCl~X{wx3DxKW zMyrYUv)}(&O|o4MsV@ zeuibq+VUw`1UZ$+!HCG4V_Y%t!y$plJqTP@q?akF^5w@^n%21;%x+#pSz#|!pe93q;kqodMtxjo&JgSQzFqQu_uQBh-F)Nk56MkJW~y=X2NOEI)a z-j4u=dncuN=DLE4#_y5OoG9rD`2;y_EW0_2ECMu(#%5nchQhgL9KC;rm>K? zTpPH@32yDJd+10Ud`D^RY{F%NMV6Pr2CtMt-+ea~tKW!9l0istuP28MTZAzv08ges zv$%o{%2(@fWLqq63Ke}FU2lp5p9%=VQ$R)vz&QjwO9(<#$jP!xmhZa?7idLI+R$s{ z!e_P|EDgcRPT};o8n{g{uP^@mIrn0}?P^R!1hG3grFN@ZN&HZLb?RK^9&x4adH{D( z)P2XLG3NiQ@{T_mi`m$SP3T&X5weJ&bE6EWxuwZDcRtIsVdOnJuxTD(X}H}56Dh5( zn2szJizd8|HS(R8Z_d(5rci;6*ClYUbZ3gixn-aS4dIa>MbNkxysE6Fav5vQLz~Ib>NqT3(DY)qr1D$jeMV z$=7!2TiN~8bz!+8C1Xz3bL-@2&8fR6_&a@hBJGa4t~l!NXM}y@AC~)594(}74Y2Uo z#ct9QotKyYq>FHO_5#8O1vv*SOzv5L7Bdzrz1oysAGEelTBs|Gu?$Sah&8*6CbarI z;d)oH?ajr=X*CN}zR^WyPUb;?u<+?+q2P_uKJS)dV-gG24J1+od22w$&=t>93=f=S*LBM_}EBuGt1jHI;Xg`w?UM!L@ z5$=Sp~Pka^hGaP?d?`W6Qv!*7@E4!1cD&$%W{yKz!z(#O}XQY;ses#s55aP3}QP zsyY|UooFG%e{R`poqzsi9{gmIn#;kmi47&If9vWSClqh}`ryt4HA7b1epQ)2`1Ll2 zNo5B8KdiZRrt81kw+(6jFYm~eXHa;V5#+C+R?6;QHRe|k2Wbps2=c+h#6+!jCc4>K zdS=Y>&7=9#W#*%#Gvyg_%#Wgq@5M`(3yk zeDXE5KdbZ0Q;U;YUQ6LMPL{Bp@Dz~c44OBt_VoL+mSp#@wlxgm{@hj5#@alv;$G?M zK5pYzh%q_u&A+|5W4Xh zu8*B*x^rU+pp7l2b4ERWx|_goEOU1C_EEz1r=t(&dDjK@XKj zI`j#^z;625hKL>}W3|8Ci=;)iy`*uOoNpfQi|WYxs}NT}x8pIWY0s)W5J7Q+cI@MV z#W1TDy&P}-DB5dx!`RP?SgA*<-`zIonyzOw-#By)M~-@fg-Q~Rjgk1UA*w;dnBYX+ z>&5d&IC57UA*~9hWF=*Q;_g(#L}47Mig9@N9b_4_iUQ#xUPGk~7>QH6o<{ykl>x3h z*{$0{h$zchyIO_jH~ctY1xzysi+nSxv$K^s9bapSxJmlFpfOJkS?%QB+qK-!ttari z|C<&iiKa+AW+?=fyUF;`lcKT9=fXJKed9dR*GfT{C9*s)BrJp{5r+%DkN+~F@s*{? zh@wplQ4x==z=CxObL%uxJy_3HZ;vBn>oY0!-f1g=4#+rR(+;@f zR%sZImDJbAt{>_cA*%J%fRFng?d{J4o69efTT2623aGS?%eYcx-1Ui)is;yKL;+T5 z)TcahQ*MS{&vu~Y3yG9_>pM09T-zHoVzOj#Y)wzm^0!eiEkG?Cj&iuQ9Or^L_EwzD z^amRv0z%>lMd%KE4T1b16uKY~jk+Kp98+*!BobLgThQm{Pg^a&?B$`;WmG*+o;k_2@MEr3e>nD~I|1}XGZNO8kyK+VLPT^b(@t!x^M(`)s0CFvUPKuYjo6>l)FA6Rg5d; z{wvVM3H|R(ywdFe)3|bLj1d=Q%|y18T0ffu>o?EU~r&8&gD*=xT`4yq=>n`$C@QD}Cf#dPh_7M3#TOuO< zdNd?e+?7^XFCAypjQz@Yaf}tPWBR>b&~k5 z-qemnPtZp$j1};e27M9rWD_gMpE5ff;}TV?F6FgDn`?i7N0I08%Zx+45%ugnU6sNO zRu@p#{aE3kQ{$Z1HX;*JHOd>*-++VI)s^K6LCLx1!YghFR!1QZ z^wZGn{oY{r5?97X>biB&BcRkZWn)F&H(tK&uMOGpGv2uEs(|1lg}{2Dt(a3I%$4zP zBa-h9nfSF34L=_mVJy8D*P*EE)rpTs4imHG*pPwV4u#*UFBahM1@K&=*%S(Hr`QF9 z&wZ6@;e*U}#PL1I!I{rh$&jEbtJFQstoU#{bcxv|qSfld=^+iZ@ZbY^+MYeCday>B z7ugy8hz+*ik;|WN&~`MnlX+TpUhlp1xF+!@smJ5KojL-vT6BkQ>5gBw4sQfp!pwH*caoHA>v*uB z0T_$ao!3vK%z=9uj$^#xSL#Y9Vk#3;ujp-zu1^0v@j$zpa6Fkk+br)>#`qnBD6g zx5Y>ueFo7W{5`1Z?{4~e^(%@uibgU50Ww0;(eZZg;$DSln0ESP<;S>YNBA#DvfOBE z<&<#jp2ht~`SCjAvBt?`sk+Z@;a>d9Prj6Nb!6I*vuB4emSF~L^fM-{Tm0Df0Gols zayhWUV{g38X&I)nW6u_rmr*P~l%kh`CD2(-;WEWoSvH$u5)yCI?NuiDW0KXRuoqZd z5nXg#p5IAn{nWj`)YZHYu=2(A@Vo*3I0nT_fxT*@M1zGkQPO_Jll>1l;_tvg^+V#8 zt6mUR%pk$6BSluF@!Zg=^`qR<`@EIMu|Xq#7G1qX-fAF*5tY2)D<5 zu8K>VU_!%Ed`E~R(%$ycM~voC8V2FTB(fTe(cJCw!TjLmfIOP)=Kgt3GAJtQJ+FgiTu`#CrbjYqv4Wi`vdw;~;KrSXSoK zoy*Z)1G%OHop=~ON&~AfhxUin^C`|no_sOYh*F5xC5;mOCge;V{xU#)HrS3hT_;3` zKep#{mDr6FHwFLi8K_USJ*5r1x32NNq3+M0(2;};)OxnOz=Mh@?xE~l1L@6Fso?B% zK$V7kFN$9sP|-rw()R;&HouOOdh55AmHZ7X){g90^rAe@lc3eE=cs!<^U^e3QjyFe zC&aCL5}fZ=qdtt)><+sQpCJj}p9sw7`nOwIs5>`*=Mb3vrNcVq1go5yc^0EMSb_mk zY(vEAP(r4i*4{sS5e8$po2HH{YD3yTVr228K|%WpUE3^q+xiJ;@VAVAlHqU^Jf@#1 zl&FYEKEdaOJ)^++4_^W$v|=vv9dwrNyLFzZ^3wdjgGc3ET+Hz!4=hv24)c`9172^R zPJOJ){=Slk2NtdzK`dC{?55fE+oq-q9FD$hU%;mZ&5-jLQzt}W8bF4;+L%Hu$Hg9gfk47 zwk%Tp{z)YUrzPJZgDnf!m0PSfI?SSFghLfvf>cnl0WyuGxq+X`XZKglPxZgV*&Kvt z8ANpUls%D-kn9F=44J5%_}DU;jJmw%?tB{e$KSEk!T2zHEb30=CkX>d@>QS$X}E5L z5Q_V}L_gz-l)#E@pT)d4L+WC#;I_R6)Yp-MGm8G2mYfQjJ*gAR4wV*ciK}{*9(6uU zX+a=Y(3g8euq|sKTuFnhcrBkdO9Ws}@6Z5u8c9Vtk`z8TqIFc8{6muo#ojPJxcuR% zQ}LcbUJdK0;l3wC!`7*qT7++E)m3egNBJHF;+Bi->Cw=YK#Zj;#GJun-I>9n)KGdc zGD9)F@=m6thSY>e%NfrTb4I($K}N!eCp(WYW}y$}mmdN8PMAMrv~wuK0ZFJEj|X~> z*3vnrBBY**4!PlSJ$l6+=JB=wnuqQ)#c7-`{p>lNb+ef0)7xFD01Hf7|24UFqmYY< zkNOwRTTkz_6`6I;si2vmVxS%7a4C54TqEvGgecoE@i@rZxXWwhS?{`hUvUk!2Dvmx zl9wr#{F|jmv8#BXRg5jJm{0-t=gP9u$aIGXQMHCB*^7dM@*PeJDkv2n4D{h&hHN5? z(%IntJNlo_jO0^jA+YOI)G{(zd#NbiE(KkbCkXl>^fDA3*zT?3i2n2bDQ%S1b+>U{ z{vz?i;ama#=2W(N_Ci07}qtU`u zpKR@Pyopbso}z{xlbY&y8>Xwh&{A^MpSeH>TP@AvOlQDQqK*m(Vq4iv60D8snOiVe zJLzcj!4e;aq)vC*+ZWDY4#2;LgS14tNFxuYfI8eku)#GhXH#kP_AO>(prV<)U!i;> zPN;(Gu(Y>4A^5xVA1}Sc=NVc|ivfk%D4?2DRw!8`p+WzV3Z$Noo1ELDNnIIVt81zD z#l~6JT-QplZ~iyf6(kX25n&#lJi($ULR+CZ(ZxY6LS;Rl$3bB!Y|<#=c0&H+DF~^gdVi?{=$ea1&_Da|2md zV6E<)?aQwlP1j0`t1is)zQPi(d(|tn6hY?{qH6jG_2Le?y@z0#3aAPUY`Q!_?%5fg zEzD~UJYqHQ-E>RK=XQ!MJP1O9TPP)gNV|>>>^<#yua0yvd$2UE7d_UbeKDL^uJT|1 zoe%fH@){UpogyqaLe$D&?0ovAzq=iAQQ`>9z2a)Ame+IL`sKevwVq**jh_J8s27vu z5QIzy>Sh?Xze8i+~(T$g)F5iM#BM$ZpdPsWVW9OXjn~|M+Tcq#m zL;Gr96XP_G%b2Ug+FxEhbrLZ0%O*5j-nN3VTr+Q7xicak4pHxVNe%*b$&FNxswELE ziI+A7NnH`6(d3Fa#jYyxAYf~u|LzC3BY9jyUQ{I(5?W zD=?(5Yvz=_$OWK-v*w`g{zRcTLZf3VBt>HU3=q{0$2}@pWeY_G3hOVTqUopwfT9 z{E}X3C^};7Z2|aQg9T1g4(=Ox6qk#dS9(MPb0fZIU0u^>8|khk?sxdXKJzFT)ddaB zLwD@jVq7O9pfS$va}N0YW^|QhO$4Gt7oI>tSMVvKq{pkg2tfD_GtHVa+P%zI>bLen12oNwh84v}g&rm~ zc)PZ;xlVCSTn`X-GKEVi_=n=;`=ES(Yim!$3X6G(!oh6HU{}$f%rfjIbkcAES2ZEn zSF{6xh0%{I_!~CIV*6b8-$-p*2`(-+kZMrcF#;%G?=a~>N}dl@YmPvv5#_91teY7L zo$d{egOgJnwKaQxyff7~tyKBgML)=F&%eN>#MIF}LC`*$LQ|F?Z za55DPDDH0Q7Z+~TFZ&*yFE-Ttf!Q!gM|fpB9`oWP@PFu%;ug6DUzO+iCE$Rx@-zWG zE4Dp7f7hiYCF)1|L6Btrn5c`vcRlA3cIXp$zE>DIT!lS93zU^lHL$51FWfmwTJF~) z63&>5^E3M8HHf3e=U!}ui6jsU3SP95JxBRQ0t{7V0;#iFbL5yO|B*g2yb2xb*Sqzl z)dpgMVzKJ%t=@s7A7w5_{P=qQHY$?@E8YYyyUW81{|uH_*+=d$w&?PW0h!e+-l`}9 zfgxb~vD7fC!n8zM++j@K#DqZn4wwmQ|KFLhc9IF8ZLTJQ#$Qw)>ws))=U@1MbW=3* z1zg;0%Zy&6jDD}Zl-${A+Ef8VGcPwTKR7NDLp5$^Ob%{z;7sbt6wdCN3kVZD*bB;6 zg3hRKdIETyO9H;L`*uJij$LWZ`ZW$4xp9}{pPy;!oV8+YfjL)@M9M=q>~PFY6KSsI zR&y5zvw1iB>H3X=;MKd*y-`cj-KcHC@C}n}$BprNx~L`xhn&LPo_jIseF=nUx4-A2 z*F-4hL2qnq(0xK-R?N5ckrlby@!y}KMxD`L=U zMg;kQhB#ff+7*zxI)-_D_u-PKfFK6ABBoN zE8aHoh9z;nF_t!dE+X?AhnpwMd`P&fk{f&+L+w-XvISfN+?E`6VovG`br^X&xCb)6 znK8m)^zGq|X+YF9Q4G^(6&4=M>!FLdbK>D`Xy>odWggyqC4={?-3~5B&Kmt{BhPhz zqaJG8J)2k#Rkvr-YO*cgAb=ao9StcgW(5!?%f&S`?*Z{ZyK>e|M-v^S%me+8*68s; zi=R_W{moRAR(=8Z%7{)5`^j_Rl;>fdhbbSy)&>)Uckf?Cz<(}wc97a|#zesI@U3c#gj+R!`g0HX9Q07$%Dh&mP3S0v^y|CBb5x|udF(US7YfR|SzU#7fV>`dr%eNi9gS?e_X z!9NChphAzOX8I``G z*X-)>;SdKQw<}I~aUfh+Bjqxbe5)mT2qo;z z7FXiHdJ)YTTNrdlttqSAsB_IB0Yk?)Ny~0gV;}s{_~3%i+9Nn3r^ZR zYkA%iFlmjx^+4m#(y{ZpoHreLypkpv~a8P@Tj2w^eZ#Ls+4r^tigA! zUPv(4@uh6tc^`Ml6Hhs!V3Q@Ch1S{+RS7(x1z0k-QO$j0!3G^px+NLS($weblCXN~zM^Up| ztL_MSc4ylm{ptn+f=|**4glGl-#UUAxKjPdk9XL5?_Iyzs6^PEse&5*V#Cq}b)oX$ zJ}j0fppZ}tp0LfUvMp%a!sXYC`{_)`+7M=r$w)&xEEWl)`$Gi4uG-V$xocCYdS9Od zm+WUY@i&?GvR$b+&mxOna0+dP(fc{=#m$9M@0!FC!A_Rbi973W&%4E5@5e`LuldiI zg#Mj=m0OYDNbBslQfBkRbV`gjwnj_76IYcM;pjJVQ%Uc*rcX=O&=;m*lf0B%@hf^)FGIbUBz`p@qhYJ& ztuKeZ>)gyS9k}UT)m;R$&j8oR$`EMQHb0(o$7U?`i;Ly9y4*r=EWs<%^ecyq-ufb= z3=`118kbom?!St|2#mX4-snjT>Asz1c+naWFKc2HSD2J!s1!l_U@9zoL<>B$b9D^rk{I&(yKJ(j4SP#b1URPvR?^e0;y6^A4 zU!1WG>YWX)2aOQHaHz&k9g(HW9D^g+Ba*9ZuLev*pk;k{z}E@@xkzlO(S)J_cRsU&v}f@xZq0NjJksr&?1#0tJ@W_B zKdPFsW&!M@UWEfAf~8)M70ZV(d})U3sgBzFkJOL;8`9x|@pj~Gr6ib&Ye~q>pmkM< z{-u*R;}f`lla1|B2p80V+U=7+z5Z>MPz96!G2IWh_Gc*MfnC)@@CIYK5v>!!UKks2 z;-i3d-i*1%<^HP7YDo=*QvDmnofiW@xIxIU;@V)XatikM7l0Lh#SrTyUo=S6S+Fh#Io#c zlm7u>RL&IjyrBkt`ShReeAyd(?7@L?o(m}7{u?w8X&x4G-dvPJ$Y$2-J>Y6>hum7% zfnU?^KZ)P@RiCx>RI>P97k*+~6B+oRxNH*5=u_G++GM&XlkQ|~O9iEEJ3EZMM?B*A z{T$MqnLx4Jt|c1>wKZq^w!3LqVe1}4ii}>r|I>D6{aVZN+vHZipEW8pcP1U~<@}3Tm$`pU0;jr)Ie-yWvo~51?690fmF5WhyxR9)jG0d>2Fg zJ&zBcNz{$hRjRhlhvsUdGl}&}Uv6{M3qaqL%%XHKgED1R(z}JK8Y@rmvMI(-R=lmh zBiAeiN9kB~uZ{n>zH6FMQ)Y!-mgKSzZ!_34i{R-4>+C?AGpk-7QI%)0ocoiG9YT$t zuOD6i`|=@M!lQ4}@6o@^m&AOXs5cyco+9;AGQL{8?Q9d#VtZ(5$NKslqEaSkQm2w07Mv2&H2b`28?xBMt-!Vm>Z7R8`>{bio(@CpBZfGII? zu}Ow)Cwncs6B}yZ<6L3((1hiB?Lua`dhAm+`4((+l;#KQ7&vqVf&=Fxic&T71}M-; zBbKL~4aRksBIM0rV;86T>mON=o4aDPF)rPq&Wd#(tS%&Td*$9yBU=!y6_%axhhsw4 z!A_?RM`PX1zfCrS%=>8iv{;IDrejC81NC54jcui?bETG&cjv zK8k=eGPWTjlo%ZnV~p~lVT96>N(==71r$Xd{JneczpmrH|GkgvxQ_4j`J87eieF=s zt7R0hr!WQy-TbNt@w37S4>ZKsokYxj`fBsbo7G}E6LkMw-byvf;$1<$%*5^|zYXyF zB)@5#G9$L|8CPaKgZ(8nc5`29;+y&khJOZb5^VA2w^PG!we`N=+b*8)IfaJ(y@XOj zg~ry8I?)t2P=y14fGiS#N%+e67Kme+3+vpj^@t80+7FC#{^yBonK@9xkh<^+2a&1# zrhv97^)t--`hLjxUoR-T%Dud6?1>YPLN|g_|4Ps6nRu_uv8R5T@#x4BbdP^OFjLnA zI6Yut<$lAl&OrD-DoY^UJD2_LlOF$_w%q@U|86T_mK;<6de&#!loJhlihpnD?#-A# zrDTP-UCs-BN%eM&B)U?{e&-?1G>a6g z*!lw>SZX*$bAkx6l^;HpKDkaCxd5cR|A+Z5`tFsO=NlRSaCf;^8n|D{4{Q>SrabK# zi%XAEGvNC#?}{7578pJur}`Yleg)8DbKd?J^5vs&mw9ka%yq+*n5U4ah^~%yPOl|h z=Q{JyNVzIx9xWNIce2Wo>4JA*BYdlQ6A|{AxPB}kq5SBjw-KBx9YKe+Qg7qHP|7VYsw4<*FI`HCsiMg2 zUq3TmHLn=Hp1@7h)n*DWh_!;o*L-~Qlppnc)pQ?k=NX9@ta$PGzhQyQj~ssiU;jeB zlm6>iQDfiP$XdFkBe`XAQEEHWpgDm-qO?^D@;sJ%;`Yg)EG7v8XCFPF_spWWuY*^h zp}y#dBcn^F%HlbM8`8&CBNm$?Bg;=X{&&GM#?ziW7r`mncXGu^!FX+3*ab#+a9TNK z3Vt!B;}J74;KMlv<~jo8UrIDOM*5}?c$V06$xfZqN`%5~KM}Fzl`v)hsjBjtFk|(t z*@~^L0_$v-M-)zzOI3&rX-0F=#cy>s;h8xtEa>RjFGOcr!0NY&+^R>A?~fivr!|u0 z;sRVucda3*0Sj2BGy{%M{ieDal-{f+!%A8%15m9K(4>hey?4>WypA!se?2m?)@`xF ztZ9sGu{UVLo~X^+k{Hc?8J}apk(+0my?xHr_8UqHAkOEn3&#%D2~9hn_iUf+Zb0)! z#z%D^{kpgN!F*XOw5G0l5o1$4ZNVh|`@4QI*25zO9C8W2ozB@!YAcZs(4E*eeB<2n zle@caPn0QbFFMe<5PY>V&vsx#6zn>QwUeExMUtFMer2Kc^_mjurS8iaNeLLgx7`Hw z@^DNR^W$n@kzYG-HD|Kwr3IBN#+;QpS$DfzNl~Y`SMXxd(iq3j>wcO#bvG>eR%e?B zQrodU%!L|1LWK%aSMfCNtPFN$i2_gkIgdj{YK`fU2_~kIJC@n5;_Oy22TP59!@tyE zmAt4!>N8Er9ffd%=}0-lX9!GjWSd~r;0RkPWjrR8`RR&hwmaMAwl62;34^cQcS)*0nO= z9Gi$4E8M}H1|4p^Q6kV0TBLQ~f-9qo4Mh-Z4r>&Yw{x<|*yP{o@gbU%y$U*Vp(F(- z^3=0KcBh&DluFJ0o7HxI-C*5skbF_1zl&7%&JG7X@*chL!ub8CWXp{I)HXhfOjNr` zu8c8RJDZCZbmZuLnHF@4AQ`?~qm{sLr*`=77hJjn2A3M@Lm>n*IQ@$xxYX*9Kf`-g z;$=cpusf~ejfa2)$Ks!>|K7PcP0m!a>`_tA)3~wxu1YxOeZOv#Zv@xGR@W{USNUbO zWmDwnO0j3AbCAN>Rhth++OkqGMZK)>g6cgNIJqDeX=SJ#9o%+-JD)b*jdiLh|oNP?CFSl$5b;mJk2 zY^*Azc_i4Sax+mPO+tP_ZKAuO%v;(B{b-0w;Q0a8L~&Y@f2B&~Vt4A@vSRHSOzY_@ z1VgX-iE6{#$}`|9E69gkAHM-(sFMJg@={5bCyPm=zvTw(Pkt@!&u3ml|76bx;`N?q zT)v)v5{ls&4izRajgZ_^Qa1ZqN8B)ATsal6va6G2Rc2k2Rf;R0-pX+2yNV3!vgumU zc2l~mm)5@_>gTAEA!)f*q*acidK83*p=%<_B3jcd_96V=K0`~E&Z)sbmDj4R$m5IB zKZrKK&OB}jG!x5iRFxl{$@rV(W!D+j8@H1dmNWPMcfqR-XWTGV=UwLD>D&x+&oT<> z3B!9G11}2fNqYX}9ia4FZ=Kth|H(8*SQoV}D+&^aKd9QBP(cU*AH2kR3a_Y+DitVQ zo$Zo41OKjdqr92@_Vb@TQh-W)@a2PGZOI2b5zv=84r9XZo2Nd;R;6OsUh3tk5Ts#6 zTJs4GXzg%VqHMbn?G;d@dXi-KPN2b`ad@ubbOZ}+wCLTO+vy-L`P-o#7cgt!g>-y1 z)u>{|ey;o=#&UoGqW}2i&Ap}D-w2eNzFmQO1O6oI`ql4MCC?0kJE9q=QwKfL3mWgj zQ-2}+LJH)zqTHngd$~{!V&W61{K>Z)3BfII)H-D01-Wu{RP!oN?+4@kvpv!=cCD%V zdbb4#@x~yf%jFa5ffXk1ZCd$di0PLvI%xurcAp%jw2N`Hw9WvrNQz+(Rhdy{(em4R z(J$5Am9xsK(b-ints8l5JX&KAQ8Gg$nc6zk;6KflfS{m`nIv$N<#HdlRqi?6jztHH zEfE}KNJ_D$JC)3^qN|p!eh_{vqR?wPvEsCpVF}p0`Arw4DcoXU-s$HR&tub-|7w)~ zV5*ip*oBq6p{dKz*cY>Cis)_2A4~rfkx6Z6RNr?vohc{GbdFuRDf{*FXwaq)FTb}+ zhw)_s_h3SAdfJbF_}m~R)OjJ@a1o29_^M|0jN?2sM~%(EVkg-8*wV~EkB|YJhFEGzO%?$>1qRA zzyU^uh7LSAE-r;i!VEv0mfPmO3n@t$J^opz84C5ApI#>IAIoaIc6TqFU}19Jmz^#=e#zF2-#<%EnX}m7;rz3@aC1#)$gF6srX+0r zKrgpH+F3upYcmy;=2kyAasK{E*JPsji{Y>xk*81er{yK4M!{??B63vAH)PL}-?=u7 zd&WTSz727+Y@L*;JjJ@^rOaj6h~U41`X(O0oUTFftgnN~M|1#xpEbJc;AkW%RjtdE z_NqHo;7R^+0@6s)H0`B7B=k*@f0}g>)O`oW2@b8aV6C39$WuMRb0;_uLr+3aac;%j@5o5z?RJf{s9yq%r{vHsdc0mPNz*v4SXSZbs+aH{i`6Lk z4%k*w*mxU|X?!Z}CNALHrs{PUOR-?}N%QQ`JTkt(-i$cZTE3~D$+q$m3g>-YW=Bh; z-fTUw^|!H|A+OkOf^%FaD0{p2K^7{B>nhh6S&lR93EJ!~NOM#%rftQg(T^-#=?eml z%C`QE{Ql}$FvN}_0i<`_#0sa#w7+aNmdOxwylR>__@3E8Y;j9?9_oz;;yV7+{Jt`5 znn{`sVhZ5P{|DqwFnu&KqR^%yIiWX*c^9x2!#{ z5F|_tQ}^dKUXC=?DG#cas$5ayog8VH+)KJSMYeq25uGA5H1$(A-6`VvzRH@wfAeP! zk(o^4PxRhcyOdww_6$hK^16z9jqT0g5U+`eo)Fo&h)TBH@XW2s_-a}UA~Mfx z*EVsJ#rAyVqdLjl)!dafGry~}iXK!9^7Waq9I4m4Tj5V2)K~0dZ6eax1|EG@)O)+8 z9#ZfUt2(41pP*>yvmvdY`Q?w&^9HPT>lxLDur$AZBQ|BsUm@oL0CXj&>}YWlG4-PP z>JjRhBHjFEpF-*4%9`VviQI5lf^jMdi{=QNtT51!S^DA~VKnaj;<@ctmus0DN_X}L zyZ*s&thw~XHjfG2c|-+*8}u*r-h+w)t=p7u;1CZ&)hZFcQ|J0?Xo{KIV7qw$nxbuF z%=h4nzU$~LiPbhY0FQk8)+Ue3!X|N5W4i=+TE6$GAo-hRoV~!9MZl^8ceWab26oaT zK+bReJ}@e+K+grFYxbNDfheX~4J5O04!;r0Zg$=p?@OSK%9weKu%V{Z! zI%*PG)$q^#$1X+!LvIq29X10$l|N~m%zB4+fLOAxSbE~$E)@{{Zb+!;s6GJ{VIh87 z_sXj#=i>)|Y06Fg_Kzi>J8m3$ahCO^B-2L|Zg1TTLs$!q3Ugpil`nd37s`tIqj_9c z;hx^ya6zQ$mgJ2Z!JDxurl_Nf98cB_WIebnw!gmKL>9T4E);&%X)R;vg^@~03}28% zu1z=*pPSv1Yn4Qw@Gf!-Fb+Xf`(8tJmQM%cVM;}DgpO?}$iyCV{c2wCb`+&x-wL0s zjz-ANnOPL*gV^X5FLF9#t|#Bg_r{MmEj7E``MnXHJ#J-}%XW!^`xlR3zw*FQZA`T6 z>6bOh@AUn&cRIC3oGlo?O5c>rFKX)cZiUKUkh*qR_0y*(p(MgcOni`D36R2bsvsE{ zF07@>YtLc2RCNg_>~KYL`$Cq(Oz|y3c#94CH7eiz7+ED?Bo}(95}a6)WxUQHXnk;FF_;#2FYW|*88FTKJ$mp7R`NM z3b4N7iY#1vF}(;a;Fhf9=ia4px$InvHsTLQr%_dv_BCmW@Taj$2Wx>A7YvRR?Xp-W zowT&4a_Q;SAe}H+If;F6NO9U6oP%?hBYVsC6?8C+%JiVBh9J!Br_xhmmm?BMPoI-B zaEskNz>|+z#SZ>8L8E;Z0BgLN4MF=+-2-n`#O2-1{1fivhkUB}9BTI%DJp3{+sHnS zDa-L8`~&JYOqP2p4=UQ-(hJSktgYG=WWB(DW?=eV-8!`%*aj`{%)I^z7!H>z$@LJV z+qv2?bsFEg=5`@Wg}(ImsiMSOFrYO?NLOCHUi*A+jM{5!tLupp^uTe5DU-t3ul=q` zv#J%eOY*a|#XGdsBjHO3M4kdHo4~bIG5esXQM<=y?M9<{oT<@$8J`tG!;xdXtxYbr zW9?7XUUvRL#24;A8-0@M2q1y517w$zjrj$=N&u=}ha@oLK6|BRlG2Y?2TN5Qx-JLIAPCOD#W7ERUP2^-=r#FK<4@wG(UUbSwR77a=nFG#~sXt~eYCOVyrXGMPt z)?qM83gzHIIufyFy6QKeiN)%^B_0Z1vzFu>e%C2qN>=#M>Gfo-=PZ^_OgG;rS=^It z2PpH)Z=B06u_22okDE8-Vu(;Y%$$Ew{y=@_N?Em&v%tZFb_U2jJr=9qYzd%cc;+RGw=By-5m<+1cphOYv!C=Bjb4^Js&qqAP;Xf`#_MhhDHO~1BUL>PE@rd8eq zAqsi(-U{Jrs-YI;5+Iur1QD+(2;+ot)e6xdGUl@xxKGa2v-Cvoo59c5kj~Y$uByRK zcOw^v4!iLUAwrXB#2RSSF=Sj*Q%oF6FCPlG`men&o;!_0U2*9F{#A?WiDWFmK+H;CZlVOV-iQF+5*!&kMUI zP-ep4@OXBD(Mg1@mmWO>K-rC{ndt|>AIgg>eh=ezesLQKjc~8opXr!g)@g=6Ph(Y+ z$UKRpjsKBd#&1RV>CPC508h~|6VKb5O*v-Y_nZB! z`gu&>3;{A{oE;Qc{sR1hgzr0Itvd6a&C5oTY>jh`$TbD_Bu4LQ*+1U3#<|*1| z-+i&H+{EqN^(IIY9Wo7j-`UT>AmH7{xuC}E@?QY*(ducM7<*MhEr zRVp)Tb#f95=(Sq&mFBjU2u1Ejogh9*dsw6koAcr0sW#lFC4@EpfVllD zmYA+p#l5>bkMf|TP1Pl|maaD_Y#cj+<~3S0HKq*T-6Bl4%DpT%7S|gXxvEI0)#>#y zTd?Vx614MbYH#PC)*o6!^UL-udSYY~HtgeK!Yb%x={oT(y7BhD>rMgbKKMF`%>2!m zZ$XdpjPlDCd7NtAGHB?YM5tcV?Y?&c|7gh0JqO)QSX+YUBiArrG5AGoey5yQ^bvyn z15LdOLoc37O(vMLMS&NU(Xx}>j3wf;>dmDv?>sl5hP*|K_ zyVs%m&mi!10!W+22||IwcD(Q(?WDX*Ti!l%+1YI}2?dxEpX0m}=0BbxWC@5C)9Of7 zr;Z7~oHAy@iInN~%So#(GVpr%NoyKA$qv1U^;1LunqlpahPkg&+D>KctYer5rd(M* zfq0(oUMEeQ;LMdgLuXR*OP!fD;wr;DZ-f78bF2hzNU`Qn`F~GLc zX%R^PD1aJ;<(LXQm zLl62uNii%JcDw{BM0*1(K8!rbah2-8^#X4gzEe#}R2w;TTD3Dt+qLU#4|t&l$WVr- z08*veyri{yM#H?6f_3GLXN0xAy>VkfHD%2m?;{o5_7-+?p_T8{7G0SF&_TWlaI}p_ z&8hWZn@JMFRO;-$E#3}xI$#;F-Z^Geq_jmPAGriZdF(n+AGB`0y365s??ELfl zTCP4Vi;H=h9+-DMmaG5VhN0tgbXYOJ?*G~5gE3xH2@T_^cUyexRkJR#JBNR4XFWHp zUqgC+;$P&TliQIECRvmwG|$7phiPs<4}m4jqkerVnANzI_=>EcQaF2@Z;!^bk)G@k zyxIlzcTa^V)0uxDbh0FzpYOmAR&-g5JYPucotuSY`R#mD?|j^XX@Xul$mIvm6HUl!6uB79Pr19qOL4VXpwCcZQMz zjlef5$C64OLELJOdZ(*Lh5Q*qCF{&vXgTst|Imn?K9c%Q7dEWWGul`Ct{=7FGtMSx zGCHgP>W{Bf4Dy;O*j9>|3g%GY)tFi4hsW-3b1IN0>OxQb-H%o`kIkCRYJo3GSDZ|M zs>xDbS?t}aOGneuPN|;SK8Y)Js?5oHb@L@d9~IZ=-ceFxDW8hojiBtj$qPNJ&j=3B z{1svR z8ub>u4D!ED;-)5YRS0LdO=qojS*5N0%u`1^nw&gvYHxj|igVnk%POfOk5H0+)b>|7 z*I`*-zZ#A6@hgLOh93`du6Gn|Al4<@shVk`=AG#b)1l93a4^r>om|d|8mAQk9R8Z{ zUg5PgBoo+U*}{uTuA^ zy4>yuBr;sTbC?0HmhzkrGk+&){rS&?v_yc|U9P+s5&;zCMrq0<|L?6bB(T|eV-!8pt`P33r;PUf=Mg+ti zp;)I9v8!!EdRVv{*#wdP(qUDx+i_f-LKXyd8NmwMiCv?xNT+ms_eWm=M>a&TVHwM@ zZA&*}=H!p#+k2yE^h5LA!xTP=E)*$E&gg#^Ogc?HGa-Db)>7?U@(U6BZPF-#lA ztQ`w%OOO_SF%SP+?mW)jnATWE?2a58ODOiPkkC^qW$S!cY?$%#>-Ycfrr+n~uYATHIz z^zoVT!B>u^VYVwM!iG`&UQ&Rchos#c;ns~^SiwnaZndrsRaFg zw#?*Z3Od>o6NCLI=-u9493UZYHl(4;++EZGO64{-Z4f)$#s#^l%j?rit@z~4ISe=G zcURWGB9cLqt*b(gGk87cIX4W7Ix%yCJ(=D8xD;pn{e31le_}4tjVgxjZC_$zh(l&z zlL|vhMDFvC@(KqeZHSm_ydZYV)nV;^goHg|Z%DN05&jr)i6hX9;2xG+_eH;Nhf=;= zHqtXgKbEHOE5$K)ng0{g$kyc%N5u@1ntXG3<4Im!e$9JakG^~;4{gQF!TF1^F0q6e z7v~ky#2l&4c-;|_U_|(0&ej@r)>S&*_KWeO9A8RR*px%;muBsJ!iKqLu@EDgItZpc zu}T|a5$^1IH`*PL##X(QZ?-soP5b=n^`0i9>Bf{uDaRtVnM`e{PILd@LgAP7GO%@7 z$^iUEE%kjS6ov=mcaCgqEDP3fWijnvS~K%>L#+{X9EqjVwbf0hJlC^d;6P5!Gv+r5F;yil4yl$SniA! zQVEf0Z)KpGF@zmO?sboRannRh5I z;6=yj-DXpMU1c@Y1#?k%OzIv9Hx{8(MuTK!-z|>W@h*j7Ce0Zqdzvkd>$5$7N9bG4 z>v5HXoLMgcU8(zJGx?eH);wWJxQrF$x=3JlQ1bc)SY(3B>uSSvg8~Nb-JIab7^$~;Ok zF})w`u}Vi^M@7t8vb54nqbm<2OFYX5MJ9mF2I2qs*F5_D-$;qd*yqxfiLhhmel7jx z+6ix_V9_x%$xv;y{bc`oIL94NSdp{XwZz9wGW%;%7Ix>EEYPLGTAew6o1};S86;R; zZM+kg<8^imsLgy?36hKKhz+e|H*%3(UDUu@Wv)1d*;rg-R0`&PdfF1Xb4-7&c@7+Q zHZB?_sFBUWM*h9?HR@kqRkK^aN{tACvh&HJ_ZGXGp+Xa%mGI%W#~3_ajZ=~Y|1bU_ zPj>D!Ob|d-KR?M^LOA>HggI;ð7m0h=xuLqS*-yJ6*CfWbOnnlAo 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

+HaHTdD2cAd{DZjPp6Z^1{|BK0Y#2YF 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%0D&4BPi~)&T z<(bH#;!j1kc8e@ml%ss#Jr-_}^yqoP5>I$prvXcO2Z(ZbEa#`bSB4D@?=%nEwC?_> zeK@te_}gorHf9=Z-pjoK;JS0_X8rUo-7-yW;)c&-QpKgF z4BpK1{x^*S>WXn8#CWP?lo5x}yp!ME`SS~m zBnB1-g*3X{I4`uhwm1QDR^!%;)ou?2EzS>~Q&Tlz9z3Eg-hB&Ja-i)03$0=mBXJr( zzkP|{Gm0)+9-K1PxF?InZ(HW5Q_J^&{AcRczluQ6K{-zr%XrUguykZsH6)M#@8HVO zF|Il~p0MyYcituN4@$#e=%JD5xmU6d8!tQPa`JuuI5FN+-{p7r23q%kz0Vd50S#3k zC^ypHh!sfhN@^wnUx2zhqs(iwq$S^VP-FC0m#n3MR250SVA~N;UpmDJEkN(J)B#ZAU2g&I!`^KmxVHYid>eD%(z%-BTUh)$=sPt8!<*xktcGQvhDBajGv~31$z@d0TbjXcID0V=E|W zKd!;R<#3p`kLS^(E%WK~Wmv-PFPHY-w9OUvKb{%0Fs`lg!t8lO6!ARI!haBUwFgit ztR~hwS^1vqKepPoV6Yu5h#*TDN_K+%kE-z@tnYG}RcvZO5vX{#ApRC9Ad7ND36)rM z9T$wix~)SKI&LeYDHVn-{0$e+Wf2 z+?GLWvfaVm;Gv@pZ*~3zl&(%s)~dB zU48I8>3tHW6U(LWLR@_LpRnIc6H+^QW~{02rcLs^<*htGp}Ae6>1AN@0!g(GA@gC+ zyR&#_XEt&xMFzFj`!J&U&Z{MqsqVyBSk&hp*8+JIOK=%e4ALy~)Qvx2~}WN+bjXzz53QMo^zL)H9>G>nw+9)mRe zWoGM@c8?UPJ!2n=wd3(h_Xy%15qKm^>Gu;^w(p9(BbC{BzV$+g{=v-nBCY%Y4hUW< zt(~P_vZZp>F56nOe;MA1P>K^#XdBU3_*82TU--t!j+<)pW2cDN4j)K*&uE>^8D{-`$Z-?vev55nmjG5|e8oUOodH%1lnu>St-{f{*cra{ad zAK1-4w4moLfN=rgX(aO+PNt62u@$*_E`|Mwi$50rckcY6?-SvJ`kHcw9o1R#-0b8I zt#CvDW2H3V;j>o~>PdEJV^419vOEUh0hDU~N{ert$TB+^-rMssTf1Sjp^Eg;DCV_h z6Vbc|faj{(J$%^ zdS~$6Xabwz(Gc}E3P0H5CHr+31Moy%cD+;>;eD-;Jp{DKmP)kEIa-wmPIdKopa5_| z3blGvM)pmXjAuA0B{p@SM|k=+wV{~0a)zMFBpiD`ygKxCS}IBbX-i%5R!To?*oX!?lsm zEDOR~+IaJzb|{kjEoo7|Y#Yc746%icO+@8*9Mvyz&V*gCb&Qon^n zh$vE6>pl=1;UMq=ArtIoXS z(Tg4ryZAwjt?Gw!o&&O;cc)!gTWX+QsL+b$6v~&;KzVbq=U}>V`LpEvmiZgTYi-6J z7^g%5rlD;XuU|6V*ZXxunl*>=1rkqWMq<*R8C0x2GCqbJ_GQ>hms)TK5BIwp!&v;i z7lyyBaPR&U(fn`J?3u|)ylSG`HV0p0BS&L~LX&X>fJy3QzPJScWn@Ud_O)AA6(CJ75KA?kaW&hFBzv0oJde#T*T&_YTGUwjgAvG|=_6F+V!N8qt+ zV@^^fUQiWx=T<>giF<(5C1C4?$rlZXZjVN_N;$hhS87!^0c2MAqA)PN2=)`dfp^y! zvPs#3;fvL)Riye#%Wk3g)JJB5E%2V^Q&wCl*wPa2oR&QR)jputPbKGQBr1qCDJk(X zWem4Ng&fINs4lB5)8WEg?95T_1NC7Ln`v?dI+$_7-zHMf~Yf zYvu>_hCL?tu7x@sc;cJ~Mi|Ga|x)uElM=y0&659RiY1TUSXUNaaPPO5qEIAR? z!4-C1IG>HQJ4XLXZ-`MYxT-%aF);il!J|dE;3oy{akf{{6>BCRBxV48P7@e>W7PzA z=k7y3y*Rc=f7ve%sR=D&p6THbv5cV2C`?)uax87xovBvs#&J#49JA}H*6G$UofIua zo8QW~Ctc}&ZQzCP@C&~STWuf59HVSU_rxi6_DT&`C~3YHeLyFeMM_$cZ&pxO_0id{ zG}O=y;$l>yV#-+Tx z=|};lRpRUtKh@+!F*Pnj+4bG${)zlCKHTa*i}jMf?y|VuxbrDhCN=Q3;si#3YsYCw z6(>0_G2|nt2#_!c9PX8=I{4KeDNdD`-k*OEzS~#}jr(hs$-G*D_@#^qs)VphU(TfOI-f(HXx>%wB4IV)M*EK!y2(XMwD|DA*b5E6y-aktTot?97^$hUTqCaxL*`_$dyC%z^gs_u*R1D9u}@8&=gWSX z7as+8xjqPv@|?JGAF^TS6Xk*fxRr$D4#N7Yq$luE!u|_^6?Aj`+=9i%>QgLnx+ySi zAxDMBM=DFOXBob1qFQ&=1{B^s6*Lc33!fpQmx}pBc6J0)dxIN|u8w35XJY0pvs~T8 z&x@N47;$fm0BncfJNr%XA*N(kQzCEURD9gC$6UEHiHo{QVi3JXJtio>ext?_^-j;* zgVOP;egSkQBvnjFUnt=8&G7@Dl>I&>&^=UKP^V(7fp+-xA!sd-}TJ0 z%N+P9Tb`GhJ|-lj$0U-clwHIFs8sJTCke~HER!g*51Ly_#S&OCFeDxXdbLbsTUK{+ZD zqe2mXo3Y015jks+Vk-Y#iFj)5REZ!3QWIeQ+CQaXmJ7ke=ua;j1MyB$XX<_Cslh== zf8`wwA{p;_Gm^q1MonWZUy4|u8xm^BHv_`e9)E3jpu0_}qs>j>A3?i(!d#059@9xpJy=(Q+7 zS%{LdK{fBgC$A4gaLubvdApA7hg!)8FG4O(4yyeJXh&K*q@~)Vr@frWc`u}RbLt)M zpQzRUox8Ln_>;tmvTjX&G^fU<$Z>VZ4)^e;TX2eSS?z0CBwBB5r|MdZLUWyo$t1S& zX9~&ByaxJjFF1IJpn=x(^=i%m$2=a6S%gS&^=atWCe?p;dxL_Zvz4F3ULCh!*rX(P@Xzhj^CE zG$iJ;RPG7Jz-0|fP63PX+bMT@1qkZueV~fXMepa@?hNVcSFJETUn3%tiCAW%~Iv@A$Uf8N1 zzkAf$(Ih@6{Qnp_&v-V!J`Q)#nzgqMB(+EF)nQB2-h$RDLF_#`6s_3`iHcPuB8VAc z_it}1F%z_Q?V_cs?epa2{r=qNbI$L4zt`1#O@Ld{==!stg&3&eOw{VzS`j`sxp+4_ z7aJWqxYWoyL8<_-13s}SF@@%6s&9iYi_=Hcy&T@utOQBj28z^2V~tq<#O}{5D?pUTXTorhgWazhAATnPjW%*!}eNq={h|Nbwzfnl}Yp)8rt zjo(ra*|HSUi_$V4EL zCwhbK+>5*Pt8PQ+299xjH&Vz@yE%j41fGz@`iMtRVj8#N6s!IJcPX&IfNqG# z^A$@)=Ip-k5pLLAc4j8gxXY1)*T@Ifb<+=4Y8o6U(3xlyEFG=nHLLZ~hTi|vNNTOv zARpxxuhvN1e;FPz!W5L2q^_Iux7vBf zI>XGso~j!H3pG4G4PFO3Psmr+YS|zjdhZJ#@;Dt^xvp-4cNdzNRjWI9!|T`iD1wlM z$w2xXPW{jQ%C5d`u8gpycOOzc=y^`1Muvp~FQwzuAIpk?Fhb@de$K*++vQPM4{^DR2X1k`v~&&;&qo9+YzsM+Qy-oc6eJ({VF2)T%(lq;Nor zGgm1g`<;?=eYmftFB&5$aV&23C+&e<84x(B@gTr`_-$P8rA8jAzfxBw^dt#5!k zn8szy#!SyZNm5_u_R!AZ%WM5`F;91UDz|n zuPN0o`pwB2yn0-(HuacO%HsQ!)9LaH1~R!BuOu_6+Uw(b%Cf5-LdVTQE4ROH*~u<5 zWoXFzP|Hhrz>OhWuM-Q(G)@eo+m-jP;Q^&o=Od8If@=2cX;;_jw$m5WU$Bmwkt-(g zqKpQeKilwxV;9A=w2znUl@fKtsLqcChP~aAeVXNj!hR3-v{dg=4uqAh&A#f3dA2k? zdsM1k1_>FZa zh^EQ^AGK9zE`wE2@E zrrZDWcnLzAUl?j!^=+0mvYCC8{BsvFL+9vk&}Msm>|USEe>@Q1t{y=>0hzHOy4Xlg zs*0(Konk>9DQvr&hEMh^ZhX@OR>F@IJjKYpc(E|vi!ecq=Cx%PNCdhD1b_w}Oju%p zKC3Fk1jl@tO->&wgqgv!06rjB8~HXRi4aX(W7f6wv}780fQZ zib*A14IBxbG3S!B!kOi4$cU?`r8?K)CN&I8!+n~p@@>l3r-f{R{4)s^m?+X4eCtxw2k_DwT2=ZX@rP=<+_rCk}@ge2I-U%z|(FNXo6_K+zP_i&4F{b^} zL{7JTX!$7>`4l@CUMOToR^j)rb&oo{lajwj5@6Te@d7={*budDDjrQKO?Yz8cI|D$ zo7##RZM{&|JvCH|N4$W36K$Xnr2I@IB@zv}lRIW>E{Paz@p7p&=6Sao3%Rck+2K>@ z4p!+Ud}dAeEV8(X)GGDJdaa)q0?vAQRHru_kRfSlGvixds0IG%XDBD7B0p)xj-8Zj zHM2^*kH)HxaOK=|&=9IN@B)HyKJf-2@}?+y+|@kV!-h-$oZ;*c3H!hR<)pS|)XuRw5>jz?olTi2YNwy^ zJ?m;vO8Z$F`>4Kyh_{HqcYMuO!))!0|5__~3w{rvC`mM~0nk;Y+^~Gxo%84Dfa&e+ z2+IpLCZk}SUu4MAgq6glWag;pVRoj83eZXUOVc}^@~wYPodJ`AnwJrR@Wd5~(5csn zZdgJgpKoxPfW&yWiWPcI4jfu&?tT4Mj1_cbcR;EDD_$#4@CDta1_wx4m{LuJ%pIRB zH-L*@`+p?Ys0hfHogC0m-5kL5iPwI{A>Jqoh-W!al9-!OZn3JB{$8JQ+NuN%5*qy= zd+-ccMoeJ_&eT7!9W#j7%P0{kqkLD+l9ow-wb&HH(x%ezIGjE~L-y-?(P7TF89l;H zJhLXB@P`_xoD0y5<2{>pRDFJ6aQvRCdKKLh<-E1y%ss$xN! z!qd@EGh4S&MqN`wOY|y@dQcT|GF<}6E{*#)0Mjcfm?MA}$rubZJsLPsdn+(zM71#@ z$7;S~D(r9UezU##sRp|KR``1IlSceE=>AZ$T8djF(vk(av3^_I-U^u~tn~YTmwLXi zLzi!T$Jf64$yE*+#X60%c1{#B^~MLCZC&$gQOG=zu{Pow6{2YBTp1b#7^ijxqjzsZ zn-ZA0+djoMsYQh9a2akt<5KKMKKAqgHW=cSFCw%bv1agJYr9P}e|E}emS_rqKLLAX z+He|rr8>xZTn@lIoex_5%>BT5>b9c9LO$ugnG&SuCsxpLr^sl{=f>dKS9msJY#uL4-2eYIOHr>vBz{=iA$=?=47{yi|2PUOp4y;j7d;6PP2 zCTZh&2#PS!jbWP(5;13-`SBCCb2QkU93W;oEZe@=i<{)mR2|0}_+2qk9OxZJ+BAVg zeE9qn`-RiF*5Sbq23eh=+MxDWtNarA05n44Gk%O*C{Pm)IjaGereUQAtP35reyprX zO_Oq*eaTgP0tO)(l_}kr@u=G5*$njRoNSIwVSd`E&w3XT&hIp8WlzI>YzW_9LZ_b- z{I!&C9HXoLRfq{XkZL&Mcz~a%`hrv>`kEQG_bD)+*Zo$jkeE4bZ_mvMJ*pwW3iU+=Uip6 zs46wUIt4*7jYp$rvQsr#V@(O|U2Q4**=ASV?dZecdLecshdhi#@j8^EO52G3Z}VVYvD>w^RW!j_oXCS zQoFnOy(5T@H7Px-Do;u0?E35mgd3=Eg&*|~W^6Lbu3Op8)`iUoHl}-XFKR$PB}?j9 zWSrxyG90_N)Irv%1TX$!9ejb8w4rtbbVO5y7yX6M7B>u-i~m}9rRSSj8@?GP!p42g zuq}zhrRy`*b$S%=j)l34p=60$e`Ktt`eXE$w_!gnY*#TIj9by)O?=0|^qgJuAZlKu zMzF#KmdQd*>i+fKVh+MzaXn5)x>n>@GgPAeEO`(hPZ!i3xIQk_K6G+UHVSL_uTs=1 zt&Pv#Rj7|o^{`T-k?Uh#`Zqb0y0fvBDx42$`@4&i9UJ`i% z-zjW4Md;BGngXiN~#k}pY6 zGv3Uw_Iybv)qmHt>I9IVUXpgbS5IsKBt(A?6ePPE9e@NHGsa_HrE}C7_v^8beG}&V zR@D?WBgnHoxiDSm{1C{LTIf`X&?LRlt~HaYRj#xxi3#6PE=enGEdf3$LdQI>S24R6 zWEsGQ!nBsxkW&LJGv~~h?fD{#dl|l~-Qp*b%Pku7ZgLvWS4TG}cECb1LM4~8;*QFc z$Et6BsH6wfe+|FMXAwK8rN%py&htuIY-xClI?9lNDCo<&)7s2Lmk@>u^K$spu)IFI z8I~&Df^>8O@?{7qBpc(`7nskF-w%jqtoM|?B8DL6F_lSYZ~kn%Ps@20@7bM{;Y*jm z78MapV>RvTk2MD#y&tf7Z&PXvDKF=+FWcL(D#s02;lYJBz&0}~k^Hg7SQQy%Z!=Qq z5~u~7oWm16Jy0al{K?Jn^s1l5K7Ro%4BI+N+@W`=7 z{bV1!HPPBag6~K^n2c4KxiW{8lWnM`nOjXlc$4NhuC|62iP%DhLq?nnf@@ajG3z|F(eBZO;|WZOl*$!vOY& z&Gvgp1RM1BfE>tFy&vS8o5#wzxZ6zQ@K9^NlH7?!^SE}1snfbBBu$6;{T-qzg;@9^ z49}f;Cv$#4KkG)>UZdgAsa>#dQdWu^+7Y$L=zNev|ILOc0BFpffZKh!)j563w z)a=5r_Ls>P{?@Q)H)sT1M*`aAHT91l%W1dUAs0s_0`HPcA~X8(^U%ALn-kfQ^d04E z_L+PA_owgWIcdfEky&PswZHWz#(FruP3&x(YzD0f*zP1MM8(-i=oZwqd~5X(Nv(2C za+n_1a*Q6CXUcAC>b_p&u!U@f8d)G`&j# zTN9|(9ZptVRkav948jN4G2EsO_j8ywDApgMLVQul9YlIlv>yNmJjz+1ez;zp!6AgEmeEv=Bfc3rKcM9DOUD>m(p0&P|3sxP43Of zG*YD8ENSOJX8XJ8)#_k?Jh!PV*=5xKI|DFNz@;eK@do`gZ?3{O`(R`JcY%J9UcSV7 z1K9#=(Z4lX!vG)n&gjsE_HbaZKug+$K9J*G$ zD=yBm&hh@LKocHa&K|4KlGhFnGgS#WN4IU$gBsq+({q=ul;xE0V)%Q{LW-rqd}k`A za*;k*{)-V?o~<_`xlWBr5T8@kGwac^0s2401dwRGO~!anN`UU9b{6PnPH>1u+`d~AW<+5(wAU6VZXsnG$?r&ySk8_v(@UxcjMP+8lR zE192U+qX2QPnJV>l_S^}c$0g!mnFqGod`h-)QRj~$s`P)e4AFZ)AGve$-rnXv!;M> z>D_s3U8qd%RW&8bE?3Wk5hpgyO-i)(kXHn90^<1bvUipjmyDF%x?#)e7Gh=1iT{^9 zQjJI0OXikl@~v{Ae2%mp_sTYMRZdi2)JRy;0`ZT-F~ zOygGS=2HRGI&H5`rW366y<6_jZrEo0=K zt=2{js}sEeHEZ1P4JES9CthO0cCP7kZF&Pu2F%2(P)#Ez8)*ld%2Y9#(onIF&@$PY zgEzc31`^utZ&rj;T}%Pf`!LfAPCfq}QEw%4+2Ip6nQx++FWx6?IxPEaqLx)MzEsU> zn|p{2#y>s1Zb?+6HuayDK!MXv35(Ygm6nYH;3IqYwsZtdl%ay1qkWah$dc7GT39Ws za={>sQj)st_sg-&kGZ`>o15@9`@y4Npn0S}DS zuRp9#>Xp{{r&&0#G63sn|9e7|BX`Cdx+!eJr8og*5WlGEHzaYj#@h3)K1*JnDu>Fko0-p4JzDZP13GNRv0qdW59al$pnIVJ97iYQmr5P2HtQ zSfCX%GsDV@#=q4(0#jwVtCb^#_Iu*|)%prQoY(9HjJWKxte2JJ3v9QS%xuNHfn(X0 zrsArlTd>vaoZ6@nRf%niuppuz-r>( zZ}e2z2FN@mB`I+{PT}Kcf37U?uw*4)S_>; z-%aYT@5A<9B8&ElV9w4csuTRZpWNr>t80rj;&2YHX@&Y*EX?r8_)s9y@kb&UU1U?HC1xj5<@bkS2cliHgxvI`a8TzNo*M6-BO@ z*}l~3^`@CUbaNIbRS#+L*$6v%x)Lx)d_1LX4cJw_LA+-q?3FrJXA{IyCA-o+Qrao zi_Sf)gloeGH7I#G()60^BO)hsHo^&j^6K!vz;r;OO+Qg;+#L_(oP1FKt~4;NC2z~| zZgTtZ^K(8mvUIC*Fo>@Py(lq$_qW8u4@&>Bh_dN`emj(WIw6$P+>+oI8=cqnxl#Y~ zWW@V{Bd;38^iylb1LnWYBhiO}`|kB^ukOZv2nc|1x;(zqmM}Z}-$1qh%#_V|_{|Xm z)nW1m4rIo^^P&^~HhoFM7L)D}cQYo+DQwq0nBO+Fmt4qlm&XvvSskpxqi&5i;c%HM z0}<7GWU<$8IZ74nf~~FK!ItpXP&3Oos+^aA)^IQ9!LohkE{NRK9~oZZyqNz^b#c)& z06BNBDX00kS~bf>W~cIutzo_e!O~^IcuPu+<8Af+QzN(rLAt6jUPvZWq}e1zkZ}vX z+2;hDMv`0?9@U@_gzwdCTP8_HJK=cMc`C5K83Dt78P|@~G|Gx;cXZ3V|DHN9;f^@K zc1C+3HeC#T=y*f7nE|1H^T^}zk+}15zepcB|5HuqsoymmgJFiJU;dY-`j#g60){t3 zw&R|5g8{Slu@Ou*dEWo7IGeDo^e22zG8?nNQ>cd^{$-VB3&NgFvNAMND!O>a&mJjP zeZT9rO2PMEGC=;xdCzl?y*XuWE}S*eb!2fWoomyahTUZCmkLQWbyeK_MEL6dx#nlQ zqJ2|Sv4yGD_=Uk-F%;|gfpcj?$(7Q-ktVs8$p^c?S_g5wy4Wpj?UIK&q?Z%y7k%4( zw~#JHS;3j=IH_Rr_Fy%P*os(#_ek8$l$aV%P5V}w3enSU9#szic4Vd>Im;&-4dpM| z+}ZIC>h~t7sqx+RFQUvcV96OZyH$a}^%hgGqgS#+Uo)gN#eM1x6{|pz?d%-?+1mEb zra4R0t37#Egf%Tb-;)<7WT0ISzGZ`SDE~lEV;>z%>CxpER7ZtN&K7)|>)zzRnPeH= zG_(DS2I>~^+DeS@$C%mrx))w|tv=$ZSatD5xQPsagHc#M<=OiD*9hkR3C^4n^;x@g zSX5iHbA6E6mNLALEW5PSXOYO^;91Sgf7gJ}LZWJ=WikN0W8?vgb5`Xb=HiMG#K#P6IC=OejB=qf9ic`5$EU68 zp+7M}%kdUyUyk!&&4Q25uE+%)UVDc*FuclvI;6rZIYx^K^{Olen_tx}H`Qd@o6cm| z%u*g~Cl|OZE}GozMs!r5{RQxiZt)Q(j!wgPXC0L`z%{ZNX~w_izyML$mq0na+tz4b zS8tFiarl$DwqgAAujuKn<%>WeYbqI`37Wz^;Y#e+aN9Owec87nv9i0O@N4EZUN^1R z_V>uZRL+t5LafGYmCr@l@W~z+cDn;L>BZ-cW_av=CuB0Bm>gV0o8tMh}{GDpRLUtYw7%nyOevog` z9egWA36E=OuOs!*E@T;UBJeeETXQn3&9(vT!Kh94wa>LD>#0##7m@7F)W2|smECZ^ zD&`p%J~Pykpmdt4=E0cDB8BQMo&TW;Cq`&AYUQB5@P_DcRa=b5Z!rtW?_Z0uBNs%$ zU?Qobp5M2Rhlr}le$>R=;d=5)=GNX3wW9$7x=Hm0BliO~+S^h+F8eH{ou3ul$4eTJ zOZI8*69?a@m{e_q&vZb!V9hP-clE&-bCj*54Z=tRT)lllN^dKGpTe=4bu>2!XCgwq zd&FtD704j($75b388Un_A=?rFU6#o=_zWbWI|xnfjL^HNGbMw{iR?vZmBN{i(H*7P z&i!{Y;(2n^>>?~2p<}x@z6Cxl=6uNNo9$TmoVnePb`CMl{r$3mC^kkUwsI}fKy#sf zm7Ro;Cm{c9=MU>mL}F7LyQ2W#1HV|4w|kE1M^Bs$DsD=c!n{O{l>Oq%7xdqi85_)u zT{q>8VDI+3R>**w+lv9_`5=!o8!KCpCJqN2cT(r}l3Ayky7Jxfe|{o-aDi;py1ZEk zs3Ft~KYHT(y|SOKD~#d}t#rULxUc6(tkkAQrC1KklqH$)nOrH~QL##|=TBuqID)&R z*jSVChR7R*juV<+{}!r`sC@rNE}X?gs~_vJZ2rV1(!Gg_ym0y|92_C+)LW=)e8(dREgRhul-#wG|~?}G(`yM9IJ+Hy|xU-egSUf zbZf7YekyOn_r5$akjbK$+^;F|>spS6$z6&bUu?^(NDsS3mDuH#By7~EJeUfW zZ8V9k9IY~7Kx+Bnn(m3|oX(r>{w?3!T*4BIEgKVzsS|Jf%>6S|s@;D_izId{z^u(a zB_B^(Afs!VBr-ar1BIMBs~g6-*<_d_{jO@)0#n6|0$G~BIn+@IvE|HYFOAUxdU*4m!ByewIkuvZ-!O!)#9<(>Ll zQ#ed#d$Bh-UZwxXF#X^37YpC^ff>_+X88d}6d~h)XEam;d|3mJh7X!& z8v3QIHWx{I5s48kyg$!n*Wsk&g+1-13pst>VsAcV&}ap|y0QMaM(hig+0QTEn3MUV zcG`m7md%C!i5@F83%C7#oE4dkbDD>=G{uiZP;~Bh_U4~cHc5r#26RCFH$$tdgV@%dXpVq=eI?yZ%oa z%jlCF)XnaNi^=&&O>bMlXHEuo6m3@cr_+3`9m1__In(0{3e^X4>Y*qhy%*~L=9)Tu zU^Oy(SUdRM_Hz@LMgH-wcX(`Y6lg{=dBFKy5{5m+jLMevtA}emY568Ctq-gn5wp$fqdfi7 z(t$4mIZc8iV?)FJV1ZobK2yD?E!C*w-;8plf-a@=OVwI5UZ5k~ZOIa@{?8q>J2RZ_Uf-LmWZ z(5be-JePocXPm*#UNvb7gyo(2*<3IclG9ko$SFK5KY*4?U zVtTF&*Dp?+4c_IcK!~^(3|VXZ$>;@SVZXe(H0NvBq|UTQop|feL@-(Gdgd!>0oi=B z9Z8kvL_~IEWE}26zKSPF`O{kE5AvU78gP?Iq7*SRS2_DPez|?WE6qi|q9;|N%4~Bh^dZGBKBkg+8wL=RIRcx;*@hm_L^6b4JfJo;VK(7jgVoWP!ZZ0kpOKJGP2O z1bSCndj**xexy}?;Y0DIxKcso)Xe6#@J1m<@Axe3 zEHL$!whkbjMDO5{q}$Iar=56BAM$opCJS<9SfyITYI`jUvNw7A1C_BEHX6#*Ftno& zIAEm7rlT_>LHvEMHbG4MUo%0g?`b(j{*6c5+J>g(k5=+#u1LI9;6Om#j9*`YQ|yJ_J1YA>U4KRdk!{O+kTm7?1I+Rd%1GU3zYF zj;&ppG6syUrI*ybVf$Re23LxhM*J}M!--e>BM{AY_OKm%b+p}Ehr}+=VsDnuA2uOy zk_k8Y9;N4@Y=2+OKJyCRJa1oe`%vfj>V5O`IVguTyL*j;_A61LYKn3N zLni;&7_hJxX>-mmUUbO)z4~fcBLuBC^v<(5W@VXEayCP-<9oj4>zWx~&I0ef4GBw( z<$yBPm84ioiE_RV(y;=p=^LF zFZ0|*g>vDx^a+a)lb}0ExiUx574VVUzP*YAVkWZ|W*%46>N6eWt|oRBNqA&BBGs{w z{7?nNNBi^!4K^14qjRHYTO3C5+}U?wiEfs0&1#?gTBMpAWex%9rmG)#L2)@5`=1A; zhCU-wVc#1k15R{&SEFn6LqI`J;SosLa{iC0D+ivsVm=w4KSaOd{h34U=8u^I)7*`I zHaLNPOPsn5&Ms=0jNVGFteD0Ms1IQHNAr;!30T3713QFGNgGI#A_bE5Xrlc{$Mz9F z+af=;w}<3fYrl6M|0p_PRA4C$N8WmIY$(3h6^tWM7ao0y>~K3+w8s5Xim z_h1OY|D7J#k9wtgw^)q5zb2A?PiZ2O>*2xZ8`=K%KJJBI-|JRbu0a#6)H4lPPebYl z+PyMu4INQNLl#GQJODECvvcp|=2npsU2=|)yR4|c=iOxw;fw$buZDYPlHC)Pj>fw` zfR0uOpPr1E8p6gXzuOVFw?@Bpx|f-ChLCwK1q==d;8|mAEBL%o{zVL4+=k5k)*4ZG zZsSil^FPOjN03M`P13_6szpm%f+X|6P8~?*@|5TYqYqZg>ZMS|RPN&8RtruY(Q^F= zu?Dzp6v7kQ@R4AJnJL40Tg^_u4${qqAA6h!08@=ZKElf#kMT8e`Q37mQApIR^w3ta zaiXQM>)K>9^&y1=&8ZtPEYo9?YImdK#`4IaSuDd=l;cv+1*rtF%5Plt@UB5l%MS!$y?p{L<~^8(cXh zQiqiOg40weu^LwT$*U|lGFR?hbxydw72-lmL!`M7MzR(K=Qc27FT}L+nm_!Rhy9sN z5jA+vFB5cp^90no&ViYZ+!y0tdZrUB)`V{UK0xk0wao+)Z%#AnzS^`DY7f`CYLpInq1!c(}cX~=+=Lf?Eaz$~Lpb!mZ zip|c2xC}VIfHvl|UPs1}B29tZ6nG=}7(~r2>!iTnDVjqn=F8JhNe3q~YmKP}oaYwx zaDbtxcbIH_c~Uy_W>qgksuh_w$TK|p1ZkIcQC*&xxSndC?AH_<*&diRUSRK!Jg)!1 zoD3std%3|iI3VurUrp%iP&-p@s{4R@9l4A!meiv`kt{$|9)PG+WfbJ@_u-b$ImbTJ zj^=F^pX1$_rsN{xQAvInQH>Mu>dnIbOnQWZ#IZYk(?`Eih7?z?eRw5T;T&ZaiUX9G zX*Y?F9NO`4d)sxmlWnJW49jv#iyPB1Jp1?mcggFPJB~mO0O7l2l{a8Z-wtYhx|;2} zG69ea?-pW_n#;B%QbUaakAX|dd|iI8tZV1!h4Q}8Cuv(M2NSIC52dubNcX)W?3(!0 zz-R$uN>YcXsf>kCO9^~iG}pAgBY8%<;@~D)M+-xUm{UChdlgNa4({@4Vo$5iw z_o(P%-(!C?qQqLb@~AH}>1i-a@Tg!%q@@U=v?*ha`VKqj7g%xcQ%j3Op6CgWe1I1% zm+2ZdHE$a97U1Y%n7wbJ;gM&mp^r);Q_iEG|UE#Hol0&)%fT7L6>;Zg_h>OU2N zUh_f#(-7?A@mA)uHV3-qG%0PE;6(o3pO^tk&%VSf`-zpjD)#{y`P=#0nOP^1e6Z-7$f~)z6L0W? zI0H;*y7RzyAvcr4Emo+GyXI!M!@-^g265%C> z;9id2>C*uBr`lx+3Es;sWcjeaVD;JIKkziSfA8n431z)8QE$WZF32cNnc~7wUppl=g1~(IpsfQsn3dfY1m-KvvD{GNZg$s_2&~i4Cw-H$mA%igwlFWtplE7|y!OlZ(b@ICg>^|a2 z1ln5wD`gYCqiMS_X{Q*FkiMgb3ft0jCFLA<6qLf_@Npm&p&H22@$oLP6ZZUC=3MWs zJEX7$IU&f@$_)NvT_&BiN*^mMRQo+B9LFQaYtL@@`K@?#o=5>`Q@ZDsdg~ucXtc^_ z^4KU{WacPezF!b8?+v$1qe!LNT#2VlI^3Rm#|Jk|qJucij)gAPyhU?9=pU+7m}DHE zn_SMFc%Q;+6DM=5uVelrEYrAWhdQrFXVx)9 zIVg1{rX5X+8J#JG4;=6$mA*B-cP@KZQ4BQsp<%ESX`=9FuD_V#+1ip(BMZLMVh==G;kg+F zhouiwjo<3EDiN96B|c|fJeu1Ja49zyX@TEkR9H;1)$Qjy3*hlE^zpa?e4aiSav+kf z^Er46RU-IPLsBk=z2wQl0NA-EOiWE6*5EFF{I(CSr8jR}2@Z8po~ez6(ola3evS4s zM4zU%`&uULh4@Q3Z_9~@l0uL0bXvFk28Vty97stlAI#9**UBl;6s%1{w>I8$=@a3V z0bFQS>Bw$0?$N{LRcu70%o&#buGwFHHCQ~ZOqx{L$Y}2uPSg{+%8ZaX02o|%%XCyF zyjt;I45CZYc(wq!X(=Z@?c6P@sO-mlS^RyMJAr{;Cg0``)1@V(Z75u@yh&q(BRHgQ zrj}_c2c}|GD8*giv40;=>oECFA`HlVrV@jwQrZJq8@lW{6eyu)X@+t6@m&aRPY<(LQuRrN$b(~kjUk2v^}+%}GqKBsKf+*q zhDZPKVJPYXlw=e!u4&HuIQn5*NRMuM*7F~w0~b^`p(0(e=VIL`e_p4p1(^W5Zut^h zNDEqqtS_*ccS|*&vqa_{SHm!Wmctd{xGr+}AIVv5omCTAB?Ft3pZxA`pDdQ?!sAOr z>8z{2RlKdC@=57fVAO#xkG9_Q#WJkk<9O3pIwM7>nTB@R%lS;Fb48kkbYR4XRcHxN z(KUI{s-z~)&~^COU;zDb?e4jl(D0{F7w%RKk8vS2%)st*p-fd%4f>>Y-dC*XW-JH6 zA=Sn+>_eh|LPH;18ZhMOxZZtpgZSp~M}|hYbcU!3Jcg`4o;JOc-2l!*P9iNsCPYwa9uTtV$#8?h43`8uN1Q1K!i1;?KibR=u8T z@Ak}c8O72)^vM+XNE!HNV?q6n-aqb3w*;Ejwr{Wve|>*H+m=}Ln=~hfu91d(5 zO4D+BiJK`nPdI0)*p$f`ce{vl)zIjDrxvzAgBnL#+tpRg9&8shw;$3Zjz7rP-Z}ek zwutwLt__K}s{JkT!$$@&l=@>|I*yV0eqoN1lY!e~p1K7}vN6vx*2cN4$pQOvc+S%e zG5D;bllE}%W?i(~3l*LXNl{L|O-Dcy#E&hnxolQBdc56NQ7?$xcY3BEBUhQ7(eI?M zsAyPqiQ38K%Rl9D=gQ0$2|D{b@r=mJxlYcYl`y?_R7rZLZy^v44r^y7OO z=~*#v_WpP2`v7&o?#R@ic%v99dH-AU@q%0+@6PJ%T|M8%M=1d795se-M}}lIvCt5t zpjUI-_r=9QQQ1N=FVQ7AGV7yfqL|`h?}khn-IZ4f*E3EjF$1o`#4$0=<) z^7Qn09Ej;Pp<@H)h^!j(pZlT`uRXHdU(Mrlml|h(?=3J2uPUT9kgd*~q2@(pzN9KT zQmQYlUXQX$)Yy;eF>ck+G)q!@=wEZbp7Rmam?#7u+06?LRi@5}SDro*{uSu>9XNsY zS`}jOPNppLa4kGU!utUs{FIq;{fvzMM*MKzJEN0yKfwXdm8Q<{XQT(iSYNdu{DdsY zsBi_QxuMztUlhesn4DV}1&{_d;TeLiBFXVzZakk+`t`p{y+wDvf9Zo=>9uHWhEF}_ z1fQyH$mVobpAr>JV07gsE$eXG;82!Hx>E84vzYw2t9;8`X-E5PHQ|eNFDj}3L=S72 z0DbK;uDszH4LAw(NPjE>5|$kwGxoSN@Dcm$Zj)fnni+ecQ@Gb%oIS>@(8)5fGe2?3 z+)Lc>OIJ>=GIV(#!*A#sAw>Vy*1htRn^XG7oHB_KB~wGR>|yAaJc{HXLi)ZNe_7(M z_8MQ*zYKujVxw=?cCzu_VMjTLbZ7xzc+E?=*O6L{q!CEqBps#ued`(^xAQ065oZY| z`FX&OE6d;KmmD#phI72xN{cEBZ;b_a{7iCM5w|3kHDLQKQ2Z6b7xQ1WHbjUdj3r&} z06&JKtGTdS6@!lhM49uhz7i9Pj+@kosM$zwXDjqh!64)235sm8g&!9C#pWm9sp@ec zJl@LZ3N0FNg91gQB19iA+vizj2+Nwom>RHF=y(j+G9;k_%LX;eFkc!84$Ln!#DGQ! zFh-qY>rZ4ij2gI5=oljza@?(9RM!8ElTI}B7* zF%8Hb+BqT$Mz2!Q&2E-(dxyf(lUV^2CuwN>hnqtj$g>XLr~Zz&Le3rP#3;_yxt=N( zqK!LM{crnDs;B^uGuZQ2cK7d@bf-ki9rp2m?_>TOIFnPEc$s|0`QS*F~ zRh%g+IEULh2Zc~BlLTP|MsATf(!K12_if=xM&sgqQdQvRQ$WUn;B2_>y;*W*O$ca2 z>2-G6##wfVWpIPDVeLw%{p0BX!Ucq(soli$!}376OnfOn=EU9p-T*)QVff|ivFgyQ zO{Bq zVNqvOfbUw|yZ=*k9{y~2?-%dVnr-c^Er~s9&uVKYF@q4Zw$K={t5Z?CL=r_%B#1p? zht?)mZDO=`sjb!esD6Kb|HFOV``q)K^FDIe41Je>HBXGD0%|V7*>}FADn55prnKm2 z=SBKnvkOjdPGB=06&xhNaJExyM(d1m7H_X>PTXJ-3>=0geQe%7Hjv9rj{!15tx3H( zT3UFbDg>=8DVbu`wgoc}j#w}uP2vj*0eKpAfo6{C#i|_RrhDVCsgmQM2hN%E71P9$ zZW-G__v1{t=%-hdEBEDsH$)da;$83ct{y*4dn-TZ^owW*ag|w%S!-@&>s{Uxc8@a@ z=FDOz*9t>2%v(7pw4YqAY3$JEao(a~Dg@ApnxtZ!JO@~ZyaniDzVc4K)5(a&kjmC^ zeQ}-Tg+-wQi!S8f(5K)iTMI`A15Sk$`@!(U(o9{*dKAjjbGGR&-#QU2M77QVwbV!C zGn6LSSrmu&au!B7OJk=^`+CJIFQu*%6#4= zZdE^ZJM8v{n6)%&P&3l)QMci3b9h$`sx@z4MV;5-_rYjnpqoo1Q6HgP(FFpIq62IG z)&Nr9bc$ipUFLpsVP`pEFrO`@Dn_{PGyR_SGL)BnL{#D{G_Rfx^Zf14MuMD)B{u@- z9xtfg6EGRcj9lKj*EAs;t&%P1*{GNGqSSzy=<4Y`hqV{gxr|cnAH&#fIs*Y`SEcur0(o!@@PmXwVNEOy*(#`G)SPC1Q)JKU&pxu)RwkF|a+wT* z@@FzWoReLTHCQ?}ygm4|tES&9_d#*^P412CSKJ(YZ_Mi|hG|0w`}fAUg$>aEkfT&xr@+qwzsW&^#vml0e*r5*t3O)>W46^@#m7mE_$)vUra2^r z2DSh@Vu~g!(=$|Ob9ui6S0&gDH^z~N4Nbf(xe(uVS@UlUGR&Zs|ru}O;<-BIl z&zw_TUiM0#d;PoJCC59DG(I3}J#S2iu!hDD5V6{rh#_pD(+=%shVm-AB;+Z~gR)U7>#J-B+3 zF#cB=`HD!XIdAZlM`}&5Kd5iat+*QRkn^koFl9Dkw;N~O`m*Qjn;JNyW@6c6h-@h9Vo23lVZqzHalFB;yz z3JsCl)hud^zq)GN6fb=FOCr1{D+Ym<4yN)YRlW#wi^M3itXixpx0h7pfc}6~(~_(V;Fns}+@{?h`LZAF zT2n8j7JQ{hi*STZJIBP&*&7+m(-S+#j51}3`9T0`#^XI}2c2t{I^)?N9-Oz|3J-Jq z<5uniYk4&nQep7l59oLZLwO(Gt-;1O(kQ<%%ejuJe5j^>1Gxj5O}iF!n9==$@6JtU z2X8w!X^oQg0nT?m2E8n%I25F>}%ArJ2X=qY+woReE}&>*-*S&&iQ}d6*D9)9bMaxK@9z311ITDjOix0n|#4XCyB5fywH>En2UualMv;^nM zUd&_Y=p2cr2BKO?L)Lq_mSzv=p`|&(L<}hM%%F)h?5_Sj_&n1?nz?> z5X;awe`HLHBH9hpEO!^HD!ANk)A?z4Gxi_X_gw8iFN(LazD4cBTGM0;$zLky_NrZC zrzU&{7~8s8X@!!#0Oz_sd8W2baM>x7#`F7Ml)PoNa+rNl(zuq*g#8F~K7~n@{IhsD z_w@z^`OPd|HJ7vg`0jYUb?(Ys5zMzqM6aRAAn&$8$48U2(YkBkkLU&V1F|;fq2W76 zS>?$r+ck_#RA>K>2d!#wyUphbt^9NajAvG5*IiLvzptLupMNCZO1#7NWcp`6c{jYz zUo?-d{e#u0zYk2xN})Mzimp4r;G@wtlfVUpQr9_8qoSg+u*_Gs<$77sMU?*WQ(3f| z&tu*caSxnUT>e#WabjVJT4$7f&x+bN(#C9-)u!2;29;waJFDm%UuuQ}OUg0^ka(&P z`l>vW7>8{&p%X(JUTH2qWfyUiv83%Dnk*D$VSh$-sL*dUm3J6x%g|g_dLJ(zt~JN- zq@ih|>Zw!bf3r=|^RyO1&D-@7!y9oY5j#7%E^wYysf0gmg^PJtY{SzbjX_1jrSU>5 z%p*?bqqQtLYC{GLZeh3l(zzqXu9Y#rxsu!JaIjdEa}pSW&XT|+6=#=aX* zOYS&hDFrX6{=iw6K+bnq@g3ufNuU+mMc6|t@d(GzKbE&Y4`&-bG) zpV76TOKH2buy(_Zhi}Pc{x|0Sg!Sa!{)CoFBgxVJ7T-$*lz4zdWNmqfCMniO*R_Th zuKvo{Wj)l9dLP@sS3F;sZIf-1EIP;)_V`M2_gl&Gr@Ake`IX-K+K;6(PCVOj5MJxY2FLaos;Gw5$`gyhl&GDZ z%%q7g$&-h?`5r;#PUX)y;l*Xzxo=!0N%@_uf1(>{aY!@cYyL# z#y^Aw9JzHjYDq%K_QGb+`=dEOSD3>%#hH0@qxp6eoI$eu#^@b-ZH4WiKPH5_X09!y z6x=Z}-efN1#?wtrUGhVUr9fJ3K7IKdlX~Lb#*5mbI%aX$Is?>*1CQS_Bvm1VZnZ@mM55 zttPFA{)oMHn>)g}jxZjIK75MEqc2X9x&Y$s5AqkQJ33h)#Q-~dXYo_PcfuWhEGml-ot@Mhg(Mm$6&^F4t6Ql-JVq z1xy59x^kiPl14=?jjy^Fz=V8i!H(ArJ8XZp$=OGZM3!a8MEB3&*7Qaj?jHe${YU|B zX}B?6`=RRo$EPB*V|2f7#oHOYTX}H9YO0E^R$5du+h|Yd`kUb-dC;}W#6*HE0WMpq zJ+WpyJ;+W?r8?e;QbM@i=bVzP?iRD|Vr7;hnL2f{S_Eg*`rO|@Ct6yzg5`^H45`7B zo5e{5Lzj>oWM$e!YN?M)}z1 z4Ic86r)%#eOv&iEVP@AzlHHM%k{RYh#TTWQE+2FSVy`P0N`f{edyUf#*)Zw86^>%P zf#G2m6H2QHmY#yn?cd1)a#9L?3a#-+>n<@&7*YFpppGkp%6xp5`<6~%4!0Vqm&e&7 zHY@viUGjy2ge>y7ME(1!+C^&vF`^Nyacos4WHm`-vWoVB8@5JU6)c?ME$i0nHvGP_ zrv7)m0wmQaYOi&ck8RsT|@DEbI6$vkvMm(N{+6IZ1H-alm*hr@eWu zU6Rr3N)JOb#XV1Bjdfkm>e56|a|ryABG?-Wwj|S5L7qEYZYX)2Pt!FVWUIx69}ETI7GkstqleD4Iw{_khpF4@lnaZD2>q-WRVHpy%Z7I@V9%V`PSvRZM#o2 zKjA5hZ?D13r2(J)3@-4kyzZY30u+yG`=7bLU|G(#nndzZP1F|erAp5{E$1^9XXfl& zwvrcFyL(^V&#L}KJ>z7J)%THL%k`vbp}%#}^Bcs_@1_daY)YXR4@uu=pV|%$2$r-; zBt=59${fbPdx|r(MbV}BA5u!qPie2N|5y^7c>Yj^QW5Ho-df8AO{*ls7en){u^+C} zCqzd*u)P9-{<+$*q;*)aJ5}_SFkEq-1kyY3}WGaLdU*y5GEd9xz5$ zasF_+^J%PHcD<&_L>Jl+zJgoYzQ0YSQsUzmkCwY5Areah=g7l5%Y=5dKgFbN?YlUB zU(gcmKM5I_rgH<_HqM$c?yYpt^5^$3f4hi z-ON@^ZNMO}F32MNA`z4^((P7LODHs)Q@4)Mz`8-T$MGWKkJZfa(6uvAX-&2%h&r0} zze`z8DhHLtWlJ#zZwlUrkUx1mV*b&DNe@5{0g|ujG2ibSdIY^O(tht??#muA4S3`q zMTYpn0BPNk9=6zSXpPm?;SRcM&sq8s&IJ!;vtKMHYR)&2Rkf|akci0DyLB9@H!bWG zMd*8fEp5}g;9Xt<|8(U4sCKsXMIe1SXlczB{`~urdx>}9&li)xbT=76e09A1BHnIC zr}eiy=;$TmOXDYlpixPHRi2(+%jgTmQhn00WrMQd0}6WRD~ZV$KUPyisdeF~eijLS zTaG}FvI)Hm`?PS?N3S?^0kyq`v%BAtrvy4=PldSX*P^jmVNk~pbm6b%b7Hv6$|;=R z%x=#ja9JL^lYOT0pb$4-<;iqiZ@=3Ez|z<>n0$lbaA^;}lv$8Ee*3=E*%DCBk*?7Eb2wZySezR3&c<*)4FJ{vQZjg$U2b6$e)%#eKh64{h*SP(s&(((8RU( zva>YorbI8pQJG3Xwx0~j;4m@K!sj=_ckhQ+71k&Ek14yawx7(p$tW|>VNg=>*4Hv> z{*tjg-D|@n0CYc)HN~I#PgEyOIrnQw6DW6EB86|QtW{>XrQCZN9{VF8y6KJk(Qji8 z*p2Q*cf_-j20gTXTSrS)_#TwT6v%*zQb};m4Z*fQSqBUWg9H~^Blh226oM(s7ZqWO z&Fa4*eFJ^^E0_(uV7VJ%vAk?z`rh3|?)NIDE_(tkZQa)2^&Ty6O-8-Nip%;V`OKZD z0SV^NbDAI2(lRl|s5e?h+^Vz=ciq~%H$=cbz#1r_Z3y@ox`BSL>b^V7KU|dao}{#^ zy?Np1s$6S0HW|z@(9yGi2vX2mHJemP0MHn%=;9$lWn%}VVAp@!amV%6i`yy^H2s)r z2(dh4!cgl0kRZ)p9iv&QS6jzm2WKBVdBx(qG;92cmK<`TH&LJhJE-i7*014Hw-(Ix zhFu4FD9~fC_k+UdH$P7Qk}}#Y$nA{;-D3r59rm87cDvamyW*r@gG3$Ev{(6y2i9|@ z_P{*Pe%@2J#!HT4K5l_;Z{}=@uH}ifnabmd5AG=IOC~6kPuiqEBNqdC^m_|IV3~TJ z?^C%XH3G&StomDyn*B=HSH;jg>V&^lGY6*$2Uw%k`n}ky9p~VO9Nyf)9*j!f>1s>A zbdCRn_>)SVw#`4M5`3lhECG?zi?iL@)@g){AiqaUa_mipTL0ngV*27k81yUCMeHcq z>$qt}wt>Lw=cRCwtAnB{fLs4h5{!o@2>++to{|-P&=jW5mcg!g zbW%p!-ccie34(sFI7H>A1s0t`=^MSM-HDZ{|M?p3{iRQV?nT)}{I6Q{TXOyLhWGtK z#-5J>#(y-6=^B}{Z^fv@ssYg(yVvvvlHc=-7{FILpBRch?_qm5^t=EL&>3Dow|+K_ zyKg+9%SkL}J$>5WZWYCVF|1#7ch&V&xhoIz9D#6)4L;Xjv5$OJ*W*g9kvc7laSIqT z5;kN}(fTMLKilLz8P#9a>Pyj=RuKxy6%D|rL!<3JDTGKIO`f1kZzp;1g0#Ix@>TD6 zK@0J#x3o<3`GPsn$Xzkz2$>f@RI*H@09hvR0U-OJ*8vo+FWnH&+~^y5+a5t+9&d*! zP^<6AGhBgO{GB{_qOWn;bJMKX-K7oRA?wdc@O6Y>7^g|x4ij4;(}w&L z`)QQ`l}B_!x}%(+Uj(Q zyaJytp;UADKh(q|*dAQ%v-}N=#E@Cqa+(147-~%>E|K}>i=3d@icg|-V+XJ z2^SK_7GIYafbcQ_#6rc;%f*JsXxSl2feno0LpPvzOW<=V3WfP0S!d+}Dxq3Ogaj53 zi+9Qri8pvvBrA@4O^(4Vs19+OjQD6K;Nm701EfDQwEs?N?0Dv}R9I}dc4uw9dTdkbop&RoY*!Wu?(^80rlChe{DAVQc9yd9-i1%W zv7#x4)=R|0^~#yemX;LS{;=yw!;BHcsh}iX{yONI7x3Y;FAA?a+F|DO>XNE|AFixV z+-n~To?Gvzt@nSBqxZ%&>0L-#b-Vl6srL|w_E`mGRONOfs&lMjC(zmpiWR5k@OCVp z6X80_f}+bnaY@YLMes)-HDG07s*oX<7he&FF4G9KI$h@lGk_+N?g%46@S}RbIMk%V zk7jdJ#TEWgk20}W@e6h)xZcy+L71DTx@SeE3DoRnNh|hkTrjy0aQwnvAvf==9Y*@c zSZ;;k%F5{ymUiP1yers3dGa?7!1XZCr=$ybR__{c9`TzWDe4I69`_jy3{mp5nPlB? zZ%TOxK+dg4y*y28zSAmO`M*n2PgK0(>RC~P%3F`0j$^$EPqboQGPea#vRz;Dmst%y8kv@ybYR?`+*Qt)G5p!-71^ z@Mxj4t>U7dY_Uh;V8Wug^h+;vt#K+&d{FeNu&#)7WNm)h{jMd~>Zy9VoR!9K4Eu?1 z^rg4{9ME!NVp+gpnPJ^S6`m_YuPNM1Jgv3WIF}e`Kb}Ms{LA;35D;Cb`Dc25SHig-` zxHU9m@B*d9;wAOByf@W9A;hNw-kK8atk!vgXd(ROCn%!b;d<6~jJ7uolAWbRLxdme z>PLclO(g6z7K_m7-Y1`8|J#qI_^*n~{0))*k1la*mkaY`kt5^3LXFnGKtOh3ym6qJ zihB%z&Vc^dN$>Zolz$8dhB1_@gz&eWb@q-+!-2k@jvL8q;eOW!1(MDH^qml?*C6b% zn)e#A(B;pWv5=cGW;)ONcqkd6WE$mdCJj7xH&akflr*-SZwhE#dAz}LUPM!C|EwX^DSlTFEI?g&;snT21wgIXL16&fG-Xw z8Ccr&VT0IbJ46s^1_u`vz-_Wu0Wp`o$JUtl9HU*PQgQ#gWHrRgng3Oq_n*?Apuz!; zu#>v_UiF_fRs|GePdif?Mr46Ra>ZMjEuwv>8VbRVoe`nj& zoMajXI@Z)zhf^h}4rRCjW$&-B`iUhCBPFRHO!WIAZOvJ;I($pwo%2+*x;2}AfNQ<` zF>~Z!0`zk76EB4OmF6=sq_bsamRRKX70=9d{S-)O*EQDstL(x9_dyCH326hYR&EVE zmHV>DeO?br${c}-ZzYg#@NSxj{VO?7dS}TMqqiLT32tYf$XvI+1ZU^S9-B|P1p((~ zk9xGwSdZYjjfkg7l@t2(X{^sPVYwuK5C8RR6ygn5#WseCLQS8f?{wG)gvDjZ@M)4@I^$CN)>qd( z{qH}Y+SW)<{Ln)PeVT#dUb)P%uT*vIs5@ZzG6;y{wxz}!UyB8lo)&g`zSEzs=ZTpZ z=0jv0`h>E=oqRO(dbfKa5f#vL@>#Y~m2kq!Byl+D=mB=cL$-n#XH;Hx)CAc+%r~_x zS&qlTt=33Tp})oIYK=B?2HHF7Zj4w`3o1`*Je|l(3YtRp%A0DD)b%wDMvll4JB?_c z|3u5<_p~1P`nhCnNcql=tJrv8AIlEjd(xkVbG!WH2Xhl^KaXLZxUbNrY5k{GmFYF& zr_|m@d}eoh1ASAK}P1{7&p5IIx)tXij+of=2ea}QwLysI~i?yRZ5#iCw+pXoZ{ zZ-YFAz8M{!FV&{?naZ(y9ePKa=k8)o*Q}D+ttE%9&4QZPi8c7Y5J)BjRKLg}s#Ros zr{$7n=g!lah!;hM$m0H%gaNNm#v=SB_K5Tyluq?2LmFK5{u7sl;+yO#3qp5j2ADFd z|Jo#fE`q>{>+foaLhkhx;pLr89@KDYEu#5ocC{=acrBlM6fnMyI5QOUT*TmWD`l2c zit?mB(=D5Po1Pf#>Wfwznrg(`aVqt z^#8sLx9ZHl!*7pBLRZ#)_}h6{X)5ym#)hTS@{>Z7-2a9}AnICk_mdbY8NA0(ogOPA zmGbX|%gqEfai%wR?B9>5T&RaLgxdU!K{iTN^A!9M6Myn+H`FRZ(~8ZcHxXl_kf)gS z);tKqF|)U+Ikp~Vk>uc|HsVlQyS8c0Q3h6)os1C1qr*0H#*r%X6BlB_O_FHa8sT}f z%d#U_$=gCqb_NZWS>(NX!L)u2S`yMJJrd_vk#|sJ8zcuaW&YwJg#XQ)c$Sd@dcu%m zXJ{OIbyy*Qsf;Aq(Ny)(H2qEv|3aaDyO;{Pw*$?T(=7eJOP@O|?1x~$Y@o;u&QUXh zOw81v6tK%7XCvf@;GNBE9`H!I$NaRt)vNT+%YVOj z2hPsKtW(rx_E}r3pRB*jT>-%K9vQ%QinSH?KD{hZIi7w^qODq*9pNR>gu@d{&`z!x}L*qP?T z4@vl%OPQDY=y>*dp9Js@$c9#N`XPhQb*3M)ftNkQzkt{}`*(5j5@;AQY4&DesA9ix zyW^o;V*Ox+@Cr{6?qPj*Tyo=eQGM$a^>k4KCU%7;C~@`)=X^_LxKv+b=zmZIjj;SY z%8eJ3E_JC>`YK~>L$A((VjbN=>%tpg=nEf4v#f(?H%3%aR*cZIm%~BDJXC=_Oax*; zT-6lO12&J&6Ex<8>sxJZloE$9Z6}2?9wCFT66`?@*{!vWa+N=#IuRek>QSHDr^SJe z`Io786)uguR#?vL<-2db&X4&N=P4D_`m{RBI;ltQgTfUu>)jNd6(&}h4C@6V{fD=y z->b?O{doPx!{6h^wn`P2p1uvg-^wZK3IXfVtu-(5rTEi7Bv-E}#XphR=-W!vqnonhABgVOLJp(CGHr!Ca|yK{k8%O2nDcLg z?s@Vk9$@eVcKlzS%PT;FkhgzSIjT?Og4>x%A3wx{*@H1&X00#XgK1jJ+ql$Cc%n@d z)_OCby<>_zdgyzn#8{(s8GrWD4}(g^+4wt)?cnkWPzl`oP$?`qP#X7rT?qJ9q@^|b z_}T@8etn)?(D%B>+CC8Q%e+vc#4IB>3NNxNrlt{qzEGCdcZnR6KH|L!MccCW2Id$K zQy&x>n&di3sL*sg?lg(q9+TP0%5Aih@#!F2GK>`kYm0atx>+P|i{r_G1!f=F>irX6^ z0rb=aMuoZvZ+CF%2dp@PhZ@6}fySD7uWH2iP#dbx$FX^2yz46O;~xzA z3b~xer1}Aiu1rI?_N$O~xU6-UPzX=&-u@|)J#Xf(vCN)K=HIFYhj~Kkpn8(>Y3yBL zBeM@bfPl!q#*lL!|yt(fTO2Bw~zY5aO>)*krV-5_0nH>4k!d((%D2cJ~wi*gJZ6_44ZfT%x3LjLaJSU=L_kYQbIiD-Ed;KmV+0^OKE3 zcgJ=VPp)Tu7MGFC>64mXo*S1aqH8W~##(`xNmAe3mlV-pY?$ROUekJprSf8KsH6hM zwU{p`fZ|0*uaSWapDGN< z*G~4u*|gGm3O#Mdm2nDiqS2=L-hpzpv~*#Dx{Qm_LJ+PcB`^Pb=b-u6a38Ipm2KcD zN%8M8Ur397ir#Ir_3I!}_(K%?Mrh3I-@C6q!+L=YDPmEY-}6}qTX$;6hujg?Cvh;f z=|%gObGF@~>L8|AAyD}r)JgBre^b1oxILPRM{t6gXVjwBae!xBpS+m6nU>D|*S+5v zt8Jko2JPIm8B4Pq4cpl7orH)*wPMpOyoioJJAKFF>7cj8c1}H=j5!ki?@Bk?vTLI~ zc#Z}D>t+kd6VMA2<75V)pxMpWv9FIjtOL1>LITigYmo#fpL#=#f^?LjgYg$lGmh7< z^^$_L>hyUr>p!MxRq?=t1uVaV(4bsFmxUZ5PZ;YPxX&-19^%iXRIML|}Y5rhc`AUVwr zuEdQytVi1uG8o6ZW2bt`QS~jebhedGj=1azHxJ7txtQQOhf~oqripk5_9QPbrzaMq zvqa5k1rxRHex?Ty)>bCV_vL&gUt-mJQ6#892?iE_xWN~yA}eNSKJaU^BrM;Q1= zM~i9Z+WcY!cfZ%ai6$lm2;YJc{O|VyR>2IeFa?qf95**IG5P-uE7OoH_FYllGiG}eAK<&is&HVhs;Vp2jQXdbf3TortbNq zKcTGMJ8NJukjtE;FgZ0mm-e5dr1uWM_XQM?x-}yTkWPKgjAZMQe$vexs8u0Czmf8o z7fnwPa<-~I#7mlHy>Bx`r^l#Gl;+j_E}>YJ>JtsplQqmY-qi-C`zZq%Cc3hSps`|T zu@tmuSy^;tYG(nH{u}9Kp+bA#${oV>GYJ+iWv^6uNC4(~k7EC&)=3#rOWhgsBBt*q zr?H71^A&Ip2YMipVz^_6h18=6dg>Kvl(@l*o?bzbK*@EywD&>zT~-IDH`mLaWN^`P zR()i`fK%OQBgUc7i%oFK+_d;=lJu_9cZ+!`r6_AmHQJ9RzFb`&a~JcVTsn#0m3m;m zLEliqBxQ6cd`ka4O5cX@a=NyM1%_xqv>hi!2Nv^xorPi5)PhubNmE4YF`_cGkb>2y z48)6Wk$9{&f=H@^}eCY=CN6}G+{ zyPV0#R`aHzj)Z%{F5Z|Pt>Tb>Org$C5=@OICP=i)uPYwx7iGwInnTRr6I zSDE)>Yy;~jXa&m}vSeSBqZ*af0?df1QX!s|`XM!g#3Oe>IvEe<2H-@fJlP|nBM8)v zkMGM=Yx=%}$;J(Pmp8RGkl(uwUtgJz-TG|p;58`T-Q+fUMV`x{npWsao;k5>!+4y$ z9=&ZTr2>)sump1#=X9W!BsWDp_V~8u#AS3)9>y-xkG^~_%tb)o=8~Qx1nl;i`4H)K zn$3JAVRkx(5C~Udy80n_cJ`E&Gcxl=1~vpaRHxyQw487nN4@`9`h`-ywBG5aMk>*| zr&r19{x5Hf_2OMS61_%<=j5v}o1Bh|Ig&sN>-{&}0beX0u2?N>!R{7>C4?d$@U^8} zg-zsc&|G_s91C-2eDu&IIa3y*?lNs2?>Cr-K$xe}pThjrT?$9F#s_`<5sD5po(~Qk z_ktT1g9lFDdCwgzJzK2tMC7JM;I6};uC(sPLxbXD|SkFoLOP*U8ta34*7^v-L7?x<-vl!QbITRP-&x_(AS4@r^s_X|0hqpVG}KWQe_T zgX9d-pVvrcn%YCmP}GVGh%a zvft*XBaZGzH01{G`5P#5@;doxx#e)h&N8fZd~YS`R?WO}324EuF;`b=G+ z?6C)6HiAP-I!d=85(B*JseyhEfyM$evtATdY(WKQU@|0}>%anQ4AQ zjL}1rNvxT|E)9G0Lx4N-V=*L&+mWvnM}9gQLZg(YD#~}ukz%#e(*6?`XwO`g$UF`H zfwj0#Sbx-txBFLMQ{4wpINeZandiUalJB_j`7VU0NKGn4Ad$5@b(ryjG;tezRa{1i z4J3v~I}|E7>jwEsYl@Z?Icz=t#cvh6DDzY-WzofjrEJmcWtxvPl_;Fdn-$I~<}U0z z;3ZFy6QKS@ceo0<>EOK1nl&t=ea1-e;kI@2KZ7na~ zaJ~i3BQlmMtt^`=1fV08B?EuwSIO~4?0gVKw2;v`ggW{l|u#y2S?%E#i z%z$1az*N@A-t<1Ky$-GEy>~HSrrh%$^=A^J0b4+NMPXcdI*m2tV?V;DrXjAcG}UU* zhH^LG(*_CULXdCpI_n;JzHAn7`FD1hZo8p9y#8D4hGraXj-X(ulr6j7#5$K9SE0X{ zoFWV{$TqWeZ_eGg|7CFV5qd!rawFHR9k+d8)R?ZGFrq2di{=kamdno=N;xuIa_8o9 zUj(G32@=p+T)&e<;-r6I8N+XRXt{Qcyq}WiJd~Iw9~=*f@$pcQ^u2_G5l(R^P9d78 zKAp2|)8%q#{hg{9tuZC0@rq*7D^Ss8u*xmohc(!0Ms+mM(7z*ArsmfxC}uCT^NZmN z2EQ%0xVh2JU%QP5fOYd`B3&UoY^_RT4iE`Ow#||16k)Vs2un{ltuYR{!lyLD_q0Z9 z1i8{giQgsG0GVsGOVK(}Q*vT&gx{j#*Ah17P6%nbJQW`K^BrYywhRlM@vW10(CWI= z5dLtd$kvZfcZP7)FA9DMD}F}e4OIv)dwHMK;y}+`!n^cSepn~mA)6or{W+vqh!wL& zT}W>~Wy35b?=YRTZFwe=QIjwY*!(76Fpcz{_-BbZX!(`IW3xZzp8hCD^;ukcSpt^+fdz5 zLyj`q`}s+8u)!S?134qz?vbIO?FOzI3ii$Ib$|7l{1_Ii&eIq0BwO_g9tQD*0VtYj zL%*jlHd=J}45Rt4mQnv9DmPnVRu?AX;4Z0c6JOi2*3m2-5jWnT9<( zDh3K+k%H%WIsOvw&1;U_BMoAE9bt+p+JiyQ(ZwH1YF_?C)aXY97pScnvR}SHLKS7a z(taQ2AxJX;mS?b=XkCc}`F%_idMs3UmKY~n;VQ{OwqchUGAi)MR4Mms6g}#|usk%Y zC&O}S;!xTNN6OM8Ki4Lt0f$XULO*?i23SP1Z}yvJ|L~bt99b%oNw@_xt}KCG#vv+& zQ@m2tHhjxkThqkJ2v+zc4ZsA*qd>w34eC?wbrzJFhC7(;d4K7csk#x5Cut!yY@aFO zc$Y~!(c3ezS8_$k<*UqEL}r0Np6`~CoeIxLT{e8F#Yz~$H=@|th45stfsVpv?a7CF3c$pG$SRqk4!Yi zK4#i|qnTzAj_prp*ly@2Qqu};S0f{YK+}u&|BF6QdsQj!wrXIT)ue6gD2dLInE0=t zr;jzdN+(4aOneHoF;#=FNIhBbp72SL(7#9$8;VC_)(ZJ5EyDa^<4LQcg+g$^TE381 zfsceUh1^R1BC}gwbnI`8Q@!owO~!(CXviHYVs@Vm;qwfRC~wEV1D>4%H~vjc$s+yuW(Na_^B0ur zE6MWrJY$#F5PLA+3YG8*ClNpM4lX1CG32TOiM#XNXT!Es*}IP^rB{-?ZIj{{Gq?$( z1k5rEao>0hVO7_?VNI}*)2kMumLzPR=FOf(|I(Bf6gbqXf_fquimGZ{m_xn|M?wICrtOd_Fk zoR=4nr6^#MhpaR#q&Z}3=BTLG7u7~>Of%%HrG1Xe*GS2VGWu4JQ)iyO5KR1LJC}i( zSGz*4Hz6y$rfwGB#CxfxCCe@`h_C^M1N}U+Tn7QSqnsYr(U^?#6v1hl+(r5k#3g&5 zi}k$Hbkk&&OwUvXc4Or8d3Am}PBYQgy@`zJJ*jnUZc<#N7f$ePkQk$#K~FMv)=iEezti8hKJ=VN zI>~)~o_tZhJpyLSLTG!0Q)MRi@5ThL5Za_*xQ9y|UVUDLX8r5`M+=DAX~drrU{QA+G@2-+&1}iTh|r ztF=H*^sP{*Z5GRW1j*iU{*FRe^(VNjpPxH+S4b59AT>q#irN=LU_MS)zOa)YzD!@W`w4&R0V>{%vzMK=4AcZO;Np z?=Zd)`FwCL+Xa^2dilU7SL8-~E?<)5io$<9@D*TGj)O-SCtp+217m&OP6gscf%i>W z7~)Ko*Hl^3(WGY&kC;xc^+k_i3Nj=eMhv1`EFI@&^2QYCnhNhj&=Fq4j(f!l_Rn=1}`3aTQmb5MdddxjavPICLeaq3zWi- z&Pb`*A0esk6|t4DDok;o$>zyW%M}MsS|f1&^@wTQFy|!u=cAsdu+9x0Klc>-Gc`ig zLK#HZfEw?eeBH0uOSw#@eoaOAh2kzw8YjE}3U-vKZOoWSb&LqB(|>y5IYa&agve5u z9`LaM`tv7sSyoswnOeyQdtX>stWf}3-h(T5e{l6-3yKvI|KjEd--BX<| zw6d5k8?!}xK^bU3X(OM>;1(8$Fr4el+U=A8+ti}cEz&oBwccT-g^z;T5>2PYOkOgX z$*!7BMx*TKw(e_ZHR>ScqhUcy^V)@+b$H$L57l=71J6_GwNiE((n*ew0|h$=efjOR zbBg0CgL@ItVbdoK2$ZaA6ZzF$rf@du*PV4_cVHUx?-?7Vb1zuKTQmEJtA-w>=W(_U zx_sRh7b=|SmW)^Kj2W6~l2VfdZTcr@mhlfonHYQff!j+)2~T!IWr(l;QyW?wmCc9TGGjO7q(753@siNNf;sM! zw>yc?0=p-j?F*f8?9pDP$|4fr25!dE^y;8 zjTf1~r)Ww@`)T*lQ8Jt_g8b@i$eExQ?e~B^=W8}mOH9t%Vd2(T<3~IIuC@1Lzs6n<0TH7ag&`g8xa;KT#J4m_R zp8DNg{8tym%H+2rVYJlL#Ne>>4>#^St95T-EHkp!90bHYm*G3(aM{}0Z zp1GZa30p-y)ehjKKXfv~RYo`eUVFJ}dI=KAq)m-P6h%HzSzLd&n{MbWTGN)cx9gJ2 z)3u}<<_2u*uFi~OqnUY@1=#VIMb0U?an>&|1w{xBQIWv9mbTno)`Fvt24~XTDjABD zpv76`3%nW&8LFjU_rOrgf z@i94b<)FR*!rGY7wR52Be|2$`BXoto`Cf|nt{YtCQOq!9Mp3On0NIxrRHVDM6=*c> z;HdAnLNm&5&D`4)MgQK}^$)w5EpXs4rxjqks3Z^Zdco=|cu^Jy53bCwt>Heg10@LZ z?h)GB$8$GK^g~3gYUKxCgoGXKhb4?pp-1+%CFX~5zH*Y|zS-0Bh%J9V>A~&W1$K{F zM$$@}>Zg{CDA7kh^NSsgj=wHIuI7NpJ4codjoYoJM->+wA3iVr_QR!gGJ%wkBN-S} zCZT3gs5XOHho*O_txB5aa7w!?jkuLp3qT{p9NNFTt$IuqymG~|Eo7iHKpm7vkmH3*Mg_p1- zz~}l{Z61=-knn4)H7^3HU#^Qp`2t(WEPW9KPt6a3NkIUt)vli*K;dM7Z)DW9J!ip6 zga7qXqFZ}&eaxT4CR=#efj56MW_wmX{EL;U(K;Y%Lcd}9Cqty1JRZNi{G$QNH=8>n ze%7qdxTto%sY~%C%UIjk$X92{DJYP_!1+kurhH`7tNnISp*Ir$<%xb*8%b0x^JdvT z5kt9xU2MVY!+R5ksxYI{#FC@a0(lXWh~^}>0v@9ZyCf*Q*Xamf-r@|J;548@+|Op# z?jZE%VMXS$Bzh51lbj7vcp4cwT{iy_rr!r5&G?#l-T}#OZswZ}mbUhq#0$KrTDP;@WUdkM2 zloiUlM&Q{v*h$kYecd1KL0IAS@~}E!tJ5+~eX{7|-1@oowFa_0jN^Ya&PhRXp;hi2 z0oH>}=6^<;P7}`s@oR*YF0K4rlsL!fMA-fJV70{pp}eU-i(LUK6}DgYpaJZogf|I2 z2e*Bly=t2qI&o8)P3BsMEObo>2G!80$RrdX4fKJU_6Ei$dBQS)mT(dTmWVA?58U2> zmDWWAVL26`7Ek{QWf9X-Ve@R+cVh5O62}tA#MF~Yo%M&|t)#u#`Du&TMY>JU&SHH^ zWk47abGkw=&?e@NqD2W61pvGS6_2bEzY9(MQ*FmvBdZt>%61dWbe)3>wG#HWt+~oO z+bUN2$=^t+OGz# zXzVEPR2^DsMOp0Jstg$5JLqNUV{duGE{A!gHga}b#micmg`Pj}neXIc&-ML0)XyHP z!e@e=WK^l#>45w}=LqrFS@>8`WTgC1LrZgQLiZd}sI}Dy=z+%cT@4vd=P1Y3&X%{; zrQer&Up8!7CxfK^L@_$$ANnS{p+;!47nw~nWhO!R$5wS*r9277f#pEJ9`xVO<>_eR z0Ux4N{?=5A>`n@x>N;J&PEhATe-=X`L#KT42VIhTdu&)i`i5RBnF`3#{m6+~03P5w zJXmx+4sw5r?dIKnynbQ{XoMv?-)dN8y=t=;)K3W%yN=V|=O9UZ@mH|1_B>M4 zeUNoy@OiaDpL^VM7qaFXHIhqK^?GMhOp!+wqs%Zi^U(Ritm9jdj}PB$=g-C|uEKY+ z{plyx_O`nwcdat02u*dP?h7gh1P7W9Oe=_sI4-5;VDB{@H_15(>Or`0}vcmEXaTyPNRA%iD-Ngw?RI+Jl!831wB}oe&5piL3**R55-_J zK))h^%KQ)NTN}?W(^;7|a7)`&zDBWim4peY_^de2BSc*nNr9p3R3e+8? z%?#qcC(tqeSAiL1-BHo0o?x)m46Fb`nM-ruKA6+%9l9*vKY=%UAo>QnP1{Glac+Z6M`Eo#ihgoG zx?fokQ=pP0{VvRvD%`MW=vt z>x8m2EV@8ZWTwOo(Xirjic8K>TqAg0 z{C-Y;$6}k;iXomNCh7T_;pRiqtxqW1g^S+Qiy8l75slA3uj|r}%RrT`0e;XpFghz; zqj}-H8o#_$ao-8zY92$IkZf!!_eRE9qE$nu)yx8;sY8lMzUP9ap-Fo!;}@kwvvqW3 zLs@tx)k~pfgeRg3rr_7qfV06Lgh+<2LCDin>dyOQk=+P`^SPJiF2sw7wuYp4Ic znqY(f`0sx-X%l>}CQf1T!odV{{fjE%@Ok!DID+y=p3l40n;`b{VBYoB-oFAZHdCSL zZ@VSGU~}`Ae{ZlEYavH3f`5cGQNFI~p4-j;|G>Vz?xUdkd2@1u6{6Fp^Lx#E>RWfj z@T$9!f+yyYb~V{r;nqQZuQD#5{G8vUKGXWxx%fXC)ak$0m)k*YXfLG9;)2|+&x0X} zZct@`&?k@hqyl%Da@WES2nz`jIJI2%vH_KAH|mNpP`zMU>OcC9q*Vj$~<_;>&*UixVU9W5h^0RIGE_i zo7&Xk`laI9cyKJE-dK}rC>l4F`es z$I*PEEwjF9Ra}r_B2-MPla^z0q|A~!+E8ue%{g=nnrKw~QLUB(}4l#zJg#xm@BdeF7OPjhcS)-3Agngd16!=MsW=RyUG)BXYjA+MD9jA+afFYZ z1sh^RV3V2i4g|}bp*Cf;ETN`ku1)KxY3v9<>#03%%=5_yB2Pn+idn99Oc9SI5<)OR zmzkt|RKYva&yZk6{)FvP^R%7p41W3#`rsTEG@+AF-`-|uZ6#{k4mezj{0fY(H+~Op zfR)tw+b9u8Jws6)xDgOyQ zaxdetRlLk`W%ePEx>id?j`*fr?b+c>mlprFmAh9dh<$i+O;GvHA-Y~nfUWmw?AEdC`D zi~-%2Xhrx_Cyp8^rZHaqE6JuY8!b1uhCmO&*mMbi!IbvBQ|a#BNp0MQ(kz-}p0fio zA>Bfb>l%6?1U z2=rK47`&mx&oXkgN2RTw`wb#zuy!nVk=I3HO6M2~kXE|F7$cA%_zTdI$F(J+KBVTC zS@>qtQN-is!YKL+it8}_a1DP*;dPB)qZZ#z)E16?jcT&$2p$3nbRltFH-~twWJVNz z<_H_Bvqt^hv?-s-QT{fZ3*6tEA;NP-)bB_~^N{Z8dmrY5yXA7mn3@#r=0Nj~I50)q zpb-lUFEi!Jd7q#VPc#jW5pYYUEDzRW(kw4voL;%|2E-!`^R5564ue0}9?{mlCk)d~O&slC$Q{99x#W2xCih|mg= zDoM(*_@Vv}=-nI#j=6ELcf@=cd)0~%f#dow$gY3;#%K+_xx1la^G99qAtLc}?6)O|$v0Zskt~QgOJN4zk8Zp^tZqZV z(^)*z5}^F*$IP>O(B?bKZwk}TYvo9^o_oR1L`;)4W4aAC#;{VT14`&qU?$!2x_?hN z1UwL2x7=aWC)(1&+E^bGf(IAbOOK{$Z;RJK#^{o+DdtS3$EVi$$>bozwI)1}^AGil6mGa?@|{Ja<}H!;P-FXtBy@t1>yb$dC;g<0coEQYv0DMK~YVbm!i+XqftG zt8RZF*O)x{9((O^j(8Ao1{K6>T@v(fVx}l`UAwhWRuiKenkX0>wt4P3VA2$&Gqyhb zJz`L(HSa{L(Fu?gF`(ldhB0$w*5Vz_N}`n+j2L?TgQWKK7mpl|UV4+%0tKDV`G&a6dji26Qq`>OZPquKPrl|T#y*QMTFgoDvi$t{jeb_osJWsEfj;d`Q$U> z6o9*;S-&w_d1^bGs5IlQMJoTnuDS8Rtz=_(PrcZV1a{|A73r6T8;qY#{!J;r)H%ve z1Y7s6_gvh$Fq*C^o>?3toT+{rh;hj`lh#W+XI~NK7X@Tt%CXEC9gORqKuAE<0`l?Hd^pV#adpYT_x?Z&N z*IoY3eS5|WRe1x*P-d#HYYl2m9@qAAL(JZk^dT9P4tK~b%AE~Q07R;%HNUD&nT+ZX z@#(B=BaF4B8M39>fY&gJ?>DJEE4?XOR%rqkyBnyUNRGMh#7+RK+mJl~Az3`v6M#?A zdtne>Z_SV!N`~omAF*s}Mi2pN31%a5y6{|G%T(Oml%?v!Bxi;ldeMy9?JO{R41G2R zF(y5>>^39hcX9=2;|&yuCW~-#kxJ~$0aqIw?Q=JVVvp=cA%xO?rEN8p264tav^T%j zb(!aAn!2m9yg^-9<(Dh>c0@YnS_N>2(6iOwppr9S8bXibryYL>tfT0IB6*GU?|bR1 z%qdJ~E~;g4)(>s-PYM#I@QyQCEmnlp%YVBo{5+x-!QTR!AUvBSnU~loUlE67oaEk$>_g%luEi zaod*6q^BdxPKJjl`t4%CZ;$zpYzXNY!I;GrEkJNZkdJh$1-T^@C*IT#FVovU%Is** zqMhJAS<_a!d9ABSrKE;fm6TgdNw6O9^U36{achaXk)uk3(SI1l*DoAA*sBL*7HEB9 z5!&2ypK1CZ&u^bTJKo<}?qyytaLiq=))v457v8x6zD)|J!~+uM9#~8 zl`nc~IM;U(RHd6|?hIwp8D=FLaWchXCOD!rl8u=Tz~>ZHDYuyT5`0$9;(;$+JysN< z#T(qB3(L*LmFHGR%Lww|rk9ut<}f?VQesQA-XvbIuiZ~PN-C{D`gKBF4u@Hd=5N=s zFC!%C`tjkos;V`YBCxL`guA2Fq3W6q_{)NTD&Ld9XDo$ES1hF#68m1>C(mxq$$v$` ztYQ}Zyc~VFIliBj@Cq6;f=4+ZL2VB8LjN7d%{pX{AEKO&%^L#K|Ku(=<;&{H{VrUI zXS5eDJ4BZ^kX@_Q>Ofr8y65Fw8r%lrZV#~dd#0f3Ap5K}hbrYV2-t2)mNa-?-U=~* zCp`&R2-m3&xsR5&JT;JcPrPH{nUd9Sk0KWgZvlBL?1HK4qSc>t;szBj^4%y!J%=n7 zSm1mr2>mZ!&yZz=Stf3|gS;S6FWs#S47rsLn*n~HE@M{{RhM)_%llm71+Y39vY=Wg zCYk57b=P=niSN?we|tXSE=u6uvQ9_a48!HFpch5iX~)+&aA|mfGvhENJdv8X_W*aB*Wm|5&1OZvIFgg$l|*ZgL`N zgMo%jhCcT^YQ1mmvCuyA9Da6UrA%wj93l8vx^6bD*9uitk0>l$u^m=VKXnEdu(-*1 z%W#?X*5Z=@bYH>*Z+?vwwwULiRa^b719mzE5)Q)=SE1hXAv*tpdde=8L-3Zh7$Psg z3~%dlFXTU@R=+d}Mzk_JmWh6pA)#bsoFeBl28#IEx;^tZUtUpvnsA0e7q)mVS9=Uo zuegZ@G65fT!R7_*0E%wb%ARiL1mC4e>oMKz&3G{QJNSdOwQ9v;EB9KmFhksDmJGl1 zr{K#&vs=eeLv;}*JukVebDb|dd9y<|GdoZMc)S^_1OLL}R;qwNi>48mBjfYo#+2j! zv63UxKk3<(g|-9P8FhJFMhD;{asmfJAU-;|odsz|gwuL(0{#D8t@<7(r*zPvQSs@W zK2n=dZ!;h?xRtc2`v%~*R&Nfyl@;Ay#O$3Cf!}m;HxH}y%^UCV?9Zuy;GGwj%^|*x!rc!h7__l@ELY%Z0Z-Y)+nAc2`Jb z3t<)$$FQMqfU6#!IEfD{46|QOT?D6oKy)7&z5&E)RDh7beB{z9U@mX)PPfbzJQ6#+ z--Y^*Vo(nKF2TI4Ehp81q>Wk*6RTm^U&58EIEtWqQeuznBB+6{?2{_Dnfi@Ex1S;q zxiveYPKP`wEeRBO?hZ$q`egN+v6w^)>r0r0DHboH->2|&z6`5I*qXG3Bz+8X%SMsO zXea!1I2rdm%s&44*eXs^+$m{J+v7dvAnRJZz=@u^Kmp;YLi|(azyG(G&91jL>Qd2st}@+I+N`p#&7ZPQNlcC~d|WcOotCWjRQT1Fv&ON{5VvH= zSM*F|k%?cC-d(Dq_GF#wu@iWX;bdL$L^XS^VRoZ_Hu}keg{+*+1QS;5?GxZe4Cl)^ zqnNiU0MNLLm@k)g9xOBBkxE95Xqi%Ld1f@uQ`AnaE*lE-&*9xn5@}?I_92Sfe1D38 z&D4vFM3jb&qi{KmA?9T>j(k+PsXYk!fcceYXqxu1c#~D-F9~PBdv3|4UJWTgs-C@j z#t`N;16SO6S>>ppZ^f?4t2j+7wDD7ozVKVI%JG&(H%_xYtI?{d=55Apo)jalp1<@+ z`Zgc&;?KQq%BogV69?htSIXSU$&=>g5#{)fGa2ipXWP~TEZ3P9d%5}E5p4@`jQ^u?k%l=(ZOg>Bmc&7hg>(KJb~KdT_LGXZoZieK+M2xG zA{|(Wmp^f*hFz<)RlMaz`*YUDS7maFkkCjqP`9aQtMF}`$e)4drjcib1?&|8xSFBh zgD^mbeaWTnv>fu)RFe&;@-$7NUHPryQmr;;nl}*70NbZ3Q~KLdW`DQ;?8~jj^H8PJ z)_wOG;ijc}T{j^~k4k|&B|K`ovuPFY6{49GBIS`O9maHRGmr0RF|;r|lc-?+C&IW} z!hu;MLap|b8cB{y{2`~YV^J3{n;UPUE2TeA6qTe=JsoF(UJN%Q3>dTRQ8jB+uYYCv zo`ZN@VvwsswxxPeM0miTWxYpoGw$XrJ8uJuN#HQ^(mP0v+&TOPJEuxLo;n~K1q1aE zV@W{XmuF&GEn`Yriv&?!{4=EwrsvlBBw@Gdi2Kb7HKq2Q|D$<#0PN^UpnuFDD^8hh@8D3@^>goQW4y(%GN_d1l2u|W0Nq`TX zg$W~VGEW-*=A1uks&rDw-0iuOR=#M1pkJX!xnO|QV^Co3;+j2<`sW)WEuJ9cv8m~c zO*hVeaGbQ95sL!zPf4QeE{1Z7l#?uVb|l!aOT7|1uXXP0f5mb+TWAO@^~Zv>jHjq} z6V*FSXIr-HXCWzSgBlful}ZuVhO=AoH}6&NMu99?fsgz8jffvK^x|PckSD+f$k* zxzd*>H#d;RXbU@elsq6lxgvo42G58o|F+Jez$xg3@~Y(uJkb#QFQe=W1Hac9LvXlu zqA^-j|I~U>LoGz%>=(yZ=To(Fz_NIydgDG;aY;t*&k9>}3{zjl@Go;&t3^Y;CF~98 za;Z#*Iya*eB#NI^$8{x!#ujkxQ)UyB@_A4u$4F2Lo9pdrT01jlkYM04GbAoP@Wt4pveD;a#k{?AF*E zqvt{y2Ck9zzrnFJ?{Ym^OU;yZvmB9ANp#TZ3b8rA(uvT3>8Mv9i2BOYgf|_+cV9@8 zM&SAv9aS@4lz|MqLOyv?j@)LLrA3}^;r%PKKKDJs&nEI+;2E{yZkfeMjfzKnVxW`2 ztURR+HNNMX3_U;koneFhcVP8MXID?H{qbE@dm8_W2Z9jO~C|RiF~dBF0#l zV)+?d>;di-V;l+dQe&w#6nZ5imlsOw*9KBC01J>~V)?O%or`A{u;OLpsmCux zro~6y4P{ZwMcAhejOyq?xWFkSb#QQu$rQ;e&FQvN1q(^2(Y?zFyZ1Z&+@lTWZk2-< zR)ov*+fMpLZ)X5Gfd)TwMIo*{@d@%gmjF&q&Z z%V$96UQg*O@(TE1{q9sq=<8y4J20~Evfeh{L}ov8|JhHAn8$*O6qI;SHgd-r$5GpW zxmQXH>m#PQr?VG+X?5ztpzUQg!!%#rM*SEwF`OxQ;t|;HmQ3%h={NXhtvOGoY=EDG z-i=CV^Xu>Wayzc_uW;|HyHq&6PZ+YsdTfWX$j&kD&9QQ(B@)lmwH-;i{95JOg#mgj z5V1?iUasOmgjwmu5X>k>8P=BbpsDIsfSIR4XM(@i0z45Lf)+a97FDWxfqlD)t|mbB z!KOrZ_UqiIX zc5goYcaI?jwcrzM&2mdjU@UR2%E1gILH_gpe4msx61&!|0w!`?i%Gy_O49a!&qD|d(#rYf2X$Br0SjN2K#k-m}#k)dM;EwC$cD6;4^MnME#bh zY&ogb)CgC49cCxKWH>Zf0;PA}rj6{%yaD=JD96a69cDK3S16Cq)?Tlf+-lo2f94&LZO)il)LjgD z+`o|2`)(^_q@y6Q{vqx8L4GuukF}2{nYh6l?uC-C29g^-B=j8?ny~lWRC%FUPe!lN z`g3o^BbtZ<_}73x1WE4D8@HJsCVWOdS@5muj2Wgt@+rZi+#0YNHSLH6bL`4fn5fOT z%bf`}eighcyHewQw*qAYs^>Wyy;p_QI)SmC;atk0kD=2+kBTcVq-S^iP4e!uZv}3M zmU8vmjHI)?P1HA#@dPt%=fL%Whs^`Ob$iT%oBS3QJgs7Kb31(4DRKX%SvJ`PAW?Fv zSBnHiQ}sI&hxi$}Ya7QTp;P;Z2V`5Jsm;A<-RnIzAdPKlA!V@I0mgv1?!V&YgTG8S zw{S?b`*l>&`;TsVUp_MkrJ>t=U!d8r*04lPcIlZLO@B~()q2I4`$(<~YdN>fvdt}1E79@NIDzYGyL52y^DKJlCQH6D zi>1p4Rm;D1VI0B7%nXo08=Yg`aD*U(5?y6)n_TuL1}0?W0Byuw;tLUbcAT^0Zz~Wh zh=t+f5w8F>j3MpG`I-v=l;5C}=Mt`o;adQ(wEF!>iCs9%eqqzcVmSZ^F&l_g{r%!}bG z#AJgUBhfc{TB1H3y?tzUEW6f`(S|yoJb-h2z<&o9#9w< zr|NPt|Lw^wWIDZ@F!Ers#v!n!Rr)>F)YqoNNz*~lW0gVhD%*8e&^|HZ)j<1?PE&={ zb=AN$LEz$nU+xwdpyis{;Ww;_)p^q!%FsNvq;#sr<6E*uySW#RFzzXb-D`9=xId|q z6hM(er}^VV6^CBTJ`h+HA248ll*8j69mbj=o4B=Ly$o&I$Ie42N!hP%hYEkP+KIc= za(5RX=1%R+#g0p5#;v@{Xv z!}vm33*GVS3SnX>{aPKHHmE-iJF-=}fJ^=KFzLhd$?JV*tqMf1@JOFB4+^odUc*sP z&UiU-J6c%f=sYsuf4C49=Oqt#CzNaI+0b-G`qu(5H)D>-}2Am}u`E!S_F!DDzA3bcERL z?auWH_K}*Ug=KK5#Q1v$a@5u`{BHd-o^G>fzk}NXaZ%nG`xnFQmjnMvq6vp@3U}vU zKA-+3`zRMD^Jr%Q>=<4gd3H8$$SSVqEFoUS0~N<+Jb#iU{h;DW!^fn{XU8eVQc-ye#nNE&KO!nIh(m7T5@0s(9 zU|^xIlI88+P5#CnPWPJh0L(c(=j!aWs6{DYuQZK-W^~5MiKcf=V?3z%`vvb=#c$_V zHxsnuIv#|h)~bA9C@N)O4T3 z{P@VSv`AUl!z{`yLvLJq!bdpMHf5l#4`tl6Kx3@08IhtR-lwPK@-hofN0|}#ocGy| zxnL2v3P_`}`fc?pSR>Hnm+9WKxgF9Ny_TsNkLl7MnVPfnH9z)afB#B6l{1O+G9tMb z8ov`nFDtrV7j~hE|uXx#J zB#IYk)2GWTF%m6^Vvqk$ESv|Jz^0^=Dd?ThT*pJgl(nekjZ-_IM=@sYWc{j4>hS1P z(=+%*@pXWpc&UeB4m`;5`u=zNk6yxx6I|iC(|Mn%EJ9ory|U1M8;0rN!fktNND@fa z?=0Db=pmF#6skO2?Zs|&z;zF7iGbk$(J*#saFj9rdIfYAO{#{^$1_ zxbr#U8RJ}vp!Jdx3)5nvw`x|L`sfvWjxuBASI&pZ&h~ot|2}8Di)?jae%*@*TfNude$`Ez>Yx$+w_WRXrhDY29O0WPjE< zluMYM+Z5f|Cv=XM)mc9_NYZ=KRtnfUY^CzVTZv%%Fvz#8k1?LPX~939yvx6?rcpRR zvMH9}$li(H2$Lv5kH~pq+5~n+M0OvpoJgkY_HExWI9vHT&l6h_MEvd5Q*(P}USa6P zp^y&G_#)kS$x>~^cyE~B;7QwoAAQm%gc|RKxz(lFyPn6lI-6$>`YNIr+PO;*Z`U+o+KsfIFYvp+{D9)vp;r4(5({>A4-IjA&-M`s&@5Ngi|cv_Vk zWsyd!ebIjodvgHGRg2^rN1qqH%jJ>Zp$?8)5>AYgV7?@f#7vQj0n8-H?4XpBjVg8I z0qraQ6O*^gmq(J6;E7W>LAe4^k>M$1zs#?qP|*PIdC4(_2eg+aYrEi=4~GTX>zWg0 zB`fE?4Zk~xn&F&z>g8~(+fnHd){a?rc1>3LmT`RVMQlNcN3@-d)wd81FTozaZA(qC zv-E`2h1&c>T>wWyLGiO~DaY;6$u8y#uk~LE;_^>on_sx)hxl+j9zy|BMI`0fDXx7b zb6C@*0{bx!7nfW9Rst6v{En~B#rv#v%IeoAob(uzlLb-UUlj+$Ck;|$zuy)2^-gwm zUuD(0n7wl)3?waA%XQEG;*pg+$%F_oBf-l3^MpFjZ9rP`24)ZU{M#A@InoHmNr)i> zo+epl-MlL0{tA+ay60^O9_07dK-acpp*wU80E{}exT`%z04Bw_R;~Tx=@)!ujI=BrQ0%a{&nv&Hd z3Z9QVJ^EL%ZpgIsiI8S(wM%Ghde5=_RhJ4|NAM0J-zT$7DI3c8PHodU)AOiyxc;s% zt1>s~aePF`&T-}*lPlVH2Kfd74fFE}kEhhqa*Bp{5^@~xgs%M+SK!FCym-;*PB&E= z*00i*v&w_EHaOJ3AW3WmZ+ZQTi-3`*b|+hh)kSiJyTLEYdYbY1UYG4gea1p z+F^cdAe=DTqT{WDVRyN!9REwF{ThGHT0AIBIy8PBU1N?D?GP){pX?Ci88_YGHei3a z0r$o$Lvo08W;?y|kKOX?L#<%9WPNwGdWALsOFLX(3pe6u;TAAx>{ZZ0Mfm?{lz)fV z5G1U)> zGzDqya(ZWb@H4MvWAgYnlV;?%9xhhnc%SSttgc6{idxpv{`nr z4Mh&;9G+kG;8x(@`(6m~{e!KhFinfwjRR?CA!zY>R~zt8Cr+#e_Px|Si^)9J=8vDN z55@UK<)aGd1-~y5GwVg*H~ck3c;m#9KIIwq{*UHLgazM9@sww`Yr_Ro41D!2=-hcE zQM%Znz%9w*<#H8n=~I)_MLvASZ8Fe0(h`~0f^jrT?cMvN#A{nG+sMY@Bm;RiIKJ@* z47I}@`SpE+Swc3HA@ndK+#-61OZ1toqTF;^xK>TrlbF%6*_e=6pS++jINS^0h@=9y znmNNEdt(&`uAi+vFo47v?6Sxr&gP3e!_Z|1Kv$M6r(zP7l(cx1np((~7= z_s_v4A%fXc#`4?VG9cKK4p z3J2ZdjU{iJ%f24zD=%p1ym>XYpMCS1>ZVUYwnx_-L~PYX=79YQL+X)1S-$ zxa7EtDfbs!Z@+zc>IEqhYb?jzOEXn7JUV@P^f#G^Dz{$h+*`sR10*v~#eK+HJU7%i z*j=5jmdC;uoKG?@WqS$a`!}hJLJ~q#&_>m=o@Dbd*hA)&w7<@EPtEvJ>8(AnS4@5> z_KL0E`i%z8|f7&xx+plVQf8Hy< zZ!J3e$`@)bqMg-(KWVBz_jvZSFVQt+>32d??yfjHg)P8z%G(W(9 zKcfst&WKv~A-l*ZV>BE%!9%YB!XWjQ8}eeGXdk4l!^RwUTc^%2fwOGerEqX*ry<1z z`E`ABbLwp(N>wPw&_}F<>f(x7uiB7GxeU`iWvnVh%KDc3+7(vH4QisNdqONSYCRQ= ztvwa!qR)vu$`BpbBt}H4(3jD=b1eI{KrE!*$MDIqdjk2%9k02g1zXMabtEH5!btc2 z{&*L617C|y*Om3Ss5KqbqUE{wThy!a-v#C?h-!(=)+mZsaZ+v()LnW)ctJoD8O=EC zk|3ov1XZsu1O1DCb#&Mlp%uw~0S)q_agVwU%~AUwjfYy4t-&OS>xe%1)3qyMY5(mx z@##z!?)KwYO=1PW^>_r#B8S}!?wfMBJROY70N|B($9{afO=l3quB}k;0I4M+e0_wS zTdCca^ayUQTORz;R?Kky@12uSc=)ox;Zw{xhV81NCG1=VSc|-(haOPQRFWEcknYXw z@!Ll;yQe~^Vm%QVxHCO$rA3>r53*k31{Ez0f-GiC` zW~&0fg-Zv#dR&$sZ2lc3K4n{6wb>yB9BFGcQnzN;W}yidP<>-xna}o*Ce*s`k8tdw z&D6ocp6_cDKHRP!jYyDMH@RU4_1H zs)F}F3i|wfxp)~?&XKS9VFzx3>@JmyK=;Td+sB_N#dgM+=D2dqx)m4kLhe;dCr;g( zvZ>piUamV=MIG}R0QslM!R;(j>AOr{ILCoS=yq){HqY_Jn^`j8?!hUJ`$lVOy3Xsj z6|EYge%nxx^YbjCQ(w4g;X~rOY)oRHQJr`G9rcw#rgBNBF`A+(>%#3vT8o7c7>gt79)>Znjz6J zglC8`g=72F70L@JklL5n3d`(w{nB+_hlsRl;hO1p`g+>KR@N5WGabVt_jd>?_ur2G zkQ|OuDttFK7h3EEYXpVH^(WC=nc5m4^=AY8W7g9ejIjEO9?D{k!Ra0O(U;O?x@;09 zU&uT`^+mE&|IIeL;eC@CCNpD%!?Gl((WosEi7Qc`Y*qbayB2@@{IQqgg<|2A%vx*~-t*UvXg zAG{E?8w;QR`b+P4U&?NPFULaXY+h7+48pU=fj(%H0zedhg4Q#muR%?Ib7U0bHnM@1L^2Eb;n1l{cWI2g&CB$m1^Q& zu$M-|fuazS<*E8m^C-VFrTj$DK@Bwc)(^toyXy7t{iYzWw{O+ zqPiAbxFSmhX|NypxBHs!>4%vGww5e`)GL8-IY&Az<*BrYdf)8q;@0yGEfMMrvD=KO zUGyUyQDhm$ipKfKHKK7r<{hTQSBXeD%&^rSAvV3H(9oUboS6$lz2&E#`z_Y7xaqOc z3Eqsd3T48MKBMx41Fbq%y=E&pbS}TXPiM$v{HUh*Hqo~WCKDj_oDnQ_P}lLH4f^A+ z8#R*2Ls!yS-^ipo2rv`&*FX7AQwP*6xK;NUR`Y=We&X6+TASUv+mENL+i}U(S*~#~ zx0tLeENtVKSym9*(^?t}I&Sy7`es!R+^rV}?v#A(SIief!|@=bx}q_(+Pol?$gQY6 zBvau_lvff_sS+Lejj~=zI$X|1$^GzziuB2$#U>brJTo}$JfD?Hko++uuQ&iJ`Q(O! z87JV}O;46(O4gf}a5VA``SaM_r<2$!t~PKtlRq{>`=L7Yp)9uL%Am;Tt;5B=w$jAd zObWhpYd=a}>{|cb@AMv5`_&2qdc<6F)@+SUrHs5XKfhO`%#Jt8`m|teTPRHBHkvNN zBQ&2d{i$NAg%#)fLjoL1isFzvov>T?ex#8>{oZQjIi_1m(_8)}1^e&cAO7vlhHoV{ zF%j+1E=$e|8=Rb8Ldygc!fwK>b5#sGxBciarbe5k(8`wF+$~RTOIPkbM{`yGdU$)( zxPg_)Sb;8%H zw>zHrJ;o3{U!=ct_PPBRXFjAhxTzHW10ldMCYfEYZIKzz5cd{>=6UkABZT<%&uV;- zK74$rQf_f%!CNq?Aj#R)ywyv3v&c<>MGc|75v<^2Gq|dqwVCB@|E_euLCI-v-q$b3 zSp*gX)|tV3dwK^76~WC+0y5N`<#Ha)%xAnE^|NdpGo)9MCQ=j5Zu1=*a@d5ICmk#i zlWpPsa~|hCT>~cJZi>I)i{mcoTeEj)ANG&Qg$I}2!H$1teG?n?u#fSj<$X+9D4YG) zCVvLq#rWp5=btN7BD0)Qm*vV9EVAr}6;`~wEzccp@TD1lu0A*e-_UDtvG z2tf$OD_QY>DYbCK8&d~Mov05dNBtRvR$u3ix`?RSB!SjeSyVVq=B{{I#A~kFcR&L+ z*f$K8Q!nGXHuJ6HiXej=ckXbVVVKQ4dABF`WEhs@Vj&96e4X8PcX3 z5j!i5H1!-R@QXdsr}TIL<;~=Xl)IbT4o#?gUp|ZBov1&-8A!PXL?_wGdrKlry!)9C zk4k~-7ng^$Cz}tzKe(Okw#9Bz$&iKpPCzpaibM?S+nvldVM9D&`q0&MgQ0fGvHbfUe?G?kln{1h=x^1yXpBgsYH%S_r0n>hOo+N9`KIPCNX~Q*JEDN8C?`G za|4a8MLUlApC{ISBx|jGXa3#Z|Md63_5}ks&nKC_i_g0Ho=y&*vrJ*P-g3EMcmVM@ zwYT$XFONN6-ff!tZ_-(zNH3Q1$Y8~+Dby7Dd}`o!g8-~+PWkB@X1qI2&i}5&(q-8tT-i@^kjcdYy(_iT~-878Fw!KFh@aw_PuWU&Ic?S_nHE9#)qxefZ#f&4}K}n z1v6rVpD_|IG0diYqr1Wq99e9Nqw|s~5cj*jlLNP>1Vvg?#^ZU1!NM5V<+?n;J(gj{1h*P%=uV>VO0lQ=euJ!-pGY{X+B=63b--S4cXz%}Ru zb6z*BrHweYM+SBkrIU4&aJw!`Fi!8?xaI$7{MRiv$E8W&(9a}zwSaCOayVB-_wKV6 zeJC+hOM@AHM}lNpk}vC*nEQyhe{fTNh!>$m8tTc%9{{P4B+b9y%9@(C=ZTZaX<_a@ zSKc^JS8nN!xDl4rzN=A#sADTo-YN@X59aC()0dpb%a?*aN~*NfuvBofkP%6U`7=jQ}HN3!?h~H;`8c?GTt~ zqyk)1`%7IpCT9H=x6R7+#>rBS2`|9ju!{s^KmBC`ZL;8Po)KTOUPC~&qvJ^nWO-Sa znMcLk7jL7EFB&c|Gf#|GCIO0W1@0eIP{pBe$r>-L*soI9A7=%{;5aW0G__t%Y}Qls<&I&5^y zupxF|OoZwYap|=3tbCWz*N}bR_~C`x)On1ZY%|O4DZJ4qH0MngCQf0k9L%fthjGwvmqI>@RZ&8%LjN(a^knMj~6z{^;T^pQ8sME@M*uqA>f8h1r#Jt zPB@lk=18Jwu(JLsSbuWeHnvCtWCN7j37vUtRtF zgKy(8XYxO8yURzjs2W%7h)FGBB6tzW9dGPkbGxMu^9h0Lc&}GJeyUa?PS2bTT5#Dl z$#qqc=_#Z3WG3gCjV0Yhd-CLYa**BGZ{glj-m>09-(p8evl-&JTr*+b76gn3_DjE_ zc)AVSkRe|=IqMN(o>(}0jSl=a~E_Tcp?j%HJ+?ew-LyhDV68mJYDS~Q)k+Cp=tcN&Vowzx)s^jFh9ayhmu zY0E7P^YUz;4!^hbX&kLo7z*qY`_(zP{{cAO?cV>QJ)|?GC;Q0~kXQOIE_bia*(z@S zbB+$Q641yn39Gt!IUlqB2zhM9Q67Cd4{{;V^}-p7>@Pc9@ynJgas z@dhe)ntNsNmg*f%K=avUP1V;=olo_?u`tP27y{SN&CCHzZ(SnaIediq-!b3?OTc{B z*&^)mm#n@w!AYHH?R6B-q&~fG`+*(+B&OTz4*RsRUhTEK~JyB17ta#dS~T%OVFuL+d>*x z!IO_m8V;A)mN3ys_YUrmBTCj+#%0K*Jk8~oBN{VA)%oj(66@lV(k&yB-0%NW4_Bw& z!T2}`F-L^DLma#wUde~<{S%!La569X%^m5}L%J8`BQV;qLACzO+l(aJf|*^xq?QD3 zw!$D~Cu2)9LjkK$D8x62<780HcOB43%wqTq`RTpxRCRM@>yFXRg(mCClK=3)RDGtT zdHWorW}x13>6HiaX~(dEgDT$ zp;Fb22=|y-RO|`McL%%X+y@*X1-);_3@B!7^ z3lMViQh-OkqHlI{0?<+E0I)HYUgT%w;83n=IIOd}Bp+0J5pEi`Z;!J(l6KvH?`ZLk z<`7b+b`9_5w!hwqRqZ-@qXt0--&^f{?qZGtj-IC?!*Z#n>>g0&6`a)2QI@@LICXs} zMc6J{{Efh4$j>8-9ICZ(5)-AWuIJu95754h&tz))YPIkbnN2)BbN+mR%j2i!YOCG1 z>>p9cygL^wGEV%{p7hl6)5Pz?zS=_HOc(RtJO{py9-_L6we7#Y%u1O#0*6NN`4VEq z@7Qb{Z#g{@u3B*6ia5Xg$$aQy$J7(kBtIKuLa|YJCCt(P8LeCe3KKKDydsr3MaXTU zkOFTWHq1@p*4^9FY-(j3eAm>?V_%H6H$>6J%Xj{Cv=zNRb@yZ1Hf;m!=I9cTT4D#k z1rnCv&Q>U>8A*zR?v;v}nqW^<@}E!HG}<1Z&L!2cHx1sAGe(l!xN@B6RNrjJQ}AOG zMryv7F6VJ{bKaek;C=X1C3Zd5_XdzsjY_ALRbnlqXhDuu zPMQ@p*J~!x)`n9R#Ye|;6?9mzTXl+gHfjIC`g%1))gy?N$+j&(^^we7U0Wj?FwXXv zRgCP;FH0&5yuGS7i2tGtt*tETej*cQ4&u!J#IDfi=>^YMm4GdmcT9|y&UQ_mVCv0y zS2vgUnczKIbcyt9C`*S%%~wDCNX;k8t0}LI#wMUKC-=+h_m;%7y&Y02pFPfGN=TUv z@+YAkSJNYdU;j&9b6R#MyQK%-=_Fg0OUuqeNdH<&Sh4p1a?_}8srcVGk%2Zp-7YE<%j%?1%oLJ^{>$DTFQ-m4`A zWffH$H6{jDI**Zfy-IByZ);U4HC%IIqfHm;2G#AM6=fd^)52q}-+CbQVCva9udg#N zDZkBLv%VK5w^@R}pK5)w72_0*DAN(NiHFm>I`*U-(zk90h+Nk9pN|D|Jr)0}`G7Iv zt~q{R}@fCr`a<^C((n_-v7t7B`$^)L|=JxEXQW+;)djDQ7 z;9dOtF6*aw{plSzGrOaLXvRlaDgOK6;M`HTQ*-T^(0{=e-CyacCYqH?H(%T@GiZgw zeY0+2?xocK)SKX&+bN66uu!v*gjnY9W)nR}l#Hd35+>K*`|-!R*c9u+3TjfSVkZ-Q zP*m7-Il>U7mNPe4?<&fL{>1gJWHca?n(ISbBX25xr8er@Tkz|4g)U<> zg(>wg!ToRA9eaY+-~_BDL>gY$8() z#8;}kteOgUf3+o@=4`D7(Q;opBtR+QPN-`gHBHUUS!jPc`MoBCCs^x5)Fn0sz=P)* z4+VT3(80={Jg;NUNU=9@{`#-uM3g{aMQhfe_#`D?T!4wcyl`1sT_mo{%5nCVW?O!u zx(QK0+p77#;@AHjv(B|maGpl!90muzDF*QmJ~5ytEf168u?Gc1!*kj97z(ruK3Lvc z&DAHesMxd}RZ2I#BO9?Af689^D1!bKpRAKQBCKgf5Dla{$}hUQwrsNcR=nWnZ(jsf zx5B18_@fiCRb%BvD^l4ub}yD>FT9xFCtfAxf>nydaAH2HwK`I17&yV?XE?$xJtAK)hglltnvTd~O&><|rt<0S3<--f!dQQHwyhLO;wf<0{mK%b7Qeof z*jCs)JWPRo-0YiqVd`<(IYOHf(D@$g&$DYGg{!;1K#z}z@7z|3o4dc_De1PGAg-h3 z^8%LZqjso=%gMNV2TiKJ7E5~lZh<)^GgJ?YThA<>z>yc#Z zX-xfldynP?xa6yWe(jXMOl+Bsk*}*t)LcKVnBC}JYjru2{hYysAk#BrCyHd$91}NY5`%zwL3IY!kQ^#t zv+~qSdMi<+3KB}l!F?|B+4^EcN7{wixn~JG!PJ+<$`t*XHXXfexLJuRNHVC-B5n-Y6*)rf!)a@Vz$y0tiM?AS8g+bR z${vXg=T=!1xVOAqUtPmGD}5j>YvqKx&{#Rh45YQ2&F~jnx9dtftBUQDmHeODPme1B zb{lKD`?MaW1Hvy>o;#NN(R(&>QBOd12kVE2l!q+Og$iYo$5xKHDr76l-ci%G=(bQD@YXSjN<;Z7O>edqvKu8_5jo@ScCN0LENy0UEE6KKn z+)?nE3IvZFF)^~Q_Z(vOVi%(KVc|`Igts7vH@{-?ahKaW30&i<7}5M}VFUSOTX6IX z|3cqv&I26qq=E)<`FwN)$*6=g-G$n> zZ_RN=hGTl>1`ewcP#Oz1V{2`dUif6In8$PBrs4vqc9pj3&EaN=PmVdij4yKtqfm-@-p9;{MX|@d~F6XI;jY!(m6+vXCgNtx+Yj0u-V%7e63|vK!&bqBmL_4= z>G@dy!fjdj`~ofICx3GX)LwAmt(Hl9SlR(*(C9ysyEk7-0u{K$gR>Va8C|WD z4If@NO{t47u~orX_0bXi3V2VT6x7QcE!Poj_P=Ad5=KPMD=kOQTk5pY@SVINgH`BC z$$>6%tEPt;SjdV@S8}P}dDVy08zk)W&h|=JW@JXzvu-KpUJL1jRK~=}Jwt%cL@aRM zZzXdVL1pb(tEbzFnBf?|$d<`^^*VqypOh<=AkjbJHh<9iF|Al?8S!SN=H2KOLYue& zD)yeb-gyD%i}3Rx)4E4g+jF0tGB)p{v>TAcyuFmo-Bnd)Q~M{Xq3Q&>wgH z2)Y)<)8VjU!`Ia|pB|~MoUa~%IpM~f;>XJkio^f)DVDB0yBTCQq4^0UK~ zdEY>-?!b>ky}>2rG-){D#N_cLsmX1Z;zkR_LPY1UGlf)))dG!AAB~&bI#eMTYEs@$e@8Y5JHPo!D94 z7c8SyTY?$!2aw@@G4Lle5D37S#x64gx1%I<;^NvVodnG=b@7keeA0zawgtF(ed-^) zvS}}v@h=*0u-^DQ$gdOrQPE9mRZ+-36J3e4Y}k^8msRX63B=H|RzLCG!W+d6)r6ja zo)B}ngf*Wg=ZBa5Qf-w^{ir3^40p3O9h;fK>rvDy-=0CbSSZ|T)_XS0?kcmm279y$ zKMT65;g=j%EQzQ~>6_gD{&gY)^cAas$8m=*z0*jzYrEcczV_fJR!3ChVKJXt<}j%wVME z0nXf)^=ij|iP0K6)?%%~yAq;h1=QXXRDCq9l^SGn1hdPe+yAo0rFhq}?0FFL zD`}OfWG`gx6<~?%tK&MQ=FpXC7gkdB80~K($5sdib&f?t=uqdXGb++O!0LA-48dS2X$O1!Vquh zHfu9hdK`L`qG-86UN1z~bDws;^}4XRc~fEsKB~A>u5+PId%jS?FXn20 zyk6G2f+gt_;w`N0JQ#iFv&FfMsq*-@HU_nRQc{cdZY#C+eK%2o_bq(M#$*CVzGXq3-)x5CLq(ee@S&a` znJ?2sj7PR+1Wa-~)bKY(uTF)zusvX(LFMRFc~>@`whdWgaa}OqxtUx+H~7WTMOyS< zi+m9eCb+u-y+*i0*Wk-rofuiV&vY}l+3VY9hoI^*7jT|IV6Bm#dN@yJ1w$3>f7F^& z@Gv!2UJz1Bc8eVtY1{hLt4z-=iZ_O5hyA=DGPwUmk;2CO*&1BE-a>hzvwyyVq5DqI zAiKD-&615=?^Dw#Jd3DGO}b}wxsev^P#p9v>w=icMR#y$gN;PSH6LV#lYI9ktO#wI zs5Tfztgd49+XqEXZA5%V+Y-)+5wht{pX-wQ69ejPZIY@YN5#!&1@^XhYxzo?4^sc)@L zeVme7g+oovr4{Q&M(*r!OJ-K;F(?)5kr|;mZLVegbM+@z2l}Uw@ZdNPdl&qk%sbIX z?7yn!wSwuA8asfl&dEq>XE1>ocSbfYrGmJ~leRVG>>Zh^tDX99GnKHS7mRR!I5N2e zs*fMrF~o97JNcxk`k-UV@6wa#)v`YyC0*fUHTDKzK663FPrRdGKW$>T z&{iwRR1yTH=xf$UOvrx5jBEg*m$L*8{pj)d+>!Vr*`)bHI(hrmr1Xoi9LNRXe|W^X znt}c<-mkL`238)XY=Ik?x80b=@Zjhe#ZI{B1;A+7<*XYz>Qg;b+O_+`BR_ufe zSF9s*MTU{w8@cgI!5wGLeZfTeD6}qwAN^k4iq9=E(y_V%rD0K)QGp@bPGfMMxvTxK z;h9|tzxd#Ym?-1tDUVAWLv`G`cTF22K(|gLmdM9S<>@=&8WI~E9jNg=(}|krYBe27 zJ&#N~ox%TXRsZpsMbuUgM=dFww%yEbu-P`K*qTD&IE6VMW5RBqHxa3lHmGv69#Cw1 za*Z!^B|duUOKX4|+9y6RqheK(2J(GMo60A)1aed4dymee)lt_6w3d25m4& zCaC?;s|mbJqo>wOVl}oy2nN$L-b$U8>UBG(3uI_V@)5gig-#bP-4Z~WG4#KNZ$G>` z&TjC~cK zO9M!&GQ`f|1*GVk?h9CK(N!0F=+R}HJ(;$*P#Ckrh~ z{#svK-HCprTi9N%l`2mYf&)kKlCBk9=?Ho!Iv~v$x69cUfVP^A-g_6Oub6kJc=g zv~&@m*hg1nl}%!mN}MDW*j{yHb*-~Yc&rah?4T;WoP(1^a&YOi+u(8l=kUF&glIVk9i&1(eAoK zj+6T4zGU)LHHC6?X>7~KGSFzzMtG$=+{8H>8va#r1h?QiBCE}9OqO>>}A5dTU-VruZ`sVBjXGNx4}T>BN0rgUX41RG_+z%M~R^@Jho1{B3J~yZyQzd zh5~r*!N3`9I_=KR_b5&Z(6dG?u>lvt=Pz3Cd;xD$9?A28pYJ`s-`H4_P&i-$mWh__ z{wCb>zVf!j8pu4h_L@>Lp1IjthaQQ`4S7ZQnk5Z^&W!+wrf|H7Cg$hR{Tkn*cxg!kKbd?{C>cFaBXzK=+3hU z1$LkIlE=``7AK04)y`yu~*D`nG^Cy}Rjx(*?a>N$UkkFI(5I2ed8g7THEp-_EjFD)tV6b)g{| zQtRnH-fx=F;L*kbq0jK;~<+GwXq-PgpYHv}vIaH9oK>Ycqpb0G+0%=+w0*0mOl ziQUpI-O&-%b!G(aJ`de(CU_3zl3woqhi5%Az;;glE>l_gP(ytU#)_fVQx#P`5NajTKGP6wN(~-hWhhD^Ngw{h z*O$a?sI%Flb(LA4++G%w21e{?ZM$<8H7yp^%l^1v?5HMbr!+2BXD)*--pm$kc>cMn zqHck0WjAMgGIKGLwRu79Y_}0dD1xFmnJ)fZ=NHZM>k zy-Fd$my-Gig9v@&n`4h#`s|Wi%xkX#r^~Ge9Tbs7;GM7ScOy$P28`@#8^2bENo}T7z6z|!wT*q{mT7??EPZvJr2X$0ebY#mv|niK@}(Yb z9@!{;_@BZRx2v2tO(_igwV?%XM zW~s$yewf0nS^B!(8~RZ4zhj7-_@m*RDh|JYNH6}bHss$$OGhG_e5!-(sNd4otmCh@ z(X^JE2dmEfg5-y{%~b6l=GBFA+JQ$9nWXROITzb%sy)bAy>abxE2<78SFg{8(=TDo zl@Oh8k!x9{k}$_bqi!O4CGhV~{C<=ozdLDTikp^!p6a&Mnc~1clabt_Nr2n7Uvg$DTPJ=CStu(>r=hlusx77%Di_;e$WaX8uc2ky&yoj z9taO;*K}7+TU~X#e+!XoUEo%jE)8dF)#)HRkL(}SpbPZe5)=s@=Nhv1WUL(uE>DvX zANz<%x8;2=WJaH*%gJ?U&byhT0T+B37=C7`{4GrM$WOrq6aRmWAo%|si^4Uc^8AzG z2pPdrMVsoH9~s73Vyq)1nuKXrm6H}HV-nf#kik(8!mNBk)~WV3m&oEu6up6uo9{iX z6f?N_D!O82bUaE~s$R=lm#?Dq)Rg=@2T_Am^LP7WV;s}b-qK2c6~Di^DSfC0hex;3 ziSxHY#YPxnGvzPPbo~+!;;9ce3L*XiLk9-RB|Bs(8VZQD&Ss#8I!gcW9|M+G=>gjk^JO7<{JD|O_js(a%Y`izqXgV2G|VOw?mG?s?m z5(o1IOmRun2>vL*;AjnNob7IG?N$>bUbA|rJE5=DC-KlcA}UfC-lW)V30{(+X-IEt zLC)5`k8pQK|CHAWmNOm~Dp{0@({I;uAI_fdt9%<={d!I>%!pZWBIfjLd0cw>;pi7k z*q~QL1*3QQG15$@2lQ6p!pkKK~BmHDv3PijT0eitK9^3_~q4qT1@*&I4))~ zBzKN=Q>Ll#ww7_apH^+Mq0?0~n=ODkxxLNEXN{ku0!rHaG;yfYaW{A*EXd*R>8AAej_%F>)Bz*5o6@EQw` z!y2{a$hIS!feM*DZ~N?1XPpuBcEuZnxtRXm_Wa?q_spqt1o7PuWH)8}t62sHT*I!; zP4bCCxAmz#Azk}wx+3NCF+gQt3tSIY%q(?j0I?PoT<-j<7ic?2H0$v|x+TWo)P|Ds z)`q1W|G#3EHmmtSK6~g<_R^6?YWEF93qP^t0&~9!D!s)GOxWXzxGB@@Zq)(>!5p#m zmL4qwI$$1*N~#^Ov7Pk55h%RqmugXP%XtRzq8_f;7TD~Qfc*xZ&r=Z^u-a)!7@AkUu-VpDJ(p2skk=b#eREb28NDiX^}{eSOx< z-}*(F7OU0_ggHaV&787vvdGN6)bUR@d$&kY(z(W2$dtHdt!xyet9sPMDj8?nSC`t9 zW#kmw1QT_H$z zZ+J$>UGd{bDHp7sj7-xb`}*fuBHo|4~k?djOL}l#N*)p?D z>B?JCx)7`+?p}ZX?hcg_lOma8V1AFBO`Gficl*yFhxS0dt9FBnlM$8~LejoLZdd@1 zir;btwtVU`8Pb-j?nt3O86lWCXNe^>Gr4?~B(Z!>Rv?vrxy9hjNM9Mr@ksMEED=N) zxU--PanL~0aKa>axJ#NCupxM-+r;-z(Fzhl0=mRb+Bb}=?Y*rl#O%G4CM^Vvu$(?E zyDe_cT^txV%9CH-x>AvgIRnRu)_i;$vJs^kuNr_?m)g!%no+jQvz02hY!?3n=ESA= zCrkE@=C-+b4x$z49Z7IlZp_(G0CKcrMgi!pd*h53rx!*>MgDyB;H@;?>A!ZZd6kC@ z8K(S=d!O^fA;}9JG+L(T{h9fM4mu>0-a2};=`Vf}*u0RMr<^a7E`uu`@-A6LBXBBF zh%3jetil?|J+odD8R*Xc#{GVzxjdG1ER~u}sNwCXH8;_jAnD z(%ria57ebz^yPN|IK$-Ju0Eqm2E#j-4XaMEH=&a}><2X|M8uj>6>0i$Bqqx?Du#{ZeQ3{1WFdP}tp4;z&- z2Ia^%cc%!=ayL4o=*9Z%nGuw`BE=b3onNZ2H{bm-2UfcF^pbu^Acdw0%CUSES*;X& z2oKcxnmvTA$kNX`Sc1y#o)S22wR=jqS5f>`$kw-7H4*Y7Uy!JZm!H)2?s`r#l|K^r z4tsApj483oEm!&`N=+^OfkJSqU|PgQ!$UsUIlO}n<>kzQyH6BTbh4Elr;hpV`2~o9 zRtA2mWufM>gRjpkCohS2cNQ^@#DS~Y;n$;g)2pUxQnpJoAaefm+FV1uirlJJnrbK) zew9Vfj^h+oke4=pUB>jEf+R0}_qBWljTiH6wcCWQNvQ+s~Z* zia_5($ImujQ)X0UV*`W++Pkj|)(JC-LQD^*oYHHh;L)XgoZpGwy4Xye9iI*t7FVYO z9z)0NKb3D29>kvQ&k=~(Ef=;0xgj!?oq}Y0g({OH{h;2!sU&{u$r>B7ltI2~1eBHN zhopUWB$+sHt1Gv>tm^|UmRjiASl~}Yv-^&*@lw!PMo;VL&cL3|=G_91C6xP{Nz~Cr zBUijZ#vHTivMo<~PH%o@*Fm&U9C?>=r%kg1{cODL;eg`)pNw?H+3RTf90pM9L$FI} z>B z&7;M;M)w%od+SbIQ5j%&->0gmI2OZKKB~K0D9Jlin?@->9Pj@UaV+Q0a(MZysXOeT z%5V>=yE700Sn!E$S6c+L-@AI$v-hIOgPR|iWsJ}>(YyGH$;j-kQ9pUpr^8OmKcn|! z^zGku-S%*QDIk+) z_q6qxd|8yF?53f#&7NEudv^pbO1OdfJ+y5?#4}<#j=|5AsmgxnkxU<*WMY6Bag+*Xod&s*MNU8h8M z(HBsM(k*=8F3Z7Fwg^;FK6)N)6I7ncAC9Ai)aL}5WLl60po7Cs*dwfGGweP3;-8!m zy8ZH{?<#e_4_4X<+?ktIfHtV`XpEn4sxE~bBaAMhXatI^Fo)U}QE+-p9=L6w+O@Ne<7s!r_sshV>Y94cx44Hy$`MeCQZn{k-{|+n-x@!QbP=wcR{L&EbVkamFrpCOK&=$VqzoOu@>U zAC&LVjJ!K!WySGMz-7+eNTplRAA}{Vmgf`Qt@C6r~y)`o*hN z1O$>-ITgtqF}bBeuijD#C}u6qU{!;gPZjF#MZVXR-+f=AaF$_l-pL`1#F3baFNFj} zewvI5j5}HvO%sFve(Q|#F14=SBXLw#zEH)!==&De5*??gu}AI9-L@&`zMZ4_d+BiH zXp{HP#6N9(M-!($9D2RkjIp0=xth9@dL>COrG=a(v^R2ii;!fKu;eb!yjLdJ=j%6n zOJSI6ndjb%LJGTDCMiHEkX9iJ4YHFy9uGf@;`p^EuMc|NxL9PV&~C~&Qv;s)?!vTj zk8k^=&=#0R_L3((c=0oP)~4y~WPbF3iofM_%9GHdPv^YHR^)&@fnCcd@$1ECSX8ky z|0K!630Gr-O#A5YsfQ|ks4QidU=wd6rr>BX=dk~REx2Elof57ufnbo$4gE99!Kql^#yrD#RXD>0=2DZCwa7gyt<~^F4tgWYN%&mZk7e7= z$@j1{N4j7BPUL^sMJx|p+afH-75_OpYeSjsRdC%S z^ZQ;rb~>rx5u5}!)67aNX4prQd`wNS)+I0gJL;ZMT^~d7`vu5%e6|~^;gWx&WA=yW z#6kb_;?6_1S1Zmr9&i4g8j-|boeV}s1vwz8cdu|7UrfrfhYc|B6_zi0fMASssKMf3O^_rIS*bM|j2A}1`H7J92aqvgD$GZG3#P_dON zCfBE%_y)skU{v&&OROT(8WOqLOZ;d!tcw$>Lef?_u26O+>b_{h>6@LzFOs8xWuWyS zm;o>7JTPmWN|O$D+2W!n)YSprp7LOdD+<(Xnh4v;Rhcx?e}0||S#OP71l+df z-zMK~2EB4`0V#N2K9_wX6L(7SlF}S}Oxjq`Z|=11%0+R$HKO~C2Azx+Neze98Qzps zi=sE01^Af8-Ryo)E#G{{crm|LAFwspaIC1>flF4Lu0rt*qJj1UFk02FQPcB3#HxX@ zXC_yl>5Qf5sxWRsZARmoyF-;P#gUzm)_bl{7}l0lb<9H%4sXvI&x;H#~5 zZ;C&55LV321+=%iyF(9C%BB7G0P3G6n(Ve7v(&q9;c@l1fT?#L4n%IrnbR$VY2cur z+Iq8FtM;MVc-(`p4?c|d7d{>{QtEmTr5f`6P&|#-|M&@kay+2~)+Ir5FaQxO6|$HA z`SrB*yLIBkVh=Y+{C~&%Ez6EXZcCT+!d{>hKcxP{Kr5$`wKkIqg|+ql`NN2c5Mnj_ zyi&2t=u~8Y;Y==wqYwB~q;UbMo%_YRraCRiMr$v4qDZM@g?HG=T2)!&QJsTyOb)G} znG*`>aPSOBYpDO>7QCpp``rRC^Nty8m}cnPrXn!-uv7l}SAsui*Fe!%@!V3}2hUQa z^eD09CcT3h&hTiYu*P>+^^q63=_lm786nB+D>WcXlR23tCDi!03n?Kx^*kb)tzCzA zvd%Aer#&6~=g_MESg)CNV<~%`Z2aJUzqLlvPSmzd&mAqkx<#e5IK8uY>G@Z3X{wXV zSfO24=FnWSuE61l5Z6aj*o84Hf?P_ksBzfGC0UuPLTrRGQ4d&!=_Ey@dRfGNSny*0 zhS!vW`MbK4{850-IQ(SBGaV6_9q!%?x0q7Ia;FzbS^eStdLawbdMk#fWmBuK!UHuR zia?EdS%Dy2t*4zfq%JDE*^a)O|AV_U#PULD7~4S z9Fy?^%}H$O4h;pYSdcy4@H|TvmH%nKrxtM;Z(2@ePkDe)P&#B%w(B;$(?x{oQbzEM=jjQhPE* z5tdOb)lB@v%J2XZ6;&oOf*gvz@D5z3^vqDlo$U9+2~>olu>)uSX$8liI<+3Ja%36S zEAkpz!$ZIBhrakkhN3GsFBIHwdSv?c%oovbOk>EXZg-8m0lgLT4I&q+xBEeHgsJwB zwH$grSnq45c@(`3&$(cKzGa@yezvX2{MS45%1Tkj8e%o&R0#WD!NKg05?Kq*isT(iA^tMIUAx@>LB(L^_h{|XgpBRia) zsM;w?l|_BCM-+7gUJJ_2boz+2F4nBA)aTP3S6%E3<3?i?@dhvkplC6WLRoM_>KoK?=Uk|`0bg-hZkXf^6DA=r!Ze8U26B6CC7?`?{>L^kaHs}lh?i_ z3c)-l9}J~o0uDi+!?R>1KQP@aLa>ewh>yimkztNk>!8C8%}-1!b(v0BAVtwIB7DL@ zj#BP8m8uwT6S8}w_t3fY&>xCWg=wN;J&fdS8h#&SLn)rH{4XsE6Qr0 zB};y^M|B?^V^rV^jF|mcCnZ0)ic->Z5`W_Er>G}e0@*k$wl<(7m{f8SAG)T^0M&!H zZ=)k5ok=?qgQGzkfRdnlRdyR*YrybQWgv`X$#Sf==Oif`*vAGgPDkD;s&Xo~sRSwW z#Rc|UbCs~6+6EX7f2+EHzo}QcE$YW`g&`Aikm>P6_l|%suI#fMRFLyu@gjB?RI!$R zK19)bYXZgoQ@|+qx!kt9*501Y+3SxO+O?FIb3WcxrT!ySXrPjTiP%5*J9@RXmGs-+ zg}rbP&E)Ts^|9yF_Y;4Ak*OXV{rJVRa^-ttY_>ASb8PT~R$rhu@%Lb$6Z*{jm4V^r zitSGsEWFlZ-l5iawjVIZ2lv#Lr2J?_Ob*WM$7jX(Y1D{Jq_x5{xHcJs}620)(RboVG-Hn!ALx0Gw6{lR@V7Wq@6qy@32 zj`p}56*()jmB}t;*%xz$?b~?-8%Es2CZ3e^w|dqCBam6LK{_=nYhwJmDl281_K9Cf z!22FAIu2psMD$HZ5;`1;BvPmOF%a>XetlJaW#!P2vIQ#QZGK0kQbBlhS{iJlq_hED z6G}ndo@ay~$?(#*M$cqn6jE2O`F&h_~cBx2`=?&H}9`kNz;Zd9wRv*lr5Jj~MbK zHic59UcmcHwf{)M10Vf6> z1?JDlM19yqR;Aix6vGaEQ2UjN6?SwA%Owqe`=C6#WF*yxaMRC=RFZgewXbP5*I z&0wQZV)W?IpmdBJC8MOJOHsbY`|>B8AI@{`^IX^c`ShfKi-yw{ZH*k&JcEiM5T9t? zj|W;>mvc6`;6hJhBeVs)a$Fda^oG8|RpRAejF6Z`Qf@_Q>99=7iB~n)J?Vt@bH-u7 zXkyfhDI=oAde~2em|F#FdaWHenz-Q=$=3aTNOPG}$JinWRc@dTwrBS2=i%&1mEcqAS0B?YL3$jqERK~`_VNcfx|^rM9W>J91W%v{l9`d+=9^Rv9;(}y znEFTkfbvn#Gp$5QUA{QuysxX^^ZuE^B+)2&$nIT-gYMxJ5fKz=x^5Lr?{VCK-ebE0 zK4B~PIKu+};c#AN^xtHWZUZfuT`myNpzUR#X)@dO@^QDZ%c4cPO(m zqu@FqEuvItb4wOv`qy77n0UQA72Sr-ig=krl%7|IIJBhQqkE^wYX7l{1i;y8u<^z? z>+;VKdFqovHR1eY-bGvW(}!L)fl}JekRyt^6~*$f-A}(26W)J90b5F**G5~d@tpl4G4P&&8OpM|8 z`y#Yb zwC^}l7A8L^y}V+>Qg<2*Ow?@AOS;)ZnjGfh{vm zZCB3e8Y(pm5P(B8GrNY$yZIaM=<2A!XzuD{m%o(fbGA4(^U0#h3(8ijA||BD8AY%0 zjd?DQP`eN-HT%8GJFe{A2ZoGQvwNu5Fa~E6iyEw_tOvm`4|$zRUtJ1mzRt4gDR@;N zJO(mJSg@w{n4(D$3c#b(^Rk@29tr{K*;~s_xI!oKug#F&{~0}Bi2SW(R%E;BobA?s zIi^T+Gj%>XT1A!?+?{Lu&OOL@C4Intga)`fIYi8lcasyLaSX~>iAiOOE^SF~(1vo8 z0=>IhJTGEDztHQ4^?QWgLULf|E5*4P#^|ot=W4%9_?d*56f>ZP*W~TT!)JQEc>}|A zBUL$A1QyTmTZN1@REHL-Su;J!^J-%1c1pe}b@LnY%#u`q3dj}I*fEH)49iqq)rA|3 zgH5h+zQD!Ldyw-< zG1N?Ndql!+A}c?$q)d&=mwfSTDGi_WA!!va>2VjUdFJ2DCTi>#srl6COkdf-%2=Kt zz=OpvGDtM?geFI2EP*S?1+gaNGMMfXnNlD2XuGeMuXRD@U~)Zk4?AFu*3xQoPieYi zZVl&=05r)Ll=JZA+#4kb66gQ;ZoQ#6oOu?P@u^An=Jtx#WCmZeY&EP7hzzg zCFh3gqicFyk&+#hpW-Y6N^{Hy4N<|-`ALJb6~{d|BZseq3iC>^N^^86g_e9X5>E8*&Me4;SnI6f%GT0c&g-M=PH+Z#20h^`1~|DW z;$hz@&)v_t%cXLmkFNI=rf8QV+bO#JS6c)o>|g(~yfFR8IGxzC-166R`?yVdxWWF` z)l_CY#4t?-4-U9ok<6ST;yh@0*?oaxm5}CPZR)`Xu|}ejj?tj-iq8ea+Okv1`fudw%=(h%T9^ zu^-T6@+vzbUgaq}C0*ZX2@WbAyCc_1NPlrPO&RHbQ86$Xq5n%`TTe2 zL=50S)QXa1Q6#yEx+~P0Gmm_wzPP?fVE@p%N*q&Nl_n!9FWap-YIVqShg&M#e4)9F zS*j!BMQA1Cg}gzlc&$ZKQr8JC;Q^oqUf2zOKe-11yWq&o=0S?^w*E%{!SxrOX3HWU2{TWd7%;{%UPIt-+!-Q1JIGh zEFhZSga{aGi>PNcO{#blp@%f|N0^0}%-$~0sJbo?4`F=sZ(N>{g+bMn!U8zK)L?|% zoUL`jqimH~-3cE$E5}43Ku}J*XhtUEI4{j8z`N#k-s`nz^xZ<+oVT(E5>3a}bJ&*` zbzY0;X5#ALj1<{-tY%NgB^^nl`E3g5F*K56KEUJp$MZaU(E1HY7;(d@t@AfiDZ@FX z*B7mRJR-Q8C8yhwJo^DZkk4I|&mtYXa@%bje8zcXPott05zbUvwfv$w2eSy%*v0I$ z_D$!iN%ZBeTio683PYJn0s0}luZcIQ;;B$m(qq4Ih4Jy4Dwh5yT@??Hw-)4?nYIo3 zC96-XK}JQEg*yAUcZ(_(zIv=m&AS6L1&+e00lWKIuS!fZy>f?obr{*ZB3ezn4iWda zG@HZH#^!(AqO;k;G|&90T75Rl+pJ#Cs38^)n|cO8DquP4Vn!yexIs0(_JuQ_! zDqNRL=EP4p`|64=!zdxVfe8^)7L$NlgfALA@=NKHS>dxOAWP^Q)UNS+wX$-CI!dllDBrBxI)aU zOd$r<$U?HpvA!zP52f(~j^ES`gHL3^!qFny0d|+aZ1b{QS#1F)XEkfBWmUh92HWJQ zuDya8yHqFeR7*>6I$!q;?$jA_n5h!r*d@(98`!YM*OUtg>z3GT{`)~}yk=!xtOvI? z(Yg!c@3NX4B7k@SBC_3+^8ZPbBovHWy`bdn41761x%CCus*@Q0wH?immJLN7&eD$| zEqH-WOd!&(mNz{XSI^yq0As6Rp?3fJ<`Bnq`fU%qLSp|xAJMJzh;1MN;fq^(2_>kC zcn!M7RE5%()Y~0-CehnpDlom(Ee`3ivm*X6*bwD;I*T!|j20jtHY?0-tssj~dRikS zbU9wzG%zJAc6@TOZJKH6lJ)AJ>*VR!)b(zt4?;^V4)#xUUY639cPhk>=!+J^=83)S zb}1EdM58Tk9dOMYWV_GFEbzaxV;@vi)&?ATa!n}*CvNfU5AOw~OfB1lV|PF(b2tlc zOGMkg>?O7$Sw^cT@1%~2GX6A=37)a%E2SN8({Z`vSyt?rQK}%Awp%M~9{P&;d~OJ4 zS5eXj94`N~oD?XN7hQ5&=;?FjALR|+Tyk;dg7OGJ?kLa&4!wc}9ZedTR@^>eX7aXP zQICLO&fektLe{DGCRqqb!OhCGS!fMtJZrO-Eq~XC83C5_%qp#r`5+Hi8eE07 zUjDF75>pcsUDm_MRz(aU31+VGf6-3^5{ucX_k>%ucOj`cPRzb2txX4&TaG{wf2y<0 zR&If23lXHz7LSliY|E=-I=uF$`#af z@54(dL$R~?9%Q0s>Z&bf=JtQbW-;o(7|%E~h^NZFbFWApZD}@&$Tvr8OIG@I_;wq< zj;fFa&0)b;HBa0s=c9`${9}c|wTA|?S*G2^$Gb}PL}81_MAM-CEmOFWt>0?q3C8meDJE)mq1V0k|2{Ne$)F>OK6t z&XB$KU-Q?=Hv>iT=a^`vm<|JjtxM+=XBSc?Zas2Q(zyuf7VY<%tgBb7P4IS zFPH0^>yO@ciRzN^?26M)H`ugigdV_piVfm54%6uWJQu=+OvAto)lQ52Sr%N6 zOu#grvNo&Ym{)E)CwTTlV#bd8BP>*h-U1xgl!bbk^6aI5oTx(?_CbLfAr#>&5%#n2 z<sQ*0Nw6(Vf6-P959n%v-Dc?h24#!`)MVypq>wopYMmOuam@!A&n4yH035M}nMZUr;R{4hm?m1m4<0SE4+H4YXQ2>TbecH~sQG7a1sGJ|~8yP2!67tjWaryc!v_ zy34}J6U~CqpZLs$<=bD|{m79m5eZJB(i&jN|3(Q>uot%YZAXi9VJwIg z-*^MCcyw&7X7^>t_RY5JMtme6{G$=$S_)BzZG?lFZknnepcM|8sLlptbV^lF)!pkx z?6UoPd{M^6mG%l=rJH}UX{)_Z&!qL>KV~QXc2iuqQ)Is}_g%+y;iq-_A^tH~DlWDd zq1ge`#2UkvPvH=&=!3xDsf+?Ff;bjXpwLx6#Lz_dU|{!4p1CATUh_3>HS2Z#Y1y|f zEI$T!yn|&Gx5(7fx_;PiAYy#}8dLTQKN#A|6uLz1^~$|s8K$2dqRyI(j&bq&plCbp z26y5Ge&r4xcs$$lX5^(nQp@j@LrwxhhHAuXHSdY{fl?~`Ap z#Wn{PDZ$}l=vreLdru)RegKf-Et9MkzuC?19YF=a$2EJ)4ELkQ+PxH6c1(Fb{^lIJ zkjRsMjF!nrUhr*(x>ttb0tXAVe|iPn+*ed8j8x;TH3to?Rl@~eKm*hz^>q7W!)10> zZBOU(zi)7cJ?vMaVl(LLZJT3r>qK53l<8s?_)X|Vv+24{L~aR>bo#oFMiW0$z4rP= zyt3`S=s784YwtY&zTw&0+DRYoho_skkRCQ)hUPZY4folU>g>jPB-fnUGj%)rZ>_X8 zG!z|~wZ^#sf!QIGJx;CZqdX5lp>%Al@^|E-wjIw$|8d%^ko`!)d$mWKgipKE=1+W; zer~?4N%JWyoP)0!{X~r=yrWL8h`%&Nn4#2A-qScRG4po0DIgjH(gJL4Dy*%8$zcJn zpdnmALRa(E<@>>S)9ga+z<`&a>I`(1Qo?ds=4@Fh7a3t?Ag?0*C+}ZhvB9QVJh0fI(@IVWh^*bdc%3~(p2s!;vNG3 z8=FKD(U!F=XyM2vb!V_Dkj3v^{0Pb-m6d>jq)AAlFsv`M&4B`8piY#TGev5BbJo{_ z4*GrL>n6xa40JdkMR#oOC2(RxqQ5M=b7!qIq!6|3Qno$ebihTiB>PwR)WF@i9UWL+ z+?IN}J!LgFo>HQfs(q(Hz?l=n#9h@>Mmk*(1m) zo*r~2d*K&yRNf8Vic&3ZKvTNnjow5rxHo|CeegQuyow%yu*?xDig5`K2SKk z6)3%7RilceKab5Qg@#$I4;ajU{~gYI3-rG$uWrw;Ti%P*mQ=n8RNLh0f1a!WWk|fC zm>%l%eSaq5BSw9jDQI{#rdL0_>lEjm)Z&=rZM^ax+5Vi&QM|2k}PR}2x*R(0t2@H2WO4u~vME!|6JmjMnz0#Me;<~xlnNlM}I-8!B z`+VwYvIt?K@uDUkE&Y(fO2Gt~?A53BVm`~evQm9@wfYo%NUcpM;8c`Ox*uIdVLaee zy)ZasiNe$(voZrbAwElXhYQ5T)&zew0fP4*D1XHkwK|dA8jnu3a>A`pMIhw*F~tCp zRn8Qdfvn%pUAYA&3Q`j)Z|%hsNM+HtQ*bdYYq1@|(Y192I8ReV+@VF1x%`B4ko6|))< zQmVrT4+wYsYClG)aHz6yLB6l*gZd{0ve7}0(M7YepfDlONg$Ur|zQ=#kC?%7; z(5zeL-SijPJ!XU!RqBeTLwWy)8Ka%q(q+*t$gNOKIk zvT~JN-OVj3%_v)^xfyowLq7I3IsCt5;_J3rn{W%I;2&i#aqSc8i>tP^UI14Yex1wQ zvInv}P>dUi_}+gaBmY^vFM%BpnUcI*8SCoFw(ojZ2OsNr@syF2k*adR2}_9GSSd}HKR17qZ!=hhJ( z8tw~604z*9r`X15G|S1#`0k<#KLaxW14`9}4Q6NBPx)2 z;;pd#!!nL#3@q}a8qQi>u+4#XE)>i|fF3)Sj0VlVt#gx~4GeMsy z-gx}-yj;Ap$~3(^L2H6IbXcVlY?LoEGQB7CtsE{zlq>x{$^Fs(wOR9Pk@NllVSpM_ zR4B}PTALS|X<<&y_Rv`{_r4aD`mLePV5P#vf>iSf=9b;k_W3c%kv&OWun`+vj;-@> zc764r_+Lbd3faEtE*fdf4+5jCV^9n83gk4TrH>2Tpga3$;})U00i{n?{wDcIvkg&K zie|%Lc4W(T*f8dhf0taZf;QWssoLz~OYZH7i&B_PN-}6AA{2&*7CDspXoKytz1MihuAJ>`xk0pPX`V2V-!qdwgr#W+>W%d)xRxPR~2DdyJUt70xXpZYo6yR zKw-(3W9=23rFhbZhOU@7TB#wdj_p zkU6en9RJ>X)IHlT$YDP;dygqYt*2q8C7<23HI-e&;vJu(pl)BVWVff;O<8y42Vp(j zTM6D4DP_evW|P+DCEVlV1II)WILx16l>91?MMS2W>-UlMl@Ut6qa~Y{{j9rqL*KMOh{Pg2;odzug;RYG5;BW@ctq z2ket@K#L8AiP+ZT(ZgF8W*PI3C5`6S+yK!s0gIXYqa0a#X%r#TiVmG&+3n8KzF;&7 zIr5vD9VAR&yF=u=jm_f6Xe3AQ#hcb? zkHV0rr`JR;<=;mFVKGxYSs;ehwj9j_9`A9wAStSxtz3-LFSQenF3}q8a;TDDSRU%; z+t$9gzQL0<0?L)7y3fq4P(&*rpc=Bf8+l^3RV2VrEouVHW?G{bm06?=hbPJ6b|i3vJ&VobSc{hG~637+CiX z@N^*P;u*>(n*u_O+GOsPWM%$$AMIfX&w63qRMaz-F7~ zgk%P14O;#x2z(ggUkJog_$*rvFIH$7GHe6YpqGNf23Vk=n5&{iQkO}<%jMJMnt_j{PDc9$jykAb}Z0)aBZ_Xl|FZM{>0uLqB=( z(sA}5@JZ~c69SXYf9symE2-4^pm}=~UIdy~P#{2#D`_p!K!dp~MOzG5GCwiP)llfa z_J?5H6F4gj678-C9hx$fG`0BI0o!dU%nX3lbYZ*fsUIwCeE{oq#rp`vZk*^YJ@(AV zwQ!FOCkR;Cu?Ju7z9{ShazV}Ayj6XTx?75@SxHBh^-K7GE&W@7SE)XT!ug!Rr@j49 zLpwQ3ZxzKlyy2%sSHhElq6n+cK)rf3roX=vT1SU1MJM+_PXU!?t{e|t(~@q10@SU! z)n7a<>1{s$q}3oH$mas6uS4lRhEp~ru+22yZ4;-Eyr-XA!wd;JGcZl=sE~L`5p<|+ z(CMG-I4K;M3S&Bc@jctp&pRBw_B1S$%xkx0ku5Wf4BMEP){)P zjPu2rlgRG1vVe|r{SP&%loY3=2a1>ea7mn4$dvi#N1xu zKQ=wHy1hJ5SwzoC0TD7pMMXNU?vvwcCuDr{rkjHD&P@M5w;7i3<<%^ld_lerX? z9ukFUhVH-jnK)obJ@fPHYvY#PEs~x2v3yed{fpn?PwxNSDIen|&Y;P;i|(=|aMEd7 z2yvUQcU?-Rft;%=l)f;m2@W$h5Oxc}1>N(ztn`bC$?c+#r`E;h|L6r{A0Myq&S-?RUa^PXWr@qxJRdi!Z9OkGd*-LZy6s9w7$}HG5ET}NiHr|U? z+yyeTwwtB3C1XAMISpm}2(PE;YJvra#;Jjnm@}Cr>81t2b@53rA74_X;6bJ(Dck2q0ZG@Hgc!|7O1C^N^YV`kD{VgXY^#r`5%?#{P&>SDR+!2SlVfLjM9 zO|6=S%rDKytXW+#3cfY6qAxZhy2y{6l1?tILH8TtWinx)I}v4O#_~0dE;pY+OsXmI zyOuYLhqEOa+nu^lBm_}T8;KO9xEL+6V-sSs^z(T#o+%+jaXdb3a5V7veb7N?9R$S+ z?%6b?koDxh;YTTqS4V!&jP_;A_~|Y<7g}gsW$~${@?*)in$_WkjA$=u3(RJf2sUZj z?Y_wyOeByO>*TDy@M&ysNt6$CCwo=RWf7dQY3az4>*9)1=MYh({h->Fy0`f1V&(by z%Cry!QL1GoLPM)rSHp6-G=zg>@}uva4i@iRW&I2YG1h9l}E$Er$dEq`}I?34K(Z zSmsW_@HgLgr4OI0GS+0!YP#r5Z?NemHUNhqK zhf!fykLZ+|P@x+|&A&{*&~xVpH_@rHF{#XXye9*A{?(~(fo%8L-@TGiu1T7Aq$d~m z0k+CRzzE(}l&Ytp!eOjv8!QntO$ZzMiP8IH?-5@!wN77l~HH9;*hNs zW8;V~GkRJ~E%!NAhthUEpM=tRSC0hQT>Uo{UTj;+qHaB%Bu5wo!l?{+X+nod5=nyR z^q7VHV#p^K%v`C=7#xKIQb09e&*W14$^Pj1wO@**V82CTvVeGa*El%eB&+P>+Rk<@ zD$i3-ccW0zGjp#sMS}H0=e^jUX8=FDN!g+4R&-JoA4PV~SDq-uv`$&H$)hRg%SrY`5;wt{ZM;dNaAP4kn8Pv_qM z;kqZoy&e)t$g+j@WOje*a8v>NL84AC*zSwGjUP%DZd4xQaGy9;q4X+FhMTMqu}N=- zX{l&+>$7|tSD<4gk}I825c2yIZn>^py5hJ6W(%BWYBu2MT$RW$&M-ozdq@N8QT)7pGdb_h&)NUpS0r(A1OPw4wE3BJ7P zpOW#QR7N`N#N!?pdJsdJ^jH@iw#D(a);p4mSeLUPiA41cP}2<2+V_Nv1buBvdtWOk zKV$i1n;s-1IVP%QxleTuWjwlW8z!4*YhAOlVs8i2g}PBnwI{j{fJ1ZYkfcdYHxaJC zl{r{7e<{AsyX-&wkL*29yIZPTk!+6jJMYGpbtmhx%LmBS;Yu#E3}`8}Yb zw#JHB6wLfah%jh|5z;ov&yVp~4m69Nx0OFpWCNQatCS!nk*J1w4Az|0)ToFWUu_Bg zvzqySudT+q}k^^c)U0nGxJrbn`Bq+75zE-8MNM&)Ue${QWo>XntQyQUDKLJkd zSVxOm$j6T$ts3}E8|r56Ggw6(9<9qRe*fKAp;Q*4W{-X+H=H7Od6$1P_v<>eYzstL zql>3_K=n#kF}WuX&0FZvp;yGwgk>GaD$N#ff)wVlJ0Vq#w}KU!o2eDH8^NtZzF4kv4Rf``lA3Aw>-sD7?6~7Z4&x6^MZ7Ue?TKb)=HW^~@P!JCvf5H1Scz3a ze?i{fzRmm|M%WDF8iy-DXkjSTtkmG(f-}5CNJzG>Ab5u z$jPj=1H%%&gOqZxuH`v-e9+keG4agy;;|(dWye+Nb`0!b=7nx z3*LQ!A4Ls^HA9*zamT&E}1f zXJ$(@=^^RqEPQ0u*%a^|Y_7<`T`F>`dr|u-{YvH=sB*m^OW-xU4@^EKlAX~vHOZf~ z;t%>w#G2M)!{%Ph$}%cNjfp_}0&lncM#KiChQbIXkr#t5fh?r=qAlLJSvp^q|HsTF zGZ$=~pHPBpP4YIG-1EI#dZ#1_x}*K*G9Ht{8AWzl;`mfb(I$XP{#-6jwYN-d{e&K- z-T$gw2)=k=SF%2KH^10fwyy?>f?=_onX$Zju0lR&9Fal9>ks!POfEd!r|qfJe}@0DaQHXOhJ!g z?LxBODj+JyI~o9Q{*+H4r@f(DwiMTYh?1RoCy@1!w&Vs4DrBxbo{~HK$tXR5)|-;u zn_~QhaSyT-Qoti@5>>_4eF4Fh>{?Tw&Bs`pw96oOBmXVVc$PV=L>dpa2?-f!KT<*Z z7M%z#Ysq$JBIJY5)Lgxw0U3v9l(wHw{5vnY6T~jk`OKoi27Qc&pPsL@G}hdEw4nNe z_LO;+CfUVTY@cUt;_`!|`_us~v&g%YaWIY9*RS6^xtQALPHO$7b5D6Y9QZy&u*Yj^ zuIlTFrXJwAc}!4d)y>kCyCrnsjOOu6;XM$WTn3$P88Jk-Jvkb*kYNZNUR&`qRb|+> zpsQduz;b*n^&s9JCBk4xcV2Y$Frr%RUsHL>PG%0#KOm;(o3Nk7?$0#>LiM!d1Pn<6z zjDvR8f5#gX;^Y$$zsLdu!WxLVjVOWvAg!0&YE#nOZ15_N>Z{QYbDjc1*2qy zmNo!C-TjG!S4_IJ9EEySmj751CoBecXIe3x+xFc9F{J0Z7Liq?5EV|JwQ$xsrwWLZ zB<()aT?&+H%q+vr9sdZYTP=n|Ng(ZT3SHiWRo60Yy>L2ReK9IWF3>%)04HL*l3WdA zZ((Su77e-|EXy*b=PAlmya1n~+-7RlcxdZFi9-i9eFdfO|9?gd%OHuoU3g ztjuZ1b9uTUS`YdYdZi}OXyN=2n&h1{wa(T&TO|{!rAI0Lf!7B)pXR2>@I_9V-lSGFe*){+Bj8}f5DL(QbDHAIJ5z&WQxA`z;O zB{BV&Fle&aF?alZI8_MH-5hUg4XlNXcwG03tT7je86=nqB*ryk&MdKDbJgz6q-YVLxoe;57>e+WjBHOQ;Oi>Rv`q51d$FBil%jZ`?{ zZxqo3tvu>$;=}3`Z!;h=!)(!(O*2V)`q5&wXL4U!)QPw&-aAdc%H3SV9uf8@Dc=eK z=t>2h5F;vGq5A9ZBAmTE#(dh)AsO)NB)Y$-KvHb-1J@2ps-s;@HGYq*j&Uz>-6brI zxCN#2-piYkke;|gjIZ@M`-cmId}%tJkoWKFJsSI()nEc}MERJUTgw9VCEpPBOxPkpCr|GduIScY#EGQD z&H|*YhZzQhJXG3Rue{cvVnf{@T6aDlc>K~ag~-A41Pm?KaKG&nWP$`wY5#h z>3F~e3x2I5!yAk6?eixsmeOAGn<$lQv@wz$I+?v&3`q}H4|zBEHa-U1-%0y|v?I%t zu&za#@KnYC&f$yT_{@wXtB4-Bj<3s@7qzrFe&LQ*H13YArxpc*&j;|24b2;Y!#xOSt5AM=X- zCw)Mh=ASD&5App%alXc=tryN-GIML>nwfTb2-#fRTwi1M#FY!`&yw7t`(#H>ei?GN zcxX{vW<{COfOnXG-eLCCO)HkaM;CdiC2<{AG-K0cqwN#(gGg4*_`>dDTPrQRcK$V^?M&xxN~y?kYu@EiwzB*@Q2`U!l9 zr;~ykcD=;Gt3#=ykUk#N_YR&;197d}?5H$6F#*^=@}M}-yVr&=#_+#8UCD7teu>ta zJ3%WzHpEhT_MNqGW~En?M9dF@O=I?P_A?@l)mX@^O~nV!qydMk4EDc;d@IiY>><#m>)zGagr0Rpli4E4-&&n+#cL9} zpBn7f!hn0FhzJfQ)4j#zG8#aW^>{|SQwS|^a%hsMc}J@S#eM1XiJ+3RIMKOEK+7rE z5d20QuGoz0A+4NdF|f;0lWAJR{8A46Mhcc=h6-(QG&zn{d(5ngeCT-)jjg6dmcKRG8ve{AqQm)P6@1Dw?hpBs4t19Z)UiIe zr&_#G3sdi;x) zr|oAXT#?E_Ry?1g`yvEC$)T%MOaMQ#rR;3rA+d*-j$Uk?cwe^XSW#L$ukKZvTdO>! zf!;$C;~2e}Qk3Jr8lxk7Yb*1Z;0lhA`|PHaka8YT>42K#p{ZoS->|Hj8EkyyA5?G^ z9s(B%tV6IFJWHjIlL@z1^0VnQ&;qHMpz~6T5L->*2)CkbVwpKqkB8*#Wr@n<-Mg@Bg`XfWjZ8stHJshjN;bmk1K?zXrbqihM4 z59qGzJ1O?KrHiqM`To%RvITc=p|f5ivghN!h-0a=MIurXFR|xji$A#*wVbUQn828gLJ##{YuQG(-fZTdzdW@E|`FyPuoxXxC z1GhrpGa8(`7~FE}Q`z1)aC;z7{!$%@D=47CsThYnLEXr{?rD87;vaS&eD_3%Y+EiKLt4iSlAzJVFh9i+z}W%(4X?y)tY3Tw^n3? z^`tl&jIsoGckCQ=0FPJA4~7&B^j1wkvgYNPU}>;eW#8}Fu5M;dFV}L_maA2mi~(oo zba1(0?A`lT!{@n~#!4;Z?kc2kZZLCubIj0-J^AKnBgvv~!Bx(Me!{L@(Nx}; zbrF^e>0gSjv8YH%5#{tnSQM&gUidy#7h#5V`QdK8n>J@iu*zf~;KmuRR|M+SdazSq z+LRRFa}oL76o!kL4>esI9t%|nu;q1Y=tSiVxt4(m2YA(qam}VCn|w(IZ4r2>Qq1Mt zZOfalJC##SfxA=4Z|QQx>s5qL)HBuHFz5EhsCy-=E7QRY29&xRE*Y3tnR;R+Qx@Y} z1nY1K@BPGC9E-#qt-Nnzs&k^umI*;V0P7YUdT7xlhDnR6+2)k0Es7s!JuT_2 z^4p=cwfKjEGj&AeNcrcK+=>WY9|QcV<{8Hf3~iaWzP;aor%fK1s~9cz7UyLN<=|i& z4(MlaR8N({fzikqa7%}Wws4{F(+Un-Ll4u^uAq_=3`l5XE6WBhQq`d>vsH4#f3q9P zzr-67_}(ar2&#aLA-qIXb~xpveeM*wM8SDIv}*7DM|LI_IoSU9_-dLV-5yqWLUl>B z(-D1oa1PII1UHwoEN;5A^)%%I^PqKZg$PRAMNUuY$0Bp2fntTf!h6G`sn!&1@~jPr zI@+RnMCPP*Gj}^|Tr-w%dV`8KR>IK{i!GlRxMme*OkaaA0*vcth~W3#7O-xjBruNF+3(qtE8$pw@UT5Ylsa@BK* zDb_>764{2n;Y)c;4LG8xi}@9A;-bgb1wh)XwfuyiFGA*4tZn);^#Us&z)4W+|>t=mZM*rni_4xQ9h
#Eht*=WYOArJMjXbVtI>SG~j?SUxw?DBaTqH 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 XMvA=p0DppCN37MA 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%0DjRPn(z}NU3 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ⅆ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�$t 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 z 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

;ZoDxdvbjZ{MYtJ4qbtw#6xRC6D{G&Q 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 z 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

j6d+rQGD99j!LB-)0gSGHifW2s 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 TN7sLYM(D#}LZ2t6eoy@m^j^F5 diff --git a/test/samples/images/paris.jpg b/test/samples/images/paris.jpg deleted file mode 100644 index 8fb3d839f000f22fba8980312c8fc5b45ee89f9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8498942 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ð0-+_1xFD_~t ztdlfux3FD*_aV(%`m#@XgnLemeJFDszI`hLgUlw;2_g*Cw6sm zQ{Il~9Nz50S=nC^`57EN&}MEtf-T(tcu8c_cE^W829G$n)iV%oKp;Rp)L7tEo34Gking8#@_tG~Qr6vJEjUm60% zD;TJp*=~G7fvf(}(jQ@t=oYq_!=W z>tF_8dBB(rs_ z_X6psM{lYGDPg0%6mNQx2H;^@z$Sp3Bhl<;s=eGt$t+m8pVm*yeNxxDN)(LifO*yF zzA?Z0Q4a0u6S`hJVSu1Js9aWgVJ(*`=6^s5=pQ%r+Z!S)DV`1YNhZrp}729Sbu$!kupdRLCsIvycIF1WEIf zIGtQVO?`<)P|i2~0)W-HG(#Fm1bE?s&#V5cy&4HHC&PUO(`JK9iX5PT+FPf>!AD9W zJymB=v&R(orKN{8Qt13ZzmDtqs+`>^j2an|;L&x=Wzl`_Xd^6CC#uS+(8FbE%ZQaD zv{>W!*K+a1W_S27Wczm9daRR_RwxnkyWpgwf@)zC)YQ1A7`xcS0wVH@^T$m zKX==)6#tHEqd~JZTo1P^cp-gnb~Bwb9Ta$9$bO#I~H|}9`Cew zIeChY;ANLg@AX_!O7J>_d3kaL3@|&h7F2hU*Sgn7q~#qlEI+d-GjnNVx*#di=;*j= z{5UJJjq0wmfPe>k;*K4)C|%}}I*Y_SYh?R60Asrv5wwAm^& z!T&&L+nwG0el_M*<4=+aADqit@B6lT*-h`h&VfXzUMxu88Zx{Ep;c49$(bUPG1n$R z*dl3aUXjx`Ht2Qr)NzC}xFO8L|Zw>Wo%yNy`o2loge;XG;gOT**`C$yGuU!eDKsq zLbKNo#H84s;EN-q_Ah5kzh2wIMK#>l~Bb@9uVHqD^j6R1W{QmdH-8bXiiKCye1)|T!?H8@(OeqAW+Vpd`pu+qH+Y8 z)c=7@BAr=TfrBe$GO^APH>B^kX93#B!~rISp9jjEmA1PofsWFRw8Hb-&;dZl5I|WH zF@y_S*Sg#GdW5S;R@3J00eW1-xQX~j4DbET@*FR9Ra zVk|JAiv6*k%gI${J(f;O484r7nq9 z+H%(s^^GB({NAkjqUTea=sM8L@iMFZsuC%2FDh5j*1}Kn9a81mU-t$brV;pnZwLTr zC&lncYv0Bo7A>yc3;fZWMTVTv9PdvJjEDkK-UhCyD=8R=OHlj$Fus9a?G3uvINwm& z8YzWge9zDyNT7z=wgYQiMGA?caVWWpFuW4Ex__$B=cH={X~1}>x_3v8Y)9q4w90(3 z`rKHQ-YD5zAXBf@(@x-6Eu*WrQ`Eoe5-2b+=t`!si(rHm&ePT=V}NR}<1fweI*ZOh zy2IjDwRNOtOmY4v{zGs}VB8`Q2Fb?b#pmTJIGX~|kBTcRhdhp{7TpLbLeqXX7S_v^ zARfY`GxEO3QEAA#QJnVFluLr$i^@vFOF;f2=UZM}B07cIHK%YbwWj_=qTSuSOOgls z17V-xHG{3^Jr&?Q5kAET=rO!@wmXc+AZzO8_0r<7iNp@x*^zh447u3Nkh9c*-|JL* z>>^N0#lgH#nO6T(djgmM;L_+nz_K)G8NVOw7gnT7&bwjJQsnbTdgRg@V-nsZed)*n zyT!8sXHVXHhXheg4$aYQS{#;@TM$oM(42SFsQrQRL7bZ*xTy9&kBC|MRW4veUUVQ=YPBr>PSRCKU0#U}^>0GGObG5*78=m) zvOl3&t6ZJ7zHty?H0feDSz{l5Z<30(L)Du^2F3_?^Yjh5D}=M`{H7VKxKyO^nKZm0 z`5mKf(SwaJLxMCE?+lfCMf)*GCK)U8eB1Y})?Z8RVyG%>$f#zbpSAKzNKfJH_Tw_p zHajE?>qDCmr%St=2y8ezRsW*zF_R_OgsKf+hKbqP*6VF6C3$&~pRIVV(NIDr_&~BE zJ0@B(D3^{?mfXWDk`?M7Sj({Mvsyuuu`YYqK>f@WPucZMN7T?@rCx#}U+A(02n#?+ zAR;!m5&tD6#vWvHl;+_WDoid4T2w{C&J)yRQ9&l+F;-^5V7*u1j&TgQ|IM~b1*0}{ ziJD(yt&Edq2I0)*BlBI7%f4pj*&`O8G$K|!NDScLvpvkg`76cLx}4W84{(-yEwt^gR-6bBpharW0_u`~ zwV5quTy;>?uDItRH?KHYEmHp=7qr4XtQGnDeNFg_yT;cu<@-S*d16L~(ek2HK=R6g zUC*7D0z&EW(7+(^#(b=pZObJNk>F^L?I>zhlZlst6~=AadKsm<$H|Ce1o>P+SQss++S zP6=iP-wV=jO_ps7_f=8-1>Iv9nJWWH691o*n-`yNuQ<}u)7U?{_&Nk=&&sWG_S_M! zt<3EPzHav{sUxrUqLjKukQMx26J<)7R}{3KuQcK^O8j>ggVstn3)zsr7Egnc4|$cu zw4ZO$9in{&=J^32sj?eH38nN@9ZuxccXj*Yz#2AWR8sttioFp>TDk#vOt<^oRjYf!8C@G?S00g z0Fwx79NjJIkHxNbdk8guE63ldBKrJFuoo-R)Q^irloj!)5VUB^t#>f~FK5P(_>ThA zOUQOrcijQXz5>J>}uW;avcgoh9KBbBgVK_n=%=BjV_Ay*S=-0m`_PE;`LKelJqDYbiGvx$DrC0Xi&^aH-B(M$GkH~9 z86cef3dM`H326Y<_#Y_29_De{3yJdPCDa1+y07v5E^XRSj9Tzxv3iT6LGF&5XhdZt zS5vKVTEs|m zDKUuVQR6wXoa9RMex4fwhsE9&l8a=};sLTLfDJGwhV#f&$*S)wR6{p-UL4B=S{)YFm-{uq8h(*EO@bZ)LrRMb_`Y{tn^m#&x6luFawG~p z87*od*1W_o1?t5ZcGW*M33r6#!jRn?dC8qVO6?3ey6EV_E44q$jwbb33NiWKqNLAf#wm=vyh_LsB7|)N8h!cTw8Yfm8sPBX3W)}PT1+D z-11Hb!UFy1F^XyKL0Qy$YbGaw7rqT&!KgjEUUy@bn8p==gVrS^v(xikdH!YlrP5k~ z`_Jthhhb)29`oAf4CuI9F->Zp2lLcsc~2m&)i+#nqr5Aa6ziHjYnc*upJfE{ZfRp;KZ#+uM%dA;b5nvS>vGT}M145fb!d#snZoATFZ2H~dWuS;d^d-x-X4G{@ zz_3Dbn+My_52gLg0*llyNa%#Fbm^}zW%_8(xh;m_sxK?%RCjsgZR@cGs{s1RiQ4BIdWIFUX1#o@^a}0T0XVg1 zQNlGWx8CKyF(E-vETZ#l_&BEbbfmGw6=kXs8gKYEP!V@t^z1WQtX3-Y*|Hglj7QKM zsa{a1LaXPH+VdTkCnks=aRh&r@V*?BQq z{^o(06NZL0F_9ceI@-AVUlNtHWP=^T`5(xB-gUW^9Z(uYhYI70@Ey z|A?C??eNj0U9c1IgrEk(<>rHfRtkavq-BwkAx$#I);=l}ol#FXcKG+@vEQ=XJmEj-USOY-D*-N&n`S6;ahU&XNWUWUoDb zY1%((=-{g!4-+czb1v+~Mvxy_?W7or)(k!5k-nAqcS(522*{_f&nLcfG5BL#scPuA z-JL5>zr=Lx7t#fZ*!ZL6Huw@g=ul6@a*=RW-G?m73hxa>kf*;b7>y)DpNf2&wfm$( z8kE=iE0OXy3pfBe4KJGuUAEk)#$0^`b8VP2Y1O$SU_~KdR5hJlC9LD@_!^j3gyI+8cV8ZeXI6xm?HJO-EnHWOa&BpMtHekratgwl#Xgcr+9H8Ci59Ytx z%&n+asJ#j`dSvm5}~B|jC8L@UlYm)8Ck9Gdmyq-2xLG~DHD3-JAj2>}s$3qadjH|(?BaDAsx>X#AA zfI1bIJn09pJ7;K4mXzu?qVe#10A;|glWBm^<_)diqb)SWnQST-I@=o)P@84xfy2?*SWy;);K!mn!JDHl=9#sV9>dLWo9hboa~ z1az`qpY33*kf*KgSUN%jT3Ze}8Zo$>*Crn6*f`%im({x0+OHgRMBbf5fl!&&_oF?E zV@-+>^W6VHHsk|Why04Kg89=VIAUVdtro!&@({9R$6-T9y@dlgzUfl|VZw)AsID-bX&#w)BaI}dr zp>yNByY5ow03<^h_&Pw1l12T+jo&~ zuv44;BZj4enyRI1BEcVDiGsf*X!i;2UZB`sJPeNE{{rRGCBQSyCo(nl8ae}Ls>Cy! zJ}UZR!}RF0A86n-go^)8j0bIIAiCW$E6@o*4_*ZD(8WI(#!9?U!Q;64UTH2*#s_Yle70+YG9A!9~WFT&>D3B$g*k_-NpEAuSan^Gn z^c(7np69z~=vuPT2caLl3NvQGGOvf1*`c%;tRQy}GVeY5|6aOKjkwK=1(ic{uHZh; z$hA%Fxmu90P052q;AE@y0k37c9A zcReEP=6}9`J)7GBuLTXq6w{CoApz2gHa3l*wJ_DW_?<`widx=dh{W|t#nti$GF>u> zD1tW7NbYJM!5=2=+1Tkz%8J?NBVBfj*S$#6i^8UKH7-*MQ>6oQi4dzzcg?3*^;8fE zT033;N#5+!C;9o6WXserCtb0Y;+|1Mh9-t~hlJl}+MK@s|0~(q9x_P{c1&E@tsszM13Tu#) zE4y@MN0Q5mM5)LXlNm!0w37L4RuU~d;E`iZ& zi8p75#?T6J#jlqve_O=FH3Aj43XT6&Gv42P}G9+ptp^ApG`<}4DfmcC}wu- zImUb{2h_;S+r=-IY5tSBRDHFZ(4HvJe|Y~M4iR~}J5jZr#YK%9E7f7mxSWYx>{Wnc zB6kNy46fDjr0b-!jdtXLXy=VpR1R~@+e09obH9TrEEBe6#L#7Q zu}p%euGIR)of&EsH*xuu;&zWN?bxCT+NNB|mFG$Y&2HfhZM01VIZh0JcP9g`WJo#E z)$?IKK@DbAB%E-p$Z@JJ0g`CTMZa%@oU(mVupbZiq}{zI_#<9OT@$X7IaA(tZJ2!y zQ_r_$lj^U3i1}@cs0Oo$`E`L}hCt+Vs?qO!n2E3IiJSUwlsJ|b!;ov4T8qLut5C*U zc?s1_o06x`Xl5Off0SqKPr8{#Nq+7xIZIHPH*RZraBx=O=gPjRrPj_8dq?{1h?D@1 z{~(XM!(x)nj@RbUPjr$IhN+_YfG#37PXeSw(Bf5p=)#H^JnV0HrV)O3GKU~79%+E+ zlA#VC40?-3^u~^ZC>jj==eB^$ zh}M(&RPt4ONCE1P0OTTvVeN>a!Ux&qr=i<;2c}+;$ogfZ9T2-MErn98It6^VInI9i zQ0X$ekF^eZO`?|@IP%SW227OwwVrQZy&2^Pl@y#y*sfnY(l{8vKP-pIC@a0GrDXyw zHTDDH7`x+FaHwb5>EO2l#Gs9);-Ek_7mE>wwG#iIkw&`ZNr81wtf-#|yr2TptLLP| zbWuJAM#oLPf3eE9gEn%X8>%$l+U(n!;|pBP#wK>{PjJr2SlEWv()e5V>unI2OQH-Z z715l-Y^oa#cz&pFd{xfVfR_p0VcRZULf2@dw2zZ!l$}m|;{X)s< zZCPz>{%%NsyxdtbbZ7E#Z)gLW^rFtV6PMvwU4nE^6GWE{8y6;!{kA=`&qzb z@I1D#6uQ}Q*YQ%{ZVS~%Iu+IsfNnWTIOu5~53@6XPT;_8_Yd^(-4R0NcR{VQ zjO&)lAX(QJ+xQRE5tX9rhMa;`%p|X2*9C)?C}))t$?7KIRz*}xoZU1lF&Ap6Z0{Xq zR_T|mn(0a{aUWxmm3S=LiQp*v6dgeZeodby-z3hU@BJcJJvOKqKf#exo$kX^Lc6lW zJ+esnA53oD9)a`Y_iS`5*d=uDC>(EyODRh0qx#~}kqld7H=7;}Z3+-67{(E@Yb@ms zbpo=mBJp@lXlZ{h?o?BaHr>#&qF7bJNR>qR2NJBk9BFDJ;m{7*Q8YgF7%33FFtQiy zNvpb@G~f0ktWobXXYFiQD@Xd$~5`%JG_GjzCbk_&=a>mT{gS-Os<;8%sve$5rgL~$>oqF@Q z4Cf%cI}gO|dDvx4=&@LPok6ycBctdq6i@g87uQDI?Fz ztw^|WMJR~UIaeyiVU%-){-VfOvW`hoP{Iy-Nb34+WG4~$;{GMD-NBbqky2~m%9r^V zGcpVWzD~*sXWhwh9p6$H(D2_u?f(N!Jt+TGYp{|$$MqNhT?t0+%F`S)p2(0N`3Xsq zOQ8=Uqz5X22bHxhSb7T>bOVe|KNHRw>Rb@x>AkCXLNVw(3+PtnkeW@@?{guMxS&I9So+#MObM52bz8aFAJ-zK7h)b{R4e7A-`wip;{5z zi^6`$j(VM!`~w-B=&$@ntc9BGv$nvF?mGPL_4IHE?A7P6`&KOkg=~>PCBW=!UNrjT z$Bb8iS%LvChnyQUSSuPG%s!&Y?4D`T_{uq_N3BdT!2oSOjVoCzrsc#aP1F=3)rSyz z+~Y^c;Kf``^Kcq$)=ISNqeJh27f92(Mr^XcQR(ows!M0vFw;np8iX^k=bF|}Z5tI| zNr?n-mph|2T-{=>tU~!|*b#MoYvGWNO!4%a-I0Oc&p8$!*=RI0Hq~Vgano|ta{LT* z*diCDCvcfaCeIGG=hMg=g1z8{pF51U#<%m~-ic)Q*~<_nF0xbiT0sPvEq#1DEh3>Y zEGulR-N&*HXnXZ*fWS!?>m?p8M#-KV_IAri7(~1AR9hG}5Y#tkbDsuh_rqeHND9-y zHlD0sHfFNyU-8YFoLPUubd`fW#P@$;IZ`LYHE29&i+PAI~ zqfxq9HQq0L^y{XIyH(`T3Ejtoxvy0-gP>CB(OiUfs_8Sg1Zz{WhYg0mIB4D9a5d?< zw>bfbZcecrZ1fB4{fX>425Fs&cAB#X=e@;nhm7S5^T3`gNq9UcduUR2o!I4Y^$ zw=S1zS5e7HX9rPjY0s7WSgF96>kEJEtKgoQgJ4wg@f3jK%0mUM`H@^u4q@xpE?)1+ zJ(VdI=0H}^!_F&XzKWlty9x|G>x}8QA#!sgyd{9$urk;Ppnaw@Wv@CC`4&((V}U z|F}Bqx2E6s{f`cjMnFbxzzC60ItPqyMkpvL2HhZC5@T#M3Zq6N0wN)(l#Eai0j0x% zgmm}o^L&4Q{2m8?0mpOqeP7pko{ux#c!@{dz;j@}GDxh$VI^5|IiiPKB2*X;O=Y^R zn;)}(3&WIScb(37CcJ!@PHYq`$b9K^WN#p`sH^>0P-kXmtavR$>*v0iI;_I)G{Z;1 zGH^F?MunMN=WnaTz*15w5qYFZ(hqO#KfvYliLKsY=0`ulQm*|`XT8-wyH~%f)9;1G zY98uAD^*Kmn6*Y@#T4E7k-qIToelsB=06Zy=aLkxLV{IH^~qt5i?&Uv(AJD?&Hxz! zF@Ec_ZRz1LGiw{EpmUpx`bF+yuo#X+?RdRkB_np~);{%=%UuCNL$-F-m!WeNP-%i{ zWQ#FK}+6tZ^dL4qoT40<;-;a2BUn;e{BV^EA^CO%ifr;uA zD2n$ie12DwoOts&EDW^rW_o8cEAB;`?YLi$8|a8@3fKljHq~YdKX_*LJ8-e`0(%5!If)04phG?Kt76AK-M7Jf*6c;5!_*z{pf=I1#diY(Yd4;81XNJh^hV@s zWc;=`!|J4&qAn~Ol&j>Ioq3NF>(52Fgk9KM6EY6|ICRt|NE@&l+tiS4&Gab{cE&bg zDLd7=Cx(4yo#}#B(`?}iHxvYeY9qbqq(<@&A5yQ-@6AD9FH5uPPtGQ@?QU1roF(Fe zPl*s>sk=+%93RbxI-RGNe`Da*euK-UB5LVc`3YnkUAz&hp&3KQP;!1j_k~35*}6AD zS`2?7VAmUZ1I7vG$yAI1y+vd^A4(Dw{VC1e3wHfw=yM*tcXfUz zF2LmD*wyFvKPebX&c8Q<@3x2LXA=)m5&wZytTVl9`xfUdOK$H&+&BHFS@z51MU59P z!nUb~L(Bg@$QTLIDyzFAkiZpbwJLS-z^FrLY!MXf8K;$#56p-;@;wGD9)~}X(&9!t z%PyaTM~>Go-`k0hkCz_hkTXEMp53V1XQk-Qz`Q+{-&btvzee8p`%ENf@9EEW9+@B553-AIow>QR|GOl{`{3tgJ)U`du3BJ zd~~^Bh#h~Ueye(0tA;t_wl6ebo^2)4Y(e#RfXNP#ms?a<3CCn))-oqt>$6_k=W_g> zDQdw}ZD{OghA(ez?E^u(8a=M&o_tn2Xb6#avQUj%fJqjMD06f{DJZ4TNlVZ_yp*G( z^x5qpXj`#*0+S5Z1t97E(F4I62H)0uC_EAEaLGVr;PBk6#>*8PYDS8+?>>YRe%gs- zrk>4*fm9!MZpaBgTY*((eNxlgfE>=ekhHSM4RU*)wxO_V!mYmeQbcb_&d5C3mK2I* zlpaihln0Yb@mrn_Gw7wNj2j12$czK_Oz}h&l{c*IF3emrkk#}Bvg?8eFH99Kg{Fi& zrkM5CMM1X>#gwFGah;S19kQ!)%zbOyi)(?GvI1HWJn)F44de2+rc)y<3sY06CD3d2Ke5BEG+5M3bHFW!3Je-tOKj!FF7rXhTESKTSX6SR>I0}r!;#a23bM(*|YUZ=Rh*%*|(X1QM z$WQGQ_(Ug+;@fD$m7qcRCDWLh$tY`jp9Tztt*x%BMpn?xdN38ngr$Aawk!aDWgDKz zYHmZi91p(Y2=MknUHXPPZ{+*3r^vhv)Zx7Bl(tbWX7%mi7$TzlCk8dEEoHqFI;U#~ z+lP29&ds&2F`s<^Dhm`savN3VoJ7iR&JA6%Tz)xv+NFHye=i@x`q@r8idoGJ8Oui2 zxBEHdf|pxf_wE~p>)WC3Yt)k()Uw&~&gTrXzB=$EQKbhkD>-Hnqd`3Pel6UBx z`#OOn7^UASTr3ldn=~_vou_+XtzL#P>NW?3?q2Q0ll3kA@iR(hcPn_xz6E z%1l0dp5nIl#VT6FfvBWC>1?CJv_??nk8r2vX3!2rlGuJ-aN0&jx(gHcc z7&tBtXRB@sT9(p$({c98Q6N!;C%&g(2(Z|Hq|Cl_D+o<^? zKf`C{Q_?EhD5ln06gwG3cvV`yzrRa#tWJ1*zHcDzx#Y-{n~3dmAz16 z(0j=WTMo84%p@W}o-b_sf~dl|R{ZzWLQ%ABy%;6?Ta?YEldF^>eDLkHgYs%MbG^#1 zw}^cZtpU?(8=|Oy(W2-rC&A8T*@%eAizBP3dv*2ccO($@qYc)lsPoeOvBiFSpBMz- z2&gb?ub}lV%CY2a6dl_)nyos!=GtRpM{w`IvxU)WrZ@4K zCilLlF!UX&U-dCNSWUZ1n0dM-H~wwY#oO9j$&v!pST#!&UJND}Q}8hIgqSJe_h0@J z$>LHip^GBPIC2S@JLWqIyRS5mj&mlA=92BOJ)tI%V24IR` z8pMHYE<`PKqf^TLVpYcYNMHoCr z;)49fbI-hZVQab0(25s+rd}~iFBAJCAqIPY(CPI#Bt#%s!4aaV>?_HoE9`ByYZ801F(lRE%jRa% z5|dlrN|Q*bOv*aI8qBZ0LKz0sCCFqv#mQmMr&Oi=@Ll(fssppbt`Lq5wjeOC0O`wBmi z)*v?bMiP$4q09M&+42gIifJ7h8-6Q>*Hn{Iks( zbsli-ujH@7R5J6y@T+51(_bd2AwU->8iir}5SLk8DFjQ`Jxlb0g#MLPmv^ejkL@H6 zUX#0FzRCAM;x=~*%gZ7CxOiz29{c(mVd=`zV>tpZURK=^6fa_<@{I>*`)q-c7QBU@ z6>A`!R-9ZJ=N5g%@OH*U8OCBH{KB?mL}3J1m6QI=_9hARwel+x70JiU`u*|y#z8S1 zOC2C(Hx>P{Ze|5NQ9hnhQ5|p?Vv#II{7Yqm+6oZ@q!%VzZZD}&Y*{kK)R+He$eEu9 z?atVK);T=w62^~hO0D^Qo(&c6=jNnue z(OxCzVnZ{ynFu0v?vR(rLGbz?YN)MI^JQ4 zw{(Mjqg*hTz0AHYOC(!9tI=2IpgFcTTnV}#tyB{%*op8F(8X{LVMrh zfmtkq_gT(UDz2z&Ot-N*VTRkzB~ZbV=iHDjV9eFUS7l7G@)4)lnwC$` zkd2*$F;LIhmN&S&-n|+ngHT&j%)_R~kB}fltC#Pr^UvzDlebD|U1Jtn7I2Eq0<6`a zI`>Q2kj5KBg>X|#>FC@ANFT6URHZWS``%HF4s!Xq&-i_%Y+)FAv+BlNbi&R=gwR^uZ|$7L=|!1MLNct9hCwrQjY`mD_9At-AwVM(Vux^U;0!JEPH zXZ84dAL#1V@P+2`e+x9ICXL5#OLalhl#d=EVrq3JRL3p#pm5=NHh5w;isUvUTmhWL z+k$M4s%1qtgjZgaK9l_-wjG3`+f#wYj(xbV=GnjwM%83bQ#Dux6 zZjEx<$(!YN(a?={(E+^?xLhi!{*H{{tvV@G$VlN8_dDV0#HRb2JM32Yd47*-N80zw z$xy*CDaYXng+Aq@GBQm9zg4J14>s&==BS!|3JTM<_*HxsO0JO z43F4_swBSiSE>UN5hPirU9>$I972W{AVG#zzWa;mt+i~at|hDH?rr5tkvf}Jfbe?e zWWFqRzfM_wYhJrp@zIXYih8Kf+ZD1BVKPZFN_lL4Rx_>e*H&{YY>5o+(c)guP@Ubn1#73uHv21q^Evcm%{--eiWbD^2V{4fU~olPM|GSH{k9K2#3ex0Je z&6rIoyJX1Bl11zXY*R%Wa`!|Y!2g@L3e~6PZ*~$wVL6@8P~oNCJfkQ#z?|B*{z|mb zp{6gqbNfzHl{wUj^7k{gU;>Iq`N%c9G^C6(+tw*5E>UV@Gc}08v^j{~fXsO(npcYm9`d%yQnAD^@r6BrO~EcGe_-^tYv1ASg6QVZ-Xx zV_JUaEKXe5#h`$yZ1Y2jI9a66NFnsRs8ABs`w>lp2H#hdd`qQ z%1Zx?;#Nb6XIK_9qpikeXJPBr$V_R|Y>*MsKMM3vI!`%skz;_!`#<6BTli};WucHH zu@7>tn$U*mp*}8HEknF2&B1CFunJ%GAy0)q4QeyB5|1CeKpXhh6lQb*j8Sp(xYt@E zB7miZD%1F(8zr3jsGu1@BV5O*hMcZV&u_@FMlYK_yyUy>WrXUPOEY*5>3@rRzQF3g=S(bq-(@G;ikB4Xg@b+tc9ck`w5fEMYou*-~* zlM(a#S{7mZ?MZ&r&o~4y)vWMNcjK_=7NxZ7-e|4m`8NiP4K*;2MhU%)pO9J8U1Mc> zT&Df+!SA=LE5ovt`1&>@51L(_u>=f*@tYED@r;)#(&s4>KXL_WkS8EDPm~a>JX^@r zyVxd*NLIeyvS=J;qKI6s)(zHNSEKJb$6U<_RqpjE@&Wh!Fp%*1{tX8sc2 zMHR2SHyRg>z`tvln62(eo++{7%6dqC9u-kXO&BpwEYr+LI+0fG#7kfMF$X5G9Jz6j zudZIjy*5Ony6yf-qgZpa$RnD2IIcS-m#+@?#%vLwI_oz)CQp9#L{tf-YQ#gvJQsBlmd-F!iPO~1x@R=ILAx>*YCHOLZZS|#m*kPGpfABs zk8o#XVDA^D)kA|6jkS;Bb}E@Ksy~X{>%OCaR)l3t)74hxvCM5T6}AB`Q^G<1@9hsC zc9$Cy;YB~c-*n1zesxnZ&B%F%aHf0Ebfy%l;5)n4PjQdK-T8#^ol;;yiOnCZQ_7h3 z^sFmh{$x{a4DC~>;uP|e*~9&ojvcvTiqSp43r1G2aeD+2yGgZmjSIy#Dt@fY|1lp8 zEo-7X_bwkdxB0#v^;g!tpffDC6GE(z{?TZ0KYorBw>~3b{|(E>M}e@%-&L#1OcPE6 z2NYz;T~&W$V%&x|R(T|lQM(3k8FL#i=CAt49`8l}@+*^gK6rFm+C|E=86$|O)gu5m>Q=0kYHOQW1%F5;?@5{lxp1y9!*}|^-%+G6 z6QI0bR6|vnbzi_r9BeZgS+j(}`61I^)I3w`1Sv=7tb#V=C#8#=IIU-cyJHOU*v}i# zR6D=WN{M1>u&qVWlJuNb=e&&Tfvk8@ z$!@r%0>}-EZi>G7y!MBlxq*GVKR^@Fx;Y+sC z>ckmhAJvVM^%!m8%&7G9SM*Fem8WE&mzH#qVSA(G6jI{`uxwy@MI}31#Bt?CZH*S~MboPL%_335uFHE)p zRw`Vv)W{t1O;2R)^JOK-!UShg2-KNO^3te~6i zMyn@PeeN2wyJQ^ftwB_aD4S-SqL4SA4P1I;68IGoWy((EC-ffxO$L8HCkM6)2iHJQ ziaG8PQ9A{w@54W+0ISYUqM^$n0?eF^li^`R?X_V*vDJ%s-rp zl9Lotshji%p6nwh8^PUme}H1B<>eTYyP4$MMgvQk4Bl42uxX`^Tu~NEf_4SvCMgKA zGB%K2vfVi5(bzC$Q<>d=^8}M%x*_x7)!P*zs>}OtHY0aNqh4=8Z8=2q$ciodeD>N0 z-J*}L=XB*wo;HW&AQ9&9Hfyqsc6sb8bjaf`T8jL_qrnG#Upr@SklHNDasyr}nS+B7 z!v~>7vvJW`2>slsd6gNLy{x_+G9oTLV5w?Zh6UzoTEkL$&(S1`o-)!82oJZgEmfIb zhQ`}B4))Bn^Js>UhY`_*&tGVTra-GXUePXf$6a=RIqUCKYX#QfDUGcD=7hGWEc7;; zEGG%ynP_1Juj9CD71^L7BCBkMf4KWN@^#?WTQ}9Z!eqA!N}5 z`+m6B$&%R??RP<>4b4_o-ltv^I@^luNb)j2D1mCV`z z5kWS8Z`P!#G}XDHCO6(EK))RlpESH;%TOj-R%gq}W?JN`M8<5BI_cCKxe;3H%;#I- zo~&d1v)x@(T6aZ{RI;NI(%%Vq7N*-f!8Lcx6SX3KSl*KF(j1Q9P8&he$l~=U9e8Nm z>2Q+YPx^rlALDpBPmb*AuZi-jQD45y04Dgkd^jKT&*%i|;qV^p$Tszw1QuDW!@&^0 z7t@K8*;P1OEfp<_6F;}Syy7>qv#X=g4b{q{>U`v_ z#{uFAFTFVQP`7aJ*zP*(QZUsc%K)5%pr~^FGv|JzmjAgnflA>=9*AoG z`L_~NW;244KK)l34cA_+8$I^=0xaMkppr1D5COiG=B(-2X4RhSFUR?6SJlFDA3but ztliVi5UijMrs2M;^So+yde+d2pIOPf&{Xe>HpO|PCSlRcs%TB91)reV|buf76kFFc`qIJw2_j1 zC#~?B^UE1I2>ws&8*RMy93vHssS|s8MdhXTZ!Au@uP)U4Qa*lRK37FsqBF90#$h1gqOWNVx}OnjFhX@aA|n^(74o zZ`&@g+jWP3@(XHaLubDCA_26h#9H#`1j)|G=FsQrx_Z$SlPk-vgxtM!U1BU?JAQmE zbArD`E8@bNFT34k3qpCmmX@d0nGHKs2Z-kBPMWczOOM9~>mEq=Ftqcixd-sk)cvdu zO)$wyS9=~$SBIqT@fxNU9#KDD(DDcn+@0ud14$hk3vepgavTtcm7R^JwG z>&JeSLz2VmYMXw**yJl#;xS+4A&p@V1aS!3q>t3^M>+!>=L#>R0>1i5YBK+2xn)u? z-3BqvFwD7Nfny`(jj?s^fu8lB=E^5|KTRxL-la}~F7#W{6#CZ_X-%ZlCnbbmc;&Ko z`QJG&cfYWG2>eUDc-QW0mS9Zm%^I!Awvv)=w#7XS|7y}Q5yEioh*J!lGFe3re0&)9 z;;bmg6^Sf0ep@yZkgxZ?l@wTZktbbN{B;TR81eVs=}fJcDzJ& zqY87VH{b9H+Z02=Hy{vyEIbXHXr(%j;#F0|*3t_63D%o$!-5hJPL;usjKc8>VZd!M z!7}Qu*>OnyI1P4-qcF_bbDUE^0cw}gM8~Xl5EU7Lb$*fg$C|ABo>fAmZ-avMz6$f(AOXSvViKUO<7@qpO3>E`Zqq49E_k7@A3KV#Mxjz zR?E0onpcVDn8UFjb&`0~O~7b{Q-V=bWtYCzm)z0b4mO=YPKSDr8PVzn9*#3Gu%D?P ztut#HHKx9<;v&WJ{C;d^yod$G%j|wONmGFbiyC}R`ojVB_2s9S3B7rSidWwDN(042 zdd75alsVG?PN$+uTNcr;D^CP7ceI#s)EDtY@Y#s^$-NsE_v^SVw%Y;^80@`mv=i^tA$)3PMVqB4v zniR5e5fwwYEZrKns;D;laN{iXHfl9H4VwK}8GA6Es_a`FY5B07mDZ%4BZ+#t7pDt= zs}+kk-#m1dar`8w9-i*z%>8*OnpnuK&#HaD|G+hxV;+UnAk-32*=oQ@2%`pDxW97j za%3S_@U*4ovF25CKN1U}rDD$Lh>NhRgP2m$kx6gwB{4*WN^QK_!0rUhLIzSl#b>ru zK3rb*_SqY6qGee_C%~mRuv3H4{2cH~hDHG@4prk&b_SRAKREenZv(=R#Kd2fINqQe zyFO77igo{lC+wy_O~bgE_`lP71{RW%vW z{ct}f8*(#G0*A4mL82$17qP*s3efO#6xxh5O^{Z@J{$Z zUAUy*YUpVmk1*CydU*XwcDxQl^yiY@nl7b#d{pI^4>;9S6+@Tg`2lLC+S0juGG13d zx97baIWKVOV0F7ydObOF=-MdCth|gmiPSn7I1b#a638eFUF53r*vPp@t3)z=xtm0~^k=K+SBh=J39@oEbvFF4jO0%v>eIaB(ww9IBgpgKVjpC=X8%MO3sjOGLt} zVT3%fR8vo++-G0XIjb1o+s$YAH0Pv=2TIDG|!w8&JThIQF#WV^ms_RYu-W0 z2-^y4E|K2&q=Mwk2QYqH0Ziwf^2<^fFWn}gAj(^6#aoBl;$UuEzvdND+JpZR{JvU9bBAUo!=sa;a9QUMkeyFMdmHG;|DPdm9c}{CY);ATyL79SRG;q%wEi` zJ11Hck+TCZp)r}4+)uA&b0vTS4z6enE zqV4#$A~m38Ojr!)SmE7EDW-CAsGn@F)DE|CZNPP8DU1!!M zG9o9J^^s;0zR0%M*I=!9hHpx4CHwL73(K&m@UAdFbnbUY-C5sxfXieRaP&)xDmUqy=2p!YhY{{Pd(JnWqI1a z9O*b>+rB=y-D%-urfk-{*}&h1JdVCn0D}WWF!H;x4%8JXV@Ab+UP$+ZxuLMM`m2u) zA?k}*t?eu&o2CfX&CY(_@u|}hi`REPu*2i|bTY}EB)`%0k^To-dAzV%4kn))1*+qR ze@I2O^6~zQY+Da!A}_hEt8qfX?`@s-f>fU4e{%~uepn?lI`*Rxf~eN{d}U5Hn$kYQ^GY(SW7v#7k7X0oS~`hW4HGont~L(lhMw9tFgp1_ zWyMCpSZWos2p=Dg;p|K61;7TQR@Z?g1pgAyJIRP00T69#oj$%?Y|n(>k;NE$R}|Ls z?S^JJ$2f0h#xj9Wyz*d&)fk5B0+P9B1npf>#OMHIIqY2@Xx+Dfyhs^Dy3B*n5KcGI zWj%aTQDLqJX2xd}LIcEjO8s<@;B;yHl7_ZZnXw$Ds(vg`Rp-uFbENxK${vOAoth`y zJn4GO&9gk7*?Xo$4MNibB?}mmKEFM56ndRtS@j-;e&|LPv<`Ai0xXd<7eeQ;twhyj zPC72t1+=o;&Uo$mQ`)DMk1gaWx~Mq8Ap@!*YMy{sGnr+SZ)Vt+EvkE)3z-m@@VH@Q zrYh4PW!=fI3v#6OgEb&OE z=qwhnGqwpR5v-bAp`W<@_Ru~st{)*LOMJzEs`(to5Jg2+TgNFnZa(%@muWnRX_SF`z&IWODAxkqm zsa~q@bYN7yvQLSsQLBCuyg!vihi{mzt~MJ-+wh_pRHe|hp2T<>(2-&Nsul91!8-3x9H7JcU@YX%vj?dH#|GtkJVKxroTgqo>AA!V8$JW}{75msmp+ z)NKn2*vHL>LBp14zg^nXji%&Ye_ZM1*R+=qElc@n1DSW-c_XdZ16<9^nrMmmY&i-d z#I5=MBWq8;_0`T*fJZs*wQQbMk$J|t#duR>63$4i+UvF63C5{Xaa#(E&t!a6UM0U} zZUgJ@N8Vg?Y}*k2U`+5XaL8>VMs9#GDs2{hKfgp2`Gs2+?c>Zn!zZU%F&&hg@^iqZ zVuN`>ThdqAkg`*rcog2euN*uw9C=3aL8SzbMcBC9f+(r;C{O`txSg@+rzX@%!d~BJ zT6x&THHHdN^r(A5noqx2(;+jrM?U2{te)HZ91ziocy_qq^`%#&G)D&0qV0)vksG2bmtrn3z zqIJ>D7)AwZo%RkfD%0CbE7&jk&@l-@`nJ$F7|vwcmO;vc>$& ztvcoVO7M|3hsd<-*}OFwPMQjEPW332{k5i{Fsy-O)62p7NFZwOqxZ&Z$thS0p7E?@ zjmDvh`@CaArOtpWomi!S?@ZBWs{f|$&P|}A$h|r~CG^Ssz$CH;%Am-J`IOUeTnGY) zu)&i;)_dFdC_y`%BN^wmIx}T%CC{mo>?GD^Q&*(z*c`Y+h-&U(SLc#S@tjM7=}0F| zYXwX3wLnY-W-=ZA|G6ij>s4&bA0-9QxnPi0-pS!9+v z=nIkORpAOPn~)psC0%GaA^Zmds%NM~ zQY|BBDuNdGcYgeoIVyh{?UzdLM2<}ndhK_}V}>9QcE zlbuCI;TQ!{*6-oXz6Pn%Y^W=-(ll%Pi%P4~k}ksSQt{FNrH82Mt60!v!TM9z<7@qB z2>lwwe^Nio>df6GKn_xpc!3{&pxymMzH@NvM$+RU1yvvnakxanJ}PV<-CUGUiY8@b z__F=DdzF)5GDy$t5zF7nmFe!z{mmd)nt|LuFa~Qb+>mm!*tXts|J^Q#TVAL_n$Vfb5(4b#9+u zJk|2mxkFxONiKwvuI2+N20AR~Cg?)oTRl8n)2DwZS{CiIBO2vtsz4G<1Y|uItdp#` zO?4Ju0gh|dH~zEC)kpPm7&EBr%FBBfUI#45Ect?=hr}tV$9_V)db8df`A>95Ky;^k zXhl0{j3&9ZVB+Nf6qQe&rbNPdfeRJWZ^cWcVjFr)xbm^xvML*$k&$Uf>+KcAdYl2z z8aI7s_KRZ~)gIjd2=rC|Q(`Q0#BLqrC*?Lc$n~~2%1K_e5#`rj!Q9ESZOKt=1yCf+ z0TgeF({e{J@H&r22?>pAd1PygynoIN8McUSm4BQchRgRiOhE}5uj|Rv+pWG3+pW%9 zQQz;WXzEg&fgJX&;p`W&Jje$MB*gt(v|1at2ES;p(<@pd{hx$5kegTAymEhgn@C!l znu=AVXkf+0(`#QA3fZWR9LTI?*b(vySzb}Ot`%?l(35K+#X-J+D|W<~^SkiD9qGi0 z3M`()#ZDfy^l;i*>D2<1SQE4#r3&zjOE=6pM@rX{10$`poIfhdychn|_?c=(MRz{5 zD2SWIuM*xh(bnSU@%!4)KMi~>Dz;2 zMqa6^(yZ@f=G50)!PNzWSe5gf)ur|&Bfk*Ph3{y#xM-JJ8muhCS7t=Rmdv$*T?1!7 zH_f50Ae(r+cSGNP1HXQa1S3Oe>FLN8%I8Pl%?gow(v)eFCe^r}R>n&F)?-t8835Jq z2`*xvx?Q%wsd{w85-j>JMw&!(nPq_U>YPkNPEh_UQ_#T4-}|VnD+Qht$=F38NB5C5 z7(p6Qdh{M+m!uBnb$@A0qUKdkMO>}kDRYePQvKvV3XA)QlNkp(mW;QZ*(o?hOzNRL`9jA*|U7QZ-CI0 zJ-QI-Qv0%%)*Si{Lb8T`#;*ai&PnJ+R)VX#F}>cAV_QHnX-JP z(s%mRCi-_lsu8}SKHYjs|n7#%1b zBZ7XR5QrKY*Z$Ofxi7PtCci7Q=s*7EqmdFsWI0NC(dBdx@Gp3#CYosTR!45w-RyAN zeu$>JF0ge<%(`7$z!WaC#VNe(z%t|vENanj8{+nhU)KDONZ%y;ImCAAmv-kWU8fLx zmw3qDz{aKniMHv>l;jjE%a@(~uK;W#MXkYb0Md0a}d>7fOGTmwgDW*L$#(KWjYvxAP?5cva=fDll z)tdlF;X;>+npQwB2}Cg!yN=~pjB1Zk820tmBZBkYVgO2{P%qrfTmLs6~ZWV9|mA{4mp}|jxRq}j4O~XkgV0>CvheLBISdtAS ztq0}ZuAqv$mT2!-Vucqs>x;>6y82)K-WpQouNaJvP9nq&NFGolW^@c-<|&`X zmAJpPI?>p1^o4-ZxbH)R(*3NcnCTi>co-c~`o5;C(ExY?2vBHzY2>e-n zOf*KrY;0>upP}SV0ld(?{oC`4vFE#|x!N3;A^7RkFfNp5ycy-qxcf4O~P5ize zaclIR(7C_>olM(IejL>pJ@v|sFd}*MSn;Epn|Rr^D~*qmD7GAjxsm3nsQ)5Bo>_a#!gIhK9Zwiobc7su?>kz8X&N$j_?**(PvcZpRS;svN6!?mLV~k zC5ECL@{V*+)T_z7ugAfhY$c#)md@!Nq7)%>4CL6%Im`pAh7A}?)iME{kLiu_=^ief z58xSdlDTUHd4C0yJK(R&gpZeFSBr!v)B_%dk4b#Y-uHy7Nv;zFSn7+lXO)k#w_KuPz~j zrOnL(cf%Ph2|bL~eHVpl_zy&0@OeLaR)NqXLH{Ed8vc>YVK>Jgw%6g|wE6jaV`LJK z^>cw!a*VXhPsArF>3$s6k7w_Tw=&gLM4MUuB?-#^t%|_kB*vN=lGgeFB$*Fy5o|S| zjt3*sNgbDXP9nuOe<}^+TCFc^%C>q&!xz8v}{!X zETJG?FRB{4e(09vlbc?yOjV_HkJR+3)bYM1b^d)m8nH3S~=YW_g1o&*ptr5K3}xS^Cs?!E9p*`I|DdGxQYZp zMI*jsW}BQPa`rHDdz!Nq8+aM{&SZ`ox>+-%n_R~Vj+t}?AEc2V+G8+^c=MP|Ah99< z)rAh$=8AP=I@o~0(U?_hO5HnUD>VsKcLdE(80HA|7|J*~UGHX239c{E5p}Ui_?DIAT2$(H(f-Cf;m8?5y zZR8}%?i8j4x6qk=-f>G4we;{U4S<%w#W$(y{ z+_%)7194xfz|0(}Y!)trDX7(Wt=Bwb@h6W&TEtHWf*N*0VwKKNiaEOy+5 zku^qLU!|G@@ofgnql56Sww*I(1@Cu;aP%oMGVRov4cI}<8EX(MFGo7EndO?aj8&%g zt$F|boMfY*@S?7?ldR~aJYpyYOSZ3`#dT= zQo8%ziAJ_I?)2!EaMz8D#Z?s!SAUJw*a_i~;~HtL5;k(luv!-xqW9H6|JCO?6~Vs? z{4~{5j+1x@tcNE!KI$-r{6qw_C^E3#Y-=p|2dih3#Fxd{m^jpwKL6`@%Rwc#&sLw9 zF#`X~dU4iN|0~JxA=@-g=FAJ)?t*PzeHq>iT*y~vjNhvr`CvC6{Wy;nr1)#!PDC;= z7n0y1ePNgXf!4IMQ@-JMG`tTdi?focW9rR5W&I{E_`W@GfmS@{k&sVErgUgV8srV1~ zwJ3)A9G~zlg%7f?s*(FUR&w8g{v20ScE{hE$?Te0Pgv}aSiD>lGQfYO>qnN(t7pf`;T%#+3yOX-x?JdIBp7*Qz$m{ znUb8p?^n_PfeoRK%T+a3vz;KVlK6(J;p;oIjQ}t)d)I4mTj7TWhAEA*Zqofc_n9^+ zfb&H0E+^-5lgPK|106`uVHyxzS6eU3NOf8na-R0d=w zzP;g2anhZaOU-e_gc;YM0Wy>X&=V4Qr=l^g&h;Vn zwXErr3H!!8o4T#f>nc03=cIT41F;@13R4JSr+harkRb84$wd5?S;m!NSoCTI35~kW zGx~Ln!zdvUSvG1-$7X)Q$@1Y#b(r3gAYF-GS>-dRYxoi?<}Hm9$p}a1t~|G{4r>Xw z^?b>St$^;bo0xI>g@C280VR*GD#Hl+bt{5FHet}2BF|Y{*blXX5!q#!g%RL&+vtnkr`q+&xUHHkg!ji zx}}$yNwopFw$axdaO&*g`YE;9W~LsiH02S*1Ucc`KZ>KK8r)0!0>|htyA$_+hoEwO zCv9dpxU6{?c8GYU5@b?Tj0@f8zteibfW(3>kQf@xqF&O>V9}B#`b3Jgb;N`nb_(nC zmSNvaJOjfX>jVvOLc`L($gihS@NXm^vDyByxfBb11zOe_5Tz2{Y5NFW^ATIVgszaG%rvuD8-%A(z zJ4f_64?w{zg(qt!T8_7cLUL65{~jA~x^{E)xcja1u6rtyMSc;}Kb_AS_5JIJH&ZxhQOTH}ZGs zt+>)#%I`BDbAbgeKEY#;K*3!X{<3*stQ1$jTK+{+Qt~3hIQ>$TI&lR4C*RiCfEKgZ zyB!x{F2(mXkSx%Lk4}IdfqOukS9DwdrzrC~MQjaG^>l3>Ldg^>^CkUYgwFtO$=8MB$AnL7IbUTk0*t zzh6PbRVuU$Hs2)w$L;bm$qiMfrGYoMECx_0pzBhcnrE>TZcu$USHf4lT}8pHrQc!# z9O@V{a7sq3Vf--HojUx~Oh4(ioHdf+EFOtWZWA85+3K~hHSsG7UJB_Ch%4cGU78S> zF=679q^A3rq+BiX%ZTCHPDxfq^u(Re9a~!HPu1VdirFXIs#ZeAa4ZpBN>?VF%RMSu zs`V^}_3-5801lG+K7WUYDiw4mWU;d>9QY7IgZP84Ecx3BDEEw zwo@5=O;1ec^P^irZREuO&g z|Kg0Ya%#-I>d{8H&C)EayAfyB1xVRFVS5wl5lE{xE0wA^(PZ|!2}kzobNzFzOsi^~ zV8353mv1@b!NPN>ueQdM#~zkY(r?C#CTjRgOlZwm{4?sRC+1y9=N?8qvDhmyzJ0%w zRebuGyi1pE>hLHq(hImSBT(zs+dwl1fx4GQ8ioUe$c> z=TPpqr^)=(S&^PTmDwkNkDM+nFvw|z(vA?ztpi!%!uKS}#G7iwvRObr3chfl4?mCE z^7N^6N7NB@Ek6Bf`P)w{_iKA3`BO2EWX^6r1k8JV|!b5$lQ`R zXc+Uc#+*z*ukUv8s6BAW4aODm@M-B`g@{^#MOD;t#+FG--u&oDHG_ZM!Fm$idN*## zbN$XaT#_caFE$|nP^*Ui`#W@o>oty2@15gpBxJh$^#!_Te~qBqz-7+|&6}dswINT- z;VcLbY;sqbWrydsdW4=D&Ob@APoqxn>tC7x>3u;*n6whjWaBiop1Obcnl7T9{S(m^Pw|KF!`hQoxifx#fsQ8*9MR)pWMC zG7H%^-VJ29j=nOuMU!t1c8=`4@&(!^pVKw6Mg;~t`3(1Y+K+)ZO@CPk7gI=`H<64S zA=7#KZLz)`kgpm!{2Y^BHa7b=jZT+HCrf4f<_b~0-o^X%>!D5>=~6U!MCfvfX69=?U=xei{cH+mu*U4C-l9^brZFG?Vbx&A9y=~T$J z0|}$p*V9|^caIrLv&1Q2f7_T;-)!)z(?ksTFmv~ zV5J+#Yip@TIyqgf08i;GYvvSV%!H#TTm7P}52yq6NJPc>Q#EFGeC)6kM{vkIB`2kd zQb%TixG2iG@G)ZX2nqAa=X?XEcMN(V>k?@TuDf=2{S06xxj(vMg{ zVq0BFJ>)By)j(hYVof_Ug_YSa^Wl!!z%qBL=(3f~b(mp-ksA6W%N6Q&i>B6wn|Bj6 z%++{U!j_e}rE-)KKwW||o7L2pe7|9ej=^)}no?TN%mIiIyW zvqJj85P{DqLUB1NN6`+u!huTT=%do7u(TE8jg8t@tKFUVAA^kOe0r+QIh*T3@H(QA zZeJw!5!gt4GO^iIhio#I{&|UF%Cl*gIXG~ikN|q2mX~F%%)f`qLV3ECsL@RG%7Kpy zDpI!Ot4UyrBRxP~DnDJ_hdq!m4Uu9=$rxu(q7zo(^)J@2bMYqu_^}?XhX&a3K~2S; zJQ2GF$r(63_wyNV)zjnjnQ90`%~U9-?_XnzoP8f0)Nw1b5cp{H@FCc1kvdjSmV2MO zrcl6jrzwe@SF_L4JAg9irNlz}cGyxo>5K zCI73M`Dt0;_tC3jk#LKSVi3?=#}#@jXH$vGdwn-kI})F-gqKyuyA87-;#UPF0D8Li z$_e(<@c({Xh2uIs5(hVu37Wpb`HYxFKXtu96#oY|e7$%od8lHDEVeG9B|wR0hz;QZ zxCJT#;F9@eyBg7Bpuzq)rQH^szB~6DZS3!3Y4J(4e)7%I4zWz&tmrSP%2^d*9gW zV&*{t@RJQLa3Fhwzef4XzsZYVW3j&}aJ$L#K6(oRYPQLfteiDpU#s#Mye$uYCL$#Z zP4t_mMa4{&8RUO16D4AT%_X!txjeVnHd$&sngycukN3Lw#^e(M7o$jN7BWvsh}Tlt z`byGI|0D~Ssu=ilFPB6|M!aTB<}!D!$-Q&L@*r@vPr*kEnAb)>Gywx$5x&OGA}lXW z$J)UtF^;ZDoQ2Val}T#3sCz#&heF?VdVdlUmmMoo?%C(sh#Bnwz#-~$%xf}Qp|8lU zPbwU5-g>jcd~d6x`6CZlAOm&1;8h9Y;CUwU7LIE2vAr5S&lz+wbU0l+$h`U>C~;?6 z<11w&{idB4>veIEcR=(;7J48Ptl#^la2T|>Z^_q&goKCMH;WFr+9?9Bu4v7NGpHwJG=CoZ=ij<#|j z7t7<8i&JY%bdrqGbvm$Y)8TgI)HuDOd78B|Q`P81qN!P>3*;3=??sl(wZ$@1#@)~r zz3HK|?t4`~j5=WLR#bZ#^@wgb#5X;yP)tj@-E5tL|2|}qYF-`a9wi@)A#P0jSw>-e zz7$KqoysNDS#`jK(*blu5$j#G5wqFzD6TvOmiYe$z-hiqK=et1B=G=ib}(AH-m2Su z#O6C-a@I=lgT|Bqn5WHD1!2nO2vMK9I>4srFmmITR5!N(a^1|>x~ET$t|43{Xp4rj zS-_X)0)!nUuOn#8N}gjx;p3*uEV;Je=NfaPl0a>+afabq<5$v5k|0~2 zc&(;`Vp^5IXmyQWSgI$BI*-J5bUz#x6;VN)9_f@fh*v%E4I`A8o-JP+jXa#Rp}jqR|%`H8YhO-Yq9TvC8Ri)k21C2iftI{(&{!-+KZQ? zIMG*=#F@vzRaQ2E1MKzky!gl0iTMEKwP7N9nr_qVyF~%8>?vdg7NgbF|xb+%Mos#FPWj=Ueh44sRIs!zQ4-IW9V4^*=uG{pnE z^@)uDTXcruD<7jMR!>NJPplUbc$-TzzAZZ=;4&mY)9RYrqNT~N9ZG+q{_RU1kyd~Q zJaSiX`-?n#eqGeedqY{xY0VM+i<({a*(1jyPs}!le?9+$aH(&+ZuhEZBR~RzS7(0> zY0GVuic_TS^xwE4H!th|lPp*pgdx*$D7{6b=Iukdug=#Cc%3}&I1%lKiQ*iD*sM?F zIDRX-b`2F(lcNAxv}9&Xj^q94kMc@KZgiA*4PjB0*~$>_nFjZSkvCtaj27L0$3971 z6rT-TnPkaXMKNVfBI0~iEGi6l2C;o?9obZ_FupDnKZP1Cygc(0+aYi3ma2<9o_0i8 zLXc{XgpQ~$uG1(omC%^4AVu#hT|4)}c1WWdUSmF4Wbx@v${MIkh={kxN|f`(zTycV z^HcqoZyIUo4a~I`We*T5Zzl4=k$Ht-0(>U0KpBmtZ;-D?uAc(jEY>-?pGk@Q_Wmlb zytA0*o6cwZ3-pJo+5jW{6?dNbj>?>g2F_#FvRG0Gdv;&PQ)0O_T#?_F;6gR zsyN2_dlnpDhQBE`vZd?DA|AE?AXcw-c!usRb2L$##*IAdvDt-W2L3Sr3!Cx7*gM;+Dn_z7k$BJlY5bv4pyfQm8smVSZ%)J zC3*9|5qtHZBKTSa=yd zn+lUXIY|nG=hCT>qX_>y=%v=`*KkVUuqiJh9U_dlM{|*a? zvB){8d7ItM^o|O{fvX+ynb$ZwTVE?{F*pAGWC`Q0KRhtVjqV+k3lUJ)GqDr2Vi>lg*jyuM=aDSW1Fb=aTyB}0{++oQZ4>1O>XP<`&s{fM;{$qOef zqUx(Y@nK0S^{-2VXz1$Bgry&mi(y;6%rSlBM$5KEG#?Wk1)%)vBQXu+g#6ZAvUHuY zqPou;VQ%nF*7$TPQbS9jp_b<{q*psb6o}3qhai@p@sen^P+w%N#}z2e3?&CXZ->>) z90LUCw=GANo)YJDHG>I~ucPq$)aG@i(aK?&ldi3=Zzs1bN{R^KRfH4>j0)99ur%Z; zA7eMAlySh+Js#YxcF#Z2X%AFRoI%gPFX{5r{upiD5J~3d;Vl*w37*S^Z|lv}@j$3N zWAN3x$V4G4cl(5necCKI9_V8F@>i|5w`Ck;l40;Aim<|g!SVY=ek(4MIl}zpClBKA zRZJqq>~bep2?8e@3M06Jc7uO&RrGabG6HkD?O@Ndfu(q8>Nj|uSi#y0;RLGoQP39b zPcR96w4s2Dslzb~<9&;|(_>Bmr-!lG&?$p_ybG8#$0Vun&pPm{41D*~7`>-| zpH{Vxo>BlMM_zmkK3R))ddU}s;1PVx1A>L816$T-;(sv9eb$2JmOUUs+X$|3YxTOK zUV25t0@chn^E*j|rHvnVony9?URn9)Cn+;7F=+M?yx|ymTVgkOv7}>T!j-PG;&yq^T|{-x z(4d*UbucM9gu?gW1X}Mq2&?_b`BGBFO4%j4GyBar7dHf`>n{0q8$n`Pm8pA6#muApl zL(Q0Ez8K~qZ&2ssHezUg#h8wLxP{&LqHOPfoEe2W8Y#YiEQgC}MqwpE~W_29)jnx+}lT`0} zk!yy?M9bfWcbHT;c9idGH8_X= ze;}NG%`e8^as%wM<#%pfltF=X6O%FT(1Thosn%5~v2SC4auuwst@yW={ja+sQeSWB zC+X&HZ$k8{knuC&zEhG1ctgBwk*^)ko;w(0wnV`N7J}d(z)+sDnR7DPEs@4rqFS?&?~ zBN-ez|L*NXwc?kpQ&ysZ#IGcGZ#;%(of+Sm&Ge-b0~bkP<5aJp7Rod^_2>`3EEL$8 z;9SrVnw>tJI)5VI*D3E#8Cq2-MUZUH0#q2gumDwB-OogAoAtBUjAo2WzKH15e&B}z zE>O-vbf{Vh;OGABt$Ar?edCM@D}2Y&Z?mC;71R!j8eAgqGwHUa=m==i|A-6b=CSGj zoNH5SZOz+k7c96JEf=bpbdokaSSbt6h<6my5Rr5-Fj&MMf}+x_3g8qU5gY&9@U}XPih3b&lUP}} zeDQf616aygU7{thzX~Igt?yy$*WQ)`OO#AyjHR&>5nXe-ky5$g`5;YhzRr;0X0A|R ztV02g9@5<{iF&+LckO5;Zmw2)CCKjJ$GAk)5IBqM!m3ZO=ogoRc^6Y(!-=@(Hg7X} zNHG`B6z!jOl9cjSoccVHA%tf6uyj*)^(pBvrnCm-y4Z6uYfB3DPS^bnJv!2`n8}ri z6(wbc!IG~N<6iWTP1eoy*wK65L1%wRj|yr&tAOst{dnv#mexp?+gm7&8Y3U8uC^1 zerH-BY20T^U|&qDQ7-XCUJ0(sjJ99G!UFgv%V@v4z!Vgz?aQG5{hzrE6%g(8aaLQx zgV}7%)tHiHo9@>|*kQZzi@uK5CexA^sa0s1rjZ|`WOcL`9>}TPCybz^T`4!K2Y)?K zpGsd`1{$zqHMs{YGeu0xTz%Ozm=)_AMOM}2BIGBM4K6BWO1@#bJuXC`Zj|Z1ph(*@ zaJfc~I8X;*!Oi0UN`H=431K>mK>w^viLH#vwJ#WwEYBnNs5>uk9{}BBVF6?kt&Snw z$j!*vsg_X8#gDbT+E>3kVk-odS3X(MufbamLA7ks=7dC16>%;vJXLy_-m6O`%MN;}?e|T5>28$-oyD?=$ zSSpVee8lDr$gB;eUvlxdHi{4Dg)NZ$wUAdpO8^bc8x^Fd7b{*DahXQZeo_+TWY~r* z?$|L!hdKtl2nc$`O|0}brE%?{igW?uM-llV!-CqVOjMS)bG##-D`*{ZwhEx)i8pD? zRI{)qI_~S0Gl*78SJ@%u$A2QuE&^gs+9~6{3Dq^XPZ&>d9){cO2X-9|fO?#Z-o~Fb=W1F`ncp^`DWOXfbbXTe>r$p! zrmMa2%rBql+*-%~d0)<5>*5lv5RM+EDWfr!!zERg=nml zl1gR}@zb#(=)a`2mdgQrO^6pFcFP32Sx2OHNHnAZB_4OZw+nwa3iLzGZ+pN!bl3sA z{NtllU0r)ZyguK6wxq+BhI|Gf@>rHAjXe#NdtsgxDI^!_S4zJxxwu9Dx8-6AzXWjr zo(5CWT#t3D+>I)cW;6WeJNl>&eW+AE(~A0!B~)a!B_gE$X%mk--6Ib6p)o^V{MRo@ zv}aGDyomw`{>X@${9Dnln?BLK7#mc(V{LZ!&_|o0e-#orQI`(eZMZV8bv06r=U)L8 zx-c74<_LJtls>_}(vKhEmDWFQ&e*j5xDwH~R1Ystonu8CElRd{^l|&?5&e8i(Cw&z z69Zwc*Ty%9-!_klrXCKz{{#W$R+R#41+Eo?;$MM@_LitN+XZ41wOYv#t6_#|C=|3W zQ%sOm+k|G7v<7ppGbc~v2udq6t9^@|>l56UgPNgZpK5BiBZqU7fG|iGYB~J#l@+np zgf+8=_06of2vKjwOQi>`X5pXHh&0R<6Ah;DFWI_a18&FHBCfNdcC}RULYnAmArrhI zqd&>Akp0{3!h2e>3V-~sK1O<#v1I*L-!_Y{_To8mB5xI*JLNHhj zeMg_TU>)F6QR7(|4O(P0IM~0N)?xBn;hy*`jZCz%4+VXMp)w(2&W541{E@VJ zhLxk6_$kRJv&Po{1Er2-ev1=u$$f>?@{}L&>GsA=fB&f8&fF)$GKxq`tpp@Uu@cS5 zQl1AABBCYkG!(z%&%nhd<_V!SwKvO5VGRV^5E{R?CF}C?J&>!eGs+P0C_|?j^FcGN zr^40koED_dY?-;>Zg8pKi4NaTKvj6Y{Ot$HO-Gz+J^sUzQdj9b2M1}T!Ho?A8Y_1v z?uj%*oGP(kPtX8RXH`@@adN6={agbk#gLIT6q%S6Z#GJYi{~{BtG&4H2X5dTxdkv$ z8Phetp(y_jx!5wNU`8e$0UkBXO%|^=wL_9oSF$1uTeAxjhz%9!&Ms8rzuG*2)o=hA z;n3)9Q!i%?tnmiXAK8Dih?%>q2ag+s^V2_}nC=_qS^^!>QcmKto1St|f(sS4)fX?& z-@_i4N}DH?l2uhbMX}&OrX!F-bvohdgJvleZ;|`$ZyQqbj1^BtI}2B*+0&bN))Htu zIYj#N4KMQXvzB;QjS9R8B+W#J(sQ`aq9sl=L)dkQVO8BP(trPMc+$x&2J@X+UReNW zIXKj`%e1x1C-W(5`^MnYyluZ3pEm{AZVW0Hdfto*NRf~-)V)stS?Z@6V;Md&(g=p_ zk*;@n*|saqr>LbrUf49Hrb|Ye+5lXVPwFGgT&4OxEYUqd@>FR{K>Iu-{9viLQ11zS zOM#>mkZ*|fqO*Aw{##|{>UycRfcxI(F<I!?M;U}dg*)L55YDgHoFhuWTxZzl+R9wVl&ev}IHTWm+fCs(uXlps* zijRt8KRJA}R58JAA(ik-t~BQ3B^ZD@N!*pkY8Yl^CfG$Z$Q{$X+c);P`?O__HF}8` zx8+o}PzZuQf-RG0tKC0l)r1)WLUik$4xz(pb9t z_IoU3`;VYVAngd&6=t(E56zeEymUmG^0jBm??#Yn@8e`?c`SXLrPk4{)TT4pawqjM z2cx8g^5&R2TFYq)H`*2=AAY{C+b(!SWz?|lsfK#KV;oBm zt}`s*)R{Hw7lohg3h%pK3~;K|0NmFp{_k>D-AAhml|~gHk>J|<+sxJyDoJM1MPEzl zOD4a}6n%-9<2x}om&GhiFHK5Ys|LA%ixw`u5`}IPRrD4ahDiJsE?i-cc|Wr4T?A;C zgV#O=nzaH(PAT@4<22>)&x_Y{%FX;N5`xsaNp=Yqsr@i!1?ILMMCSNg+-vr_P6*-6 znM0PR$DaptnI}CxYgusMm=?)D9%WTp`TYUq<*t9xMhIBYdGWgKX$#SDRsk>fRmU^K zKH_&DaCxkjkTDwRj|1~aS1e8Ex%m?Cn82mwLr?xXWn{VGKGA#h6 zr9=F<4rP;c{rmkd*%7&kFvz3zxr50>Goxg*>90HzT!Go7y||D);|95<<3zl-b)P-< zQBLIX=tB9iQC60C_iX8)VZF2s$a&_2_TC=harK`&)gQPB6D?0u-%X1^)yZ7Brliah z0Y0l2uj}OlN-G1(?~N&z>5%2+5%UK7J`oEGbt7x9ym9{n-4m}KdO;_^^bYRp<7Wdn z=-Mm`=YWGfgEirUx|)bj!^XZhECD@E2cYTHn6fqshwUIQCEq@9TNT`b`PB56M3}&Q zM#nW`& zuTH^!bYUm0ywd{28ra84%S&H62>DmnqWAxrd?K%iw72ZLh0L{?Wg9MhmfK-s6UVC} z0Y@8|{7Lk&1_PF+zj87hqJW)}9s!UnsOYK^z{M8^x(FKl9Ol6s>2LxmGA-0wc<59u5z$ zK-ZzjX~h93TAj7vyJ8cV9*lou4@vF2Yv_GPF8 zn1BjIEPe&uEtK+44yIfB3mZe$Ku|GiZ_2+tN7Y?2N=1RXr$?|1mM&>SppUsOiHIXL z=}=PPMjJ6@%k)(Rfhgze5+JY~n6|E3u4yQw#gP|671Vm{z(n`$f**?6artKaU7yEc zD9EK~_*lfRRG@99X3)GPc7?J3@E1B>kW@%uTV6d;(>QcrTuQUWy^+&v;oNWE_>jlQ zva2WV(-REiKtMo>M7`qJOk5%4Gjmwuqd>pDY&!vO0X_^aihsWlxNQouZJi1@`I4}V z>tvmGV&Q~pQr4A@Lrif>@tQQ`i#1YT-yGudXOa?a@m)S%>gwY5d3{l1 zjYm6}A?_l2s|3DUT>WN+Mm^~~BO_mE_@JGiBgMbHWCjRUHC!9yd}1rms!F1p$96!;6rkAt#TKp^H*ddyO>g5sde(&$XhY$ffN z2h(L{Iqh)4U6J*~-sTgHLyit8XpjWM7)#2r`hxUa%dnCe0X})YiRj|88Z&|SQ5HaO z&CUfDpfhc#E_6xfv&5N zHA9O>5`0G83>AbD6u1Q0y@8P{^RE$~v()!aZ{O)C)pVQ}1y;3gF* zfDo{cdgh+`-hMT^dp|Za$540$PSj-8@oH|*v zotQSAAS6HmeSi6C>AbOP>f-8yi@hnEXn~XEX`Qg6O<74%@utP48=jabCqIH~O;p?`maPJg)pgf~Vk}@0JxX zNZ74Tk*H{&q43zpsi*uVq?uA7Ui03v3R?r>`X-@1`o7TeVD+X7^woCZ;XO+kVMPp{ z)n9O4U%HZNWN*cHIjzb8;#aD4SHw`v^2GI3(ut+@|LF$<+GL#e-wAJ z--&H9yY12M(C!h(gJQpke0why~knZrj8po9#D&OFe+Ry1P5hjP=M((5b(kj*} zspzy~0ulg`g~C+MyaMTwNjyD;rV;&8`0KJ|vcy)7xT&02A5HRvAkaSOt#OI_rk$m( z3$gYy2FOSMq#6IXE{(WW*-#wvonpYcGw059kP&h8rpue8LLiYgQ}r9U5xw(5YADCa zxtr<}EJVY1AY^b9SVU9w`h{Q`G^i!3L*HzXb4^WT_<2QEw@BJgrdf8iN|{Amj^xbf zh{^pCxf#!+5KBltc}c4%eWQTAce4Kj1wJ^q;VG0b3=tTQQ1CB~?O+CpSP0W9)eUmX zxh56Ff|imPuwR=Y zzNW5>J0mK5yP@-w!`XF7VM%ezVurPp+P8|{q#vdOZprtS{1CP4?2KD2&*Ou6W=3|> z-pXHPao_**^zP*K%R#t42=w1=SJt>&?b~h#d!t*EOF5=3O5H|&y0?Q>+>%mm@1^@k ze_lHQqIgEn#D%Pb{XC16GAcY2ZaWN;yScsC2Tc%Qpe1@;LsJwUURD&?{6SoLc#90H za|jcdsd&nm1n$*&{7)#6-D%C*`LW8#4(RfkOyzdc=lgDl(F6HC)@gDaFlSgdvVD>G`km5!#S?JE*U;r=@izaoyl)L8+G~uw+kL}5*TVMW^MOkJ_=m< zU-#8&zkFVKQ|q3nD#xrT<<`qIxz8{C^<`V?Rl|mA;;kUEHs{Gb@uGt1<9Y)q=W0G? z{#sb_TQS^uun@)XTqkOzI`?W?WS5Q_vt_mdAH=x!J)!FbkLOHIhuoncu&+@R^4w@8tYvpKN6A6V(pp?%nM_Ackg(@tLt= z`hKYDIEyR6UWhV^I7*(5Li|ba@)lf5@FcgHwu_WDw?$$P!tblrzJmX#%Gr94hMC1+ z;H%}MUi}WZk=P-^?Wgtfs%iqio^kA3Y=#$og}j98BeQ7YWxXX6@)7rX)-C2chxvo=(-jJo-MOhQKDHY34T>8Wt|N3ediyReZUoD7a{VB_zvO^F zOZLBRJ3UzC>FoT!UHqYUIF2zqF4!LeyWJ6Ly_R27K3F=`Lr}cJMS4>aK@I2CaWH@T2oWC$xsPR@<9R9W6*}l)!}F;p4x z9x6S9`|SL8Wm=QhL*Ku`X5Pqz8C>tqC@Z9|t0Q5Ic#v**3NHd%4CF)5{kweGa~8H`EG6}3QSKdf$QAElBYW5_LcL^V)pP~4^a{N(+Y4? zRMy4mS~NRXUT;V|hEYIRjDAe@dBFtuy2~r)zK^!)xal^pxH&4+TX=QC>7%5QUV1KK z)F9KlG12x^FEf{YIJ7uMQK|{06sE|Q&c_i*L#sbuXRRyGW%9LO7j7mfa#8FrG);Sk zK3oUki&<5~vOCMB>v~!Zgn0|pgSMb57mJLk6>&F`!P^L`Pgc6PxsT5cgVQI}_5KI4 zye?waGBA{9qh?FYq@J>L8igVM_>rSVQLLbgfMnmHi=fk|YiMzWoZ|+AFt}u!bjWVU zIt1InDqPNEgSD$k2NTy6ux?k<(5&m(L+v`&tfA{d@y&1Ve%KI|?XL%xLew947iM0a z%bE(^yV*)%b-7q2dc@{v(`7cDFBs-Iz+~|KyDkUxA1Tg9W)A6epR3`ATdPk7d?MG! zAtyRqBdkIlqG4OTG11H5?dj?sD1!g4LlQ*{=7z9T^hQGD`&lg7JoDUtxn!oA0^Tc= zq-rq8>uVHrms71-$W&RXG5j_YpU1|3ySs&2TvS1g`=kiN!=HeY5 z2%m*D3$&q1X3Df;)ix%O$Mx;cR@{2ipT_R`?}qAM2<_l9^l!$=X4XGfV#|tm_uWUi z1dz9$tBh9l5SkVG8;0Lo2L^@46o=tMeTYZ4FM{2&Tf6B8qdrw1Mt7a4p#zSi;%9OX zmsCer;qr@71PWk%NwFSe%yKcw@HIL7(U4Fe5l>Go``bXZRoT?Dv68j`OXMSCIr&_VB{j)P=khaa0pfRZM~<2?^@>)I zupHVMfCcMEtBW$Om13WA6z2RXY~;?G4%UT(C4EUGtx))8PRnD;I}7c9uD&MxQ}39C zfRvKwu0LV&MC-W+b#nz{2XJ|X0{6{|J~u8t<`xa^S>=<`VUA^u9*!;rciiyOQGK_b zc@^fc%zsx1R|$^&!yz48{-rarIxm05%MtFM4M$39EUDj(%_u3r7#gD)*T$M2Pmh1V zaK(zoEbb}-WeD0GEjTkV2^v=TxnIP6qv8sj5uBTkzMfOwwb%zer2g1b?Wmsg1#C57-w*!Ql*F z$V1XbNc7o<1i#jSJzXj0t;4w`k5(OB0fjBic!s_1<+p^xnNRH5EPEJRqbCn0M%G1W zo3+r@?y$%FCR(9Yc4Gf!2sw$^BvZ!qrY`X-=rLpfu0L+GAY(ZdlR=%6Or~637m;{7 z&PBjr%%q`PFLQfx?Z~_z*7-cAagbt`qeD``H}fK7scd?Rw|Lpm+f|lmpl(|t`RhtI z_zbj|zEfOit(9j>XXu`=ky*AEK{OZC@?{mvrG=Vo`oA1wugW{h#K&PH8tC5s?O$`K2RDt`)tsI&Qq~e;z>w!8@iQ|+2 zqN9^~KIX9uH$w>>J6fAd`jt@kFGB*SBpA$m3Q1$eF9qDtJTvYuDHV z%H}#qpo6p970=L_MARssr5f(FC*mf?&6Ki9Ftj=>EN}G4_2b@R_&F;_JmM)%UriSh zPwHshWjlh%oLqfK`oX>kX?_{U(_`O@x@gNN`*(&Q{g`|Pc%>fn%FWBjq)EVq0&^|R z5}iFdK|b{f%V~OOHF+Q5$yCE}9@<;NZ~mi{OI!9ZSDCNClNN(FxR4xz(7L@^zpAS^ zw*3MTamJ5t;f29`iuStlp1WCkUXixLn{N+yPFHHo^m1B=mL?C%XdntB%Kv7CU*Ki@X|@)w7=LlPZ@0L42$WjX`%jM16@wSWz7?pXc!DnST$3d9yn|EM^M91d4#_^+iOVj2<;V%4Ok+7$bvcz``oo7| zF&~)36hZ|f`(pf}j1ngN;HhS|`5JS>Y~A4Hu)PUF8wFX%mwTH`f9zuJexe!8*w15trp0KO73E zP0pQHDtxN;Lr_LGnv^m7Z(O(HA~dGamC_|g@Oq({9Q*e}lC~`D+quY!y*Q0GLM#0XM~+Y zSne6Hd8*H#%VWQp;CA`e%=f0j=3rUdbH4&-ew8zzX8#H8mg3MjXX>~wpXeb-wRowSDG<0Yc{`qKDv}r#ft|7YUVnQz#U$xk(v%!(sW5Xx z6+R<0%Z0uZ#fkb@7fD{XCH_M%j)PcI3$@BD`*JkOnGbLl|Lw)3ru%`kMf}*w=Eiaj zUy%dU|5B^04LPL8TV|d}Tz;W*c`~}(U#Bc3ol1_R>Hy07J%z_o%@Nj+ScgcNG&Y8|LIY@xRK*Xkk`QSnGab9>A5m2p`eL46XBPW+b9!k02)7f*vP24g=#md{Li03q zb*tSZLimT^^Kq{4)RUNUr)EjA5O#TCy(Jdgd&ds2L7>jmY^O~mQ;LQ#<3u8zn*wX6 z{kwHf#H{{khTcrAM$63Ga$Om{c6?_tcd>JexM|~6tGj~iuCtY_-)I=CGJ_?1 zhE)O(Qo_!KOrXOD7HnT$k?Wur1lbvp%4;dSVF9)t$+OEg=T(Mhx~ClO?z1bybH-p;kf^ z+I@?X_y?P`D5kVBzijmn64KVfI+XfmJlUA@=-)cMKu}$&73Mg{)niM%A)kL?o!`WEo9?f@K7&23 zxX>lvk)kpT2nHA5#2^QNj&@$E?9m|Fm!Zd@AwYWs&ock`uK}C{^5FQQ_!UEW=`Hp$ z>%03PqKggAlVxZ2bGb8>$*-)mH@y_M>pJEvy=~2Hmuqq|4LakVsjw_NA<6u5dTRFn zi0?KdAnn;CcuTW%MyS^o9V&CER6+hq^YbM*twCIi&rm>*M!VsQy|d*I9Ek0435=sw ztGClK|0%Ifc+4WajmWF^lVg|I1spZj$Lq;YX`jhX2Qy+;o&^|{n7HROz31wNf_c_d zD`0}xGCEJ;j{{S2)EQj&N-qR`!ie%EZN_G_R6bFn#@jAOOEjjJgCx|pfCxq5*2TdD zJ|i-~0!RJCP*u+MWDA@?rxvZmLkGy@)W8aDhL&ske?PB+;%&<`e0E+q&1iM_{3esQ z!OK}CF+VMEmR@wOAC>|SWe}~m5392Ln1b3V_M!lr(_X_D1KMCSgFH9-KQIVylIy*` zNyOnG%H?_?q9MApJcCYS#kN_g=+CZw3|kUU;%XW-lU~=8KN#otyr1t|Dco1vf3v^c z{g{4%uAX5|aB=O?_@Q7IJL%H_j~e_XM@V z26eAiXqsHI;y$$S$V<#u*CMB1MegOKez=lDEJ;p8KG3Q7c=o|GjXH2n^4;IRh@%J> zBiB{ZHP;gs0i=eEROXgD{1gVh&fmZ^GO`KC zMjy&i>ON1>AnGRTn$i(@L>SWl0dxiRE9N(eY|oo_M>@eSQf(VT!6*Un;$u>AY8k~J zu`rIzN9f$TwG_OyO0RUvDjLbh4H35=68so_Yx3itX4}MhUWm@{xo;u!FX*U=-82CR zH#4JrcVfM9!scdj%GmD0C5O?4!l8+BD}A;vcJEF)pT>%!ad8naHbOOA7Y@_Lzf+n0RkgDCI1I3l~}E2N+dgPAcp z+V#SD!%=%##BLX#yX@{-tjsErVX;L$#(ilvcS{gY76AuhvcRjr4>}Km5YfuymIOLt zSj6HXIh=WY?7w_kSGqC$aM5_pl`PO+ZFV}Ub>jIHIn%MoQQ5+oOVBlNg$#i53k33# zi&vaWy5j#5Cl#@>PwWG!r63M*uMg+mYiS9O$}xB1XM~G2kr!b{Lu658&X_i>14xRR zW+|%wd5l6W{jU*&H`?NRC27%Q&es%%KN55EYD{e{^P}kFx+-E0PSzjQIZxdxtA6t9 zt}|0n9WRp9CJ&^|HKp2aVt!;_u|p?qu8J$3A4kQBq%#~`9ZVwdub%vuotw*C+cgEL zi=LmW!NMp`0Q{y_hy|ra=_gtGly((UxiTLjQU-A7cFmryd;U>cWcwzhppb|+*>LrJ z0Y3MEUWG=@J~MAJ5RPr8XM*#PK&RXn|L4SN5viR>uttIVh5NAEAm?;B;gxmPEjWXqAl_xX3Td!dUgaQ>UdOmqUdU@vYN!_q4-m+WVbPR486J(DC3d>>r|I zmScYWkVPhL-;lLM{TZtK$Nm1@x8G*hy2`%ChnOC0nE*zui1$G@xK?W#7HuMPx;-Q| z?nGM<4ar(vQqwxY%U}m;bDEW2rF)l;<(LlQpFi-ORl9Wri#qvxXZ88keFAfc#RHG_ zSy3$v_d9TO@*p@?i#FBWc^4^!Z3>+Yx3TrA*u}5LI>pJM+fdU{_uQS=PFX! zTQ=2`K@d{OiT6txZBsWvWsXh7&OgmIv#NO8KzUjDU_?VG{Efk`0=n|Zz>2rZ@hxA( z_4ReiJv$q0pO_1zVsND$E?cJ;FVNAwADT0wi=)iqav}kRZJXC?1i3ltV{p(mNPJ5{jS*(yI!H6j7Q;Xo57Q3BiCA1?e5m zyPxj|eAks9kYum5_FQw0aSuT2ZC`hUYPSk?zd7PFS0rjxvrz)K&Gbnhj={t6%jGa( z3vy}*QiKoUvLQTfO)MB&!!gqSj({0i)kNhN|8$DfVB5z7&)6uEe@TSofW(z4j3jBl zMU})K@pkcb$o`wwEXuqPrnCQ&nt`Vem%yYD7BJx0Sf!9v1yA!%GtU15{re}G$FntG zx5Rq#cKjti&RA~*(ySnO)YG)784MHlOdaF4w{Sf517Q@VB-&TliM7y^_n ztj7IU9dhB?#r;AlPM4-tLOf9Y9e^`RAG?9jN$P-N(XW?a{zx80lbG@6HM_ zbmK$TRBkSk=>^?jTH*su3WWk+AB*W?|21Z4u>9j=XKqk+<_yuC!55a^4B)7;3dOvy z_aReVc*UIcptb*j_{TJYMNwd3)IO3{|C-8U1yW)8blr?CBkeVdfVnoyY8PWRW*~8} zp2>oT;l&4>hwxlLW`Hcs1?FbD%=I^N}~cinQn)&+q;XWe`xS61((4)yIE-wK1A^ z-hG06ofsn^>DSfMbz`=DOiGihR*04L0FU#A;!t_ z+0Vt5U^wYO8o|Ykn05KQguJVO@9VZXPFL|2T zj3vnQqJtE00)37r_S{C%f%!##WiV6!56nMJrmRd_a(i8_W25ymo;^Zn=dLR zqeq3B9jmg2f}2*MTfpS%5&MhDN?r5J^DhIWkHDIf(@E2T&NoqJv~Gni8IKv?^{nJh z9!Yk+7WeLuMyxJi4Bs;jnm6>Ww&SLw-(E+3XgkVbVJ3BvPb-vSeINno%wZimo`^}`s zkw!VBo8o_H0@(0xD7hK`yl~nEAofZW2~3dsY}4Zggmv~PV>y?ep4Pkd)2grde69YG z>F}iI4pO88N{zBW0fM(z+@8Ee3LI*T@>e7j+v{n=2dgP)&{_(aY35juGGxyy=y?Pp z+kQ=0A&IV?Jw&;F@Hh7Rf`2=kWrcG{h9juK%NPUIS z&*W{)qOXnT_WPUm$v>QiEMQpVI!j~LBvchof(<#ED{Z^0-|2F!Lq#fv1p(W@7R3%B zvTL)nE2CzylC~cBagj56!OoxB_#X(|0R?tv{m6Z*V4E3RZL0m!qN1EtRknFxC}NRo zeZ0mSa`ABq8B?YPe#gV;dZwsHh%#^LiSjMb!a9~om(^0ZNjGmYO#Dhr(<_^ZkXQCS+ZQIAiX_O*{33SAW)EW!f$WkCB=RJ^3Ip8CV*)%fzC#6gB zyG~#><06_Zd(SyCxGxo0@!tqAAP)XW#HvqWM6M!j;R-+$X%&=^-4be$c)7 zihaw4OF55UvX$8P8QJH&SxOWh_UP%{2i}6yLi-<#JNoKsZS`7qdzprbb!TnV-8&jD zISp>ul_9z5lZ|ufpq)6P(!u`}Gifz#l}|qM8ostMl!>sxC8SIy-IqM{5hq|~fCbB|>^;G~{C1w|+ z@!UB7H4@YF^AF42VS$h_k7@ReO$FNDgO!_DsbSfkYNi53C4{poJ}w;Fn$L`lR#7NPEzuDuQnFV|?QX=4X)?^%#!DbDj)=lq z$EEL5EHr)?&xJ|ft$O+TdnnsW4{i;HhO)EfaE`5IcWvGOK*mZ0{$BNJtM4+d=HeE< zq*_+1WzLxYKwn7(Gc`>=t_0aimprm4F-{m*^pDnKy#KD4Mk1I+%~YY4f@3Xq zhMf2gyv$~DJz(+by??M)QjlEDP!xohkpg8+Pj%AfG~Wretl>BkA;?z=YH|^D*jI=#)>WtPAADI*q%q; zo(1HKrP$zN)w+Er2j8^v8$mkM9_7|;z$)#L44T$TT z>>n&xhO)uU7N4k46+J|3hEf;b)gc`MX>;tGl4Z=mq&K5U)RGBYIg6`v6{P4c9z9 zYhH2uy_UzeQqZJQl3xo-LKadp(s5TcdG=4DzR6s=Z#I`#v}W=dT&3s-QDdPhaX>TQ zzzFI=UzPc^do7O>rjDHDjVemB0$Z$MzOF-xs#^9QwNG#itrx159TXSIJ4*>IgYxDPB}5|H8% zkh1f^uOn7xmXmq*Wbx>%j#iP!^G;|jfLzUJn+BoRYQ@MHb0G-NTE%p7YD0SSF4{T@ zFn{g9qlKR4#T5kq9gB`Hp^dTpO-##RgK+zqzpLe<3tWf+*R+TU+VxEs%TNt*=~bw<_0LME`; zyz53665xdn$@_76>FI>h3$%Dnx@xOT8a^3Iospdzx@X}sq%Ctg)EnE%0uZ7a$ z-i(n>sC?3o!58?@@G6}km{Y{D#N4qy>63Q(D#5fZ2laVW+PQogKE({Tc5E^<$T~I-FO_ z^uQ89VR*j!rs_hi$%6f!ZFJDNax2FzP>D_6lK3z4Y|fdB({jz6T}0 z=u=bEoUia^6PKk%VJ-b9Z<~hZ2`{!Uv19AJ%^G%C6y9UaYZ20C0&sX^)WL~<Uhray>8Z6#h$59Fh zPr`&MyQKQ%X_8&<6Ymyx-nsxR0LzwdsTu3c5$L-!nfK|bFUo;@CkyPMx9KG|5A%y) z3j0#HHk#9ja{TBS&2z^?#^%%F)mbk8Kw=~n5ClX%J2ZDJhuX_1)7eteQEMpwaY=IO zsKfJ6RZw1JaR(ekjrv|GK(V=s?XHQ#yM};((h5k|{SPE;%%o!Qmmx)zl6VA$uNRy= zy89nUmb8zRfpNU{--_Aj-2zgcR%X_s%RJB!JpSTlB-dm*p@zQrpU+ZOb|M!wGSAQH zBX*X{{MxJ=MjbBb^EK3haCFU@p#X>{x&gr{etGOgix;_N+e{Ixw(2dE!TYSrlXh>d zAJr3zOyAv9&n4woiBWUs8p0CLV5WcokQ&fALNHX*ix|mh&6Z8clyG4B3nj-Fy(piU zfdWJbyOgTqXcb>UtPs$tXbb-fj%zWRSr!fximSS1Wi+7vo~KFN??Z*!2^>%~YVnna z8TNAYcJm}oYrTBaNjWdB$hT||A5skP zdOF@TYKO2)?ogmYrm!@Wltl}Hxj$ic&OM+HFF-HL<>vrf$gDjS4m{b56ydTpwxTB6 ziMrep&8-zzMS${ZJWiJJ1q{U^q8`%f%#2r$*w@3Ojfr-%jsX6Gp4CT_R<7UglaHQ% z_X2NOnAu=|P)23+ zxEMsr=-lz4-}*R@3|#QvKie8Ry3hKk=<>^k1aQfq+5gPpN0R=OCR+Iv_S5h9GWDXF zI%$PS(4rz$5Hvkmsn}%{=NpIT$>lqS&ul>FSEP~g{@$m*7P=R`RBEAO1S zG_qB%7b0xD6s^X22(Q>0PCR>$WQ+&()^lMtI&Ueu1sDA5b50?R9+x%fbk!sUM4Oj) zonB+CJ@g73DL0b!nQ0dKz1baI47Ji81OsU-CM4~OJ;YvB1ODX(?0vKBtL|$y1qSb@%--5m^)WPpOIX3v`Yv_Df5)xb|CQsv zZaTYRo8?nq)!S-mEMYc_6W9*j`DQb=)puJio?*mZd0Ld4%H`j~(g&nx+Psss{1`!v(S7dm>UKua+MGjXOX2a>?rZBDu=W zWo^{1+Q}mgE-4n18&``(KfVk_^ngwtdBl!i6_LvFj?gsGS{qzUi{5Sz5{a6r-s(DF zau{~EOnv^QBp4aT*wn<}ZlRf8w>IE(b>UX{yAgTw(D)?9UV+*#O~fj`X!8S#od6-E z)M0Ei-aPn+EKaChH@K8_<&Mg&68uKI}O{kJwyJx6S=1om1}vi#O2R5avXK z&fbHYd|7hVe^@2upp7w6Iu>TLJsl@H51`9EVV8G}n(05zatV*4>FhI_e9#M*FP@!; z*;wAz*R)Lg+!yd6@qPj?PsdOwU}jG%DfAPv#{I!Fi8K%JG`u)Mkh%77)bK}AOL_oB z&q&pM9uZcbz$O%Z+B}}IytrH}CralhRUd(&T{SyfU?mciVXlod)k7haK_BA6FVkc) z$iX&Q%}Ncqyo-Nm%r}8}g!`}|+!ZIHAlP22LqoM2u<-;%W3ghH%~m78J&FBYBUx$d zB>W+6gd6jKjx^f?343$&gp5S7$p>bfy;nY#kVd#3&8~8qL_=ok4IN<|fhSInq*jWh z5=C=dvJmcQ*GX9RG7zKMj@i|VYe?bzX(RGOl!{k5^a5_H*Rm*D@+NJwgN0UlI`@1V zm~M@sY09sCNDayOX-H8&Wr{WbpVk`BLe=35nU|!Bkd4Y96xYQ;(XEU6wi2>=CnV=am*K z%{YO(1n45MU0^dnbp;AZxbB^;D`m(I!`Fn&Zg~s;sQG{ohc|}R!)6P?bWeYXU};?9V@$rD?)AfeaK+3UHU4xz@hWKCjL&ztw79epf& zB0E5uT#y(G+4^#>%QWB+54 zufe-lk`U~t3SBX$Lyf?Co74YALqIKZc4P1dxJ6(hJlY`sm?b@|9-nmq-m9nkNoY9_ z-Xf%+X{D>)Rn6OW1bMqWrt=9Fq8ARI+#0sbSSj^ob=4pyUYsWAE66cl+R!~bU#^&y zo0bsnt;`XtVn73ivN0+_KK zdekHimb8{e=5U$VVmBD6iOO&i@!l*{RJCwI-2eibv41f&{UvKYFCa4f5o_C;PJSU2 zta@)p2*{6uRl+hRf*)DE<6=`~bRsq2Km{=Qo%8ZS!_URhUZjS{=u7Ewn?~m!Ram<$ zAu-HK*^&cr)RABKLnLqNScw%U_$YLk5!VB@Xcl9FDcAsP7*}zoofh0<`V>4=eml}l0w@~4|BTS1qOPY*4Q`dQOcM`1+&uc=&ojgpq z?Q9*sP0lOu(b0^;E((`<^7WeBFoDYJ=}d>fV!?1NlerI78!}gv7zAVfiaJnKW#cFS z#i+0=1zlafdjQLx%efNW;d6Esf}`BRE$JdEq$2JF=vudO1gi-@Q_yUPi8N1#tFHa# z7mKjIV|K^ga<#Sh6}hD1UTeY`5Wqs2uZ-3)muA1-64A_*J6S~%IDN|4XqPdhdh$pT z5??}Y+`Bq8)xd*?P68twP^9^8Y}DToE<+w^!G2f00Qy`rmj1Um!O-D6T-^B?HzfW! ztI~DPglT8-NRYWW!{(rB=V4D6Q7Vr-AXap2AafEY!rg~_rKU`F1m(iFH~|NM+Lum&wn*svD;*l-^yti`KiG0U`a-;F^0&NyBu z(@Yd0IW9sJ*7UK?5SY`7rrR{bpjO9U5Fh;`F*yNYsKpF+DBCLt(!UN}-aiz&R^^jC zinK^|iSuA`-uISJ5ni8Zn*^#PAr;oIdTNvCAD``sSSb7YegUcuxwWjNRko3(12E)l zj+4fm{em0A{nH1wm4N2Lk+o91zf+km#7dT-C6~wzeGJehL>8Cfbt|$Hm`vTvPp{$( zE$l>Ri_zvt5twl3kddCLB&%81)Lr~~yR2XqCrIr_^C9K$d43qZrP%x!5d1xiAPd2k zuWVilhQeD`KNn#?+TyVvpHO{}RRw-D&vaF|*FzUk@$jleFsJoyUqd6~V3Y-1OTp9; z5#)QnxnAKHrY`yCy%ma5g-M07fa)V2-$t1* z5GQ2|)bw`%klHjPls!T5#OBRXF6>WNT6HUIxsRbtW$Ieh<%^;LxU5^(2KJqzRTtBV zK#Z8e2>TA(A;O0_I8;xI=C^giHB)HDwkhS;&p-L}o~h2XiAw-hJ2C{eb3SA$wwClR zhI664OlXzVoVYZkeHs<{yxwPpT6){!H{xn=n9&@R)H$;#y~4xw@Xp^^zj|z|^G}YS zH#C{1)lkk;9Vfd#$qm*Z{W`++*`V&yCp>i@7q~i(s1Gy5ANMRN?g(Z%`Y3$Pb5S@i z&Ny=rViiukm2WkCS4Wp$$ChKH3u{#~Uy*=_*=MRX*EM!pmbaD%Q#vXS^u!@7j#|x;0|OOByQt<{&Pj;SI*q(``aF>3UQmj)V3r zRT(A>tEf7oUIa@>(p=mu8>!dvd`^c#P@4GW$FByZTQFL?U+xEJaoNc9NsP&~1qj^< zUBUWz=Ma;f|ICPvr?h1tqOuRE2gU8^hsbHt0dP6DR~Op}{BEF7Qzh%1-laGnGPa4X z5fjtbp-BxnJ0_}+i@%hRNw#NonNAgY>dyY&kZU300}kGvj~BMJ;|wvazcU%XXZcJG zY1Y|}6etWB=W2w_tPZq?m%; zHK)SY)(3@r(MvOvFH=FR4d^!<9#DClEJ07mBt}bTk@MHdFQQi*}_aZw}I(ojjgps=7 zivw!5{oO_~j&!}K`?Sj3yJK7rFWw@R-ZPh@XMCm%&lSwWjcJBbP)*ow#&L6&7BMIK zFcS3vJp#IzHlu*ATxP`Yd}a8d+>QPO^S=5`6yl8)=lmR=DXvOkB=ymRjMemQEU#da z(OOtRcanW$cW@7HF5+Z4k2H)Z0>>|2OVc3tUK-8K2;KJ+Rb_3|r8GqS9`h~v+(^C& zb36XBXc`Q)jOU1T%lzmJek2&$VrUue{`(@;s5q%H&D^ALECD;e@QsjOcr? zKfI(hwSe0WtazlSnmg&ke<0j)33rhJC1~aD(r)hsgyd4ra5@g>fA&7iglAO&Ey*_8 z`?*%fe*X<)vo@3ytgAJyGCidUbE1BK%`WHC4{N{4;fM48(8*Sn^W>cPXEy7ez}6V^j-fzA zKwIoP%Ug|9sB%^W39oeF-G9x5KaxEy{)&I9sWCGmx^oPuAz7)Bave9I3 zS66y{2}pE|sx4bMF`ODWDmFIHLb4!-nSXpz7J*6BQPcj@)B*P)`LZ_cbXiGW6;COa zR+8e;{tx7Ao!EK5b$x$l+_j+~;+Za=V(%@*0bbM+y((1Dyn26tBV%WD=5smMpCoZ~ zP>Mh=iNqsj#UKjmt1a(CwNp&!4Nn7-iSc@^dFYxB?}0E(+_jiZ|IT5fTRE2vHB;B) z=iiQ9fH36RhW`~0nFY`c*mZiedDP)+F`W?(CLV1?E+DROGH`4}h|j*tz&mXbugHr_ zf1DeDydt7O6eA7yojg2E;3;aOL!<~b_VK=bEErIWq&DHB;|2hDYE(Uw;t|Pj43xJdL$Kol`8A@-Bhaf4I^wss%72z~5>BX&m)GTK~eyU=!1-rW9aq2+p z7*cd7!f>v-7l-!-=c_+_I;y-0{dHrH!C=l&L3^^4jXAUzj`%xjkSNaV*xOcO+1Rx* z{|pQN1s}`j(sU~`3~KW=4<~EL6Fe-@w6$ya>t3J8#rv>_`#CRrSMY(WAN=2X@ruqQ z39qNBQ6K7Z30+Dar6rgsYl#o>e}X5U+XEw8FyK-+EglI;z}M6i$zdQhk;9(&x4vqJ zJ7c2ye)o7wQt`PgrT&*iHSPo!Ol-xC8eGcR-QL33-t$yixS1fyv1BgdM!_l`u)`}} z$|W2Tu$;ID_^rG{hGF3_zr1TPQQr%KsDoQua2WTezI(MmgLGuik$Y|RE|hlsXnIjo4JXbYwf`PNth;x0FgeXEO(IkuxVdN2 z{*8&nz`q5K>boz%%jzmp#y95f%;N7wvg`@Q8s%}gmFPL2ENB`TBDY>N91=Hzor2UW zs0kNnnr`doA9a>Np=db*-vO&UHb zviO?#CGxcC&PYQ{M`mT(Q_uJD-ZSk=J`C^lq+d_qLCafD$t@X?V|Y z={sx3NIb`h!I!Jwyr)KMO4Nl$y z9cRb?xU)VNc+EQy!An7CrVhZX?8ERTZf@^x($Vm4C%e}|f(@@b5vpuq#{9NZH*K=r zpMzv_hJvLJkubOAstw8dW_9u1v16;Z#)yDkJr{mamHWgx7%T))_4m?6dKCu{CrfOu;pl&yL!X5f}NC>*0F7r6@-S}c#>?gM{BsRu|ZZ`3Ns zDV!HUuhZhdyf4>%GQg#J;s&^TQ_wx-3I>Nx$*(7G`8Q3c#C#+kflqkGA9vLwHVR&C zsuS0HP1YX}EB}$_V_c|L6Ig2?fQz0RY$IxM#l|&Zq$bZW1rZ+*rJ;mP;|s8fm0?DMxov$@Dnpv@Nl^C&GEGvBRV^}?=Kd(f>K+0IVEj7_TS%(=(k(Zq1bf-~ z!aa;^Y~(^zRQs8zpGf6xJ%76{#XoaZEpl6|FvacbCyX##$;dH z&6i9vTNs0`=Y%OVxKaIW+ z>1~U{F9I#zd625KZBYq30b}Mb*}4a6#ihgHfx~9JrSO`>>(`_de>o`%GNYZ+#e$=!Uw6g%A(i26?et~l~nO+)@JpQ zr+z4M6T8V})lhf^V&hzN$xcd)UiqGT76W-8F4qONG0YYTrdTI^wHYuiUMP$&^x*#} zUxQS*O4)-m1sE~9r3+{wBw411?*Y>>*P>h~!$vU1=J-iWL)GJA@zCYG@U3yi%4o}z zEIFw|jBRXvy*j;?flGhG@PQ;XZ%@vNe=t!kyra{=t_s> zwD=lgcTy_Dm$5!=AUb67)esoN;Er8T!3>CGkh$?65>z&P+3UDOD%Q}Og_>n*g%;IF z&j;Rw1lMVs3N@>don`8y`vlAE__FB!R+EvJQlpXj(xxN=$Q1?m31fxeA$+r;w#nGl zw6#NqgfxW~u7j;{q4CC4hx#{ZuaNOfB7WVE?cZ|hoi7)a9CR643-*+ps7N0egr;9P zb|C@9?C=??g;Ajx%|Dg4b#S)H(gc7r*H)@aBNt=5s0AWEsoEQ6AdGh`P=o91}|{=yNk;Ifmj`3Eo??je@c#oFt_LWYeOZo{{BqWlx=| zTAwX5OL|ZF1D6qtoP~1>BMuxwW8#iHB9B~SO(`;^!B0DA$irz(hLLw0;tbEghHS4Y zpJr!Uu9iG$<84*u@OnZzgKKiWsVjPAok!}h3_bX8c=~a!5HUWa>{7Y=162-;R%y`{ z!j8`uGXiuQ-a@i|`gg@bwi(_KRW;uGkrpH>cNcBDV-3jH2K<6(7aCYm_qPiEju1YG zY&)*aGjQ%qG>fpeJT)B{ti#jkxq3aRXP=L$->^p}(=5eyXd} zEZ2b%Ao8coz4tl;o|G0v2^8+C@mSC}qSXfd-|KyAm0Y3O3ojj^Qt)wtU zZ3|akp}f~tC&rMP;C2N#{$P$k!Rn?&aN-Wdw2qq?oh9B~;_5=YPO1Xh$hMi~tt_>w znvu(K`Ni^64SE55>-;^2ZXvg=w$k3xM;M9eo(uSZ)E19cPYZ4INN@RmI6Mnj|BR}X zt=-*+_U#GW2~JL)=8RMrUjO!wqgWc#n*pFZNyhqh8>f3|71*8TLqspd z-Yj|E@bv@!`^w{X*DG*#&-_aMa8mi2o+eA5*`FK=8TWSliErz2A;00k+8E8+=0Zss zy+eN+m5ACujKwyJgX@##e>cfotN5#^Quln8yx}E7qu`g%j_Vk-U9GShGIO3&6YMAA zd+Z=?*wycyDQ|&mMLFfRo`Ppwfmurl&9s-tI*p$sXdAQPTPM4FU33$21poKU zzP9`?va%KVmDjsHix0HuSo#)(*pKi`?64Olos#YHB-VzjmJjXQ#d2Hs}Gf z08+!tp15%(8AfVY`SHzkLVm0CwS?UamQm3*1w@u%bn*2NU-0-n5Dke3dVFui|NZal z*#nAWod)u8stk8>0Na0{0)MYXt~PVnqsgP7x6@k>N#AVcQrMC-f)z3zz}hw#=T|rt zw#Mqwp|yij$fKkHE-ym|L-#H~HwCd??&5Xajm9a?-VtytmM zDe_f$9G;dR3ft2#e!Uwr-c((CZ0O1`63zf+_#ui|2Hn^F4@7(V$ev*Jz}FJ*wbsu( zn#>@>Y$DZhcqDlizI%6Fl}UMMCq;}os$WN0@*OKv;7Z08m7{=A?rkMm!iy?nXA~63 zB8K|29H{Mdr9-vDh`YA49ugH@twsXG?(GUMc|rN-u`;CLa=F=!3>yoPi z$*1pRxMCxJa2urLD|Y+NIXsmT1RX~QxUw(3mnamKn5CpdnD%Hrw+Er;j4RLcju;Eh z)#8~XuR^5FqdJl?%v=LEui?WVIt9d+_#)C?X?n|cM<`tU(r*w)hp+rZM*%$&VN;RV zy!9d<-JNcuTqWw7D)(5RcFs)EpF$}4J!13^Q1r7-zm+MYbLta|OY0woZ^@ltExARXxRn`B8H+(%U8#y-r*n!=!#+IBzTq+cZ;CJ>t84z;2tQ{u5;;q z2H;Y5;8)(+Ra9YTCpV1H7-)W6JHJHpnLS#;SczZ%on_zQYHnNBtuLxNZJY?im9D1p zuT^j4{84zi#~9EubMZ?{MDam~z_3Z4__qo}lkrNn4B3j^CmbS7jq3O#i?CQXZ;yA{ z8o{bpVrJAmpPpV1B>oiV;RVTT^~m>0ZbX81zF(-+WEEO#{i3LdILfYhtIvN!o#sd3 zRdVr~4X-$Rzua>59iV6Fd5xL4DPRk7Vjdye^-@Do$B#4wBQjmK+X|})Xr@f~AZXEv zBLoCL*&S8!HRzbKI)-DD>9lTqsud8pN4&INFjIAP;kGMe!=uwshR4N=(JO=^cav*> zZZ=lo%|Rz7KN{GeyU`MT4vytn81s*G$_!hcvv8#8=WOz zSSmaV?Su{k^t`N2?Xcm8iAUB7@c{+Yatbf}F zHH|o^87;lT+N@p9L_3g_G0zVwIY!cDM(IN-e*(X)#w2a-Ib0)>jN3l^$j9CsQ+Sl6 zVv4F7S*Tk)pFcT2=20lj46FJ~sZX=c(2TWg0{zrkN+xRfcbuL3sk^<84Z85zWYr1p ztz(-^ubK(^17NrFcs~`)65hJ_YuSFQ`4{X{TCV0uf1fZKCQ-Sz^|7<( zPXaD&+gqo_IXp1q{D;ZqFsYm5OPP5-LwaTNe)}hZS-QZIR$J*xQ*L-}k>F$gu}I_W zReSnG&%7FCNS!EZjB6f0_wtZ-Nh4<2-o;ZR8!1Do!b*gkp0PgGPw6_@|AB5iycNv3 zK~MbP9j{7Jqxqkt@2`Z{O$l%2Rd`B-(z!uHhEyu3A;^dF?9|ZNPbEX8bz>u$CUrStu4|PPr%J^`)yaN@LU(BR%U^)G9A(-#F zYY9%!mxY~Y!vcJE-0+$GkTo{!)ytQ@7A>wa9hXo6TN$)-3|AA6!!)eh0p@*w^y2=@02w_|M z614{imX?0%#U7ip@5_Y@nOF|;+Y9C6cmX?4vV5vm>67p{AoE7OlxMM6uN#6%Hb|Jh zk@g%Bw$<{M8XmJV2B{)@cryRd7Rs#oN7eVVJ3a68^r4eqbiVcDdX2|KguKS23a1@4 zUF0m?fSXLx>~}!_On>J$$f|+uiVf$~HbNKs8@7n)r1#gqsKL4l-kFX%(o%&3`u%C` zmByffFxij#*DBlTO^^)H`-+ffaGqYF} zeBT+pH0ZM&FXCr(_CC9{;$SnGD4ikcqKlh}_EW)ioYZP5rgig@v-Jf~?|bWcEkNah zIiVCXX6;s)!AHvnhJyiy2#B8G7=u%rs?oF znjdPWm`@e^t*NjN{T<3|JH6Dix(U1M)n1R75M@=#*YyM6 z$gqG#iFgRS-BPU-^IaS@h_jP@N@O^P?mxDn!q1ex9-&FTMxXC-`+ngz zV`y3mfCtELGrzKmC=-vQ2E@f|r~xJ9eAULkF=*C5FHG&qdEfHi{Y3l(!^!BPP=4xc zZ;kZ;(}?lQK>=N_M2#kwB;k<;IB3_f{JrTC{p;5{FJ+}=&@{aAoow+aU&4!5tOXq} zW0-KDwn7}9A)E6vxG@$2#-%KQTTeq-#%R#C)b!W9N1?z-KgZ7MS*^*{obxhjh3Zhw5S3<2G zvgEQpvbCyPbd7=gs-C5rsY<81zj*R?Q~BBov`>{5vyF-@bFNtucuk_ud^jgBWL#gl z=-NKkp&iyZ(p!3W93t^Dj1VD3zA=pO6Y<%W2hP{Pn2BGhY^~#04_Y5|?~#=dEI*XV z*4-qa*2bbFtBDEE730jhs|o_&H#I9B-+^o@S5kSyh2JRHNH^lH{nGv<@YE|n`o0(m zN&y7yCk5?R2?GBZ)Hu&Y$w;{HBz0(DwI*$-IjFVo`8g8W zc|to=C%phzhS@LsvO?zR#-H*;BVC8s>CYpV%&i;fEl{Mc`_Ei>648p@0HM}YCD9F; z6xhj7*V6890%nx3`o9VG6#vWo~pDyOLonJx&t+j6NRqT!L|XABpfe-D{S zyj!3>aaEf_RCgX9<@uoS163&zF+`Vx?$-;B@M@&E9Wj)~`#HMDwx&HC=refD;9Sy+= z7rF^3++&(+rtjYFN}M-$fP_q1OxA)?;KnIwJz^H|V*X7*^YDE6l@g8b!|F8;44wbB z=nwTy?ZoO!YS4A`u&jPEEp0}y?nhCdT6I)RGw(xnkY^g1w7n>wEb;KoJke*i(|-jo zg=C9zgU~`Ky=I0V%`^|_nk1bkI0g4IQNlE3H_IaQK}5f6U)zbMWN&)c&(mi5-W z9Tn?>iTyj-&-R|fN!o`YateSzKQbK@@9(`*@=jKN;9Yco&nsd`@0m;sEk9}CWzGlA zWZv(}n%Rz7ME^g?Z3w&|Z&x=z#fKF(!9snXw$@SN^QFNhvdAc3UAZ>SSY<-OV+oNV z^*{y~us+pvHa}CCNPKro>;LJv(Nn4NBG+9vgGporTqJ5OEa%=sR_4Pduw)=sz#=a2 zq9M$GYuMZnjWIRrHzr>S=)Z{7qNx4{`o!=*=a(h_pKt-%@Je_Vh|%h_90jEnNt4_H zZITZeqknSy5xB_9i)ZisN5_KEJxW~)4@h+~J!Y1jn_#lSn6P>gB#+m?Fl7S$`2piK zhBKprnfzkS%%}6oa{YGTamfoGWV44NG*w{2M3(7|KI`lEgZf%fmLV*2&+Cq-fF8aM zKtL2n-1wma{V9!T=2^&i%@@`N1T_xyn6TF4AiBn_o~z!@Se*h}H@J zJ^r!ne|m8H_mDEogl+0Ze=LU?L}-0`lrwOL5YKB0F<>(Q&lZ9kb?oLq!ktvmtj~X- zv7!=~*t8V`kPpuB7kqVyYYmCN-!}V@Dk6=lSbHKoB9`q1flBH03xLVmM>`|YiKEZL z60Iyhfas+y7!z;JyhpWhk-oMR^1+N)JF<0~whR6(s#g9(ehZd97sc`GeWVYbu2 z2~=dX-D!k(+k4oS0tfo7Td?;RJ*bI_wo?Uc{VoQ6p8{pLBs+T#*EXd8y&WtC@3X$5 zz*tu4G{&~-AWvdb@c<04wsGerj8#DF7eNz($ zXa+0jz8{9OWE)yH6d9^zre>MRxHOMbDbM2vE!iK@J>5O0o&P{yC$O?uwG#ZgGZ730 z&`4l~&2P+>|0Lf|DYTs)I%K2k>;+R7l+K%1;>>M0MMOWzIn0RKiOWNsFgEF{!m39? zO3%XLHDY~Qq<8mw0^%4%wCBuKEf>$)*T-uowiC`E0WXo=486J=+vReol5}W~xzO#4 z>QXS$Gs90i5bZG4A4c(c*Q!$W^<1)TrP^Z6{*SKr4rg=!hQ-02Ic{EC)1&A@^Wpbz3NbPIWjeX*<+1g=VZ*V=2y{lS+uYH5qHPWk zw~~0!-RS&!wDmw<)b#NuQO#c*^G^~H#c0gR!&KYI$pP; zFVlipeHfnsi-=ml9KFQ+wg1?fPnjdV9kv|0d;S0~>EO8{M+d78s!3C|^|aW7_PR#U zs3AF^UQ}#D-Oy3??hyeF^U$g422;Y;nLdkCioF_zlNc|SK8gL>uyf#lanKCi7*q^0*IPBGLnpd0XYv{$xaal=nj<6~GRpp5q7?~Zza zRklwZ*~H1W)W6c}Oh3a12O!-DI-gE~g>t53{(}Mor#I1fTC}L~K$Oy0h~Y~)50E#F zKD4k;1$Kn@gOr39I9~NW;o>BAiyd^&?Pgl&ERm{ymNd^;+D=WigEpb6YI``})}P_I zE$T9qg2GFm9Sps&!z~kR&>mr9AsrDDQGMcj!NaxeC_RJs@e0p2SAiP{@XgmLz?wQ$ zJ}!t}J7q?buFUrxC~MWTL}_zdqs_f!DBa95S{HGJg}ED+i3fh01A?Y!?uSJiRM{iy z-O!2lky$%;Ymi`xjR5ZzPAvGzse1{*Oe{#vnuT10@@yY=8K-7F zaskOP`p2np!!k0q)D3dBG%M}omD;rnp4wiK{UuSv5>(N0=UuuRD&Z2MLtbbZIkI;DFFV8QJyVn&!s|kv%}H0;nFp8415^X}pK;b! zG%9$wZ!XmwUMwMb)Ki*+*rRJ5EpAlmT*EQ{EtD-6#b&u^F-Nbye~m}>^kq;wx;pZ6 zPQ0jy+WAuhg7#T>{o&nqp^{z#>3xW(O6+?!VqW@-nb zQtYIPc}O1!`w{;LCBr;>UqJV>SqzuIfn7u!pNt z{J(C`8CdjhER~PRUZa;vK4zH_P;T?y(qo8hUu(HoTB=d5T>4XD!VdL0wlzEdSv8WS zhvD8JqOzD>w@hHl)##v`OmLRW(Ed3%qcaKV`QN+feR{hyc>d3n!#K#txF&gU+q)Z- z=w0;;Pcv5uEq8K*{Wlw78<4r4hF=GLz;73rF`i|meAlo2dPlm&Xn{h!RIUiSLD{Dl zUz3f0{%1azp#d3P1@;7qJ-t*$At)VPoQvxT%>L@l>v0h^akKw*Hh}Y_Zm1rgiM|pz zybZ7T6{3jC56&z;fy2DzmoFEpr;lDTy!v3=)LT#qK}8Pt!DVK88^Cckzt2Z)+y_g{ z>?Gp;Y&UahF#2)R4^w`*1LVzAv@y8+aJ)M2Nue<h%mNgeaYgM$y2wrSgw zd}}`ZQyTCmVHN1g7Gpt0O;;fH9b5Qr2^C_i>gj1-!&d_p1+YA$mRGKtTfihmFlGNg z4DA2)gPt_Fimg{N<;#k2hWgf4Y_h@Lcq z5gKtyGNzy(A>Nu750Bx?|AFRe>T-EyBRk7ur|Y(V<=wEtjSSxL@&4qu8pNN@g}*tr zqWLm!*1%b}CoK{9s+|oj>@k41C&fQjas9$+*`=lo%VExxTY}>vm-nLW$rrB#$M9T; zQnlLr&RcF6r1p79T8(CZcWZWrj!&{jY4+DHcAuBd)2uE~PFs_v&7d7tSjJBad~Ud>PgS93-j4peuww4$=;*vm>a^sPXsOdou#vgn>~iXtaWsPZW-t49 z*7aY^<@V3Pye051t~(#3i+-(3$)vJrXT9U=c)>|&>poJ{3EIsld=aFpZ=(P34*Dl^ zyX^bHQSGI50OPJVb$#fvW*-BNeKnt-1`~5>?e5-l~1DMaIEyXS3u(fmu^i>;bft?a7wGH&mv+2b4aHxzl$`Y! ze!Qh%(LH+p!JyWNr?|eLPt&SM@_Z?$i%t5727n7x3~#TwIzJ=|DQ{bb!dv(+sPrn4 z%L2IfrN1<+apR51k3XPopAit>|sOSpL+Ft;v-DPyFAATSei3|a_(;`EVsNo?ib%Ug$+J{lXpDkh(2q8xT5=M~ z!~P^Kjt3YB^r$aHrvmoPtp#+D{+Q_=$4abIeIldrq-h8e%3x1So70@dEcn#ehBQn|n68+yez9^zv{^rt|O=gLKn3sX% zQb?Y*-uZ9Q(h!>!bt52pSTNloQh*Jb_eU>=o{U=M%Hul+O|JM#d)`^PUJ!bT6i_q` z3uMjALnU~4(n2^{!M^cBbnTyE(j-bavTJxi$5I-idaccfA}>z@U+&qzSU?P82fz6z z2)ix|@X2uMsd4Hqw=Pi)9^r3%JMzBtLFZL>O@v>{;9eB!EcD0Q1o#a+zPRLzfDqX8 z!5b>8$;tjI_u+b+VnY3B`>KmD3kPCXLJ)y?KReI zSL6p?4jl52(bB5l$Rg-i;cGuecHd4AD zE}MI^vQj`*=wVw6fuBoxbEB-Fq0W2tuFAwrGerqCbhsR~N!9x>ZXfu?zjnT>s5$}M z>K`_50TL^$H=JEFKqTwtk0@=;HEPv!bDAr)iis`NOll(c1pGdrP4>(UIGJIhntw}*CULdYCq7Ifi}wa0o0C2=u|Er){gqeYUaL}} zK7>2mpKRx=9^09ue}0a1;mE3o?sgQiodq)Rfz{(wTq#ar`24+<-yWr~ilAZETy3=D zX#qnL?gUX`bSohufJe`F!b031qCK9meOCA)p}R_^LL+omnX>sus5a^d5FO5V+H37{ zs-&5X->LeNi5Z2lI^#^*-RAyiHYgnloav*_hRZ+PxU0)exz2_F(+)ob!|LLR4 z@o|dWzao>Omqv}T_-GpdSlonG+Vi6UJPk_=&l)*JRR+JKQK20c?eKfnKIM1+5^GTu zCLrG|Mn^-42j6eD#&q6oxCa4g#DF=sx{q9=7Eo?XD}RyhmM_FWm}C*NdOGrBf>)b$ z-@3g}$pD`=>1z6s@?Xm$Z*e8sY~fvDvZLSua~+=w!I;9!k~S}lowaH~@-(RGCGuqb z>cpG9()ZasTl^rFt4eW<&tbWU%{}!G!W$)i6}+!0n9VKWq4|1rh#2#ow@@81(67hJ zcWdb~Ylg#T(_Yp^X5(Q)+W(A{{jMs~y7wg1cD?}V+-tZv{6^`+jVG&|@3gnuhb|UO zCYe<T@%AS1jbq8Rq7?8vl_I8Fsx&)4FS+!v42+I ze~PRhX5X}B2;mu4;ZmJ1+a4MQ<~|ocaS2tVSKGERIEkaWlB}n)JJ6C#D1?KNo39ha1W)xPKJJ% zyGdt$aI+|*szU)4R| zL?GI~NVEh@qlyTA^E54dwqiNYhcO^*4vcXlNvx2{+04v}xVJJapPf}2<%x=O@omR* zMBs#oXVbWGRoD4JBj4-yim%@vDLLQpJ?Dy24^A^RD`CzQa1vm`4hmrSlo1lfkiszf zHt7}8^jROej45G&ywcL)du~AD9WI=-l(S-|WcrT$P)O%vIuwpbr5 z^7=ickt;oe73%*f3N`*WtICZ?3$rj3@ZT`tx#u^!E(<-2$PBlAE=ECt&lw@QabEwTK+8U;GMv3(IzSHTZGgNjwM@*?;3fz)MlTN zUto5MAN`_JPPUclmfLXiv^bC~b8BgGc{nNrfn0Q=4lSapCnK)^EzSntTu78*x$@1A z%CyHlxPjIv*I}yP8WoKF-9{osgViwAreO&$GV}^9yru&_#;by-YCb>E=b(2g2ys4HImnjyK zDwC(TGZVrcT;0yS(oY>Mxuwr87N8p?;VJWii1xo(e{2v6;(*VBQdL~2kPz@mdEIXk zU;8lcrSbFO=h|hxWXA%BZXd&kyQU=0pP~V~WLZ z4&6ouyj#(A;&0+?E-_c}So@HvijVzMIn$=QgJwnw_+WGqGrjt*_2dKG<~qwdqVUC+ z3>+@9cC>eQv?F^@n;ZXrs>kfzGqY`mAhjI+8|`0TP{pQ-00WbT{@sFF+o?$WMqTgf z(}XyKW&vX8kJ&IQt(w;*eKLXa!alaFI%uur`PJy>07CFR8=GbWk8P2Ee>u`Yh-4FG zfHhvCxE!uCmIm+{a9pZcm#%1UV&NbDIv2MIyExG@u@KCE{hf@->2+w8H~t8ynPBO) zp@y(g*-^8$9CxkC3Hvx{3)3beSz=DFtE?J(ZP<}VjIo#&R96=#$U2R$ukAVVm01Nr zj`fl>S2=eyPd0S7t}%eh+w|Hv6LAzaXJ=b;v{o4R(w4D^z_eB2vwv9rCJCb6$>tdb z)AlXaVjSai2+>hldWfJ!UDR2Ie5VZ-(1@zkn0QCH$>SjwGtx4G3Lkhx2`02h8cBck zk|1gbEtDMJl~K-nvFtoM&-gt!Sz&CHi}^U!^&Xkv1iWG6I}ME8wFwnSzOXPGP^Btr zZ2YLD)D-{G$epOJ-c0UjU}Tc^9L^}3EA9Fr^Hxh4Z^Kt?ToelRr|@TpUHc!-;_l-E zqYo`mU0m+f?;!w>jEwzA&@=2cMuU^0EJZ zJE|!_2s_%WPjH~C~P{aja>;rv1C z|3IVQ2$eZnW%--TSLK#4zB7{+Bz)_>w|wjha3fy_kwZ8>|1R&xm$Q!C7w{4kbqG<( znC7A+NXNuwNQ4s^-SI?ah88UloYcIylSXwuS=@(9hQH?^dZjyb4heDyO-0{h1`2YtD@2C$lsLbK~DD(!Y%#WHx+}#B&9=E^Y4v zBYcpuJ(2tmTiM*zWDX>>n@AFVDr)XGpzgX7!HE`{Od#uCVzS&yG*IIC0Zfc^X`o3L z`D`)PF4{y%7;YrTo+H$^odI2-aK}Z&j{D89$&c{JU1XT3A?H*6u=wh8CrMKWPScqV ze48McCR3f(mSn5%%3F&TptP>#jog#Ot`-shS0x_{4_Rt5jj=5k`={CU4G{cS@euRL zLbBp)!*~;LGEU;ER>SsjMP~b_t$B1fz<6EAoGL@5FP0}Tio5_{t%b>#Mq7=Vz6#fs6IsN#l5x}VF@4(q zXuh2fJkP!XW!5hFIy~HiebArjZ=0M5JVC0k(j2S3?dU8d6OW72L&>DSpl4uumBm72 zOc@;I^4zj-l55okb)HNSYcr?LqYdz zmbK+)!hAf*J&1z?-JQa;2bYxA*ihh`_rS`|!+EQUzW*X18JY)7HS!7jw>@8C$G&wt z@?i`MY}BytI?KeqHPZ>2ev?w}H}_s(=m+?hA_^lCw-_o7Iwm!q)h9%`KxIi>JE%Q1 zn1_g-lo>(bSTXkZL#z?05IUu}4Y%bqX^yIPP$oAHa{7(v>G;$N-A=Fj!~y+DS*g?? zP%U-gbg-5(xhZEJ+z>6j%%{_8`geE@7{q@$V`V1m!7iUjr_yms8uSGNQ5h333Z-J( zf(@_Y!z6woT^j8iFgC+i)u421LXdHpwj)j_2y(7K`Voa<7+DBra1o z&bXq^G43Lnx8i=3RPaBpx%xa?p^rBM=R*GbMGTE80!UQNb<`L>1by?e?QQr%M#h{r zxt!XIYM)TeK1`r0B(nL`X1{RFE29QES`ebzxE-CP%Im+(5#?UNCz!*L0b=enJsbzF zmTlwyM$$dsAKPY)$LCZY*onjR{tkeSzbGAW%*(Q%yj^Gd9VmI2;T>o)&i0)B&y9E0 zlv9_5L1tD*A?W$>2A|dDZOKYv|9Ee4t+M1at8>j)@@iz0c~rPr7%Yd&dx!5ub(+f) zosR?QuxEKri`!b5wE+4+Yb!e^Z&AFjEK3 zU4<8Hgt`W*=mEp0!3d{Ns-f5;!LdISg#{R(iM9ewdcPa<6sk^>=X%z&ZaXQW6%s4^ zYfA(=*H~9xx|;h(L9DX$4ArZkHR5jBehy$acFHy=VAGKlHfouFsfNkhWW8Eq;pVdq zpUB3R6IKWQ8_hKqKnFHQ1rjgS0DgGwATzyY{U@H$$9_IBvZD8G>~7xRk838Eb8lkL zgkn6CTg>{zdxZ5FdKPHpNgugB<|5W2?h(}qNqF3uSY**2a}v>lw+Q~9oBVcSe) zhEi=mX0%g*k$xjZ^T6D)IkD4KthmN7<)@v4n#;u!q~s0%rtBgc|C&vl@IJuosSo=O zq7Fhv&(%|VO!=laVs!N^l{#3>r)+o3x94cp&#pmb{^&ZMti#1`g%D|oRdg%jNK1Ld z>aI<$l^6TcgugN+>-Fm92?7|}+w%CICQ6#PXkhTS<~DA|=gwuQ9wSeF$Q+rq-AHtK zidkc4;LWw(z>SLT4nRf?b!8KhCUz}Z9j$%VSrx2ByFXpprCR2l%7U{>taIdv8a!Z3 za7VEw@6qU}L8A%#-KGRPaNv_>-aG{wSV6x?%w^J5Vm|$m*khrza@VcMH?||&W8=BN zf_|?0*yzb-&%6XDDw19_$?yGzOxI~0HO)t6$|sH}p4=HXXa7WLB8vKr7M3%`B~;E< zlV*@^iC8B@7F-LP3;C{)62-O}{Rw|-zWR$bZ>6TWr3qsGEFRjry^0y*9gdIdQX*MU z@!KMoy>31u%`g7BBRI0|<^WdAe(Lk}_R1aqsthrmK-YuYP8>5bjJ|GM2G0*&YZ4i^ zgo8ciwb|B{Eo>y?o6H~eYgo#N=VUiCj;p7SOz;lvU!30#zQzihc=#rb&)#V$HI^jh zWxO?Vr)q?Io2GSHf%(BEQ}t&XAt4Pr$ET;oZ!5M}(U(u}_%i~l&DWTJ>aaa6lXjJ_ z_}_iE&TI>ImqWqUzh5lV@HC!fI zTxOV&j&NS3JJ;+)sb?oJN%DF>WEJ{-{M|qnnuCqM1U%Uxm0i}LEULjZ-PwZ3VGe9D zW0G>W+KI~{ut7&#nXO$OS9>qVsiXw`=RZ)t3t0#eOr>T<1x!XglW41ovgmK#aX_@vSP^~KekCFf;{@Bm^2cVXIu=sHSnmHQ6KTA31OLw}>M^7-%9Me!A7Q1^E2sqad&9Xn_5{>2Zn1tGXZF`ozc&FQ+kEX@pt+pT;--=rG zx719sV-sEmh<(4}->7ZL9}JPrgJo&*7M9MZFhe_dRO_UT36dShk%2E+vg-2Si;sqgcA#N!rAWv?QI zS1)^ea;27jn#cza0ucq)aoO3C#i{8o_88Wo^_N%~Sl!us4PTPJp~=}fZ9b$w|ISR5 zv1a7yMCv^LPs(1|o~~5YlFY2tohx?JTh9QSGc}gD3w+`}q{~ft z28a$py~x%p4TSC>B{ltBTy2$q|7T_T-~ae9S@02=2%lh1PC-h>a`Gh)C32_wJ%?HZ zwaI~*zCsVa@<%@hZU&3)J2CC>d@}z{QvrgVGNwNlv}5>_h5rp&9ko^JS6=YfC4~B* z8`|4~)y}ytzV)a5R_OYmRaP4L2y;w9UN08>qV&^x$dnMaKccQH)pg~IxGP5|hs5S3 zVui`pa-yn`TwWkObooE!XGpZS?zuSPCyVcCW0WFt9~t>JAdCHwt|3lg|2alBV*aR&+Bn`E1} znhiawfWjG-qN^?de>GW9*{1qSF%q?r56ZLDAAtJ0yRF9Qfx?8Kng;`lsz%>mzUS^( zlnkTX^hDZ=^K8vdgt?phHFJWZxWXHm;0ixRr7%6mg;gQ za2hd|>z2qIKTCY@xmiJM>bnh=^afVF&R&M1 zNp0Hp-(ii;+odt@jdIgIH8=XfmlZ7u4w}_;=%`Us*5XsioLhWKNlxsEOf3ts_Cxb! zc?y05;UqnS1aE))2mbsAUoF+hJ*w%9Ez4n+WunGr!YYNRb&Y{|kw2c6*Hgseeou?Gv5U z_K#e?Ra!k6Gjgysi5KVMtR7yxP&-C)U8$S?3(KCfW+NbJnkDW5nRIt^P=QH{mOMNS z&QM+c^+tjDt(kc zPe=8K((8(+S1g~JNwv?n-H>t0mz);2fF6F%_%w8~VRy>RhWnmLEDg)%d~?ia48Px^ zw?6>EFfuJ@evX9bE7PB3Dk1NY*j)C{lS!$st#V%C1i+|QeF|y3M?UU|LP$55N;Sgb z$^%SE<4IW#wad|bR~=eQwsmVMC)m0>shB4<3T%{I^Tj@v?dUkGvn>e;Z2DIVMy3xD#ywPjqG zlK<>1q52rgu^gB<>w@DAK={NdoqqKecUqh@-3%HW9R1}1EIM*Z4~-N(du*H=l`f5= zfBOD;pT+$T42nFU8HfXs7%3%ao6NT@Mrk)a*R)d>*4@20vty!LaBA!AIGHca9`nN; zx}G^`I;;t+W3ES)J%2a0B#XCY=#wSizdpVpx5|uH766Yxz@ys}nC@Idf~`>FdP{$A zHTTCnuNKs(UN=7BpM!}3-cFVW<;l4-Gf>4f^HH@OMbtMR-&*fC2L_=#yT}TVqpRM~ zGyz?y5aAJDn44zNJezappRYs0{r`$?xiJfUvSd_*tTUY_+ca?xzgMKqFAI)t27Pce z<`BZJc(!Y=tB5KU6>a|wt{v8--Tv4oaEZD6vn&aOOOKs7y{CyfH~kbnSD#cMcYdiR z$;RUiJIPK-T=ybG5tgN`v^zESD9;9duMMw$mw-o)o%s*HCZe1OHnF=!klMG=AGDGt z-=soVH&o;ZGrJxCfi4xC0nvw`74xye=ksNc>vHYb`_jt^w|w(~W~Y~6pt#P8?8Ulk`FxkbD^4U7qB)5o%z1~sqP2r^{_7q5+|sev!zwNR-; zK5SY8|2zYuTT~a~ySw*rz{Y6<>#Q+`-ML!3pueL9tF(kM`LoKYgeOBDp6{to4{$yC ztgy~;e-Us3pEoVgrbw08U@ZB~KlQeH_ltIpxZCysl3ozX%1K`Eq4|oQ{MR@maYJ@C zVH^~;+%J6E8rh}Zw8;2&Mxmv@o+ImQ>@t@DIXk2c5A59Nfna); z5gb%YKj6Q(P%qsz`GLnW1fD}B2eS!Z+}iDAv}u{))uD2h&r|x)4QL1-X4*Ptg=GwT zJW34wtcB=n_WGP(z^b1ha(M{@UDWSW=Nvt{auqZ2ntK21$M>EaT z+66}|T082&T!Z+nZ{=R%LHvW-HU zc0Qk{zvKJKK-Q;xUe7*H3b%Q||2$f!UU^OY4&Bo^#3VQj84I*1f4;)0L9FLh7I@GR zNu+B}ya~O|4I!yN#UfsyGs*d3mV2eK=^JR{Pn1w?f(5Cl$#5?bcSpjrfSsR>g_G38 z*B>{LHv+U7tOj29S&k25Hj{l^9PW8IZ2lcT!_GFdDkvuQ2~z9(5R&WtmbufK{*Ozp z!=1XDPj%V92#F_M@n2r$CemupSTzw${Nn^8g<87@DYh>S)#l)0--KOhTgE`0x^#7O zV|4m^gxjy+`Zg&$>EXH?(0XLlW1u`3}AV&9u+>_fdD=<$H|#rH(E%N_AVh8?F#_##0r zw1`=1#VqEO`TGO~bM9_;!|TZLyqdACs|@?&?Cjb@$k?;z4<5dXMwcg#?WP{cQz8+{!L;Jq9qs zuiAmSuZiLp?P9R+%+9ef8kU(|OAY`%rfZwXJE$3O7TAB+`+)afJ7`OYxa*^PtX(gH zy4l&!lA(ygsPjwsd%b~Gxo!)He~f~he^7-S*O@O`{&8lnoV@Df8H%4SsEQjZKK<7lu@U%jSzcNXAdZI58 zaV-y?dKnsIb$Gl#<$z=F6MC#?#-a4HcQXt1)6%3GA(^xdMVyD%(+RI{bvfmNc0PhlcLg8T>S8^UIq`{#+vrW>Sxwrj4 zd6)Hw`i;e<*X*$z^gCsh*PTXf*;6t+sJc59YntUB6NI4CeUyP7s`mCeRc+%chH8n4 zl9z#c`Q-Y5Wh9D*&LG(6xWqv$z21$B?%>;f{MDI9usuu{&hJ{GOrffD1l3>-WG%!U zSScJ=n!#Dc+)Ah;aj^ojpZ;4dLW1aesUvCW=j$Gw z2$$;NsCB#wtBNR?aoI16z(zag*0)MJf&8 z-KYKoT}J#;jsmLvm7mGLHcSPwF*p``&p1H_bQ5DAOpJWA@kRJYu^+p*qxQmZ593c+ zD4vi&S;5hdy0spp$J9=!=R7X87XEGk^+0Q5y_h*R`M4<=BKI%7zhC%S->2T9`T;A+ z>cbrlJ~pwMe}GlO;8~Cl>bCYDwK6*-0K~<)y-4-2<@H)Dau_5(zS!RK&|oxNIQCJ5~|eR--U%^<+jydT?3usdjY!0zFfvlyhpXKB@UJ#Xan-z89E)S z5gI!G5cx6k{QM&JQ=3tK)7iWPn?pmzJ9vag2u$ES!{R&7r>7LQbwNzA!s`v{LU_OhisM8KG%X@yE3!T`}Kxu8wc8b0N~3 zR4j+=Wj+4KX<0UB{ti4Ky3@sT>m49dpW#ffsuSnpXhM5ULn-a#PbRcw4~p1@ftArC zebYFJI|-ii{d1b+wR!RV3?WhVt3L|}{|me}mPSzDqc4X=vD%_tgt+EuFkVu@W4(Do znnOdMe`~vzzEVTw=%f22_VeBGiF?DSS~atOw?IQZ3Uv(x2{E0y3f$4G+|@XVFv&0} zXG3zGR9~W+t)(WJvK*Mjb!+$+?8EbH|G_;8c_|f<`M9runLINy=$E6GUXrPr<)2w^ zSWEy%V~!tndzW4{_fYWkkC&MejAmH_uCqnuYQFnF0l>}&cC(HTobM%(;$M7vjM$&G zWuiZFL4d-!k1xCvUh_{7>xmP-BUn5bW1M&A_tTG*z!upMc7yO#Rw06&^*Y>UzWkHe ztL9M6*g}ZmRmOX527Jbw$wIvi%y%$^mRHc6%8K!|rHQ55$eG4)JF#lY z$Z1XYNb4Yu)@_+ow$d$(ti4Qz>49h1kluFAKd{28*A9oMu)u-g%%`%<;%N1T)E1N( z0KQ@?b)3}OjniF-0eYA3Zm*auTCehyB?jUUc`CMK0dgip)uj^?qWrCA1kDwm(9zT| z9#N%#)uGeSnaIRdv*pECfs&vhWrQ}G`1w*QyZJFYF#`7_m81-c5p-A_3-?m3uP@>4z}AMvZHM@)oWsfx%%WaV zAznXfo}^yABarv;fh;n}s`;^s({n~6+ZCuk-~Ef<;Qgt{&dIZSLfUV?m{!sGr&bJJ z%gZR=xzZU=T*beCH}7sM`8W-#_CM5JE2GYHQH+gCy$`bL|LlOjn8g0c>(Y5!C&QO& zq<8HwEz923qmOT-yJ5Csf50l*w-qA;_ghiX>~or3v!9<}a-5v$yBrH66R-cUJhUiSH3(nI~6l3|f8LkjYh%skU)5CGgIAuhCZ%7io9g(dzb0BFx?UuUsV*0mg|L1&z+}xBb8In}%l8OBpZ$D0YC*BQ zD;2Xgjmsw{qFLrMaebJdq13a$VZA}ji)SEixywuMZBhm_0j+B6AlYUOt<=<<+WZD7 z0mnh-R;H+;I_0938^zK&#b3p|9=in13kN1BVf%h#oIi3#cvQYw-};Qa#RnNiCJab& zk-o%VF4RID-4E5`VOPnae0{T2T^EPVwX)ZU$ekl;qm4zNk4fW_OTX0D9Fo7Q2~$u< zOmp-@T50)`O_LfsEzqC$)en9jNu`uwoe^#O!yhm{e)a(NcW)*>PrGG%G;^CpS48#G zk%c8cyv?Q*5?N98X>-p5!<^afzi~(-DQa`;o1n%cvx5Jz8Pfa6W0=3AtgOfe@iC_2 zB=-|==zHM_hjLjV%ILSk(dH}+V$y|~rudujyJ!|reaBb_%QS@W0Ab7tA;vuYi!W1M93bfqApN10dzx`-9 zGf&AC18cg7{X3?*LzKMST4O#ASU{G0O;Ha!=5AdYUe)3KL!|a|cI->(NX7yI&&Xf43cW9YP0Gwg1xj1gLUP zE@{`Qn|{+z3*kLY4T%bN31(#2Q=-%BuK5$2gA7O%H_qw=N)vpZO%#qq`d>ISMCqi=wbIjR8OAPC=X9c&sztfm6z8-aOr znfAT2-vLwAC+v_hv%<>TS7rtznAOD1qadSHYkaCqN(>`H4dmLmpGjan(E`7%l{%FU zb$QrwpS zOBts@;FJm(i=96QB|}wbRfW#zhZ~LT!8xsyctwmZj8+7DYha{RjyFLQbcd+Z48Ut%-XA&^N%|wX- z9dFz{&}VnFcomC9!WbwnfPwGX{-gzl?|>t&8wPGY?*g`HR&dZNiS1hUAygCv;K8B_ zd$H!RIey(h&;4na4L|}2f3k*xNrkt?0gMw)SfbE~1pvz`*0K=#o?~u`W=o=r50sEDgu&rz_K2->B(3L6l!Wrp-#4>5L`G$y9p~%km0E(~)XkCb zCIKJ3#LpLcJR$Da-mRFc5mbdnwXh)B8jbP4n{qjoBp5^;8o-Uiu+TwKh$T*>?8z4k zIWv(vto0L5liv@D>q(!IbmnSF9ybN@x_ULI-m=1$MP3&kA;$p#I zY^S_Vu3u_gf7`Im_POWu4uLi0iq5O6zX|%}{lDtmpIq1$thHB8$R&j6 z)+tD_+-LQVG;-uq-a^j++a~g4d|Y-S>9R!PFBZLOyRVP^i{E@r|H{RMBGNL|HhhM; zemtZsE2KgBJu~tVmol?lFMhimjf$XtWSYzv4h~2l&}R-DYaEwTuXyejnny>){ac%Z zK!grgr%s1IT0hmhy#-EY=wc8H7~|K^ntsLaBu`wu{`)DzPIZw_!~wI(H{2tIUY#&T zI7nXbveRD2XjXW-nVWoSf6QRIF#lH{KQSl+BXwg@0^DL$wUbDa3-OMo6zhk)9Q1@DG}Ac=El%U8Act9j2- zX1EWw7Kj;O?WhIqC7U-VdN~@PEOaxeZ3mSk++?e*9U>-j*)!183TGzKL?$|UUrQRk zA&k+c_5keeN7Zjljp12yJ(6Xnf>vvmQGFxob}z|Y`7*&GS&A%n@|4=5n9$MrjEmcs zH;NV_hG{^Hr8$G6`5dy$hPV6Rb#v9XK% z8ZxNXeSY7il=WI9tfr7V^HZH`*iQLRdG;Y6Ja0nU!niqK2IC7w{tn7Uyc+)SS6YQ+RXMx;ir&x&3+{{ofLWYB zQQPotE)=)w(Z=X?Ltw{L+xbwV@#|0>AbT1S#4XNT5-9t80r~&EVh+~-?nJvC;Uxd> z*UEY?AzM}a-R|w< zR>#Mps5tvox!)J(j-0cPte(avFD)&tgWC0(Z*Mb*7clKU2N6VdTJHFBXJ|dr_fAXY zx5mM{)&c!l6KPsaM~AM&_2k z6wZ4N$;7nQE>?{?(M$qze_m{@_?xz6GLpS(({1q9YR1*t|3Ke&lz__D3Bszu)I*mP zHGM+WQhV-Po~;f5)QEpt@u|V6d1MzdV}-cUEZwZuGm8V5h6e|X&i@)h+?|J;WFPe2 z4F19h>Bu;BJ+R4?U#)h~k_yg3<1oCGru{(#vF0rHn|FnVTX*K4=x&M`V_|A8DYG-DEEk?nFk z4fAtYR$V@qwYF|5o?SnZ4=j#fEqC?!h3Rg06|0!}T?VMbIf1&CiXrZ>5)D%?j1}yn zoJwrbq(RrEbWI1pL7&y;{UMZl`(flp`0#$}F!e(~|69nvcv zrHLQ4=)d~SyCKR*9u!+YTJPmc?RH^#@POB}KoSbl_HPsQBl-b#tWv0El>41N-|m4Q zs}MOgz&X^v-lP9aoIz+XqV;vNw=m_Yay$S?8?_j|Q7aoS$f=igvsZ);7AxP;j0GZW zuh7?Bc|Q!NIT-MqH6}_Q5W|2mcU&biadAldaEYVzrnvCFSXd8aAS(JH)#$!dbEQyN z_5$1;UgzYks)pwAJB>2d*Ow}?sksdw-XiC>s?=O<>e{{rJr?C++dyBc(Z5v=Oug)K z$r#TOZc3}>?;W)tkI9#NLGG470+Z84p?`R(dZ0^9?AL#wT3iHAlBEh1NMGNk`)Ued z&mFY27v!*p$qSvkEw;>wzwm|+oKNPc6(;hl-$b4s&!#*od{Z0`ClLH zg}5ZAXIz=B?oC?v$vDPXj24oAWGZI_%_8(|U%6fay9oO$ZQ21v>q{jYlpUgQ3zNd! zgZ#kX0D-0BU-6#H8H zgZaI$wyZsvQClu*)rROk`2goTp6Txyr^X=dKu{_%PBVM#Ww}eOBj2mq;`)sC&JhNy z_@NY%(h=3FhH_1u(p;CxBm}EXW`dm`?m4X zDKUv50|pz7N+=zp#t7+Dlm=09ASK=4U}J=+be9T z{tNr;zOM5+&g1wV3@%e|nQ$GF|A7b@W?a3Jm}j)|;sPygDLsf3pv1#DN_-}|uAj!7 z`%RA*raQt&^ZL==luPIgy1D9_prC$SdReNBHtP<>B{9nQThdS$TMLI`)8^QiQM^bG zBBqyId(-&jUaGibqx4fzME3n2xF+{zHs?65R7)ka>$X&YyN7qqe<164{oHmAh|CGy zp|E=JCc%Lf^}?)6s~TkjrC1f^EQc(g?Tt~G_8&k{zyB*PO2~(Jec13cP z3r}q<5ZOr)>|y+d_vmPH3q+U>*V%m0eKq^M@eTEYVY`sv_UHg;2=$S*eYpMei!Yj{ zGOc_utLz^1>~A8dk8E!w^%0J(I@^DR1+Fi(Q*?_|4n=f6IlvJdcHwq4#e_;_Q$|fL zBrIN;!q9!0TpuCDX)85zW^hDjqLfTIczH2DEv62VwniUTvc5ZD6`?DzN&NPd&WXJw`gmhM!00L> z;x;q*C5YGBZ!X(xn08=TMZ{q$okO3yW2CecNaek^pX0P+`*7Jqb-p9Rigj06@h`C> zTx#e)kc!C0bUda)Tr3h2FW-d`MZR`F)he-`I2%sUbP6o69CqbK-^uRKlF$X8D7XTa?fUXrwdWf8yd5dBL@ zrbOeTRw)^dAPyr0?h}eOWANp$umLCH!3jN7aX8*pCI&}|in2Otb9!c$6BRtP*+{k1 z8hOif^>C3Iy`L0ezFrAW9-=dw)VII#&U!)Px^Q)Yj_wDT(~*MLfOcfu z;rhG1`|rQ4MaifDOM?+vpECoZOj$%Pok;MvEj^d}*KOc~Rx^c#LDl9x*zT;Qpje}E zi#8hH_n7p^f55||0?*}VU8a);mYEKGE{eJQ%R7+=XpMW8MsInFQau5zBGqI3qMt7l zHR-QmL*V_O$s?zt{C6{ujW3pECCzTpVL0!$bNZUM<}NN1emY@{ zKD0ym__!xUh;zaMn9DDyxTUR)Wt*o;CgYoC!GoCWu4DSB2azCK`NOIrp}=Zjxs z{RMWl7gd-$m}NC&-kmtUQFfY1aME3_NZ9?frlml0*+nn&re_WZh3}>&xR4tgL=1=P z01Krn464CrPe*R}a`iP~Ow5;?#$J8CXd`Y8lA%CFPaB~$NbkVYIaO95=;O0%`eimF zt6o7y#F7^e45t&|&HgKie_i91zq@w)cHSc&tvF)N={L_9vwI}R6IRtD)|u&Nka0;w77ETtI3^gM4zxKWFYR7 zWdYvyYaI0Yvst${$%AwHyNp4`9)|$%^1elT`Exwd<{2XeQ#K$0^}J3{+Ew?@I6Blb zPG7j9#%Gh&#N5ww?j(H`i1nS`a;j*dA+O15!rCZP4u z?lD89PIvIb3&+R6WT7Sga8&9ljN_T>-_jsM5n6@i(wwOn8&MExIyfrdD8RVfS@a zCdBfQPM|FFFMSMx&Tn3M<_)NN5l{Emp_gyoRmeRvLp5YpC=BpgyoaAHAxdhqrpv>j zHBP>J+FQqVgY@yQUSoO9BH`J!5`D>eKleMlLnOXml=TyAP6r~%*!|~gd_Vm~3G8k~ zLez`{9!5cQ4>o5^fuvN&++m*;T}OA0Gn~q!M__E^{Ae{8kWS`b zf0o2~e0U0F`lmu~sEbET|WDxeH@{1xIcck7~w{$~Ij;En*viCw)YLNhTF zDHf_5ktOM-EC#m%vOKICyOWxkAmJQAvpNC-p#7g7nR+m_TL(NKD5!t>9&hTz#@0N9 zJ))N=skVvIl6;>Hc9P<)d}J8pX}~_*B^VpYt#Q%62zVt;5Y=}lx+)B>UY7sCQmZt; zch4$`e(Va$o1{7<3b3VBW6G|gh54Na94795W)ihvjp=!%H49X#XbDp+w~S?A>|ize z^c=+uTWFFXW^7b3W`T=^`Us}=4WE9d>AQ6~Lkl_2J;lj|`t2P^w}n$BWf%ObmvMhc zG~Z6(L$31Tmvm=;>yut9Ea#{3#g{ZJiiTW>K|5>Mk846zn2&!kP_Qwen}voIaySeL z=vg^h;C+g*kImS`*0|s7Q9a;)Cz5>sosnSfFb^Yk$;xnr`~L^(Q!HUV@6o+RSJP;*VK{G>ogG`>m zCi(VXx4KjCTX8-`B_N;&SzUD9m#;b5-HfBj%$wiI6fuNdrCIqDvh$6QT;XMyt;W># z-9r#%>k)P*Ah!3@aWR*4jvLD}6+Zji$lUqOSodp-3ujm#m`CNGXS{8)a#uUclbYgF zSjDj5E6RA1nwC1E5U|8n!`tV~GFRSZJsV%kjBMH zJ=YC9y+igUDe-xDex;~A1^84%7;TJ8NFam=@aRrUiZ8t`=0-|kxr$4kAvD0zjlxV6 zokNk$^ zjn`b1F(g*%rLUhrDc)6$aM#AbkeDNt?ufE@+@yr zUrW9F2`qOo$7MB?a3eL0x93v6nX$a62T9{@+CuCir<4gOr_@zyzA|IfT813O&@0j+ zSydR)cg<+jq%|wmj$VeE5GTN{2@TD8ZK@E>Zy<+U(L&MKj75WEFQVcqU>R{18Cvj7 zCf&`|RCeNzLLB6Ha6^pYih=pXlJOhK2Fu5{?>6>vZ!2MUrb10WF)Jt~*!CjT^xI!q z9bNhg(Sgw6KHd6`0|er7u{kF&Qp|ejbar@|2k|)WMA+gyonzzt>AZx%{bckqHaYtA z!9uh3*>WjtKQ}Rcajo-v&SfXZ!5g_uC$q|>1}83+ zQ}C!|fqW$U057fFGhNFilK+X$iS7pBUX!_T{lLz!O4DEiniT!;H1BMym&zWR%Tf1? zZs5hjjZsPhUSUa*`;UfWkjW|-rMn!8Hre~eRp=o|FE?OeRv>EW)ttPSJ4nTb;*Sgm z#gVvz+>laJcRu)<0VX%63l>rYrOCz{a7ta4I{T2&sy~EyA__K`|IjhNC0X3034m88 z5Gl{byB7Fovf>$jGzX`Di}YXEnX10OC#!^dBB+!%@Q;7>yV~}56Y)zzir}Qp<$+0A z+TJRU?i&V1J+nq2>0_dns_755ho*y$UIduppPokfBe|g+;%te+6xWN+2 zpwWBG_7_fe!CvCH*^3`Ml6cXqd^UNu%M2sLqr{iL%o1;%3XS?v@WKetQnuAwaL4acrnb7rH0zy1B4 z8Oki(Ado%FY#B1b>%^TMgFf8lq)V9KXElv4m0I_HHg~B!9Oq=hW%J;%Qze9oR|X)v zGvOMY5?NzqRkEJaoK5q_qBgS)JuP>eMlB#cM=?0z=(N%wceyPsl)KbQ%Bqo;RCqy& z^%EHx8S<1FZn{##T*qVD#?#+FMb=HS&i>J>UXu~#+nx&*w#Ga>*)Fz}n9bmVo*_*S zqGPN1FG`~cyJf6*3gW`-int|Dl-HezTd9hU%CkMah$7nHq`mA)rJTM=Kfa&or}NfI z6!$+B61rEKTu~k_lTAI_3t;3xlv!c2dBO*9)MG=XTRcBsXjGY5x*0XKk9_XvQ@9r$ z4`ly7dN{+lXp0P6!18WqeSa#yMPJ-`6|?*f?asjo3qIQ9RQo<0!hpGKI`?DMjmPQ@ z3;TV`qAX%u1LdP)tfojw&E@Fs^4$}2S)U~;7xj_xQUs_U}8izj{W^;Vbf}3Ygu4zE@nln?)7%3(U>l(52NB* zfZ9#G^)=Ok%U6c~a9?(R9DXAL5vaPC+q1!c+m<%Saira_hfoFw*M-Gb&LYOKxjjUp z-Yt6Ff(TQObhjja1NOVKpxK|gf;7j2M1TWdDK2Ql{3Rh_^nQbuQS<by^Vot7n`BC-a4yY5{$}_96OTH+>8I9pgcV@99`Rc_h*$~(HAU( z-jgu_96@`Ddb4=OeEQurxV@?(S}}p6CrLA?a1gSSU8&{E3%8^`y8}}HxR!p3x?#zJ z`HYWyht!EJX*UNC?h4UfJLdI}a=9dMO@%L}eKu|nyDwSM+;99_-Z9Y2aurPmd)vu` zRZ8uKTogTWE*TDF+awZao-nby0fBJI%ND{6zX=j2ax}q)owb)jiDTW%tb=ZnshK!FdQGr0?0lfNiq z{)|J%+Yw7eJ}uR;Su;pwmpjsCHnfT!2|GE01?;q!{6aNM6ztP@8hV-tv>pp1ZJyo8 z6Eb#hvcZ}bTvc~iQTEJoRgRddTZ9$C?u%CfafVYgwD?zvVw1ocKBx#3Rw=C9G7y4& zU!wkMJ6%mp)LXw@N{Wqvo-xN3Q>8MX`N%m_2I(hC%m3iB{A&n(-Pz~e<1C^8wKSU$ zYEYq9rxg#UIEl@9KGGy#O}qmY*_ucmOfwu!;fA~m`M1MzBde<2ZO{gbldLtaSN{TG zn%|_Lupdp(4%)xdi;h+2C(UDWs(HnRRS#(E=A5uOTN+i+2zC&CDIv;`1zlzLNOGn? z#b;Q?jfSL}OLw;5L9Pw7Ww>c>8=Nu+2T&b)$@%f|icy?2EI*<4L)_;YG!xTBx zO#a!#nCBXwZ9u2$QJa6K^&Qc}3qr>Nvd3mTVP_^)3UOa7GYj1^*qW%9 zBHKYr%O>jqeC%HjLD@}gc2W|VgN5~MTz2e@A0-$T6#7ym|1O_*7H3l`L;OW~oWRQ| zUct#W-O`e(l0!P}>rZkcJvzB+Esqaqh975gj$nOKnWKxc(=fV;-$=Ub0aYTHXV^@p z-|EHj@*-mloYup(a4AVq_s6cxV}~VhP%3j~;N)rUv(A42fb!t9|a4kpgSkF+Ov~u*>7~jk;FSprGWYM7|VI zphHOD$i*iN=Y~!#Z2x|2{p9m%Hu)Som=`W|SJVxrpLhL@ps}_(KgZ>k9$}l5TV$U# zqFlm}fM}+?fDr5Uco!X$NHmaXeX(|H=guvJ%h$rcm&8sppR|ZSO{F8&mMBI-IbN)6 z2>NiaDui}@Il%;2HfkhW{e6@R`K5#fR@JfU?|CHh%@UbpRBR&WBvNQ%zEw6=HA?&c zPzZzy^)DFB9;haD*lGS#H`Dhr1_L(4hGdP-<7&#Rf8p9HJ?QlcktTR6Cw0 z0>Q3@{V~#xC1*c_W#G#dKAZSiSM||^v|m3^0NfS(iH~(J!NG}|Evt(8gqsFXPnAUN zKTJpKxwR(Zkzqtc>UCS#bx6c$rpTFUKfAEzF_4C=3}^ieYvjwcx&?i~?B)1F@Mjk< z)Mx4uByb^bNXUD{Yxv(=Y=E6GcHqkFZ|yQEc)q(hXrW46FLU_-k&EvfyLBf!XRHUNOZY+yN6^`5aH5Dc}NT zf5A(vhj<1#Nbxp1&Fh5ZmK45E);)asZ2BwTb_%<|pqgB8il@LuNk!F@Z?|lCxKQ;i zj`$PtsyW5^jP2lU^`M^{qwl02AD0a_aV%z9A)#9#S;Lj5Ek#LF+{2tI6T*^ikX#H; zOgTP9@E>^m*HZd3fclUEdz!pF13_kHTOAHKW5KVKwgOdMAlgx>9oCT*-~XFDH=MTV ztfX4;ZrAP5Z8EYAlE|8*SI1oT+`bH=DR*eqRBC!Zyu0+LW1B@pa>S#aW#5c82;6jk zmu2;UN7R|!RY%Y)Vh0eE(9YcF1%;X9+Vb|q4b5)PJ z5P%{QcDfPlT_SLp#dzHQo*y+OLN1>1zuE#n4%!cC2)z_$W3y58cFo&uq;-N@A( zqP4=Z`Y^wtdmebpEZi)+!E+wsYRc7AJFrSk4F0Fvf=A6MlG}2{;UIXLkEJ8E$AM!c zjlAy~(L>a_Pqce@b?fTp^Y`Wm&*&STeA+dWcHalH(sYDOb@hi)dSYIB_|3cD)nqCrn!8y5{KJHu>)ybE=#UHI;nE#be(kmC(} z68Z<(y5l;YKfH-?XR~GChYbV*l>&gu`=S~}8CgT~TO+i~o(*Xb#85|fa1rTny~j*l z%$X@`ba=VD!jRn&J)s83lA!48*7RS%JFrFA&vMI3Mm-O9ascC!2;H*lzU~s>3;vN# z$xWXzN!|ZtR%8V7HOUv8(U%{axprz01aJhzxJlKouCHd&=jtG+^^R`|9Hz-to25O>#I6iwC6tJ z;7Jb7kfeIvF@N#FPHBm+=|uEHZndTj@m(n_aK*N8{yy~dah|KnAawN+?~}Hb+KI@U zu>3{01p5%kNIQENb%yL~Ly2BH6W^K}pIc4Y;?m=fgVPj!Sm)D9iw^Q% zJpU(=_WRVbFPq!C34d9otuMrc*Q))nU8jogq?dGY9^4T(7Q5Y9=Zl@=#UCUfu}rsi z+=kSchl9G%C)5Kvps5)y+F;I?{=oqu@jEg+Dvd@fDF=7Duk`7muj3cc3z=Y^;D%Jy zxk%cZqE*xurk;Owf@S7AtJ9HcKXTf9g65oa6T@SO#!M5}lbeSdUU%q97L1Vy3fsCH znewIe?n7p;#nJY9ASRKzq>Dw{oK#a1p;9fPovpY6;X0hAn3+ zMmTR#uOID{luHpF;DR9x>9C^9KvjJWF1|7d&1=T)0wWmj@BKM%!5wWrY`cM9c;K>~ z9VWrLash(vs*-{F(H3PKEB}5qd;R@6@NP4P_^`#D>y4`l~R`Z%;$;#17R&x#K;=#64qXE3k4GD3@>9KmAkxvn~J~ct} zF14TfMM{=xnfH1b?EO&u2Yn}UtrFt#3G|WiPrZnclk1<#jbYcQHvA3jOAWMge91q8 zI{Gqa9)GC^3J;pdKTxsa@1W(wH9?M-UY^>%icVPG*LVob=!aol$@K^yyKsaNLqrS=X7=3jG~XWK_EW4RCah(NHw zLh5L zI4$=3ixWoPUZ6Z6t%ZN(ajT}RRM2jZycWMXrI!M8hx*eG{?RdWeqCIZxQb0$-M?=l zCJxkD3_JScuOSELPv6xY?f^ch z8_l32|24vPkGKbSKCTVRa<>DHDYez2;OYDa+NHpW+bSTAnKV(H6=f@zu~qVr%|-)A z6hS0ZYQYaMo}ZT|AkCrD?4wV*9;`f76(DMdOy|W{eB$~lDw-?!Jrz=*%HuELvCX+@ zl{>D*&m6w{A&cydmz#HN$Bw`p?J}uIJ5aWfwqjHOx07yQh)TTxrWcM^kiFrl{OybF z*4%;z9N0-owB4^~-K62z<)?oYE<+^#_86jzH>RG2N>3ikiilesc}7(YVAr)^VY1qw z0i|A5Qr%CUCQN~q$QL=^Ee7}~PJzZ7MgbiQT=X}LtvKU=&Iz-o2l!+edN(vZsuw94 zqO*0h$uG=XLtCxT!th=WHF(BHR=2-3Bz@pSaM2O2H5`JJ-sW`ls$a5q-#vka$)=NTCr3NNvu|Cdhl{uRCIC&eGx5=vOl&yN2W zkGp}f+e-=3((Sa1=~wj=s)~@@`c{BYHSwsk{F>}_joZp{wQMX>1c-IqtGrsZGGt)K zA~C?S=@*mP8hdY5lM8e*#u4SNWkt97RPH6=<3GIu_mp$_+ubd;vg0kS6F(TIW9VI_ zSbLMP=EQ9d&72*8&Ut(*%%A zVeNEV<9bnWnyc2l4y==0pWl6%Gal3D(y9GpWEEp=T8U4PWOv54^fI~amIJIga+#>f zx2Hy;q6y5jVvk$eDSKoR)u+yaxt_VpOJ3wBYhooRfJ_f?2xFfiN=yo{9+F_%l-&CU z@ID~&T#}WwILv=#J%PIT-y*g5}+Nb_RLyVtV1B#q$B^)m|Q_`xJx32a5~8EM@KWbMvW3hFbG9rzKE{(VN0 z)O-76h~qoxgf~>Km#`3R0)%XDL?IM=#KJ@!8*?|*VwM^cU+(2%lct*@q}XH|#6@W> z?#cHHFwrn=KqBnog2#+~X32cMm;?`hU=71Yj^4r=uA=E$8d4Xs*b zTeob~9t}k#8H)Nue9yNTrbwQC>@QKrGZ_E=T0?$*L!3tT&BJH5QQ3QMeCE4~NaTtN z+xv<$hzRY9kAh)`&O@8cY77HRr=cs=R~HGGHO3>3XM%9QzhPjZ`7upgGtuyF?(Gv# zOu|IPA!QlW2$x!Ji&NWZ%u6tgN;G@Sj)lPGp5QqY+jkNph5$LzhW|EV8fB~V!CNlp z!%HW4_mdVH(4kS4gRhmzPT~$exFBZuPqi?*R3K@8mE}F$tx1Y&OUw>msU~2g zKN4>dANL;Vw4N4>iiPFE>-`FHdi?S|2b3%R_bkNUUoTW$l3HKQ)ZH+^3~u%6;`(6@>Xl8YD`r}PW4Y9=zmCiSuK=E1% zb#LmC#iv&4%%kCqAlpW?m9D!JX3Q4YN}A^*goaNfaZ_@T^t=|u_Eqw!NoknH-wErO zL;l22&r2zJ#&~x_)(I)?$>6crDF6ERx0xEo7_Xqtl(OcVhq?a)4U>j0eyYn$!~Qjt z_9qtCeeI};dyFFXd7dqrDzc0aamhY3ga?f`3L zdNB_3Z>a$Y4TAs5;+U{X4}zc&Z=^~lmQ=`i=N+I%m(ici8pObFx@rbk;=f|S%mXM6 zb3mD^^|gMW_XHwJI%);N;%N;=8Vbu&!WOe9S`L`ju?&i6J7hJ2(e9OTHVtGE^*5MbV@J!GBDllc6NjFujhfdzWs zQ5K~s(~3>xm(1DQo4)qot>D0ns7d>B;?18ih|nzFOcc9$xWZLxOwahm+q>Ms;wB=- z1J9T3oYRDJ73CLVsswS)%aKznrrkY!9%4vU&+lhMS z2Zw8tDQN0G!qNN^&*p*PFOW1_JJ^vVo*Gnke16I`XHB_>ND5fo)MwP7ZHAHK9iyXx z-r_Z`N7o7Em9BSr>YTek7+sNi;YYABy#gAYO#5qGJk|TwijZc0R@N_{WV8A?AknxY;kplH zjT6tUO^o&b;M|Z15TQSKKws7BTqmGR^tMNTyG6?&3mrsz4Z|rFA8|n*x8$l?;k_|j z$xd<|@hQdNVEOCM=hq~!u;l*+8)qnp`6I6VagAh68X8|}yyVZpBR<%^N!R!)jD0yO z3BkP#(%dha(|3!e@Mkc|}Ga~N?qZmHpy z1D%PB6!!z(@M{EhUiUJdtY3zriP^dV7Kg;!LA&#I;yk`aurlApmLgdO3Dmp<jwfL$A@9}NtRV{nP)x$vB>d+ zWzU1VyKQXN=^5+Qp<(S6c9@c72xUAmn&G7Pf-Gc3czA=i#;EN!W*@B@yo`XH7d>pJTLUlpF^BFG1Jsf~;PFzniR!+_voqWeX zc+JTXMB^7i;2hIAI%=lH=H)(6MQlOnDSo)pob4#WzZI;8$=+_oJt(9M2Pb?mn7aS+ zrnt1k%+-Q9o~%(MnT!oNKehXzdL!GU5+?k7uglLr=X288Pt5}XS0SsvZRSJ*>e?3z znKLH(6S)qm%GN|0h>P2|rYcsz6mIero9|jCQ@^XQ(%C%z%z(mOaB|zp`BQxh+Lbt; zuZh?Bqz^0alRB}HLD(B=(0Kp`!J!?};lJuO!_D7H2&yxRDAWo8;OPVcgS}(!gRuCb zm0PpcMI0)*LkRLX@)iRORNWBvn1)reUb9)pJ(gH@WHAvTF|iBGM!ueS!IUdjQD<7kB(c}|G1Gp^J6IMg5lRuz>;+V=xv2aet@7 zilY(a2T5(vNZ>jIItwo!ZdgCs+nVc*BFxUd3Uv7E6SjD!dC37IyVZvedQi~Y;Ejj+ zd_&h0yRuhO;5{O4N1L!Yb76vov$42SY4A>bV;jx?qSVok;P5u;B%QN!iv~LP{&)u@ zr}u}z9&X`4xrgg1oCJIPq|9Dp1_+5dE7j@fNR~^7nQlbTSD)9_Rwqiyy*`-o3H@sm&A92{ z<>*JS5=r4Y?JKA%vn=5+IbkM9JuGXG1H4+GIGwDs`D_Us}Ws107 zeS%>u#*tR^(HG0NLx${3qm*VKd3VL1SbzK__)ub1j?HamIMHpksASrYck?_{eHmTKqn7PEx&KYV{qG*A=SP1PZ-|DlF zdqKFh%oyl%!kQNi>S{I*ZWoSS8u}lU(Bs#>`^&SLkC|1-H(3w0{fl}mmv5wRPoamAac~|X|bZ4*VrV!-8pDk zFoGZOj3Xj@0EmL%pC=CnENsFi1rh51fw0dG$v%TXj%Mpt*9@zgMNP^R?eTA_thJi? zIwJp0sY)_+?z-swk`)!lCzWdAgUPit3h3u{K}c7FfS7rc*PpVoft6^|RKg<4ng6R8 z$^dEnfoBM>%N)dF*}t``Fj=M1m|P(Z_kW|x>`7y9O%&7}S_Ovpdxa^oXlaw2ZXM<| z^A#{w{r$pwCY;*3$&JwDEjdMy<1CMz_>=82X%a~?VT#^99kc0Vb6)~!!YJpMGNPog z>@yY}9qKG9#i4?KO*s%`C~j`a6FlmFKN$FaYbu-e?$no#>8%Bq2;^;NUSFQ9mI~Nj zX)g8AJ)~{R_s|nl3z3&2<>Sqa8tIpo86nGi10kiS-$Sxwx#OWt^H(bLT9TKc?0aw1 z`)Q5G)Q3w(UiunM+*<#s4eEh~;N}mhF`Z+0UbiaA_TTJ59N|820AK&=j&uHXA;R$s zCIO9)OYaXiB{?qF@(k!4l`b``u^j5JTfXizzTRmJD=Cs>(fG(YUb-(LWWvPUqtBUB zdPE+d7vlIi=o^LTfyMxW;*`G$zMq{gXZ$?sfpk3^yr!!D@sz~9(2ehlie86t9;E+3 zksDKGrKgd^>|#}F>TDC)8?J59KGlD_IBq?%l~PJ$!-4?3;gfJria&Zz^F_f#qL%3c#BJ~| zGmv8N8%z@T&!Ge-Hir;A#q+dZs(;rZj1C`srQWS5MU&h!K5q7;{GQ^e7ot!S5pTPe z_Ff)N-RwI7KopDn+EMV$ks&d2pL8Vs%?5AYDv$ z71lH+5GT#g6!v@Rm%ZI~*a@jBs!GiOO&>A)vj*-yM!wpD69xQ070ec``fx=PExo}n zkgTLw`3?pWHFx@h5i?THUaF+Y@3TKG3LZ{z3>a95#+5w1SKq;uTxQXdc#4xED34!U zK^R2BBKAtO)i2d0tyh*8=ijY##Mexu41uMze_ON@5ge64%ya*mRx&)RwPXJ(F=O^P z+(T};bbjlbFoU$7ZJE%lA$Qt=y7SsSJ5FdBEv($iiJ(*Y3>OaR?Lu8Sbr664K zIv6H1H0o&|eHQxzq&N!9t0p3d00tTDbATXg{Z$=QU68V&!W6qrgrq1*r1#E)- zKxJq0C&!SDm+Dt!E^h`5C{{{F_F>uEce<**302b8io1TkJW;x(y8dS@tHhI0nbBy@G?@JOG=)~nSsrU9(2CW0v8p_y#8VE#AR4c+5Sw^(2eEhcI& zFbW4nIp+-?6RSYOS;>40)y?yfJ@*t!wNQ~#iCUiCNZ?ZAH6+9FwK_{ZlEho+4kM|H zcWn8K9mM9Y2s&*PQxP=u1EGq6n}BBRmcN?ll=G=v_gFG9glK$|;dfsh+vhI{J>=l! zi+sEPKs6B?G2kjE$Z7!WqPd^`^^iM873htfG>+<@N~g8sXV`VhmC`9klSLLnJFAkh z9a(rjFi4HQT(?JhZ)iCbXOJ^d3GVr8BX|ibNYB372H5;Va;Y9=2>NAlh5DG~{IR9r zoy|s(e;Oi~2BO?!xZ&B6L(#Zz(TuXEA3g#yYJ!3Z%rD;Vw#pDqZbEyu#Vk7@VCL{) zuUOoe38+!Vc=nDraB?^#B&w1qOjaM|qokk5*nWKOVH2+lyH0Zl&NM*UE6slM^IK1? z??>>4|Em}kL-!vG5rPpAvdHNpL2tUmDuq*oovrXBCDYiQ4s%EK2n?(T0?&Wh8-Jz0 z=ED*{P{+YL#J01-5kYsP<;Xa##ky0JFZJa~iBZi@?VqtrS~{Vhw_ivwP1|FtpF(6$ zBX@Gh*;T9v)k6x+(NmkQ$ippxF=mnXC54M(f%j}qp%rumU{_b4gi_xHZQuquU#2uw zZx%&Z>w>Vs?Hp<%f2R$q)XZ5k-f0cnXp^aLqAA34U?&15J+PcW_j90-)*&S-5h9O7 z&dgt6Y_Wz`ZSPoICJH1Oy8i=xKaX-x7oVp=asp?*<;fgyMZLFjYTH0mRlb_&cvBz= z#l?4Q+V85FSzSBUC`=JHmUB|uBOOsg?S80uS{4d5=C)(6q0E)yjpomzVyaoBYP9>e z$a2iiKG`&?fD=6B=CGyP4HwH@p*}n z2pH{g&$hW@{}F(Z*i0rQL6^ZP7V!K9kihvH;!+K~({)oXvpa)%0m6<;K^kG>Hm20& z_3n9z(^i?xDvE|dWicF6iHzDy@UkCmlAIjIwLJ`X^D#~!&15E$mWEMs z7_uPE!1~^M$qQ0r&J#=H3B!LK<5~2+*j6kr%bND3UGx_nJWv>JoRGKcY^H}&LuA?G z*Y5148Z9K6Yb(sWOW}F?3BmAgp{ zS3#DLz7mC^>%yEUo@)}5(&At~y`T^ZPC(G1S26ClHs?a9KkqQD%^kBa5S>_eW<24Z zVr{`8Sv!`=CjLb@3p7_^?Q>v<-7jw)xQ6ZJ)#b=>92LU&jsFSyN0pNpI1$O-m^!~H zbuRhfjB}|TL?0BNXJguNxB1_8=quH`rH!Rjk6Id~JiHNKW{>xERa&`<6$hT?n!WNA!>h8Gp=0OMSUa%IeVU`Y$H|n__l?U#Z z{^NedPG3-ri;rPEPiNX<{MPs6LnA3N=Xz8CWcbOZTp8Il?5u2LFNa)1dFokM^&%!| zYQa{ib4U2%3VLrOxCke5`XRZl^4C3k3rmw>ldT-o?Hdd^xLJ875m>^v_U-CG+jCTk zZ6Mu{8)Hy9k)RSY7Nj%P@LIEet`t6>4Cb{x>v^3Dqa0&&qT~B1>R4VWgV=m8g)E>k zQe{(eAv1WFNeB&I|A-O3pQx&rwzHCnCsWAP1?VTl^; zQTx&I(1jsL*KmYGAf}8FzBsfDRHPVZT5QTHri!+jm`ZssgvX}HXzl<}VA#@E#EbC` zW2T3fxpb*pG{HSOYUJ8iD=Zj?%_#i^Petb476rf}N0VcLI47E2F~O_jO#>WCEQ~N& zWfJhk>jy$U*kLa|+B@V6=6t!SKLD~vM+1MMj$(>(P{$RYE zY}KOEvzK}Qu^M6zAzc(-?Vb}_5c{V#+CR}W#mfr@LTi}HzV3+MA)3_HEV^CZL^md7 zz_U#8K_2*R{^_1Ehd&C`lI%pG&t(FKBOR4P_&_)$^9H=YP~?;hCs)7gb3j{-&O7GE z*Uvd(TK>TDE@iWE1d~e&+awu;HvO@D?(u2XmE!L^DYGFYEcZ^y^Bh|4;L+iY=DHjY zdkJeZADy~_d(1kjfCBao=*PwsTtyoGoG(6d8}>x#c7&QmFaaj)%H2N|993oZu8K;0 zMrxL4uRy~nG#PQS5$PI=f?7>{bnGrKRKBaMiiKIFWobs}{GAS1FB04=62<7wcWX!q zqWcvS2x*$!d(;EAysdRCLB;MOf7s3G>4SVaRZktd9-2hxsp{z>tjJj;TugIotOq>cEH!`Q-YYI2wf%3LB@yF9gUh$g|Lk^1=_QZt z-kA&Eo%Nv5K>#knCcfjQJwB}5)f(A^y%PkwR7>H!a1k;UF}2iEF{v6<;bX1SLXUCu zF}+Q9`4|bvF0~(d?1l~1eWpa;YY!adE?-alpT1KyO-!ELYPGPW1X{_PvlzffyBx+( zAE~ZaN^6!UmMwJ{$-D^Tw_knV)eE%8vaE>hSIUi!OOPbI7=lwYWfJxhNRfm{7HoC-Wb;-J?Ywb8{`vFe>-p@p^J`p7*stz(TQ} zSdrCh7)j&oR@sC27_PhqqS-c&Ro%4joWAZa5xKz@>v{=H=qJ&r3a-Kl?Yki0@muX% zZT0ncUtpALZNNeP>Q2fMlpB|LXKa~e`Gh1SpzP1=FL6|TFjcs{l6lcwF8{OP<1}n% zTM(C>u8vo|4YOL-Ui(}Y^%pK`7lHdX_zDgV@E_NetE_EAMjkD!6gC+!X8q0@hj?ro zFMB|N9`OV{N6KLR20~!vT(^bWq>=yr7%6qz1kkkNUZbEd+}aAzi|^k_TBc3w!3Ax* z{JnC4IfY!wAja))_Hi{V2zkKTI?x{*6yE@4FLD*p32b{xWHz+|8%lA%uCtWQ6Bc@s z+kq`yjhF8}KYjRX%0a4yad%hjGmp;iI#t&8@w&=Cv9v|U8?SP=R=`#)*Wo;+)83*h z2u1(Hk4D8n#)Nx{VpXvFmeTrsbYk>CvUC4|HV$g_X`uE%=Fon;Q~;PF-rA<^wsX&+^^hB6SFu` z3>2P^OCsoM7DdwG-WyD2)?b#pS7bdbQ0(Gv^igy0m+}!On#A;Xg2_pbQdE_qr4OAj zZlicz>#DRwA5{hb)i&yw$TdA{v)1~3fpR(X<;#x?penU+PxiC3{oHWfI7{YceFgtM z{RE1zRX#A3#%3sNX6Beao?mGCV!Cy>GyW+62>WkFJzilkRD|5@OIBpdfV)5&~y%2mxsj9Or%Be_+?O=X##s?;H31xl8EdrmCbyWXshWnXP|E zzC2XzZB(Z0^-`qp_goL`_cCSNyztpWTGG@rar5rHF9XJW!EI9dCs3A215TT$U{f;@ zXJXO3lWVV_(`yQ8Oigs+Mhc^yqp=Hnou^G$`wa58*9Ep|Gu&(|B|lwMZ)c?K`-9%G z1wZ{U#RHwqP5DQPro5K*sS7o!vdWbQ7mDk2*!haI?7)f^J(!z>{}}2p$4|}^#(iL+ zy1`tA4&f+frc=|d7esN$U`H?tT1xD>4wa#SA@d!sSkiUSqMp zCdH9=jhMNR*6)WHzvmZt`0aFX^`B!CqxT{=?_M>vmm_1C^E-N>GTl=;pI&>p_o%1O z=}7#VnzJMN)9@MU5t)@0RBhRg1s`+_qtVg9hnT3)+lvewt+#r|D;h8I-7)4W>cnHt z#C!2Hn#lMyB;H0BR@cCpw^FW}Rc+ia6R_$IeMGl2!GkKd*C!deD8mRLB!eWAaz8Ai2RoB233hR__$Qh{ zLIB966!*zxjs^%-QRk6(g0Vk_*^`72S3Cg{(Er zV5xM!*ly5-1|~}u56cF!S{12q?Ta-6Q)f9+O)fgkzs3Egs_l-OCF~Ddh8(O~MN}{B z3T9Sz9KAB_nzkJmP#$a(YLR`kYorRPAERN|3wabb8-2|3RqV=*jUukab7x#s2zMJo zxu(T?HWQ4CSbYY61+r;j(Wv#jP4FQ<)2dA&_~gf14$tp8_5D^ImjI5=`fd?nNSCmb zZ&R^o}%%wHnD=M(?-R{)Q7x}_)rtCvkDnpy{RFu9wEV}FFi$iqK5vS)-f zhP+meSF4nr&tjq$GZ|lX!64$!uF4JJgC88ZNcn}ySk)9}^ ztX40Jnn?DL-w~jizgUgzeF((Tmo@dN@tDuML|VJkj}*`dh}3iUiBNn6WXKz@Zf1{Z zOd4Anja~E^)aO`TG{s}=%ZyjK6qxA7CCZ-0!)khv)snS~bRJ#cuwPb5+p08p@;KmY ze8#Mmd8dYQhewA#oj)843gpswLRKJBgpEZ)l}!Ch>7&HINh=I@;W|h1@MB051iUtO z0N~Q3vm0Dk8hzzzBDyh3HrMZKJOSip2?^s12~@1T@cFGb?dp%uP3=?RHliPAMlOr8 z1TU*m?h174Cr}m5d+ry~gUKhT zt8?iwZ?-Bny7OEslYD#r=s+Pf^eI65JYA-jHcW#cFc5>54cm2;Za}hKLXu7|ywOL` ziO^nCMCD1K{w9jnyfm%Ng=1|Thf>e>INN-2A-;wo&y@RQw={l(`UeyG6j)LXw8JPD zM;&(`J_yP5`FrLjH_barZBR@_AUP+S%{1ZvGf%mQJ9gG}&2?=a+efpl_>r>aW11@z zQoJgq>X+}N3lb_wp=ZRMyX3>YyPv?D4=hQT44O7S8?p12=Q{avJFSVNBMQ|-RmjL+ zMaqWVoOt6qXSq|hadGmnOzw0Fv0g~2Spi_Nh!$4 zre9+XiJVgqnh9=eqH4!lnzeAq)IF`H9Q+3|K&8wiCP@bXIJ@BSVUo4_jOmg=6N*~~ z-x)6ee6mY@+*t5IvI40<5p>ijyTT}O>n{*;aXqbG!(2Q@ARbkJV-3ocuc$&!xh3X~t z6u~@ch0nk3;64aAV2akchax2BNzwVt>1Mrrs)k^VO|gX1T^vq(NHE)Z)Pw5K1a|96 zrrwu6y&mQsE=qsgo`wtH8Kzxdc96 zRpBye*AfujzR5e9p3t{LIY*tr1Co>9z-hH6x|*{l@=6f0q!khnF!4Iri0e&(nUsI2 zjx^6M5E%Ug^2*M=(vG=fN{C8YzTDDGQ>;XX*(<4+Rj?SvI^H4h6 zW5<8npBA&=`Lc$f(G40P5KR&z;ajliM58Dl6)NdNf+^RBfVP>OI z9lkFd)uJZS^h(;`#?mXai3lQbay)pHesp#aleG)E%1*C zQOyEPuW^!JO*wNj+Oxe*cpns0!0Sx-m!p*dIh^60{_MZpvRJx;p^#qJ;EzHjh2>~( z2?-3?hW6FV0lv{|1LAwHCBaNxLEjHg=tE614OR*k46bRu?RfG$5x%()&GEE2A99`6 zD52j(jI37(gC!84CG-^P`_M%Waoj+|K;bTg4m3>cb69*OFC zL+se;-AOj@^wwYnk~;IZ2<;O$-^EDwoEi*b0k-yAhdka8+#NeW8uplW@b_G}(5IK$ z715MpwB&-V(4&S6>ujj#^;@a8J-w_)Y67+Ag-i$Oh-_YSKb68 ze_7-xY8iva+v$A!peK+|bY1Hw!&Mm)_A1U)#{oOXR9n^E9uGxRyIq-)TD`G>m6^-s z-@Tf5;7sCtJi7R6UXp{FTn?&m&Y}DjJO`Q<3|!fP`^XMADwh8g5u84GT z6i{840j@P%h+#&m^IcWBRJk{Zz^Y@mzP$08Vx=YlP;|tW&ULz3TK~@b&h&YUfiS$5ZC17qJaQE63 z8awnj5ZrZIA?S^P&)t~J;6V(l`oi8)3>3G}9ew(idhhi3JD*gbDPEY5LW(atMB zRhv;5!LoeF<1!+6egwo0UkF1=seZ&JKt*C(`$IOVpQf*v?@$OOy}&V%4;~C zdmWB+2iGb|w`cNRQ(X*4G2idcb>@L@c@H0eR*d3eU%1^Pq-Ea<9ug{Aqsi>%im!Ju z9gGf8)!vz6tbUUD=qxq0a>;9qQMX@8Ft`ux4MvByFF_s*3d&X?AM91jHh#+Y3KrdK zh~+;K0>2z_NY8Eb|Jp^I@uTHPx>~zug~cBh16B>w+t=_2Z>xL;GxkHpph@nFBk{tj zwrG2XM9HJ<^VjvMH(-G@I^a7}9MAT8@1)`1v!Yd!*4pJzZSlsd<_gJjgAa-RC$~6-d!~AaV<* z(SW8K+6wBm&@Ybu6$p%h7maN1i5P=8%%ALl&y$Lsn|tVLucpw9kgiRilJn*hx)A!K ztAA>N`_=Hf!qrcXQ&+@lz3`fP4e`>uE(;;@%XF0LvV!C#E3!a-g$XBiZ2);{(&j$t zVx)1lF?X|!%i4PConG6+!a+PgB&%y6eiyf^s>Q|+c$W%y3ai}1olrLY2!}U1_83qL zG95A?pzm)KhF<2xhNG!iz3qhd%wT4=cOr=kN88&QVFWz_RK`5G>%~4A!%fe+e9XAK zn;9e-Qg9>KcI?+XUMsys^C&-e(e~8&JrulteaP6s{kLAC4zsyEj}+GkzCMTMp~&Ub z)pck4WW6c^ASHy59Y65LyRDQ291zfP#zt}RpFsI*gH{{+5NzMFh>r*FxuX~;TJ zw%a3RhN+*J60Wg+AzaC&A}J(jDee$eHE40QECN9{<#;Lu5*6l$J*B+yGk^K*Nv_dz z#(AHOIuoUukbR>1H39s6zTuU>}|9?hTA-L zz(CQkGr`8C8EKM$^{^O4Ku_hc42dS_=gnha@L~z}vxQpa_iHJId~RQ8kgHOXt?GeN zB{(pHmUf4M)iWax)9v}}sO?pH1NETpr!2M0wE`lCC*ziLxNK=()`HR-nC4G>4+>~2 ze1yJzIRmcJb?W5=KPv~Ban`tX~>%~tLYu^24d$`}(R_Z?u z-*$5#5dt2$D*wo?G{uYUklrPzP);KJw*(@-m zf}oz~n&^0o(_7uodEkJbawsvC^r}g54>j;FF5w*RIA++3yf_~5`0!r;0lzMzy4&`f z?%>A}6x+NNX@LsS@HACbP{i4Y@{MMZ=I&Y$sDk~U}t$x-yptDUS z*kd18904vKmXA6fsxC|i6~BiM*Bfd}yfQy?>w_WQJV=q4I?Yc7wL`pd6|2$5j^Vc& zY!FkNMe(dSAzi=L;uVMwO|P``XEvFr08Z{^GkccBn;4isrTP5)qG*6olZ0==IYv={?_Ok zNQd+cSuJL^rU)xewF;5;uPK6j`7MJohNxdaejK`2ddSvTm5b0_>|@>KirepoxfS_@ zr)BNiamGi5g&uJMl^&kGKs}l`&2?O}S(e~Qu)?)IZy7`^d}7o9RM=CeKaJs>zm^$_ zZny-B>)gCLL|+|Rjg##bYU=bd{0}5QivpSh;DoswG0S$d1H&tIFdRs(nSZlY_0CLP zullLKJRggwcTct=*b_OF5qn7s1la2en zBE>#2a(PyifbS9#KRgV^bdeP8pBKj#dj3w>(DfEQcn>HiA$}(+6D~tUvm`r^R;WSjZNE? zdLG}*A=&lV8eak7j8S@;G)fzm3-8i!uewqJ>_iPV)vbsE z?-XW@ni)g0bD!6(1~kK}4EjaYbE>4m;F+EtRqKxnNIwHhDARyK$wE`0&pt(4bptC+ z8^b?RNr6;+$ox^TpPOZzLLV1vsS{N##FYL{2m*WRQah}w;$H``(86BBp1&lH?G{OZE%%Li#Q2s1XNB~f!x{=%No07BJ z>Y6D*fCKcMIH~uGbsy!3)!kDoWS~Jwv-M5NdYRZ~tChNL zyZ!zC3rf16I!0m_e;1XzWUsAlercOiE%AeIXVqK|HMw}7yJ}fS<7%duSVER>>c4-oyz8+^T=VhBJ-i17qNLrWJ znUogPA($wUg#SVc^(NP}EN9Ipp1~2saUqfG97_Ceq+v#8hA?LGX18V4fYNnzeC+RG&>^$O!`Aiw)> zURkH8kf<`M??&4G4yxd>H5mTwLY8l~BBcQ9rY>P7IQ0L+tPgkdletQK<$j!A>3n~V ziubpvPlGSS9K@aFEHpH0=;+!c>ItmUeC!Utp;`BKAKL{S0|Rym8YFcc=U$eqt_2h6 z5v6UBGs@01@-DH=4uko+Nto|D$6uzLyoJF2&|%_EuBLCL3vX)wWxESRQskghXz~21+LOC+K{|-iJ6+P5l^KxkGCaPJNO@cg{)I`7 zw{F|D3KWr#V;}E`_d>y@-v<}!^IJf~?)zXQh zrF7j+4`@L1N61(ND;R-^;`*`KYc}cSqW{}Lg0r2@e?3H-1bZd`(TOxoPKxaJ)CbQQ zccPyM0YU+Al_pPorS<5r?Rimu)MJ#&Z+pMsVwDZEh_>Z}LI)$V`uCTtm5#D@Z$)!H z>{Dt+aB76J%KL2W(z?C9UPHQZm&W!BGuM`_3=JMD9H_h9XUZ-K)~^hr$%~xq+RfmdPh)(kUvJhhmRU7 zmA>}H+N^@`TG19r6IDXvH~4hRh?XZnTG4JxIa@Yf`K;tkK1riK1`7*{Dypa>2=hFA zZ&fo3YIm@D9cv+&YTJ=Z1yXLJIyjU)?ZgeYs0z+TN3I>}kY#zlYoG%tMW#mx$ToB& z5{P+U3fd*T9cH^}Wtio{OULABU_cvLyvfAWQU~ew1OGsRmK!y@wEZGrM?D2A686`= zyK^#zcs%;caoT#MnS7^y9Sg3%5-d$y_L8YQRZ4lyJv*0R!|VwPm}OqaLN)KE7xmia zyc@PMt>UPS=U6V-r{ z8xu9GmR*IwIQt>vkKhSpRM|)K?8_RX`zE=GwtTXDSvShYi8v)R~y;3Uz#9?Vya314`nkfu$>bbMLOd@qEXJU#x*9AVEQ5c z5L2l1ZC4b&)p&nJZ%0Msx%2n9>!olJDt4**is=MuL6%%ASclto${MtQ-q4CwoUqY3 z)pHE7#|hP;5&AoUzCRpU&NI$7ZGxYy=8q6WEF({vUV?)J`Xlxa;-)He+D_77$u-Xu z-Z%dk2x!3XJ$Vo)p=UO9h?b`v8~{NS_NM`hIo3C#x?k zD2AU_$Pv*R4E!r>PrJjKR|Qe`$h53_7njxeGP8>z*jPQ8#4KgVWCV0b z1ATnI+2TQ8*b85~XTjSJTrxN@74~v z!sG8TcN%=sFNMnIK2lLx1>OqHNwy=y{8^7y2AR!tJT8slB?J4?GJsBGzI(V&PeML6 zc^SZ)PNT5?G%D+Y^=#8mDd+qqBQi@*(pwtZxYBG@67u%gdl_oyK|^Q5dFR&*x_O%baw12jDgZcvXRY1vkyN`OZsQ$#+XEV~m>njE%y82w% zPb%cZCIDct6`8hIfv8y5v{-kDnLL_zPma;@7gmVlQ@W5z7Yd3_@wD-9S{0?^CLeu| zbBJceUaFq9N!p+YQf%ock;Wm}=E49@lMaB;J(Y?hh-rRnIrk2#vB`Xs(5vbWJ%bBB zop{Ea8CvaNWk*}>=LJhl;)Fl1)eii8@r)aXskM{PkV%6TB|XhbQ_uT6udNluh30wl zy}jWv8It}b)llIJZHTi~@X4~bmZi1S&E#ekBS<;Y$kSLPMK&_z|6a-2P{|8~etkA` zC*fc)AN=!sLJnO#n67d>w7XKi{cjv?k772i46Oo|zrb$(2h#l}tS47tchElVosaTM zUlLFM{>w%FaDT=TW1sqpdH0o9AIIyLvI-&0_G{+PyCiCqzE|D~s5oQ@n+$8#DjoX` zjmo2AFNu!}NST;xfyGb#;^H`SjAmHw@_^-1KZLeV@(ZF0bCDd@PPAu`Swu0@;RM4~ zi)&V9tBq6WUHWe2Hor$5OT|Th-MQB0S_kDE&UFOx&gPrgWgEc%C+z+s7Z{qcB2z`U zjZqGRmnKKhI|VJ~Y^0s#J8MAxu+@&PRK3PXP%PEp(olxgQuY9p+P*qQ7|R^^DF!6%jb-a+&)1vuSP9WE|9*8vr#ZUlppN$L1YUMk~8}#+pECS83(Z-*t-dLhx z)3W?EZ9!HZ$-%{QA78&ZP*d9t66%8582@fkYy7P&XdCI?5{@avCzh)RCoLx}@9$4D zko#?Zp!yo^1Fc?ax^1p=V+ux@OVY z(2L$fU4DKUhE6EKXgu@GY<*wGRT_4sb2)DWi{w5JiT2mz`(gDGvSRS$F>R+yxODeW zB)qc4*(vT@TtK72yxotZp&9zx2lIM~@*qZ4ZKcTctnp}7(&ixbB>HKZ@sEKmA#rN!;=tkMhKGrcR#|tbo zWDJHd{nmz3-+vVNCtCrOFCM!1A@Oayj`EfHB1X+S)#wEBR#?(^$6)4LfoAE}AzXN95V ze{98S{pT$P42Q8Rqd~NitCV3)%f}qqXoaEp*1Vkira`R=f1><8f%cR3r^HP8L(9Yt z<+Lc9b^ck%N0Wl5BurBLi@M+ntF3K0=gd~z_oMIHV`=NBTLNme1rsvX9T`=akxgnk-w*mLVKc`g{3JCELQbT4K;Jdd^1Z_Dn8=g4~0^|6t* ziaUTcPosS@?&sm;_tVo;>dQP1PrOi>VXwT1->0X;V*>HxnBWNzUQ`s}v(d^4K$A9$Y9yCbRTNjW87A7W6JpaqY4peMa{Ut0CgdnSZsL*)q%+GTf3K|n{6l! zeEg~VBfudPTB})k>z$5F+45`e1*fLa?1Rr;hY1OnMRfVz+4pLKDyDB|NIs~W6oxhq z3T9rI0T26;wkFUf%{XPP9#m$xI>hTCN@L}8`cn6vu9N1AYgOcm?f+68F*bI51bZQf z%v+X}2wPc~K7%j8j#=iJ`FPV8mLnmN{yBMk&-#hz%gZo#;aIiNJhqW}zhfJyt{b#C zb~$eUecdjtT%kcc&A3K%5I~wc$;Owq?!|2YU?PrJFS}d!0oU`U&ErP_2ki9lQz7Xi z%ZKR<%{`a1l;Pi-J;$aWZB$W$9dw1k=(CI9>8}RFjNo|olSh}@#_w(nqx{YeG)ddW z=b`l0=E-kPw1VQIj|L=+84sTJASvS|c*^UFTIib|?IqyZg(9zsvWAK?>unNmvTKAA z9!4y?UsCzIEO)JM%axCV7Awvf&NWJ411&4>oQzY|{>r*A znkhar!z`CSo9@hdo$|2<>^1;$RCP0p#;A}SoPH|Rjr1`vFutwuWzIkGOvlJwG~GMr zKLNJOp9MFpoG%?i=Wl=Zv9K{=wi+F;sWS>UmPo=PpGo2+3{e?7+v!N)mH>xf7n2NiCm5|VXeWgPMN?RD}Ye)2|zYx_r^GIU1RuelKc9dUF2^AL6d zJECeaTD*;(@x^m8FVFTO;YC}!CTU#YVt*>l$^v9y!WqhBl6+;dSOLmFUcwUhPd468 zuq0leu5s`LnU7$1ujI^cdj}H>_o5u)_h%Ts=_I*$^uu$Q!dZi~6oKF-ab^<<2s-7_ z^QefJ0yFOO=9lYqC+p>pY4N5snR*3x)T6(ic-sm zt8a~Wli%jE|9kUYB27F9=@CPslPF}%{3cdO;A6a{Lquh^D9|?JG@7puG51_jwI!cd zY>|8%=#yk(9eR{d;<3@Hl-$1>vIUrXlk@+9DD1`ga<@LITb&Q$ z(#DQm-*K>+K$q#JF0N_X@az4`W~lT$7RnBUkQVUR&#-4A8X?IQ1dgsOf;CjYB^ho# zyJr_c0fh0P=8knNMqlJ+{Tg@r#V!6yPoQcuL>b<`8&sK)%iscAO>E?6>FnqVi@gL} zefTrtaBHU8DJR1!#Nb|jUrDTBJVJ&7#*~Sh(^@y*Z&JN4R@5D`>YeKSP{45=tI04a zQplVI(z~BM+E5oB=pgtY9B9i(LdGMv+KZfaROFl7^W7wT&~IDp@K4dv``?U zx8D*&BOLBj#;3d5T`)l$Y(k*eoIUWkzC#hTxS+5rNa)cGXpXtk1SR33Fcc6~(JvQ@ z{^^zWr<*<+3wzsEPwe*|UwUmL+Dd} zVXv#btw^Z~ZxP7>k(IglW9eY$nIo19XB)CS&-#vd`_AKU(zo-^f;0-{?5hTzY6{7Fee$8I!a@`ZP)6dPwe!!>O*dH})y3$LlH;SW*HdhevS-I~L49(OBrN)fu-*deypLcslr7*EEX$@q z8Y~f7K^AJRTZF4Ph341J8dvgWOD%-pTJr0#*hOWjpqw(P)t5-mj02rBs+J-JuCf1( ztAa)fqY9F)Da|njJ4lD|Ej&8a_M@J=>4~T#iVzFsPcA>Z+WT)Y^|D&Fv2Ot|0cIP- zdE$=eYy-lr%03%s<`-A8Z7js^F?{D%r##M#R>yFDCz&Q!WgKxz-YlAcO4|lB%<4Cq zEbaaH>;51A-)Ep>Q>RlYr}M1_X_;hp4)G=Uf1HB}uy^>sZE z{C2`sL8yC56(EEEED6b&EpmiQjZK<(LDm^)=n}#If%wa|QlLZ}TO@)%oX#k)dxp{(Syc`7#06jRaH(aU&b`S`YhO8hPSB z1hGXQ#pv;F;{0uk8g$+4;1Q1?AA(}3x3ArqYS-~ggf8za*HhwS)$pY>ckICj^Fi#` zxHb;k3rX$msQe-;)mwI^+vt!Ok<5_MU*x@Vc*lJ0V5l`eQo-`2`q;*Ixk@c4Yy8*! z;u4?jS3Ba|IOr~`6V1DOpae?E=Y^w-=OW@ULV=~7jm!?ThNQEAXnO7QqklDrJ96Jj z2N1G-S!hOTWgGP3!8om`JL$A9^L^jnB@zac_#Tj>6XifG7sry14gca6*OyLYcG1V5 z>NUve!k4h~wRx&me@m;|%u42ScGN)C4nEXc$)A$opNrpg8XD-8f{=LH zI#`qiJ0SwGGu>7u1tX;9O3d*K*zike2>rSiXED{6uwE8uz?c|Niyv*N;UvYo15r#3 zpILjbfW~L4_AY}Y)-J!-P=d`A?pJ5F7xyI^zh7Lz+>KQDLZWeVDYbkDUFm?ylh7sS zq5e!T8wagIKRN{h#dYyRD(Sr}HeOAw4P18o!!XNi$0A;rAh+tE?(Ulg4K!@^ zX{S-~0jSvy7z`cChD7+ZHRyfaF4?*Ox%N;x!{&Rzr}~L8cV{A^l^yFwb%FLxqx%r`QfmeP^Owk4>;Q0@46!oW$*? zS@+kD#|zQ}X-phh*TQJh5w5CY8hoS0^4+HZ4AMM)42~2^bXMXEPDEPo*duz*B-ShP zF2p_>aG_#C_=DK5UPIiVaJjOVBoz~~hVWWdC%(c;1Ligy%KoRUg*B_e2T`V)f5rZP zr>ZB6I#kT+GVsiar&0Ksd$>U6V=@=5-i?!!#>1dxw z4%Jv`8vEr+>qxE#(IsmOY?wWX&)nfTAoGX%Bqu7>zm`}!&#*iIhW^VT`C|r(EjY6@ znva$uPF+ewYqy>UXNWp>^JogQ%raiHNO}cLYpWMRObi{Jr-OI z?$J1^BYd*bU&*Hx8vZ;5P=)jMtZt`o@=Yh1K2%&q z%EP?-`v?y1i*Aw;U6%5+F4l?yOBIYuk?B}KV+85M0l5WJWemF@5DCy2X~bP5n;d1D zzBVqRPFs@@O)5z`(bQY6_BQaCGE`2*W7UH9Y# z$gG{qSRqvg@r@AXh-^6`jVY^H_GP6o`!68M?3q48OmeGhvCg0c9iw^O{y4omHOj+> zb?7!5uje|aOq0a(*qZ5R5MbLE)ds9rD}q{mlfOWzfBKpeM?j|~L_&x>`dIvKIu2rf zST6}Fz=< zzQvE_>I2^HjPRN|?AAqb#dd;NcpvJ!m2#`3?ud6{gLXBd7zZmA7ahqlSBDOn8T!(#BER#r^$3`ga}UYIF3N8e@oy#~yfO~%Epj}x zg$Zze(iNhSs?YXC*Tk&kUf-%bIfY+{7vxzOZ^Mf_!Dpko{vi;nd{4olYtHpZ+Kn5;Q|+ z{$jm0p{$VPt2nu1`~G%hQMiAqW;*#rm&pvSV!&i^C9xZ)=KUqzC=E_j0W6;7MY)8$a!zru_Q7l}`MXOOgWIIbN~@t(Q8U=1`i&YBscQO@XGA*|Q2 z#W{F7zBEqSolgJ+IA1j?jI7eIS3XwQZrw6iO+n;{>?chH2u;pfkD^Qm_tvKu&5f)V zSkp4ndSFNMM7|*6IRllOC7XMQJV+ETR@VBLd>~IU3%b*^#6U9#2aV%qq_aoj;K57kckM5L*^31Ipec z*OPmj8ZZ!25sgXiQdGT_-K*21wxdP#(%E3PaZIQ9#o{Tdl$wP#FQvcjHifPV4f0<{ zdf+9bdneewPPen>=dgRnXUs<%dH`> z*xdzZmR?~RTTXn173qoRqRJd&byRB$=zHziHnp0?#zROmBts~2{su{P-=XuHV|F-z=Be-$J0AwMT^x2X4a>32SD zevz3@k}VBVEc7T5)(AaG@@`?Vd2PqltxzA33#C??H4ciKXRftutS-ZT@zzu14H5Q|NTErg)2B1nb9V(`4Cwg2;>eR&gy$zezMgJaI&FnPBRE;Yd9!YY64#)^+2W=JW!EHzng*Ijp$ zX;nNdRa*DNwBV12H)1(q+CqfE758Gr#CO9)Fi#_xnEai1tv`vY<5bm6YtiBPTqWyM zOM`9SFZlB^1OHuoj?;f2XNOT0ipD;E+Hkt^iOHIlv9Y2VRK5`DQLi9>|Fbxk;eliC zxTeniZ_MI8{Q}L89eIV!+iBZQ-c9l5zcz@;FZWOhjE8Tx6xGYgAeDxghJ&af%@KH zQYl3u;i^vNgK~$3279v-?UlNk0}TKi8TXI$p)n68+whBdin5#${#%-CylaUUpbjT~ z3tbap%eZ1Fq<)^ctCUW4(CWFc|CpI|3LRDzf(ApB<&drS{vih48SA?}OT%)N4>4VA z(mXugLs>7*YT<})vvGg5B-SmhpobZx3CTm2sI7^g+eGgvbrl1KmG z^{dQN3f%MIClopXAu)>Y7Qt6S{-RxIg>gouzrK*3{S-vo1^;}Cf1S-{z7wx&AlzV> z`+)LvWr;05B7kWqVk`JDm)^}FQCoRJZ#l#fo|ly!Mk0VqjyH(3OosWoCV45xC+E(( zZSj;FFDMJf;ELq8?l=*23r@h@3zj!*$-;4n{ru}2Pfz7z+n^tpwRXq6b}sRjt)O6Z zP!uo1lxI{_unc1Q&n>J*ifh-Z?&+C!K)!&nh(EbX4>rJ|&biqvEYQ49)&6XrFCgHQ z-OZ(|&Oa$ItFyoPyXSD6r0;;fYOFV59()7z%8-lQ7V_}c7Yov|yr!6BQ0A{XP0wNW zEd}zYsp0;_m=_;n-@NvWn|fXGVCP0w>Z%{|4d1%@>CmC5VD6pzUXjC7AkW;U`Fa** zVe89UFJv|&47w+dI$fnJk-?XIwl1(`%ZPTnW@+QT*;Z%bEMUqbA*%E?F*?y0E@a>j zHM72Z>p#!{MlN0_Gsej8BI(A`q~$O2CDkCRoY^Nxa~zhL)s~%}o9(aeoE{hs&Lyt{ zdq*yT;E$^qshFBU=K|SvQ6n%O*a=@!l|42M{CZnFJgrk-smdqc9GX4cQPrlqq=G|r znRp|pik~F1MpN~)>x*6h@BC(;6Ot7&L?#71R8V4iaaq(gB>1a1uYBz)RJy2V2(>JE zJr%}my9*xPc#{2g=4Qo-7z!g4Y4cruG_C-ANu_&Vdo{bSG(m5yyBFjFL+7poKgwY8 zT}CH)$Xa0#r9P~#vj=4du?rdhovh0~9qw6uR4&~m0hSGktA>MjCTR(uhPT*Rm=8=x z7Phg>Jy?ll;d+gykG+meJL1R8;=kd$5=L54%(k0v$-ts~k}y$aXq28iLM{#G%w9xS z=|>kwZq`k<>Dwg;(%xfqJvZ)h+T(ePofR%r&KBRmI@_2BSal*(1S^hddd%Ta81drh zxX;CxX=eG8Qa&`rszG5(P=xvd_NO@SR{0HGg27Gc#$VQjJkB~tt><~|3m()aOVf{5 zMDJvbbA{*&eyoez#nZ8SKIVnNhZp-3w?OeFfcSfNNrtYoCJ0DJhmm{Y{wd!t!6yK4 z<8ZHRgDTUy)~%asS*4k4W>E>PWB}7WtM%8glKeOmmE)QB$B!_TdaGF-dEeGp6xvcu_m=n5 z5UawbM``u~ZTWTDMn~>fO}H*THvH`V^Wv}#*yUTADr^~=DE;jy8D=aK=|4saa0wSy zP<}d<@Lg$j+*Si2AKR&VGj9#kb${QQ*?AaT}tpky>@0HQEp1G|Ho1$Ldb_TvO5v1Ui~Md#DAb#M7a+oN8pz2 zZNq+ndCn^^m4(4?0fB5ALAr2ySS;1aL%+^jJ9*?3iRK#etz0_rM)Pr6-te7tz1m*h;z3w(| z$E!XwSQb(QgrjnDIfm_CJNlMOJQ?0<^Ly&y+s90bUz(Mt{-&e{tpxPq8CaBfQ zks(pR2cAF5-Ol|!NO~e8Nw$+UrY5q3D384N1M#u}cEdY@yhS(<-c`zWly2>>_qsnj zA z#4E~YWEy<2LD?a_LxdI&VwXhit<~1n_SD{Luc9#$qqMeI zp^DQQ)nQd)lu~-^(NN={_U8Pa@9z)DmFvot=ks|#@B6-A_ghj#wJ=>eb~XN~nB&I_ zUHzH5o~80imiAkSkm)0!^g<`}IjPQ#hEDd@`&89!E1~EwW?0ddD=gxURm8#8$j*tV z810UgCE-gWl1}8yiCKZZ#ss-`@gv%^&xkY>Rm+?3Y@>i$tNlj6@Nbu1u3Wb2;1%ir ztvw5hN}u_Z72WzyTzLONXq1Ao;~^KWZmr>^*@x+|-GITbBpd+5OBbpe@UqwScwWc)CZ6zP^5OoTdoo7Kzl! zu98qn{~)ZFpll!+*mde37PM3B10J?&uwxQhhe=$?i*IOFwf}_b)>MeRpZX>aO~!?R zd%;#TM(mX8Wgy^i2LxCP7p`zz{v-ap6X2ka#ck#i67p|uP zSD0b)?M11wbRuuPJO)bsRDR4NrabWG1C3=Mw<5kR80?1TeA_yjbm!rJV;5@HHhluf z`U7~4t>z3lV_j<>`tQiK@48)n*9}I-^KFQkva%ps(U2leAYJSC$PG$>s)u0n9cXK5z zY;$OJq%9H-#QH!<`Pqq+?*KyX0yQf>z0qC#p%+4;C_N;CN09fRTs{;`dPI5z@Q<;onmY@clIiCJhPON>a71 z^8s2HDHdoyuEI_h0;dCY!>&bDPjP}q&j-R_^s!EbHG_obL5YIt3#E{^nQvn+hU1GW zIT*(HOdtE$K;M!=yUL8}2ix|8qs#%Pger8#A(V`EOp7^S$2z?q2H>z#!yV7z^$9fT$xWIj|!2Ou*^w5w*TQJ*z(hYj4 zT?I}6JwhCReAAIe%Q$VFu5C=we%v8xAr-KTt||UZ?80NrDi9mu`BTen_-bIQ2)&(3bbv=jt)4+U;N;k`*+4rk>&M2j}ES(y3)FX$E|hJ z68%FoeRW_Fffz@-zpv`v*V_uws;d@7zIK1gp)IMdL)jynGHk!Ry)Wa&tQh25mvBWF z1EFE;OzSy*isL+5OO;5s=__4xR~){sOZ9c^trHY60Hux6f(AgrKpv*<>7+p5Rcw+x zSCx%z-&G`Pragqhx&-Q;<_5V5!rSSoq@tJ}0i_QMa|So7@LnWDKI z_O&a0plG|zpK=)|Z~jurF1jXZYb>>&#}72A0%HxEQZK*>2)~Iad;TMk?fH)fNPou$ z$1g`0$yCy)+SeL;zF+Yyd}rBSJdCsLF}^h9`IWkrU7M1>NI6!NBvH%(Gb82RR zvq2bb=eumop5Qq5>O(Gt2A5pouLJRTc(79AFhbY5{;KM2=n^x84opXAqYMkTq=)Az zTh^^{YJW8P>fV0Z_ljHQD;)QYg(B^`nslV#i3c|R-JK$#Q&EZ?PT@!p zQ+%7Lg>|lPli;!Xy+-4dnDBlJ^ylAryK51cUx(Td z!#%#Hp4SxNW!qV?;!~PoMCE3e%hIqNasc5R1JbBjk25dd{XDV|zf=^u-lLmkFZ#ow za0&i_F?5WU0_%F8b$Ly99*RD=q2AxR2uBKWLv$TM%f_(pLHX;~a zpgP=^BE$?6df{F=gEK0j@pRW_Hk>fHs7kB*(qjBOT#V_#8^_xPU=JsqX@v0TM@Cy1 z-9^TKAlMzwz=ee7t9Em{Y!oJ`0YX2gsw&lIz5)|#>W4{z(@kx>Xz^x79C%w%h3BgW zuuS9!mQ?y6w&FtBQyfwdAA-!->=5$TI1t($TQ13VV{_(6vM38n%+zsnNHLumj7Ay17S9jq)ukWWU5P@{7W67zo}ld?DJNv+$#~-2p`Y{> zHy>>qjC)%zM<0JO8kw~VV^Ot|75$|mKpb>Z=wYt|z6F>%T;Cu-mDuq|}GR9?E?&X{LUaB$I)u`kF>`cRcx zql+uzk#I*!W!ITM+mU-6&~^#1EeZmD{KLYt6?WT1gtr}2igDiHp-r{Q6@LzszX#hJ zp&>KB!23~n$5>@DHxiK*IY+p@){M5PZ{&2PQ4ypVmM=9uJz&#DJcOR%a4So5g9im6 zo9Rn39k*py+ve)LUrP4Aam{nuF z8L+LE2m#y<{z42rGX4FXIW6t5MKU1*pc@71r5h>8MP6K7zEx(#C=B&-i7{<3u}TUg z+4!SQ1ocGdYbLw!_m&8^j`~Mm+RmJTP*#A?mlIYLUMscekUmCw<@JqMllEDQtO6Uy zT-dQ#geTB-2uMwH-6s69#C&su*9Eog>kwH#T#0r;z(Ts_3Tf-{`kTf@bY0`6PhGpK z6Ua?fQ9&S|8Rm2zy*4I(r!~ajRU+7V074yDa(ADNvuD`V?hO~LxZcTJ%ec2D%*K)r zk-Kdj6??WD@MA;zSmm5;T)Fuz-3n7?l&KiLSFn8Lksy$~3B_95( zsuWw-KhBr&zhy>quU0D{F2jF4_Oft2CD-3rC8&hb(}%>R)1f{owy{0 zR+i{CsOmb8swHn1q^4KF@$-VVMi@OkVl(4nXOvyn=%$!Whq(||B|Mcw;PD~n!5L>d zp1G5_2s>**RQBQkux^ssp68#PG55l;H0cP-*lVDTot95lapsXnLc!-J>&Q9l^0Iqo zh*-$|_UEb^&8*Sp8cP|1imL^ZfmT~fw8Gv9;pzs;%H@T2B;SiZaVJ_*^RfVDVG|V4 zUI1GmV?YT6f>I7;2G>brIkSbLu$8ArxR%q1XPvca z6YL~rH~}*5{XE0yx_7bj!)CkahoFh|bAP0h4?~!M8)tV^x;Fhv7PV%oL)B((Z^YoQ z;>R8i+{AeL_%EThUc@WH#DWz_r?8-X+UNd)gzEA8+Q>erLApU-?-EO23$!0b(;KR_ zHs0G5M|#-r8vYj9U_S`{i_4E!aht5UL9=bZv~E7f=l)N>b)t$%dz_i?+r6{_6zL!p~qt8&7U0jfKC zExpcQTA4PPGi{An_z6^8Q&|ffO#~C7q0KoLuxjHF0$-cfIm~>igLA6iY$lb4(Bimzsw+om1`!?KSm=P} zs=Y=WG7{B*ZhZ)kIwqU)ur7CldNO0!amT=`-(ZwM`28Pr-`?iDRL|)ifE+k`u+ec- z5xs`7!$w(g>Fha%DU%7I2e5=5551Rm53>sJ>95)>1@4F@H{x=G8Ttykb3C1*Z}<$S zhfz!XOw}Z%Mg+!gPc^jXU2_AE#ZP{5_9@1lhY2zit&*Gg0^@EbmrK#*&9+Y1iIoDS zTV@EYFY~4CmPw<}su;@R=Rdf6V!7S=6Z|&JzjeE6Mjy}WTW_uwO56EaJ}~5d_Q`;S z6%;vAy%5I)mDC6lz_*a1Vt0+O?=ZNGKIlvj%9sjIH`QJN*k6+l%)hR3_b((Sc?>M0 z&q|)s-q&E;)>xuuswIAFAi7rX7SjJK#98U^smU$ocbSH-Vd2LG5Hi}k?7G!U@il32 z2N$W}KV0Qk`drg`IIt@*CSJN7MKHt+QC@KpKu2Z>d zntgzDxutKI*=Ct|ffUi(y59{&ouF2#9s6zRM*joZgU^ZP5MeAV^Vny+e_4k@wirdv zrC1ra-F=CY(apO`PyXoKVYUv`Di6;D-kiKX`%kZ%oWCP6YSj2ym}}qD0-?~AtfB(t zl7RLS;%iJ$LzSpA%RBMT69*>>U+xQi4( z$K;D}g&fN(%k=#0+%BEir9F!HXU$o5u}`n6-2Q5VR15GWJ#^l^chq-+=JJtpTxb6K zrxcx%Y)$5t<2im){67%z*PO`B)-Dq&Y04qkfflXnxpk8UkN}5W5G9mc|9#3=rFv?; zhrJ`$yga6dQ@CyI@W_10@-6^N*goV3r?f^a6qF=wbA%28zhBBqg!HR&M&wQ{&_Ij{_0A`bEhjzT%Ub|XQX zyu#nbEW?PkAORM z)WF^1=4gN%R*j;+)L4=^zAwXUkFP=9KKek*XD@KP|E~w_vdUrBJ*izce2)~C=Y2W= zcT_&T=IXf=BJk1Tr#Bftts{yv(u=YV?ns9K%}aJ^)_kZ#?oRI9p^zViX8sJV*SjVTe=rPP+B1D^Z% z%c9IJA6^oi!7gr?G zwjl~KY5J=n9Sff1BWjs;7Pg=TzJfr+w=X!IN1lp-Nv4a&>ZT*|{tGH9OH@GEQ5UWvhDJ zwYMZZzf_cG(shq^r}~1Qf%BtiTsMuGfVJx%DsTaD5l$Z39t7xgI@3Doc=SCKre1FM&OQcPCsYwrrXT;BB)5iWtyTn zZw#h;mieuCjoj*bIjd(&q`zVNbPK-IN4X>jfSfK)?^(VJ7;>O3*z}oaU^$P|@T_EC zmc>4iVX0?i_NK8!f);3sae*d2QfB&O^ZB|h(5X}GrR_G<%+{VSxcvQlBckv9$R=r) zFmr{;|3LH8wQNsnW#f%9UX@w@(zb@hX)}-sKq2!=t-3mCdQ;K1ugzgMHdZ{I?Fw5Y zIitA6%0OM}{TSardviN6hd$saclkxz(rx5t+j zMc6Z;I>zcdc=Ml%k1-vS83FQ+4MOw&$7pURQ=y#qPl=^DpMdsz6~`px8Mx7*95tUNTDy8T6h^NM>2dg7obM+D^V%C! z_*ukCA~E{ObzR!udhOD|7mA~b^goMgo=h>@EO6YZK2X_|O%&Qp4khCXf_Q&%c=5|J zgA*G#b3^HUn%=w$~Byp1#9A$OW<+~@*@bE0r}n*3+_qG zKj!aB#qozdFETSW*!0edhep5n$Z=}l_QweiO4ZRmYpIz>TqY;g7&GqZm@;O}p zDMwVxhH}S^lJcRh)lB|(5t~%D#v)dyfQ#Yb;d_Y8CeFKt;UsYnnmi}|Ll0GMLk198 z%kPIB^I18UIs>w{1Th6Ps3!5V-%(f;7Ov;S{-gdzWy{$V-SMG==4If-IF05T7sg<=2AZglzbfc`y{l?cAIE~>!f#8d!y9cF2djP6)bZc z>U*%cVRbTuwn^FuVGqdhn%LDBQlarLwGBzvbh0FDLZkyVqut5rU<`*<9M7?g0{)%X z$6OniRSp56h1P9OAuNFFD44T&&c*Ge{wK4RsnBTQ=^PF0f#>Tg6L>1MTygmu7S`wPL?p7E0012zMlcXcv@pF2+y&hnKqwPvEd3sPZH zo$s{lIE8;h$X|Xqa2UROMx-l<(=XiqBNG-OTXMq#u&BDo&$Ft`-R+`E ziQJ{Z0+`Giz&P8@qXW@WUHiAq=uE_igZ@c>g-Y7zMQKMjzS)@26HPU3{{nyn6RGVg zpT;dzau}m&6`ciG$A1uCH|KJ zZOULo46t6UFsHD8wL}&j$3I3j3^w6O8E|M{su`d!viBJjO>(lk_f z@okJ5fF+4Ic;#_x{O;6TUxdm94jEZ~NJmDY_198vV@F)37#U5$K&E$0{AY2QvaFk% z8(SD1Zm)CosU7oOE?@>9iu(VY2zQ620tcu=_^D^<*6R;@AsIg4qm?RR4Wk}4-B1H4 zeA~nXVu|cq0I~;YK_5#a?q@2%YleKyT0jkeCQxCVW}pf=gHgMRTggRv>Ad18xVU?i zrSl-}cbM7uKSPGYXMyUe7}qJkB|6H^-VY(m^#s9yj4bNKDbHwLf)8-joS<3w{}|`< zY%y*WfiE<}E`tKMrcj1fXTLZr%W*>{)4sR?PY*EpI+DTALvF7U)qe-?b{8+M|hqW851#4 z{sP0cjJIFQh;|!EhcuriBRZ!{$DLFUFW*dTbI#ZL4tkF}h|Z2{*Q?}fd$9-~7T@*&6^0d|w!`jUw!cHi0a?9|uj0z{H&V>4DJJV$s)-3IJ zC70v8TtJbdUcJo2YU{M~T$cA=rzTzJ!%f>i?IO3##(*=@&CH%42~F}W?Z0$#xK$ZiPWptOh62!D zF7$UU0;Po1Xs+FRk3o<>%w;fak6I4S7W2jT#ay#?n<$O0t8K_SWjWuY2%jFn_bs?F zZAL9}oqe}wp)wVw=!%#n&YAS$%$I!0k?Y6YjfW*rx_~byrV+*Sbd@G|MudLNfk1pB z$^#@_Y zTcPV7*&JBw8(P}Zxxp8$I^qe(0zA;^~ zHF38bm;la!Mf84poB}sie5^4tk7;vVKE$vXe|El~(o|SJe!VKmHdTRG$}o9h%cu=j z1p)0q)73@V8nx_vyxC7EsVtn|f@bnHOQ;CdULB2-brlIeC!TEqqyDx0Um^3l#k_>Q_>;h4qD~4&y?$$GDYe^3S6Dq@oH@|b#TqY+@ z87?nYcpFxh2rf6=146F*53Sdp@Vp-5me^AaYp3H>)S7n>`+pp?&n-QvkTT(fdG#})ay^uV0{a=AE>#n<#NWj0;htfX#ffD zPLucA-K@R|6iWpw+roK+@E@|ab*vPRictbniL|-mmc{NoY@hE%0yB+`a5j`LJ|}v+ zQ*}0LX)AYAaYd3Y@ms>dLx8h4QRaat;@GA3kGq>C?8ZdauA2YLFMu0n%wZvx z;9Ihi)~`BHJY9Jw;d)|-lk926C&6@DB(4#_jS;LrXBt?{2jse6Cvc2sHly1BC`j}U z!KaLeK!>plVesV;r#oNQB>xBUteAyo_gIYHoSD}9GuL0K9q^o9$PX|+>5r4Xw95DP z`S{UeaRDoITWTgZ$^ZNI$d}&M*-01#uNTnvQ^EARp1K8twGJ2V(TJ-Lwk+5KgF8)e(h^d5_Yp zvAKy=;^%Q?Q}Crz2~+i%-ZDfhKB~7+d1J)$Ss54Q$z2=@2nZY`?;6(Yy&PXS}p znZ~$iNr9Nz+<8@>PZUSB_Y)YV>`66@F{~i3^PMh647;+Gg%>W^LBkK6N{|F9^N@7G#N9_3HQ5(ggK}EoE%( zrRNX{M%o(QM{oPOsxQc$!qF|3x3U>T?T(r_tnmeIl?&13XVHI-)J(c81jO75mKM^Z zYqeYf#w>~RE3R9TV0k4%c^^s(Ttmyp73#tksa!8JFXF3yxV8*fn@PgJTNG|tf9ad@+;81!-Fgk$drPtkz&%q`;rgt) z&*Y{Yv0DA7jX6dW)I$?Dpsq0og<_*NX|*F{D~0r z^~IgcfoMawv4pymNCQYRdi^Fx>>SAnZIt&MA6^8UzJLdQs&UivE zPP6aJ)c>oaWCNjE+9F-jvY~dGwLHG7+81q?-8J^*ViHvOHDLg4ba(|daWDJ&;ZW%M z-9-bV$3^;HXD#ZAQ|mg$PEHE$C&%jsiM*+|g{rx_=-vduJ5{oip~ws>JSg>iR!SHaC3C{la$p0&`C_(!x! z^#!sgZz3`7rN@Q8v_|2V&5;?)q!V}+?K*r>!Tyl8FBX**?I>o8K`0L~WTGycR(L;vF!HLMvc>+e=bb`|v&|$!b zct7=ew-4)hPDW#_o2p-C8`kaNBc_j0Gt^2E_9Mak)WI z{w7N1?x5*)5&!PhdBk9|q!L91$|sVGxW?Epbk6fL4Zz31tu>m=C#aLXvzt{yDNi(t zGOga7x<1PefPKwK=RDi_e(n7YoY$fV9orw0*fwpC>I&)C}qL&Qgb>!u?ejWfy5CbtWcIPW)vi1F&czEgv+Tt8CZf zP%d>TN$52@+5cGN`3$Gv)ek;pC#Jh4oZH)T0oj)=QxSzTf#Q%mq8=QbI&frz10%%k znJ(Q*$c0)8WqKTXy5uJN*_e)3lu)JhYwO{8Iih6sy0G=5c%LuHIrfwW?k)wG`j?qq zQ_av-FBB7_mV@Lk8=Q}e9m}W+jet_0K(bim2idZh)@e1EfgIbs%tj{{F~oCS!{MUv z>*tk|t1s?8ZDuv>&h;d-^engVu7t!EDGlH8*VVEv!ld&fl5>!Xb~Zu;TvU1Se4O7% z{CfE_PN&RaqYj@}D*L}ZB-84dOx_4ZSr_<%=WFgR-`{Cvl|hZ|n&dvpAx=b&=&L}+ z&$+_LnPJq+L%rI>dtTW&t3Skbj-U$W41sKXS2T-Zu2eLC8Fx#Q?zY$i(pAm!D{#f0 z5@B{&GziG)Uhg^3{T+iJ6YcvuUc`A#2>lCjTEW5y1gU!bcE(CbZy#aADkL;$O!@7- zQ(n)Zl}^0F_Kr@pym4xopzB;?c?W3Hj7Yk%cTmKxJsTr*7bEPQj209NVu}PD!I<(K zQ6Cdq^dQNom3~{NV=44xwe#<;wDW`)qhU6z%&Z6*UV)8Vlg+|mk;?)QhxV`mCoqm3 z#t@Mi_7puf!oO=;>J@3t-cDb>E0|*GVZd6MLBb8`ChL{+aJO>ky!;svYtvviyY&FO zMrJ0By2MuG_=YfzS9rpeEe-qoxU_x)qZwc|Eb0GTM;t_(n#XhZIPvw0oq&9Gpet2R zY=))PbrW?NQ!MyYx~c*b&JsdlAkNr=K+gn$u=g98jh!+czO9P%Q|7L@wkMEdL6CIw zk;wte_NnK{98Bd`T9<40mbZ@9m)pVRzC`onzm;&5bpBwr#QEj?m`nW8S_bJFU#zm+ zSASLpsU>+9Ovf?w_~KOI8T>kC>Loj@1Tzf#1{bo3UFZQ_n2g1gOnQuTiOXX$d|C>t zSePL&*Z8Bghs;-KUnrZZ6vi+-927ZL@Wf{T_4dzWUgpe(?km)(yV|if?(lNmq5Th3 zj|>I&0O%VEN0{DEmk&3&D|@H7^Ot6rt@@b)hJJ;v-@?xFx`^Mn=jJC{ij>Ol#)`0P z;jB1Xp#UB4-(d?Vvr1hu##}2dDgst&lH-o`^QK%dv*uZ^J+bO7g^dD(j zNjV#enScGSfdMto{Y@C`WG$h&xc|Dec5`^2Sm!Gny|s9VzNPgdBPXy0ISah>kv?yK zVCdQ5q|N<#O{xDwz5hVV=5E+o;KwnO82kwT^;}!K{i9mRzooRG{>rs?Q8tncExP>obxR(NI9q<+e4fwu z7S-3Q%_7mN~Aj7)GZ#Q*DUAClyhzLRG! z9CBQn7W+I#lM3X?gu=yKncLnZklW{m*PjZNC30786cTrroCxKRy%A6Cb@1qt2N$ zIR4`FLG&{NmnZbO7JL%Um|q6Cm$@__RLd<2jLP@vQ&OcN==QZBrX^PY z16lZ;`TdB{wqgsHdiBDArA`+F(@7 zji2K1)%LSTna|TYKQmLInw&QC3N()7v|<1J={MK8twd6AuMOMjkel5GQ4@}wEjDb2 zj~_u`Ke}>9CPy*0=!8vtLP`C2*6BYtR)m1EX{cDe%|vObyYb`es%H1&Hc~S4CgLUo zyV5m5ooI7{Rp48sMC)BuFTCZQ_4mlKt9Da^8cmx@!p%_~{^7X(Uos=f5cbi~vQq2A zXZSAu7)5!=EzQaw9mfj?bTifojOo0~Vgmn&YMJNA|I)_ta0C9T>dxaSH4@dxe)Zs? z&E46d#gs@1d8Xm&FLKwkSPTm|(J=o_{lgcSU(E(}Cv$)I^61v1>tNpWPQKa;QGkT} z@|*bW_jDscF5k0{8tlsjEci7|1=L?_n#GPh4=<~r) zMJYeVNLOSw@8S|_sR`)E=-VcT*=l9=X_V3s-Q8* zW}tN$o*Rf&%%Sfn)040?X?**BAk@W>{$$-Yk**LcmSimLG7^7M?MkjDo%?`}#e5CI z#psJ_FnDpMX{H?FTnJ3f?U|eGUMA9TSU1!F#$-U;{9{S*M#}X5JLumvvo*aF3#{&F zXy99qImc2$>MWRE`%|OahzuVM{@sq6y~zsWp{qyRe&c=vV8yM`+Xl@7e|h0(+U}Z{3I@r@#E* zR$9p|MfVq!OZ0D9FN1BJUcW4yPy&a=eGy*CcMY1An}hfq))w#4kbu^e;`Bmv`4xjs zmc}zmNIqsB=XCXfftq#dNSA%Qh-HYJ=Z!uC)o$-&)YQ|3&Z;g+FcKPXs`WC8_pVYM=zJ{N2~1jF08Rox-xRB%i!n&C=7Td%e#BmD z{zc;8e-TR2NKbfweJtrm(v-VPEw8k;?;Tm;0J=->*N+6%i9%U-?08!)MFfT%3q)&t z9wW}F3mgRsmGTUd=N7g>X)lbQkE=H}1)1KF-fQnfpfyKEn8Mj^$_Eha+vw%L$4eHQ zb4ngU*9LTTdMX~K>{BJxRmuwoUsnvrAnX>IB;ot&*M+utBoZ>BSfSv|DZKO z29kZpsCCo6RHXY6YU%+uqKjEnXp0ml zAW;=@mi|UL#NuNmOMYm6;iptP9tK9tyolYShjAQO04PCcEe{Vees9_Hz~puCCX&bS zJ+`ZqeQDu52x0$>G>YN{nl9J-{D(Kvg3rc7;J&_J9YXh3&<=k+vaEaHC7Wa|z)ZM# zlnCkIz)XK^*vWu%|3FFKeOeVBL0b87K$puV{*uNT_V=kPRB{-ty-;b2948s_-Q(&M zxZ-IWnB}d?LOg5S8*^^yM=pS6w9vQJS_=)tgRZmG(6G|=)R}3b5GysWm{_iA1X)}o zrBu=9f|ZhNAMSAMyi3k@C2ujU{|mlS+jb}|nvBf1$a<7=e}*oG z8AaS?s@*~nL9#9lwI2dLJipCFdP8ua9~s1xg%!K1wau@_e8z%cjk_8`^}Qq3wMIJ2 z%2#H(XAw#U)ok_sb%VFMYz$>O2>u43j$zC1t0bOGY;Z_?l{Wau|I zn(&5v2wiR7>01@iV`Eyshyr~9$p*MWCX}dE6>*; zY8Lgxi}Kv-dqkiz$_wcC45at z))l?ch5)V{{*~Z);f9m78qu_n;i?qwgmNaLJm}$$LxB+J1YA5{N{lT_c>gd@R4$d3 z(LgKjMazByjBZ;Sa27wvAN#sC6a9Niqi^29$^S{xI9{W1*W9LctIp#VuHhEopep24SlfwVA=9|{UX{I! z&9U~!+ABgS!oO?N7NITga3Arj8ILoK%v$AjWBen|_c1!RDPKeG{K-G6Ny&5SbrB$H zxFR+bvkD>t$MDM8`M2`;5^Q{jUbm=N7nIP&ar{rbMDs96U*8P&$o`;J*<@hO5Cp-~ zX8hT5QPtSbni9EHOOL#|-#Il&FO!aac__SmvPL>)o(j`bVhDBf)o=2~_p_h#CNfpw zqGpxuR?JQ^nNZjf!h;e9mTeQ|>dhP|YQ{ybuRaS3`Bd(0ra4jx1pP-|HkSPddb))o7ljwe^SSpm zL&s&7g&GY#+&Oulnyj|L%a*(}b}=ZZpy^IqcK+Y&V|CB&kE-zPzROETy19OF!l{VT z;5C`I1+)UrmQ1)mRFv|)G;)&nQ`QA`#-y57=lJ>vZy^K4v>2N4XpwG0y^j|H4I!n1 z>?sI9oAn|rH`g7l`WsTRU*j{uQeUAUtARWAL#utL~z`^$dr$#Z4_JSZzFNQ=fvKt zKb=;piPbc-o9_B1##0{9PCG(6EmJvP27zMH(<~XWXF;;o-X=|0s2iRe)F)@ZrSGql z^AHyb-T6_fInaxg8zC$$(>H92|NTA;%X~~Wiq&xwzoRx-Beum$Q%?V^Gpkz_yhM9d zka223vVExx`dgdAZ_MF>`QFHbzeX6WqKW~gw+@{MB56&m_RBK>cL(3}wwuXE%~-o? zgbrH<>&?=dtU5$?`^~~-Sf!*}d*fr6x3zpuxmI)by0#Up?e(s>GuY~@V<|J0+MzUN z;3Dmv!zar(x8udC0>=8@)0WYvs(|;b!(CKlaZAzIj@6Ehgre)AUsxq;c-juG-Leqs z6<);E8z@r1RU|!kVcw{RBr)f;25j)HW|Oy@fK-!xzPZNj3{n1nKHHsgqx%RxKc)^3 zt-O=2p5@3q#8PaG(oZ34jyXp=Y>L!VP_6&qwsl8GwMgugZ~(~fU7Jnsf(A_yr~QwY zia*CoSzjF}zMuM;f7Jz>=r!%`G~d{bD;8cGmlnUV^hRppXFA{E>>b*eonB|3zYNgm zUTw3s^oVG{vy`3Tr)-nUq9MIZujenfy)mDOctKx3zwQYG`V1UwN{a8hrj!ZgO>eT% z@z}w(f`F?h?21LgACRY;V^*%rM^FD1nbipPFW#k@+t%NJ{QsA=8>P;TdvVo_9ca=( z`u*oyzG@{~B#P;XH74zS()W1;aGKEKF8ZjI*FRf;?U-ICKB`J7{5ys=ZT^=CJ*e+2 zfU<6nm{~XfCh@&wcb1rI$i_-}v$iDIKR+IO2K;o<&whix*Z7E)pq(A~&Dq#C)zg15 z?bcpKMX!C|Sj5nVS4LaBWEgQhG$6x;ABDJlIlq;4`AK`x$RpuDkcm23^zXR(TL=ZZ zNA$iVv(2IKgcp3oSuB6h;~U~K#owSaO5GB-WLtO6+=MSRw#kP6sfH639Qe7gB2nW2 zFF<4q=0XYk6kIN3wAdXB@{7(H#XbytV@>(dt&vdTG?)+H%PcBZ?OVtU|HR?z8mwMc zBQNbc!*BY1%u1d3?zckI7bsxrm%iV&82!}qjY`{F@82W=#~&CL5|gU=AZy}sE*xEV zSEP6!?pBQEWO}7)su255wy8Ik20SyW=y9y+A3y-Z(#tbz?(*WyPMlxPC%K6P7Z&Ap zvbXOS_?yj>Z79n|JYVqxoNiAlnn;88puWt|Ueu7;bb1_q%7WjOYZb~@(_w2F8DDGx z@gs2Jc+UbEs$W?p1l<$OH%=(=@FFn>XLuNXAs0heN))q3pvu{3SERSw{M zK<8!O)PF#@=^*|7dFAUQzrj>Y@1&Z-l+I&BKctkyo*7w92gA2Tz7f%fVQaH2Z2eo21?2T%q0!4w2QA6s4 zMe7TIYzENc=57;_U-d1vW>|R`RjrtI&1M3nyHf*_K6_YpkmHg&<6}-9K6-Q%1$1r% z@#gWR1yzmN`0*tm0AM;#t+yTP7UcLWYfR(5EXX%CL<;sxZ(ZiIXyluiNYV*eazUC} zwH4bZi*3uUnd;Z|zqh*#b4tH;E4FVpTqV_FUW#Lqsfqu*VVCiU&vQtZLe8Ar{kW5! zN_ZzxZL-t9tnbYQpPFX9!ODaWa})|L%4FIE|MRpD>X_{WP-T2Ce>2T%eGXe~u81fd zu!2~~Z>Ov?IKyS7BHKe`Jn3EWvD8xbTRI4`R7!20OmBsG1C?H3$xTUNJ1T5-8uHoN zG=z_r@4ceJVe3Jp&WZ6I_I`8^bulArY(a|khwE4e}1oS&8u@>egSqJNwXeJ>9pioxxC-83tq6;MLDC|Ke2rSURFzQ`z`>bj39V5O;H<1 zp9&Ugs=|bs8?-fkJVJ}@QF-ph6#7Y;}U#gKAr#yxS^+X-92^mm zm5~a`h>y*&BBPQKI&=`SXY_l2fB(RFoX7jz=Y8MzbzQILlPXTENX7J_+y(nB3Hz~y zWqKb{j%$2O`(8wGai@7MmxQoHDW0#dqdd?<-$TuSCT7(Q=MU{R2SYU&yK5{5ic95R zEs!P>Q{-UsBZDeG#>caJilN{th8*!Z&#DF$R-)J`XQP5F%7%|G7XcdYQX!M7MAvEu zICk=`bQD+q=6gRVd#-;4GAP#`3XTEPdNy+#m1dmT)K_Tv?#{uyU*nMWP$z}KJ>UST z(sYgEu4x54?ae)f-);2?5@!C&Ip^4Apa4X|)~FQjaJ}eCurk|3s918g(AY2kFpK&n znJF%)>i^@Rys-G~>KETakNr0qnCL3>XNbojmOm3)6mpu?UM5waZe(nj^kaPZ=Af^b znfrIpq@w7>?VI0OmsKWhjDHJz2rU~^J7#q)F<}v*-5Y$M3K++zWuu378I$RN?D>vD zd$c$C;fCCZRo$e9xTg~U!9ZOTdH*#1GEwiGh3X$D^q&1@`Fvru7b7fR?z>Cc*pHvB zBVzjM0oxa68C&IF*~=ponPi4GXf4}whlZ}l1HWZ_1FFJUMRxMaISCF8Mma^6bO63?G54se4r2d2|E=O71z)d*Xs#!e9^{_)Rr3>ji7EX<-q{f%d z#c_qO_^XT^F4dn1os3)Ht_i$L*PN%8twFn8=@!qG={&nQ^P>LiDNh($*XUyW;O3P$G0>gIWaTv`FdzD4m*wbnlTP)pE=0W&5;DSKjhawoLqMN zCcWa*l$MIPITwp{1(+w3eG#XRdF8liv23jBzlcM2F)VfHuoXjcc(n`USoVWL*X9yu|<=+1p+j6 z<-4snX|pnuid4-df^V*xl*8yUxdztL5DW!Z>7oEV^keg)YBpva1GnrTclQz62ZTEy z{c|Ya2I?u0VZ8t^a9nLz@e$&-U*M~2gFM|8TG=O;8wHH(nsk-oV_OF4wSLOKsN&cL z?S-StwRfx2$|zT;+9<}jwR?q{hd`dtPE!U-I>@V^4P`Z)vzxW1U+I2{$no*+l4F1X zO9|MQ)jqDKBA;hgvFg4xW$;cEIb*RI&B`entmZPzC8I6t|6M2JH^6k4KQ!ejq-Vmu zeGlp{TllYBPxA|Z2XYIWC$=5WI_jFs$ceR3h`X(obv}1YD!0I<>dKxoWZ{$X>C#(v zq8epTzm9OjV7;8X7+3aZ&YfQl<>M-u8nO$?Bmw1HJ-ZaX3|0D1A{*r4$`BeVQ1vHS0ycBngGE=`XyQSgm$G&Y^jVEMB2B;D$<;&tY=%w3*!TEn@s9puxAZf z3U=AM1SE~#uzCfg(K|}{=t_LYGikZbT3}_Y1D|3c!ZnY&l6P?f{HOTO{%1cLQ<3E>)z4Xh zkcv==^l6+$A?*p(;OYLBEK8}21R_<*4in09esNMS%3A8_+X(so;A%1Ng+oGJv8r6x-QHeX=c(!6 zpiByow>etbqOS{T2I_V6y3{CERFiQ^m6 zmUg#gfb=rPw+c3(5>bEtw~*>Hccz|D*r73X3{wdnNOe~1DoU-F z@7@-%i|`6#!DBecR9PLG(bJN=|Dy)aYrBlOyQC?4yF)8yqb1`qkJ%<<3eR5L@4Rp_0N=;q|c2h=TksI<5jb z@P<414=H;JESRRPg7@zTdyagB~`x(04lk&>zW0JQ0i^|aDPQ&Db*v5;q z{IZ6($AQmhn{Lpu&%kqa%@toq<`p*=RX(C$)xAeiJ|?}2EqlgJ>)Z$ptoK#cIt!XE zpz$x;Hwg5lb#X;f{l_wgbvccmPm6!mJT4!ZM+ae#j(YLJ z8o~a2rAl5%+>78r^~h6Vo+raBbL$`Iy%VDpV#A=UuuROvLr$Iw6jHsAbFGc<+Bi`_ zAfU%-k0G?;jXpaSB3}I9wX3t==TYT_Vz9UX`WKg)TjN{8zB%3Z4YjzwrZ4&#^{uHS zB;fps?Oip!LU5hSlb|S_gO!2Ny*%lMz62tF$KqUVweQyioBP1iFHNgIA*l`^m(N9op+@t3L~w!7(lM) zZH$i_vxzo}-wUUdPH@fnS&KgUVfCo?X|s=LKp_*8>q{vV0oD@K3b|29$vZaSq~Z}k zqJCOG?JoV6y=6mNx5Cl5HUBwE@ei48fH)9Df*jB^Sx{=<=WG(@A;y{ z48SP_GklP~|Iox6lw%MK@}Izl?Fi)TUbc{`1`p8eFY=xUo($cpS6q(a??pr{cK!ni zu~CyawePmYP&xVZ&gI;X1+YH=Yl7kljPmRq_j5fqshR}M5*Ip8>QjI45CCXQ58WF#?bH*BA#kCj4XzwlsWD|iBSU11ElraPMgFS}$4+d8<`a5;v3aNH8k2mUJ zgomZsF_yebIFwX1uZ(plQy(z8c5#+cMjv?-b-k`3_p(-2i}45!WGaeEgPvA)Se2V3 z$U+}1ZfY)Zk`g0;b8uD00eZUgTd&V71jLM>Z~=p{aXAHXk`>BMre6nii_2Y?Tq`NA zlq1ZNsDp6UWEJ(m5NI>7b_Q`uiEK~AHq!d+2c5Lz@v()VC^P)-{&cN#oA$i|!E#?Q zWbh^vE5p{_sNs3$;f7C@akAT6J{Ynh@9&bE4>8mKAE<7PPNEk6#Y&wiu*EUPK&YV- zFGAjo$SgiD;DxZZPG{fr2nmm^KMOezVar^*AD{WZ$J^)Gfa(0gAoZdJF3G?OZDI0< zxUNtX>6@%=ia(m_dULmbWGx17xm$&6qm0FlrH2GxjL1 zfex0iE}%^uK+Q03wZeGGMK7;4I>k<0Pb*=pcEzkz3r5YXF&YVJ-zm(5#V{*u53S&f zVgOQtivUfqKWNc6i<73sE4P(L&(ZPAr8t~u}WXJ$rLA^|6HN-4W&+!AZ?D8HMs z%>ap*G`L?BqiX>Sjp&)*p^np`deI5Sw=^G-ORk{>9$II|@`9TFFvzcvq=*-1tUoM@ zDD|$PD4Of6db05(zpnj>O${8+tF-(H|IuOM_gtZs*OvrI66VPbr<(0-KRveE*Vd7k zO@0D@n2=ylW|KVjt$e~Bmjl#GK;xloKZLEdCw|}y7~aaeR7~}TR*xuEP^e`x<#^SO z^6ubpKT-TjBZ(S|tRq(!@cQZTMZR+IN?S?Q`q7^jKWL^*>^>pdQqdfkYYb5nu-$dW zP>V>>qZiegSN6O2rwb(Y+6kLCwIb1h!^UUs0gX2joOp>q@pE0JdiId?#hb=zALP86 zLQi}#UyRfcnlor?FuZ1v`Yp^=!jjBXVXd?-db&`gim&~^7bsynT=QDkL?K}P)z3TI zb754Z%u7RWo*uuOy$K{Pi|gX;$xr&c25Y&%>n{4;WYGRU&`WOEqs_{+M`_^?C24^1 z#X#C_wq4c}^5E&|1`paMR-E4L3ERlFjQLo;Ogwc9GGFl97;^pm3ExBd_7N#PJu8J| z`|oiLiSqsi(p!%BmDs^9!SL5Gn(ub7$PX&|_K8L+Gi#N+Xcg_b5VYMv;gS=HTxD$L zcIRAdc*r{0yo{knH&o2-v05xm==faq45zQ;bFa?m*gx_^8&cuEHFk@c@%R;{eWI0* z`7><#%x{hE_}6`g83~CdUUUDA+6P?5JnkS19-c$c%reKrcEw&0E+X8Y!>xb57(s+{tmDK?#>3Sf+rQdeCRK?-~gb z%`wU{S1r3^j^)70f%@xEzaqS8#{vwIdq2qFE(z=wAO&>>INz&v;Vy-oZ`@qAZF-vK z%Q1*MFlcUqzh>X*nuU;JB%&-}mW$EH`XTRS$vG%sWuH`@&n}1zsbb{>K@=GkSd<~q z7)_%30ZMR)!(jL!={Uh}XZQ~V?-I0W({si3;-lwHvDT|@KbZT8HMN^Ndjsed?|}%m zcszOQ^VZAaK#IVgo3{oXV!g8DQiUP8vjOpgyHk%><<%|EMN?g~4ceTkkGVyvX?F__uhM_fHk9fW2eM7+n3lUnS8x#NHW0}nSWLeG8>%Y-{%LSSHYgjLSaA3L!s2n z`Kq@uZG1+4wwY72!}NFO-5^0zA-c1ASw%VC+J9nd9o=I=TTUZ;^6^A$@fu+#BO|gT zp@R1#5q70S0BvAN2XxxQIld_Cq^9Uo3F{`^M4><10N%hOk76pGd{1L|urMq9 z9}mICZXQe%-8mNCTQu_NT8f06WMWf;y{Q8m!Qk(wF4p8ME--WvtYJZjNwb}KL{KlQ zJ^Xp-#ITO5^bz_6S@$%j9^#pPtNBEABuQeKJ$=8YGu0?G_I9AT=Q(%V@EH0bDK zqM+7V?WFXL^oXh>pvu&&JF8)Z4by{hbW=li)Je#>f1uO}97kC|*B)wjDNy~fz~o!= zyOABVW?(4nm}tr(NuBtaIbd99w~KGX$+Dc&G7JoHRVHW7Rf^se#SwFQJu?r0J=XMz zAjblA0JZ1&?m)oBM@AZ11}Zl|QFt+~D+#}Hj=F|rR)$^x?%Mz_I-E>=8ibJR% zd4U+kIcsKulEF$IBp!?W2KoC~lrV9<=9YRdzPRNS$m&<~PWQcf74hCF7qoN&0g{bN zaGY6|AsC$1Sq}q>W8pZl`@(*ca_BE7V+KI(KVz64>WI{~mTw)tVgMWQ_p*qe_|B6r${{YuyUbo+|zD~^?!Zt~tYM4KwCFwvHridHnPOf|*u(`~G54w#99P2gl7C(4<3g)t3UZ~c0=!1zB`!qoK`NadJD;&nVA|x1ZYsfz4m4b?h|3~sL_)uX7?=!*umFXB~E&`L|m9j z1M|uHV*xQp!xPPLJys*vpNg_2fYt5}Rr8e1>JR`;Mu+n}6`{8rXb`C3^#vsX0#&DY zp(d4~6C#ml!C}xQI#KRxO)w99c^*c6YVAi&5)9{;B-*UqA9b#ir_K!U)aP%2KL)hQ zZoog|Jv(kAM{%Jf8^k`b#rERu%NT3v z7MOAS8t1t5M@?cg9$5NwKF zS83gp{icd}|L0!0%Rea^5pwhU?h+TO`M1EfG zJdepeFmmZ+d`@M}Py_Fu3NNqKa&(PD_ZIH(LxT3g);=b@D`NX(!FJ)7x#nN~5lI{u z$~;$DaK83*R< zKg8PfoJRIb5K6>KFZDtC}hbc$C)A*tF}~7!9P?``2&oem@x69i;n?4Zunl7EG{dNGl(h&L?TomD1*(ljjk(cCno!Xn%iIsc^`3JHCxCgseD$pxL zJ6Md?*yk?DTQF8ja4eHOzR%)aqIsu%|!pQx#8B9*E^Dak^{vN{65Va>J>U`PPUZ z^@N`VJ~N-#!pXc|^n29gbsLugXPqNr1iaN*`jr#b26*L{2G^v%(*favpoHB!tDL<7~$07rKQ1UbLtPh=kUq z+!iSn$`jlfjjXV7fU46HV>6qJQaEJ=Q?7BQuj6V#PH779V){&)^gzN}w6|2Cqv}_w z%x1wCH|D(A7PKYe#~+}zrPV%pT}D)Hs@2IN%b;sc#^K7g_;CGB&>*ZtR+l%oHlnF} z+ffwR0t!2hTjWIsD*OWl!zDpxZ0J=g&!=T)ZvM5uGx`g!pHYS<_8Uz{T`G;7_R9Fv z&&6o;n`cr9PW=P*uSplNEz;k}%A2@9MK@eFPv#dG`>6x%#6W_uDa?bAP=nj$aI25B z55_mLAGo=TyDBbXAV8{>b~ZDTnqEwMc<4osJg(9!i$9cCQ*-6-!ICArA1*s9F+U|@ zUphAu+kg#}KNl>gpinQpVt`KF#nA<4|2^e5U7H)aAeuEdfK^18dmQU$U#jCt5N>2S z)zSV0NIH=t)$seXgG6{A|IqTWz}%PQ^>LMxwHVYDYTCyrTdk|xCcc>FxDaagzvME? ziQ8fh)`iYfvom=AE;Q1@Lz8ZIA|@dxuZ;_3zh!5e2}9)lO`4w`($-UjOJyyK+@E9xnl!SNH$qT z@9y>-T%uC6L8Aryr!celeG=~ZR_LCjo)qT*ZuPqchA(o>=n}tMtg`-^Af)b}e&|3N zQCv9D{3{IFfp-nC{>8G)RW#my94Hs9!}MD{%xuJgjp{nQwla%9tCEk3TvDU=V0Rri z$}HCviyNzr(yrV62kKe5IP?Ag17OMBih9}{gdyt_m--kbZkgmfg5^hF2M3cO8%(TP+e-Y4Ulda#&p529M(dwsiJkg+lVI=IQ#;qILg|6!$E@tU$S{ zUcz}DEVelQ^B2+SS*wj|J4}*$zV4&>1^O5+j6E7JlZsaa@{vU*DW5+Md%A;C20+(kV<`sJ4I#kyWeJdR&RGt@;F1iq9_)Hz>AkG~>RPk>>FN4zKybTRqDl=9RpUj=QDzjfF78jNK zFQeJR;9WgNTkq$jas+GSG$%XMi&ak6pW}6_kF(r{PW6t#L$f-bmz};ZSiVF`Cwd-g z$k6oU`uRsZ6(RwKLeh77lP~O21Lb0WuVe|^x@W|WfLP|1;)14Q0!xFcg~M{1VEH)` zvltBw59HPI4omlj`JxTqlLOt_$(KRv@iA!~uN?eCJ$p`&&J$a7Aws$0lvJ{j+K7!d z-s0(A<^So;&xEq5n%w=&xy@e&+A}4(C~F8Q8?yfv+myO|Aoz}P+eKf+hNz)zD3!|i zRJ+=oBiNLobrnBWHK`uTz8HF24TT{<;8GMRkM~2e#`>(uH zKP45FKZFrDW0Wm3zD|~v8?!m%Wr}K=7DiR(+L^H7^&Fq}stpAmo4}-a7_(G@pNxr~ zvm@>1G{c)p4OVUO-l%$VGg=w; zZ>k#P%_|IwmwyWyj?*I2(^o9U)g^qF-M=aecOPSXy%ZxqPW|}lx-F=*Mu?yz_APz3 zEzoY4A-29=F>HvxK%6*k_>Lj6(#tPgdvcj{_id@I1h0WZ1Ulvv3GpP0SL+tuPWO{Y ztzu+P1PPD89c*n9Lh-}w@(nX8%Ee}46+>D;Hu)+iu}E+ z=0+_RtU@{Akr+>KGpNY)YIjkODq!$k%K{R}PJhi! z4AJoZEx)TkKb5;f)MAT(fv8W3oGL#3A;HF29X~jHm&a*noUtwfx>$;6Zty_qTZcAt z9{dcQpxqhEf=1*WHN!Cb#fvWyA^NMq`fvU#w{xly`7!k0Gs+tlajan~0Ap!~eJ_>n zS+j`9$Z#KDq@=&8+sPd33DsD*-%a_Liuya$PV`3qqve;%Sjv!RfA5$fqe>qarJ;3i z7utTK_n3p0^YNw{4D_B6pdn*XnhW4O)aq?-r7v8fWuS(w$hEfQQqBQ|IN-GHp$wGj zj7J+WAfbOCSpsRyT0{DmcA%21I>1%dhp8W&ALYmOx&u-hoBSsg+ms(3e$si4vmS4V2ckIn`*a&_K+IKrbQhX$6)u8c!M&w)Elu<>BY z1dmvLMX03*{|lQet*fQ)z;L4(#zK;~fbz(bb7AG>-kk5(((H2xPh9NZ)l+HiZ-eT0 z0``#2mdz4^mM4!1TbQ?}6q5>kIgL(68JMNm?qes{t?4)?^E?LLGW+fj!RJ*Wd36h7 zeM_~z>Jp^#`wznmBX3HMrq^p&#t@ZcH26%v#4}zvURm@$Yc_AKe(mdwwYDTH(%8P z4}6ZeyiggG?BIG4r~fz4px^yqDEQDd4P|Jn4olTn)4G7WMJ?!hD&qPZx!!Ymi&t*B zFtrskoi4Q0cQGLA*V`wJgfom30?Js_N8wnfwvce+#J^h01yck3nvBuk-ta=bSJ7*F z<)!fxxk4gLEzv`oB>bw@N&rzkXuAJvnY^7FxD-(>QY>R=sQ3?*^rx5|=E@AF&iwN^ zIi_HQ`mz31TRkQ&1$Hc0rY00pEF5Ku&{P%pnlSK?RdTcpROq&=PC>y4+5mE33MZKXDc=x&ij zo8gZy2>gb-tww@TU~77zy${bnTc6FLMdJf?HKvsH0*W8pH$z0{_?&E%H?)P=1WMG3 z+mv8$Py`OO<|!517)WO+cR>I}1bu*db)OR~ny~{pZqPz}W#FZVsn!&lH&ZJhpYJf30*_ z9-lOHP67&S-hpM39rhKX&CWJ?zWyQM1uYDtWuWTIEIJ_gTq;o&Uq9~(CwprC%C%Ex zNZOARo^_v7Z6J>grg%zHE9t=k(vVyTsMV95MD1DLvP-_^K^DMb_&B1Ul{lKlsz zUoKf#t%nBo%|uGx`?^p=RIa5zYc)KcXr;&+KSn*N^_w7NI?tXJQ{9RmoQta-;vIzj znJ!@E33{MAKnfrD*R}gZ<^@%a&c7 z{`q5PT}vJ5TOBlb2VJlF(TVe&Xv@MA@v}@z3dbtP^yPGEZY@)4uMp?_Jogp&DS803 z{yD3IA3u^K{(!<2G6)ciigMNcnZf6eMX!_$^mFT`xwr*Jnpw#&8yts6yM$36OsBA8 zv1Xy^d{|bLw!e8SZsl+0Vo_d#PY4i>AEM!F63*)}U0Xo?11WW{I_hpeVm(6wl4D%q{K#U;5)Q zAE`mqq@~ptps?kixR#NvcBE8JpQ9!r%kTRMo7^S7HQ*mGt!F@ahh6>}DQbcl>g6^_ z3UCRf-l11NByy@f#LnW=bChyjs z*7(Nx0ql*q78@vEM4UnAH7)sp;L%YrfEr5?N=`KWI+Q|YLI~a>&Nf6QZ-Py&Drsot z-coDkrF$h_Fqj?qEaA+C);JE0A0DenZT`vVoxbwkm5Lx0B~Jn>3%fMK=!&^4F++G* zo*P)JTe}yle~=AC{xBZB>UrY0ZbtwWxh{e9D~i?FeX#2E((U~p^*Vmq=yK&#(#qrP z+oI%IIDZpU%}}#Ug&PbP-H9y(5ngIBDhni} zp8$e2Jv_-ATQ)f~V=rfi6Y3QqtLbm6`lsYPuPHzCTfZ?P<0JyZtuaEW)Uim{=?p&! z;|xo`T$j2AxO=L^WK3JD=3Sm8!KiSJrZU5o8pAu@$6F@H*)+%>@I#p7f6< z^qzflJ#ji!xNx_6H5Fds8EeqQX93Rp+qy>9gM$Y4v+A%-c7*;sJ-WZdwa1Ww%)fiqI-r`}fUtUE6OeMlJzi&vKW(+x8CuZDvdiUfhV0b+ zYH$A0Xj$=6O|&V8m$|#p`AD9^{U2zfy|{i{*TD$km(zXM-X=B7E#q%}%B7W%1xnBCs^O^L=l9K^eY(O(zl6YX?C9&AjxZkPVhepFQ;rJo(M?>c{ZgQGD_0g=Yt$c#A6^^;} zDa*Q0A4Xa_*iX`J!Z)`Zvk z(ymkUS4C|GT&RXFhBR)oP1c@Ln7o$33=i}39op)vdC~s*CGl+t?gjv~D=6a<)CjA0 zx~1x*2?!sQLi?zSjbJ`iz{Sv7kEwqJcQv6nsMW9cHP03CkFN0O++CV;_Nb@@(<@Sb zD^>lvz9;YSBDZJN5gZxfMBVG)ZC7D-o&?%*MT#-VH{QYkztNxtAWI6d5dUnuTV=V~}GjSi_JC-U{#r3`3Gp`034Q2>uuPcLDx29WWbA zx;^_T%%*%Wo-#PE54x@Yu_I!gZFnSb*Sl%jNzJha|XeetdTd*~0opN=wy!=qIxF7|vKYxFOV)PEob<8XX`Y}e7>rTy$_crXLXPzxyPatMyTt6=$W zeI;{`U@)3k9^tyMO&xJ@CYEsY^wlXmR}TBj%tLDqFSu?MsJ=lr76Cn2zsM5h9OZa$ zjF%C<6U?|}%hbkI-yFmO+(yH-8QANuHCSf`4bI)Ob5BLxhqzu_0$#?ib5fUSu9_Hf zYbzdtgYx<4$P1S?g4PEqje`el4ctDhd=3oUc1)ei4aB9m(6Q)F?Ud_oc0b+%cc_kR z{Z`tAOVMm!WF65^V^a94R^4eBy}jw50P-X5Ya~rT3bWqZYDAKqJ04)NpxE$(?ZNLS z5H~a!bGr88rnrxtWWg=S!)U`<%>_!mA@wb4---HwjD%NzygOI*=ElK;z*bUk#~@<& z@9Tx;SUkI@>p=bcEzsUbca)~t+&is@_LaDN)8PL1%9s}uQTawHV+Vd03ezvEaM*k1 zn~R5y?nj;xvMeh2%b0J;r%Lv|?rlS` z4O1zo1>{YiQv1tKAGb&ZZ!ML2LH*jFqHJutkMvuUn={pSFTbzHXzyhkTW_tm1YB*u zC6&b*-4hi9 zpJ!D`C$?4}Eio3;Wce$jlTDO=sL#<#k!Nq$R2ts(;y%xASLE0|d|_YvS@EaMck^7~ z`psOe;X38Pu8l?vg@fB%TK?R22BR=O?bTO{^$u-1`PT43xOqAAfG?$M6PzhYH-OFj_}6R^0Zaqa~|LyJ$O@YM6xb z0_FZaI$_yccS-|CcxNlCX5Snej zoLLuJh_vvLDK*GNFxDaZSf4_pnII8P&9HGa2<4dKd4af*@gLOdBiXyYld(6HsCppz>OGH>!oC+?(@jVJ^L0L#y^D0tS>E z6Jea`SpxarTzO~j2X0f**^xZw03{0K6%7N&#-&?^hzO;B{EKQuoXGAea=}V6;GGuv{g*7e)2?lU@@edEMAqalk*?Pe>Zj7&agZotqoyL z0cUw9z5rWOoMD;&R<+(oJ#iPcE1%EezfxDpL{yti%I`#lzY*69l(IabY|zEa`8qUn z4Y2O6L_9G$Ts7LzH#mp+yllk~*b04pI==c7yZH8}VoHOW(k=Ku^}X2G&=}^1>$FI{ z!`&f6)eob%K{8T->g`pHehPxtwF7zx8b_&)O&>j=q(Mi1%`8E)P?_fTkWy|nf1$6O z($(KTB@lUXdDaWChh;h#X>(?i z^2Uu-^dGB+)Vrdx6F7@HyTd@Venuzk^$e-rW|f31lOOyNg(DMtg5dQK)NWF5xWCA#WeoWc~t ztqER#o`+Tm62s8FnQHBl?;ebR;N%CPRDS?TD7<|0jo8;K-O9puJR31_EdWkl!$29;E|k(s7YCCUxz(MJ z{I|BlU(;|M&W6{%r@hZ4Ja8A)?Yshs0NRe~{uoBdem0c1RUN)Tp#2&6pc&{!mNk^m zN(ytfrQg8c2<7`b{uEIxmTA$bP-u&wB3)tCqhn{7fV+}xGOk0IN0TN zgtdnnU(74dK}IzZ>W2=!1fTLr0i)*15$B1P#Jp6G?y)a^g+Xzu!H3!_Gop9jDy$7G zJGP8awhWR6ox6Bf4#l7FJa$(gFd@46gF2Q>YQ`#>sLAm}!Ke$BRaOaM>_uXnRLPSp z2j)+i+qXvkf%3vm1(Z$c=%{OTcY-}7Ab;+5?G2Oh=Oh7E6SB{(ebcdSUEg5#6FeUK zO+CtUK%J?ORDG56=`nS#QL(Ar6So5k#CXPTDsLiN1k0b;3EHZ8OTJZehz}j|wt~dn z67=1G)mU-ByMm*kzwsPiu$qQhjg(=^+ufRn78Ylz$^i@TGz&;1#p zb>-;%P+Hq1U+V6+DALtI#v6Iwa+dP^^@3(|&}LhEu8^$fv-d5n&CLCfd0q^s2j60r zqDsRAZaGRA8a_9nhyF#C>kA)@byZ@rk6}2ZFOJSgPlC0yMs7Yfj~iJ0b4fE=C(Zz_ zpq$&e|oqT_2!Sd;*9>g6Vtwd$unv7=XWx*2TwPY zXk;uMR*lxB9Y)!!Gq`xBaPmw=Ij>_9I$@e1!RTglm9*cE4B-{eX);{&ZO|TgLZG&g zx*j6FZ8oYe;ETgmKZ5gHs*eFTyAVF1MlFN<&)p8}k_ox;J>=DPAk>03Lf>1y_Npe$ z{FnA>1A{Y~PZN?oFo{4T=U&NN(}p)5-m);~vj4=7SaoqS_A{i1%PS9A?2?EU+>J$P z9{&xVY`~@1o}>CacxD;iD}+gPP>k`Dv8pazsxTHw`)b?a75ZklB@p{TYc&a-2cpIh z5r=%v3{D3taxQ2?SYUy5i=%$mOsFPuaWg#mqcmFITI4YMq0AiTi@Binjx~qm@j^;u z#6f><#yeA-4T0TQ*rhURt2a=$Z~KX@U_cLf3!9xsnWLGtY;K(3z~J-}^=4}hQ=_!4 z0@k2`u{1V;4@OkC1wZR>LQ|+!Ui|Q56T}7^T@UY6JFi-XVd&LuLX2>0NouN z&OuOLDK`muEhUe`#J3m9YVDZ~oj+mYeD$bWrC$VWt>BF9Z3RqOyXTY<*b;w<-nd|+ zM70ou;T0U^c`E$;&e8bdOS?qV{{QI~0Xi1ZO7rDpPz(LQ1EmA)ZGXMl*j1jOC?ehc=0wGThE0 zDGPWTf(_4KXA)!E3VBntWk4wC*#Eg`mDN@H`xJboA~$FtG#~_9(n66&tiL61)?LzhHrGPnJl^up)YOAU4ig zDwcigmZMjj?s*`cdxD=g3nK)h&qs_i*g(rIN+}t6#bIo1Mx@Uwy?M1h-o#(rI005g zOBS;sQT%o70}890;=a5ZsYPE4i?lkLLiQMF%p&z)5)qJXmt|C4pab9;j6xpL!!68{ z>{PF|4WYgjK6j=1;6+K_DA*F5dvFw^S*~aAFHgj=mGf$^Y7F78A_x*2=NGL%(SD5; z(Un_7T?l8CgO+Y;9(}y8tSt)El{xTPzZ;NGg_LSN>o#&OP2|>U_rnjPnN?DXCj|e1 zNg5P5g0u?-zi6ZCmR^b)ZOW2UA6PUnR6|%8h!9?8h53|!*AOW;Dqs`6))(fP1B!@? z;;-i2wnivmIn;BQ?%aHoq~Ie{89WFYmb_mlUcC64;xet(dAt32#y^k|kyU&9uK9Lk zO&g3c6SyIWb$+49fE{Q{4OGLR?o*_x<%&LnM-lR23p# zvC;p23ajVgZpTo&G0Jncg0FAHpF2Hn7N@u(X)QbHP6hUooVSR!Yn>ZJLIS3Ib+6_S zDbf9Pd}&pJMMkt^t|*pgr(@wR)}Oo{S7P<%?;1YjqjE}FFlGu*js`=yo)jnsMOb+I5wVtbtaKM=I? z`ogeK_ZLZQexKK9$%wpm*OvL4ZBM{#43iK$5WjqsRxjmD8>yAOn%EwAFTQF9^d%DiLOtjDUNOS4FyyCiuDwLF3AuiWkSti>k6dJd5yR zP4w^{;Mgk&y)d$Ak0lpxO`0+U9MVxLh;Y+5+|6*6Y3|x(f}`g;gDBTdS2#wn*aTSzpFV~e#c<#?siI`1<^}cPw32D zM}CAb-?G?7Qt1L?V|jE-#r(_>btnr;0xB{s_~)&EAYLH-E+B9DK?9^WXbuTR_-Qa>B6Z=(~O-#tQyD!-aWHIpaxpN?~%h2Ai!y~?4aHS-RX0Czue-y zs-&(S44R{`4 zG8ZMjF>wqRG3ru+5pr#12Wv=Bqa-FS(33(R!YpQ0J7#nAF80Xxd8={5krMUWE=JO{ox@d~79|nwMex=Xz6VuJ zt@Zs`c;0uy%yyC&<{%?WjSU-fz4aV7>MR5rq`btgDloJjo|tGd)NTLM za0WN78wRv$?o^ zJZ7wlSy4eqY;BE}Ahr@}*KD=5M~_Xd+N)@cAWCcR)j_pp?IzZtMq31>;RMIt`@GNZ zdaui0@duZY=f3an_!vyu{m@VBtz&P=Y@P0K3X1Z{n)=(rv?IFglO_McqHl^;X~V_H z4pedMJm3f6QyQ0|#}|VdE_)VUIRH_k&pU0seN|upWuji!x%r}u$R^a$Sb1dL5z@O8 zkj|^hgLj+^eOY?&tByzH_bn3JrzjhNr7aZA(ORhGcjVJ`+@LQ@rcRaLaz^}?l^D%m z&0>OTV3U=%pZSVBV3zy+6AFtn=^jb>vVr?jPTK^KnsNpK!X!fu7pwNsN4hYx^|||a z@DZ^DFm^w!4$2@o?9!mmvyYld8Xkn&a|gt}FJu%O4HtMdC@Ht^5q`IRR3DpYxzY)x zbPKi+)%g{3sAc}-FSZSGY&cfOYQ%6Aj8G1E8F$nu)dg&#Q>9uc#-qYNquj&%Llr4G z!)Fd(n$sZYv|2UgMG2A^<9gv&UnaJ`AbJdoy1(*=mBMwa4zA@}IEuH1!^R2e+@(!W zWJnXv2>SuByWg_<>(R=RV~)hiJPmj{Q+#q-qJeW-xm!@EJ!_<2{&OkY)wsVqYu;_M z*EWdlvohhe1_r{@1&`NVyY(rhJQz;9*BUm?`k%knG6iJqF{}^7)3Ilbi``X{w#zZ} zrqv%X4_f*8H};sJUY2Xy2ejG#&v6B&HGeR&*(%Lv8&UU{AnH+D8zIux<)f+a!juf}CvTFe zRWfLr^B9rbI~ott57s;x`%-VKLvxuC9RZ8Fj7FsI*w|$j*yUM70a2&tss_1tzoM*uvi1Mg2ZO6le` z4b*e%+x?1+_GELAx-SDzE`-0k)Fb1Du9@E@UJl&0BHW{U*Y0g67y%kB^q+kOz zi)kOF>-<7?<;;ZYJevQ-qz!jH)_9MGT?mA#8h|Ci9PIb4`D72K!^B%M#A)?zA71N1 zsrdrs`C}G*nQtB@>5!72TM6Zs9N$9chr){vR|QC1S$0(BNwrSyWZdjs4q1X6QZtRw zXYRRSQ(SM`1jFY;OX;Vvhg=}LSgbyhaDz)u zYmjNS0drhuwm0{)@>GeuU=^PzOk<`_0sxOdbK(ek#0T6A$9lOdBo2FVhxKKLKaz9T zQNTry*?omam9yy%ws4NWMmV~d^F|#@Q+b-w$(ZHbl|?(#-7-ff#|;{JR#t1~GhVVF zV3>x-A9PHQEG+;2%v{RTvlQ*(({j37h(n8Mlk#NVwJ7)}sSdpL*Xk;QRmM4B?gMUOa-eG2=4A>+ z9ko0D1Axcyq*&_m&1Z^WB@PwUB8W6Og5EfRhiAW=S8^8A?Ht1V}jcFCxLIM%cqfe5%=F_S(5DqU!)WD zJRv5%kb^brz+=qBVgjCXmX%rJ68>I^bk-QUR@W#6E@Wg+sW(|=US>j}EL+p83qK#kZcL|p>}R5ofgEqv zfV$!hzgOt0-0Jz-;o34<--()0nX=g`tTUvr;Po; ztE;HB$tsQK$dFUw?>LGoCx#AHcaM-@<0iIwMAZ4iU@{|4lNPmhHLn+$Vq*XiF*+%-n|&}ABea=G4J8c@B<1I<0EG|yh8dz5Mt<% zHL7{IO8JD_md5`~1gLeZQln2Q{`A%$nNwBc@0=W_>`6+b4Ee0fE7_f>F5?Hc%X4Fn z%=RcWhCxV<1)yCLowp?gcr!h zRRLtHvPns%G)34Yi2y!cy){vOCu!s4iil3nnz*H}IHf1L9~%kv+C7hr+MY@k&d4x> zFt;r=GE1NVy#PxYGijk!@sc0ZEnfbhBHKP{3Ru~n+haWRR^kUA-Orh0oas4Q+}#D{ zqs_~<2EHldv=q&?+LGf~<4}8TPBQee^YZ>PISEAVbT^)`@&quOI?esI56e`c)7eT< zm)zh*Eof6?=BlmpGtkSSlsb4dgW+dhhBe{NiG@Gv`wBKCFfzGj*21mSvuMNgT7{uQ z3lacP>PP|n6#SU%)&~m@4lXcD2gpj{;9yj1EpN5Vyu%h6Q=21vt z(RzW1^J`iDb(;L^V4?0E$ZvJj>1qs<9EaaJ&r>rl>VA2d?%prdF*{&fVNv`YFA+RK z*Yk^wN>}UaP(vq3(Y_$f=2U7^664on2kiu1OY;gwq>4Z&8h5-qRW_rwjL&rOuU+z| z8QSB%HyouMv8S|JZ%)fS+a8_1p-|2{`)*L=Q6`}H8pj_R#>Nkr)(8o?(ap-V`$rji z?4JjEnD5TZj3C96?(6Oe9o2!5UU5b0t!vEsA_bOOF~S24u)(pF&ZP~)2u+d5OY^(B zi*Ic`MuxE0Wh`(vuw18pu(AwwPv^_CjK|`sL7F(k@wsipQqV^s4YSOii#-&jXnUO5 zNRvZr_p8FrSToMNG!_;~Wrg{wTJ}?ehA@I*OZ1pSgumKI5DKBKs z019amscht zK%x3-g;$jbZ7pr!!sd;a@M1gv8IzbJz(N;a^TIcs_b@_qSYOD|0wyk?6|;XX5S@0D z?cjdtAxy@bnUGS=Rn3x`rj<{D(cmuIur<`y0vx*1`tJUkmNP9*_}h#7G3jRqbWn+K z%w}xKS4(8)?<>EvH$cRdlduqmtpRl=>mMzi^k?2~)i9OK>EBA;C#rNHQo7Etg@AZiokYN zHdcgMTNRpjm(~BGW%yQ~Z$QKN(ehc5r*G&QTL!wU%+;2rDTMW$1=|`#>*jtd0LWn+ z{P-V5Z`BD15MH1VY&L|FGDn$4g`=@kk{V<~nVKs*Rd2pU90B6YFN7}R!BC=+{&_Jb zfh9FxUe4RzHwGHe4qWbETZqM*>8LQe_G=it404Ru zjI>K#wrc28K>!rPU}6CpDx9#zypDwO%p=mDo$Gaz)%leSlZBd#na_gd-y58d8f*do zIZCT9?@Ne`D>lz5a3j2b4E)}2eF>EAy+jK$s_N$fwYdVTBu^K>%?BnmMHxqiiJEEs z%g-+R@m4+M*+;rk#5F#*LrF3b_!He=qb|2FwAnN3wwKdjQXc|1W9O`O9i~=Li_StF z9ZN^1%k%`X&8rTws#!?mJ1|wRUBu!i_C>0l@`y3BG_I=b`?}?_j^(%1{fN_1zpKtf zwd0qoM-6a2V;zdTy!)3g4VPmBwd2w6x2%Z+r-*733#Za^CBi<17aiBVBYX9-$~Z2& zXBOl&(@V)vGufV4F3)QJ1gmyRos;Ed3O_kHcPpjN;`)83jGPZJzIsB(0E~RiLoVm? zaTV{mdTVsd7)TK+c=06p$GnV)syPScS)F2jEJme)@*gNgIp%=t-75YL2VQL?X4onA z5&1l-S+fKA@PXZVv?n($3eMf<4IaB1Gyjss6&uR*1pr(5mvxVc#0c{9-K(DSxO4x( zY3}0<%n1>_=O2cz|1+i1TAnTW2{ota<@DM<>Lc=mX#R>ZOJ_HSZwG}Q{1kL?q7i-y zV2!Ht#VeHvQdy)7!IO580st71D+U4*h ztanOvK zs<5TfuxJnjMAEJYv?3hCa+M&a7Mq6r#9*b{f^+PnVZIvZk`>|SHUuV)^JHm?EKR

!+=nq8d{adwTtALURmth#d&djyNwlfm`blAIP?SH@IJl2gt-ip9Adi`VKj#VK$Ccxsb_6P0$>7{3i?i3ZQ zbCJESY4D0)Y842DUM|GJd^6VZ$)N12y6pk`8E3V^?}M$70bbhu!r1n*RZ}DPi!O6( zI#GKbfoTi2Vwdph{d86M@cl3o=~crTu~v~e#e6OV-$!f0Bj^K4>9ul^`An0?RTorpPbW5MX zFvDOQcs1_)5PrRMen{-ct?s(c=})}4-uL^9F-3yS_bhVv;)G^8ri(qIV#Zx&cl7wj^p>ZP@P z{mj$a+SQX~#qwn$RxoQ%bM3tHiTJ_%7@r>1k7SZ?njD051kf0Targ8kd4+<7$_Irq z5+ikI5SHgzqmjyRlvY@2{Hq>w_Qr2-%txS{TfX#4>P|#st$Qp(B6N=}r{y5dC@Egv zt4_2Vf~Hb9#ooHo^gb2e7rt3t%VVm|Tdy+wj$wgQ6)<>R1`_Ox|x-PF*4-r>`0>^$89;a<3uwWvdki& zOf8OJ{3pMWXRdf4q9X@!@%zNt{^}y4b)CA>@eV5ZY0yR;^}YkQ)*f~3sTfiHcjcmR z6BjOc8w!$osmsF2I{?CM@tzREEbyhse2E9b&^@j=riST92N_&(S1${b?kX(bHZ8lJ zV15S|F(%fg9}MF_d#U@H80x_)+?Vr$85JdSm)-mF6P(q0C!Aut9KNH1%&D=qK@QE- zU4KeHeCDRQ`0=!;nV)rGFjy}VnVgGG_%1o1KieX97L<+v`c_+XAX0={ArTVrih zGP6S+i!WHCeph@(32`e3hW#UIcml&8xDuoI8F*5j*^ewG2WcLgl=(#v| z`UY3KSM=PYg?k`p!Pm3?a#kWOnH*Dyh1l5_{1X8W6@?ADlLdn-i!(dtV+gt?H1iWI zS_V}4XP8Hmb2M}s9Wr9m`hdB6E?{Ez0Y{bzJX4gpW5dF(?fv4+@r#%FtW>LU7;#3- zGZ)Baa_$xh4~_=yfQQ{O=K1t$lPU3I=$Gu0brO!GrJOy~z3TB1(3RpScD;H$FTCdY* zq*5e$1V7cAkZlt*SIpQp>YDPOi|vmF>ppN#)6EcnutCLe%;mY~ zM@j!(ov6*3?*@ch%&-GkChCs+d<|-){tY#Y5kyHfa@oEn13E>O9pa83eJJ6SE!kw) zkf6JeCkhzC>*>bCF37O+VQM2tLb0!~ zDfy8ZT&`A!Q{)x5ef^wQ;G#>z7_cN={5&v*zc=@DE%Z>-YkQdI--+yZ2&aS7q6KM= zh?vpuoVm%X_*abB-psOr8+zIdR-D+#N?q8s-%6CDRWk>F#pSbw`61e> zSe#mf6y`h|&KzZ1wPG6ZC`Y|D9iY~r%K81gi=H$KsWrkhn3xV1#|e6-{Pir=Qh-VwnUH+9?*g1Q8;`)bAW?FW=^v zr@k(2Bf4$Hkg_SX8(T#N=U=utNf@o%LHsH0w{?i_Z(oKCPs?^8;&6)*ZPfdLsr6hP zY(6vV;`io}BU{>DE>Dd`?+FA8C>&5?9QgecPE0LoSZ$W#+OLz0A#Ha_SLHO{w{@WG zf3m1_m_V*KIamdKkIsy%0MBUtfyh-2^h4C2t6!xhURvD9+E%@gLGsFSa^WvbXF z5IcS)tmRDxOvRr3nYiX3x0J}of{{g`+AHH9v&U!q(+YEtcxMjYqs>|kz_DPHPh61YM6>2#XWKrr5Ln%`qse4cyplINzYmcop&iQ`L^q~SZy zh%XQ?ULQlBZs)sID$!?cc>NG*sUy+FsKVd*sKqY)cF*}CZ651;?xfPPq0Cn*_uwv8Vk~=gE)CG$ zJjP}Ep2cw1uxi&k^||kqL}EoPGV~hC35)U{_Zw`70f;ei%q%|>Wh_gzBB4-oUCA+| zmnTti0V=hmpD-O|eAzOHxcaI`iS-ng@w0g2){L1L8LC51W2wmp42d(WKaM^rj-drA z_EAR5A{Ia6r7~5K@q;K=hP};MswCM(H>8*P@t&xGkW4&KIQ$<-=bdMoi{!YXO3E-h zQdHkQQ$e;FcCy+rWVjk*#2s`uWF*FH`PeI?KdH*SCrwz*WJ@`RcY*&`0%t=EOx*Gw zuO2<-a%QyON*ebePU=J4Ijh>Gd$K0KrQ#=#@>p-3v3$ zVDG*5c~GYbV{3KC8WcN4C8vb-i7g1Pg{?Mk~^? z3-fhf(=O0cGVSD$()nJ35?*Ya^Qo_M#C~zi)q48mm6&f>KiE zZuh`T=PGabld$iKy}<4*P2E1~`XaEvqvO@+&%6-==Dc;zsm{C_b`W4Rqm~QJavKFt zhpMur{aqrLJ#lE*YAawfKc%bArmFf)*Qq-WsKfjPR#I=a(!K{@Fje)ZCjML7Ovj>` z1l`}>jlrc-wkN-vbj?frjup@l#eN)#ULI(V-7tkTi^T!wPo!@?7q7^z$uL(P7JaK% zDy{q3>JEg+OBt^GGh|dvLFp4izkvyFS6A@t(9Bga$}?p3TzoFol3o971e^3XmYy#h z*d4o<0x0~9TK8z3Bwx$rbZ2rb<>eMBNe?dqsXQUL2fk4YZ_3uPqPOKYR8;s{Cw2#; zovlK@S&||%yPjWkf17xz?EIMN4!VNV*Xeb?^CBmoOwV&cP&k0+L(rC`{h7>>MW;QO zgxkwiA9JWzAxPMZgCPy`+_-j~fHjF*)f#`qMkA2t-tfYxWE~&$o%|uMlzt?5;N44wM(ssmvcEz) z3Ot61x1YEx$t}l{!nK^JBwbhZEPpS`Vd`GZahX84Waml{Iy)ni-sCgxCGmJQsB#|j zt1dfn&WSaJjoR!tqkcgia)CdC&X*~=d$(EX z%6YD5aQba?6`z?wC6D_#Fu+zl*yPUuBYW#6=Gc+W?mw>Uun$C-&lNuy6F^Z^)%sbV z^F2`w@P6$fTTm9}A}gGr#1tM)9~|-NY73$HkN+FdcfuU!(`-rdYhR{w7wey?TQif@ zbp68=h(k`2t~GTY{Em0|mJekn;8qNqefb~2>E7Sfl-9dl#IZRk9#IlEcv)AZk$Gi@ zHj?KB4^T(T&QTwJm)u<8PBB|wi|bPx<+@hf0^0QSa*RA3L>#SSrZp{Hd?jTc+^*c? zFpS;^hJ%nP_n0=K&gxkp{Eyrl>#~fRCZ#_qoI-IozUcl3a)(~(v!RR9>gf}xf+Y&S z)T~geaVa-ni~^scp-W~SaJtZ?Eo*Pprbw<(`Pf?jnecZhk=-g)>%=(@(Y$736r zno{1&@-#v@&u2T=xFR1Ws0#)Z7W~cK%NA;$BpGp!-Y${A6D1Yho~%9{La9x6r+ebG z`NdrMRm$*sEoL2KH$-Mw3>hMW1(a5EN7ogHr^WjZ>(&XoxoMNa1nlpe7QuHxMdzpM zleW*ms&}vCY*}Rx`6qMlbLWhmAODUz4|J5_dbAy%_iv$s>=4r(ui;i3@_vhflO09y zA0*Xy(spU;gxQMlvjLaaudQuijY9OgNZf0<-`0Mn-~PBK9DduwEM*6o=VJ3yebhA- zaWwEyn(|jylf)^SOy)O&E?Gz2`uJAF!!Z<-D&!H1543Bpo_0+Y5oA$9KZk42AmO@= zZFOOp!yohf1z+s9p?>u)zj$;>yk{WBmE($=LeNQWo_>3+Ht==DCO+Po|nOl zRd-)EUFCIwNO{lQ$0kSmqWxuK$TigdDIBry8KlSLc{E7B*o(XgymTfkRcW%56ExlT zFps8gBj0nec#%3<&@1X)Y0CP-DeOH|wz>Ron;o_M`Ex_aV450b_){+Jb&1y#jv%W& zRg>IAGz6sz7LOSBkSrKx5IUy%{Jrzr)1SR2F%yQSHdl>9NxKaM-OY*SHDB@uI`A7* zE147uYD|caPFc(j_WZO@QFofqr?M1&t`gLi!TuJ`Kiq47c{*koVa`mD7G(EkI+bm! zSzuUcIgccc6=p^biv4k3;kvCd44z}3>$-ZX9zZVTXG^z0tz@H9DrKcpXwI2x&c6VJ z>E`^vyF=Mjm>KTx^aqGfvXl+CZfQ>8H-4m3RTo9%JDrto{GbZP!p?bbAZ zU3ubJTKu85d#SlmJ+?if5ra+b=-e!p5%^=mi%1s;gXcx?$#bz$HFY8etptj}p-w%p z&@ocwR{maWvFLKdrg(#*2|Vd9L^?9`1n8X% zOskF>HWP;Xu49K}5Zb+5PN~x;YgxY;)tfS4ch1KPOtWBbdq{$a#nXW`t~a6DLz@G) zrDPbpdJ&MHk0^1=xbOIzXF_3bkIvpVN?xmX6uj9h*|MXTe{l%qpPVmcq&7-r7wSuP zHfp3}QmxBbmN`NE2f~T?#veTW@7JY@y#7YSz`{o)p6pNQd9Z)P9|p3i;n%KH6VW}) zf}*HJp8jj9iz2FpABwN_rcQANb~Ym=hi@nVD}zpK$efz45^$RVi4Uq~@>FBq7KN$E zq~bnOF&7jUnrx15d=|{*`ypp{i@oeDh7@iuNv9MZwclOU2U)-DT0@)d8gyg=kk5Nh z8b6`b@uL5MrcPO4JKPW@3i9$SmuMg;H}P<$H^F*#`r@1WZ;wpF^Anf?8tX(ZOOD4s z@c?m^asFtU&~=34*+f zeMWxtUSxPaOW;<@kKAFO%!;4?4*PD^w)fDZHy&d5Gv6Kap1YkF)|fy_KmMYBOQ*m1 zRg#BmPr2!t`pvh=iY)bB9a~~BR$ujP>!rWsel=cMv0dUKVAQ2TGKM&lVi=8$1il$K9pxciE8?ybRK$su;^bLP@_2V zNcN-33Z_44T_M}mYl$8m+o`|WZHD^6mU{80;Ukr+^#1-8-%7BTdB?RrL|XojQdXoe z%loRm!n>lDrmxO~g9ZLTFD{}Y!+aBmXkLspO9-p5G)Oj{e_2wmVoq;Xh3c@AmLIfm zYiPAtnx2|#yg?T-&O(mHj2>r-zs}vWW_cwU?`Z5qn_4LxWztM@PN|}af5$81W7(Hc zGOZR&ok{zI4-Amdj_m{Aj?3y42Z=<$VP`KYgGY2_$xJ9g0dUMzv{3t#Ev(vHBGXXy zgCdJ6xK5Xz=DVs5y796}v%Co3Z4O6SVZ9AUaMmu-F0ohv)$n|p zmE&HERNK&Kk5w&~Wc3(=dR$pl6*~|`8nfB+MLirpllUe?D?#0f2Bc)ymm`j{en7UO+UdIK3HQo7PuT6DaApnr=l`$rGc?I1#MwC+UT5hdR# zEvB0zUqThO&4B|*fc;nl3AZ4X6#5-&z_0nO&Im~-9Qzf=EJO#g!crhjMSvH=yM#S{ zWwcFK|KZIQf#P#G<{B!D;vW@CJ_8OzU&QnP0R% zh^5+IbLkaeU`hT2{ku|{?!~joz}-6Jc%^mpt6u!5rclQrY$na`)B@MtH=}$vm4|ta zBf2BW)Sktko(y1PlAJR`&0#?kG4t<6x{?CvkbN+`kh!9d+P3-{5ZC?JT;d++6D2`Y z>Yb%LLgj%jDWyLN>XS+Hx6zf_YaNvO09cZlJE} z0UA%~-S6V#H$P7^jOW}vhO%9YMQlm5M9VB-_?eswrZ=ppo=y%k6sgD&XN3_!Y=ZMC zBeIpwFW%M7>Yj>8wFU}^7;Z0A>FuJIl zu~$KLRQQER$R@e`&8dL{B5a^$Em>VEGNMsbb^2-gTv~4FGxHKl&1=Abtx-0WQA3&T z;%CBl))4(StsP0aQ%oT)o_;Oq=Lbv{_uB@#!RFOPe>R1D|4yyw2;Cp2(nMnVtS|E8Qj2(kdh;6wQD?AEa{nb zUJ`(urFRBbR+jUGeu74Qkau{3`CC1>I66~vRNcFRrY)(|p-7h4u)UBK0$Lwxu7%y?3;OK*MQ6O=B;^B`pOnlD3vur z?3f5-J-ZDbe-n1b`$zk@vGe*4@Z;qPHm86Zmy&HP@x^6223pk~uuYjV%+J3qMzahQ z#1Ul5_&wk`_RcazVM*DQny{FHfyn7)O3e+G@-0q&=alz}NL>zC=hDctD%veIy-YPK zew$RwjQw7B`}&a-z8CE;2AQhM9iE_1uO0ClmmcXO@p-)0^}nP=Nk@LhCio$5$L+QU zlS<2PNxW~grEZv(>Bo$W+%Wn(-h!ARzXg2LoHaJ!=j=w4b&RSqBh}rG8UbruD1ow~ zeMR-nt47vZISz?R5t@%7zb~|s6tAtT3d@Ci?NbIX+wRb3hKi7yuOSi~gUC$Igej+E zaQeai_+1@y|Ix>jA+`}Ba&lhX2cs)4G=pQ%)vSlG=i*4Or17()5mJxY*Ax5V-JWA7 zN)@TsYbr&KYEu)I@O7cwpjRI$bvB>QOS23xefS3rEQ(B=<>&%F{|?ejM0?H(4l14U zGkR6cf1?el6UtEN$(iW`#XBvTB%UA874!zFrDm5%CDO8gx~*2ihkX{be7l-&PB#*K zCXnIruYsQ;SE0mvEpeQ=QLd7U<)Px%O3&%Ft?f3lYOUXMV%A8H}!a^X#%$gQ>%v%FQd())^+;>3b!k7 zw=LVbPQpjakg+(TY3@|XAVK*sAl{V9D9Hl1-gs5oe=d6B|oW~JUqKno8@0GFY z=^?KbNAPAksrFlw2anFCk+}s=#6l>7_N8E@e0n-+T~YC)u^^_Vws@9^ybck9eU$FV zp}hheQ_VWl^B%9VXn&l<^!NwWI(#%t*%KT#sv5g;grq4qPS@|`9yATAPSTZeqL*Un zrh61>(?Y#bqtK`>tGCw8gf=4AYmU7`N<1y2c8E!$Ne-jlI515bTs( z<3Th3tumPs4vmwOamDEV2^Pz&J6DXJK2L8prmnVofc~W7h102Rz#)@5XLui_1>-iJ zP$32R4MAIFeoZq9_q{mbuagRe1i19i`lMoF>pSdOD5@Bs)e{r1!rTZ6bZM^E^Qxt& zm!DE70?Jwb*e?@|tGsXhqb+2_A2<^z=f@iXLNMbR-SC67WD3mxzq;UNxlUedMFO_F5Gv{v%{|%WU8eziNGvzU?q!Bjx_5e!{Uxl)=1-b;a;XR zkda|e^ZshP-6s5QTIgDjme$=hZhRRlzvj_EOpG;=F=p`T+(GkR{FmM%h6bs#l%9yY zJ$9SfEN*fCfwU);E_`zp(j`VQ+1I|;wW*ED*`0aHObbF)wIH>U2loio(UbkxQ5yY3 zsujHc7~iMO%a@2MwHjin;`s2n=By*UYwg}_l(a%9k$_t3S>i^N(UNB!U8Unom}sXj zz6_oqi0Y&gKl27uwLZ5Z+zrAw+yC0Ds6JLLpl6-4=fRuzoL^B43mHN`Ugce9<74VW z0y|XKsENi_@=UKUX7~%2lc!(Q6Uwa8A%mwg1iH>SZpif1c=uz_A@{J5QBs~{^b0MC zoq(*d-_=D9Y{Hqjms&J~Yyws7Ay)eF@IZz9=&bS=whOMo((z(5TKwO%idwr@KQumjZ=R-lJv_mUX*72snV{cueuCh? zb&#=${MQnyue&pCCl2$n&UTS-D|0(C#N$z#qRrMlUa)kgL0OCS4@- z+?So5gBYm}_O!N;%esaBotXV`cBcf9qx*;;_u(*v-)w{M3tq&7HWM=w5_X@gs&kLa ztCX|J6XWVEYW37PW5-2mtQlqs|BwbgMcqWIXVwi?9Bk>=rP#Q&c}}(a<)X7nTJq-D1_X$g~dyF zRmO`Mgw2fgMa|bl3pVtJ?Ma1AMSdo?9QWdk>S-QW^z>7Yv1;zF@{2={cefbsN5iTQ zN69C#>nU7=>_$VFgKo9&QU2OC6RGvh@)=EM`|YOHR}_0JFnH(bg_#<#4ObX}!)02}Gq!SisTIW1fM5eCC} z?%yNPoS!Weep(|6!$a0yah_J2h~v^s-;bc!m+;_T&OMW?@8gUEl3o zqu%QwiopE~kaG1=owcS^XrE80?&>k40@_)h{St&n@2A7kFR5$po>j0Xql(P8o4fnKYcXMrYvE7OBcg)}qxdpf&g zcGChT;~eN0O&GQxv-0Xy@=o#4zR-lCBRa|DDd%OGfkU~|@=nkEZ8F})BF-buI5_6g z(n|7nu>Up;h-CTBb^1sCK3wwx1?mWRNgA~3#WfA|Zz~~-coF1F{dKt>_l|xyvMNDt zgITQACbbo|Z7wH!yd3yPW#zU^rE=|W?;fGPhND9Iqa~B(9Cbv^Y`2Q|Q=ul3^h)$x zgk?|aC@+RI;+0NXX~P!>X||LLVj-fxf1YD*u0sqL7nicomnZ99+3~GHq58uo@Jw}i z_IwTqU=}VDNReC4)VI=`cJ#$|7JjEp_s#M7k{4NE2O8$smVidan2w^rY1vsNMZ7uW0-+&$X8> zlHmd5+AS}RDhPM4-RDXz5>gZI$aU(zzdfvYsf>+(G?{w0$GE$d_B>8N+kTTaJUu3@ zB+x3gan|>K&i4uaahD&?k1M`V;>LbciuZ8IV2iJ}bZXtayA8-VA(|eaOB3yty$Xo- zi>#1dyelpHP{OHD=jCm2q#cLHUym~D+SDi5NxpM>{|frdxmB^hGHr<;IP~9R#W-YE zPtR)ZH&UQj6|$x#0l)yqs-fkpOgSTM30c20V zglmmz&KCr_A-?Rzg-GN){D%EvY?##D3zchi>b`xn-u*0L3^d_hQ`=k6`9}Wz^dG50 zH3iP|LlwH}{Cf{mEiI$pAqLDcvS*2;b-LM-=#vxm?aNI$wGfMPe3O;~HwOZ)8!t~U zy^Rt%oLr z&*XnE?_~Hh{ggR0dxh(5z_M`7pMe16i{M2LBK{q>s=@g$?<22bgR0l+OeO^7pr%8! zmU7WD`)s9I14-{e$^SstTBD*0%da)5)QDFVEtEM5KCpjWR89b2iJ#Cywu{bMy=Xn* zHT<30X2Jv}BJzEYCgEo)Pqbc*b^y0#aq9kzK{VbK*+IYZSRTmr!@fWe$!So{~@wjXbvZYrfe zWHn9DP`^v{;IrD}qD1h~$tp|&Gj)0Yfm|<1pEq~GCoezU~L`kyiM+^l~2`>6yJ`@%H zmDA(#UY)`Yb^NV%+mNfQv7#=$aPhzJe{wG|qmxt%rfoS#pF$mu2gpPq4jN?g1D*2R z!gprL+D)xj(Nz?>=(asY_YDJP{8A}|sAY#W)VXRGv?oC&q2%arHr=qiv%!Xb-3FA(fc`FAlrhVmasPeU*82>?Ej zV6EZPZ=bs5tmpY6YRHD7q`o%!i%DhWn)5Ua+Wjp2bzUnSU((OJ#FmIXz@S>*tC_}y z>x19wv4Q*yF4Q|Br-{Uuy3LFmz|(<=z}<|zqC`2$D~t*+55PH zZtW0Mi(?k)(OKAoTU_jS_7eGxe;w5b>pD8mOR>E0gM$16j!>(AHL9$@@{5edhjJBB zOqf{)aZLfuwZZ`Mxx$1se@zIwmq3Xqn z=Yq{9pKs1*eAVJW55U4+3<$`!L)i;`BO@;rrar`1@^7&uSQ?~zSoc5rl>hMrk?z6I zTvv)K;HdRD@nZ;&7ayZIciyj6jE)RHVCDXSnT%ln*tRH*rFG|-W6O38*rwUs1gi)_wgT8RYq~iYs0J#M-eT(E{0gDDQRo^t9oa zpj>)1*csc&&o5s7xmRL*(KVns-1E`&5RsPsJiJEm-yZ{izFZ8IEzfS_^*s-D7h{5N z*EcGJQl&s7f0NV}YK_s&QZij(ZB5SjJGe7rnLH8s*dW3E=GaI%WlBKblYg1r1o}K| zZdzx8po2ZT|8_s|3~Z`YyNX%Q5Jut~LyrtKkPgJU%6 z&4!FRVWOu9>ro{{HM~;$)-t|0Dy=ly1R?~}C&mE%s{^h6txdfVCnF=K5m68rS|(cx=$Z}%6qv+cKDE`Vy+>r&Y7?{CqH1(#jEeP8tB)E*LsMF+ z_I`f%_jiu}a*jW8?p)V(U!V8;^}4aCG!%&h`7_0ZP|C|kSPb*>lQH9*EDy|0T4Ty> zTHOG6-;-;7?pN;_bHk=hQ|!5ZYX(M3tghfn0V1WR-mjiAe4CM&!8pVKmSZCv^2(pW zzem;*-7NIXwD~%%4f7)@d=>1Aiq1FWClBguO)m2!^h%aN5>v4~~ zDK!r>maL2nUBj7+WWaHjSa~o51?WCf0Y?FC4#M!UK1{K#z;tR*`DNVz^p|D=4lXPd z6@<=|s|{u`u)579t?Q6{pgZ3T_t@qKzV8oaGYs(D8G6RYE-3%`cxYRx^aD2n1`~OC z!B1qIQsZW;>K?;TVe@xz+LNS-ay3{ZEp4Jn?26d=9el#hNQr*O`of3uSY#v_t;m`I z9V5xbf!E2PdC!7zCYNZL#1CqKE{Y?P%_^8F2kr*Jy<)Gtz>G z76z9v8UKOIFTRPXS-t+qTA3pq{_NCi1~dl-3Mw3&z~QpDI;%~ws0e_es)J5!^Q63N zCjjS3xF&J>M;T04Ss_2kvtb|mZFFa#LOA*{r}b;OWf-zek^6e1p6H>1*WO#9IDds1 z8@aqP!lWW6bfA@{aK1!9Yu=~x43%7k?N7tFlZt%IZOivC@d5D zHrZyJRgYAmJ8S+xM{!l<&(>b)0q4E}Rs(6%=o{}#^C$(dWf~fo?`@b0rnla=v4!7bwszT^bSOgptPcJ!_*69#kTBP>qU&-JimATC6#E% zLwJkId---h`|bPDqYIA-ouE&N((2l*ZONgg18HM-f@#^b27(HNKL{#i2BDfV49p;( zL>?d}^M|PMB-V=G*o?$J@O5z9j*KFq0^<7i6g>Qr^RcvrEAyVPjn=hn=rr@|vB4NmjQ zME3R-X8!S|XZ`YOV3?Xn&!SeS3pRV5G{~m%hCG} zq#t|1AZFy*!^rY15MmZ+u1O^eMfqoJU7OedujeuF({p0BfginaY?)j`HC-Z6euyr3 z%{xF62wY6pp}cfKUY3OJ`%un5q_bl(V2?A#5O*XVNEjWK^6`@qs+1#2O%NryzX|`T z)D3^KM}cVrd0@NTdc*_C!hTkdaTSk=awA(KTWJ$s%M~Gz^FqR2@&xAKfzoDm@WZDP zk8-N?asH}u^^Nl@9JU80&&?%P?#PX`&YMAEN6f7Qc&g?sO$aMI2#1xn7L5$+#AnlK z_uS|CN}9yrDC1TE2M~s*Y*FwhrH0KCUo4*T*|bP^ti(1jCT*Mo%!>V+Z)I8#M!cFb zvY2*>sdjT;m8nZ_w+FoGF5eqZRf{U2=uBb9+BMk=k<7vn8GyWF%|@GkVA|Gk_(0~h zZ3ka~Z^V7sFlw)+@Wq~tK39eSf3o(AZ^Tqt#%ud|)L|VR7#2qu;huf6k&<8heoDWj zSQ8yn_!$wTNJ}WbnC~`!0JQCL)-VY=kx&h%M{qZQ2tactq(HW6`*htjpDD2NWnJ<7wN#cM z5}{{Vb<@JeoVn}ct9b{dN6}*q!HmH?^;>_=9*ZYdR;N4Q)@z;&AH7<+xlU!dBHUSC zepY{NN#J_(qvfZqc!x_oGj5PAf=Y~JdfJnGtL8}!X8}t}i_J|@^V5*&Ff;Y~+cNl? ztNC*rv^;Ab6`1n_2=d(!E}(H!)h*?5?|dAw0vNkqaNoRV8?d2jz{&B;q@?83Mu;7( zsu?=G#VevqZ$j~rem&F4!e(Y0`{k0vhDYTo$S-UP%l@kIxmrkWbFbHdQ7HAqGXh$j z-G0Wew$Ke+@KtB%%Mf@?IAMBgJ6Y{I6yIP2YCYrN4gM`G)N*6Zdr0TJfJQY~x@@w< z{WPTu#Qw;N<{fIii$Vq0zqA>s+t{?Ag}IF7_BD8VV4aaM-D`U|LGF7sA!(i&Yb428 z`*a2elgwxBl{9Jm!xwuKR-mfIo*a`@gR3&=0$G*>(gh3q#4x3v?u}j6_;t+@%s9=C zG836m=}--Lq&}F>s^3`9dCLA8enZB4l&;gqg@B{0rfYMzkaTb9`InQcTQ;l1HcJh} zuBsCLEsEAeDFzoFYgVp)-bK;Ll+G+Ku!nVg_oi z7#;t(qtPwXZn1-+0w!VrgGE5!3$5DlbMIk6zR4x!b;=`+L=ks={rbQI))lv1BNTn} z|L6KG2Ui`F{0*HGD9+=gn+#VjzXkz!y#!|NJ_#;&*~wq$)PUKp;%{KO5O#3sd1y9I zq5?{m2lc!~VL9iXnJR?Z3kV~qRR(GAvnun;939y_zaB#_FFd{vJs33zC$A3ER>S1TEH`JZu3-AYnjU`;Eqh{ox3&M{kq%0-JU zJC$nKQT#KsDC;db%Q*8>?u#@Fj=BIrtEKp%M$V-Ut+5f?ux=>jH1a>tSi}!YE?WN^ z+yfr6AL&2j@hDi>b~E5$l3Tdnm{5=Bm93K;e*A`te) zLt!0=(6S2{y|#dI-Sw!r$bXgB`I66S^mP`j#fr-jX+&7=|BRP|nxRq@w&_hQfrpm;0^UOR#nR89NL@sxhXU9LbL|yhOE8roDgqAD;_zmEyvNSq(rkzJ5 ze<#eT#q~;Q!d)a1&1UTFMhk`_`WP;}J_NJ?yH52UOQByVfFUIy-38Drqwn}UuII#L@2~?qZK#kr z1C4=kcohvZgM%7Z?7N$n>=OpE0{Rbg9Hfoi{RkhZeYGUi6JL2m}hSX|H&L&%7zsTzF}f9Om}K`@yMRv_^*tY_*&o^gGWv z`7IAY-a_iiBgJFCXvJll9FvGheuDMVWN3353$x?>Pce0JepcH(%huCNsjpU7ETZfDbD^L+ScD6ms zP-e?6^vvXpv1)R^f=b@*6FJ->dIc?11y=g$*VzY=Qwi#baYzDLI&m_^wb z1o=ui9|zI^D9rTem*1tw=ca=wrEKcrTymi%W=#7T0wZdNZTX9iMr1XTph{>ji$L%g zL8eBDfh+i9AoD8ipHgUf`g;z>>FgVbrdW{zzh*0xrM;N=BX@Lccm!o@#_)WqEc@Hk zBt2rgwQ5cmFYgjgj3GWdj}NIRuMWv9t`w^ydRcF@TIn%!Vcl#sbES{ZsJT;r|EihK zwVswiU)P>1WN;L7wH1KB;)8*N0oFnJR&}2%$sFPB-PSa-m5~?~JHx7y>RjwHy5g-# z)v_uG>CD$qNJ-@Rob%N~0lCQ`DrN@@%)h^=fCEcngaxe>T@XLgXT{9}vZlR~BHfME zC|p}=i()5(!GR&4errue(zRtTN>|xhN-Vvrf6g!N$r|&F(=z4J&V4}#k0CyuU=}~b z;BOQ6rm`B5C-?I$Y@|$(WA_u;v&rL{k85!fhr6wCUv}x|dvI8fIXCglP~NjxN?p62T#7M@(FP`k%y9=j)&ys#foP3> zC(QUiZk*%E#Io;XurB=ju+=#sn2pr@;n|{6d|b%PleEWvm7&t7<;Amk3J;b=vGNId zV@@IXScP`1D)jM{QB+I)-#q2lr9L6AYo;&aEI-Ki{W;4oj{S1Dt>xW)7-5|n&-o83 zm-glL_$j5hVuza_z-x)YOQ0YIzE9Q+&YGdSub@cA69~VI?30VLe6pH5V-VSHE}X$G zps?EK>jA5W9gZvhK6CrK%5@YNOdqnNj^C;FeT9C+)8K*j5(Ndn)pf@xj6Hf69E7cr z)5<6Ci;6VY+(yeXlSB%vj2klU&o?a#KLWNvj7jWQW3ckE$$_$x$hr33^(ccuUfTgj zI$Doi0ca_;@jf1msQEM6Wtmx~KH1c2QDV^*W?lAk(93Qx?!nn(w{BKV2Iskn7nuUL zrCB#b(?QfwOX_aLX@<7e@|4ov?02CXmQR>&*{7>)#Sr>DSrRN2L`JQdZ>tmg2F)h@+kwLskf^Lbqz8geNn_Y)Vb z2)pNFLyf4(K`Qh0v9^F-#-QwOj88_g(09v!BLOt?M&Jmhbfy zFskVwJ3BQV7#dgpQM)txQj?o>e`mC+WKTd?U#ztSUzr}yq!zIm_ZPqg;ifF1XCwC-H;P|SO@EqII(MSmd0mw1AbsF=pOYAw*Bp$4>k%5i@u zR_3XlkR}ZE42~>JAK#`)Cbq|?8AV()RXO>KQ0d)Xl~$;V?7KBJ2APs)><hby#D*I)rq#v}25w^QugdYfLFR>d6)`*23(wevq zIXboKT`){A=YIRHwn1w$i8-v{EC@NHtWZy#l@yK?OY)$W9Sisn@a4 z^y^M04m6Fg@X2b;*=b_Def{I6o6dY1{U;lgYr4emXRj$i+p-CwlBG#IYC2lXW-NSK zirh0W=5A;FFl3&zoo|ymETjh11jCksizYQIqX_vy8t8X4?;~X(k_&t@^8+4aI9q1M z9g@MVHh2TpvGezrA59~T?N5vYsQfEyL4T&>3k|IQx!K;HQk`l8NR#J1Vs^Gx90`)-&JlLp2Ytwh)_#hhO_E}lbC&i$O-|brlB~-_ zAvGY+hkDf(Bq}vTotw&lR9_t(T=BQev6H7_^`N**{ToI;`gKNP%JUqazb4+($A%nD z5I+5)kuj#^38v^7G2E@!uvNfQv{m;C5Pk6_F-c&%N-Yq3dRh4FWEXnKKm>)Q_4UBlL~>I-E= zy$R%H_S;tCe#_t?1vEpAC{Qf;_w=vtfCIz))@qDtQ=_!4Bd4C|G7SDfd+9?5dT)9v zV|=^VtI=nah}lHBD|dMnxJj-vr^9)B$wKOcCb9oOHc8>tn{zhn#5qsr)_+ELM3u@F zk-smZo<0X2cEhLLG{{kAz}sj1W4(6;lplX){JnqZ`N( z6KfN#(8Wo)GMIrLyIno2!t{mWSm^6pJg$nev>|MtNYbeRBru0Zk0Gk?1D@fXJxnlGgYYZt-c!_EiMTlB!bmdx zw38}O&J`6xKH8HJ`@;#`5SeQsJzhNw8*aDqFK2T<72t zgfp#w4viFs|H4Kb`XZ)UZ&w>A7brLUWyP2~^>uvQL&Hv$Vr7s(&i521Mywo&VW-rN z46hsEW@UKLT63(5ZY*k6=84RL9Gk^rd7N)s7?d4xq>{9^`q>#R`e1>R-SUvmoq}O^m;dXOuYV%crnjwECU7C2Q z#HpLrQys_pEqz{Ev#-2~k~o?HNi5d-rr4YBu=A@1$_6YLu{r(?+K05tBu6jL)tD(>)zSYz zg*wv{*rIv{o*(~QA4c$senErjqJ*dO&;CrA1IW|=Ktid$o_|4mNU!-9UWc>FW|~9j z2*C29$s$cJ^0M3A&eIu_rIvfpRxt%8=YS{lF^-!AiGdueyD%hk%z6A~SmV-Oh1w6Y zLHc?$fAuye!zjm?C+O03q;uPx&`CB$;lmRh2hV ztf3`RxQFqZ#ZP`QV=u*jgF`>J`&n6Rdcgy)PTR|6(KjiKpcm z>z|o;4jb{$#r_PQc)&Z8w#*z2YHs4}XYW=6xTIeu?F!2?Z`(jB7@ck)OY;qdbXk%2#ZOq9_rBQq6CTv{W^c z6?^u(xY*)PiP^cQ^>@O2X{A7K+O}Ocg{9;RdN)0 zpQ<^b!i6|~5BaN#NBl^l^#-2zhj+9l%XRvP#=?>|i}9`oiw#yEbUvIthIvp^{z7M4 zWzBvb%v^aO&Hv)y>!30wIOQ6Y8^D*vHmBO#T4)5jmcOK%HVPzq%78q-eqBjsr`sy8 z^JXEo*X+3&bucpI7q!NWWV~fVo#8~h8_9;~MTrgfOv6x}A_}8vJ=dEY^KT7&!+VzHXUwk?59=B{+fa0J#N>lR$?R0Wc=Xa(fnX?*Sc@CwD0HAM^ zK}ON1Nqs4<&EyNlo21Mz^ta)Ia@e=xW0^N-3?&0Id|g>}6nc0RvnN-M*>P%`6`e?q zn_2L{8bwc%r~D|hEOXd8Z(0%s8VcmEKoP}aqpp=9!=l}45j4;o?F-oE)5+AB9F=;D zNk-fhlZTvgMc^2Yao)e!&u2XZ3(tDstQmzYNIGV}d81#-s>**xj=p5{!P^XMwK zp(f0@C1=@1|MO0=0j{rK%zNLX!@Pwz2m{iNi#vS`u}Zt=l=*d1Aicsz7c@#J*Ynsh zqSHCY_wXd3e-w8hRj$5l`AB)7)ah%vqlr5Zw2f*}m+Y#|@}QkWat@^{#%uBJG&8DB zZ2X`zj=ceUS#tT8i(#Or(<_CYkMS1Zk)-jc{A`txjO~4sE1c*NC1THc-4rhzQIxNH zw!H>yNv>~`L6Rs3S<5Ps7XC*!dlb#S`)kHCsyA;p>8jp!XCVoueT58(c;&ItdTj0O zVUz3ct|Iy+UEPCQQ(W~Q^->y^eh`_zmh#FoGMYZ?rIUesLgn4aLLe;z49_~cM-9dx z9JKf`Ik`%AdA5SCGKQ~)<-W-V$(04KAFn#EO|w~&R^2vLCg$b$XKSTw&T^L>biz-z z#Ovqr^hR}vJ3#bnf=2x&uJ*EOf7Moh&03=WQbt8e&@|b)hSy!tjCpXMPK~oloB0@E zJZ$;BDg^RVcdT7jEAK`2It-+b_tPh{QO^~*w`Quw7kT^xMk;yRy=r??a;Id&35E2# zHYvO8ghT3cKJ=ZY>hC-gTKo%eciI8!OH-krpb|1J^=tZukGX#K<3?31NHw_p;Tp9O{PmC(QA&iHdCXwbHQ& z2*V=*9PE=?4v$$Y&eQ{On3Ja;bZ5C;ByEfozj&jt*t4N^Zfao2saBnh~9gAxpY6NVK?O;BKRP` zhJW~xlB!FPMTiJ!w-T!vtQmS?6RKwx)Frj;KJtuSm&_SFC(b@-jyZs^SZs4VC^JF` zERLn&?{H{MKBHO9Q_R6shl?Dp3F^1v^C9+?kNjusja}>#X=Chl%;ybm11K8~sl}OqK zibx2#Ka|qso-?doz)9GsuiuOppwSnec^e5ip{LdeHK}m>vJ$pU8w-aH$3GgiS9AiP z5FsN2j(ccTF9HXsmXc#B*3y@v-3QvOCrwzrR#?A1qYvorVB}W&NzUy^xJP#>K>aHP zet1g836wWp1n0qJQ(SF<74?C91j9R^mrU1~m`sdE{zq~^@EZ0Wws`aW~-_!I}Et5ny?i(Mmuq>-bd(#7ggTi8*t^M z(TPMI%Y+YfKMAB|gpq;HG1L|v4+Y1-c+<%||07mpS zuneN$(9*4D1jm=;wx zS+jYQRQN#cfzb37p|JY+?mqw=vIxuVFMYWj>@!T?#s{8ZTev?3_SgR)NgsrRmN)gt zD8Iae|J<1mzh=OA+uKDCQ+(c>icmgf{qSr&I-cF)#LEF9Dt(u{IrvfG$pZ^zMt!AU zgpl2sF3r%d$nAzpiGPQq%HZZ^mQbm2_vNlNS1B%KGksi`E<{jm(C1glH+IjTg6nX( zpJ{SDZsGd2ty_e<7!JzFOPrQ&(1?!4EH?w?bFQyfl&5RcwP1l>YuXbbTs^eYi>;!{xBf@B#eZsQfkFoQ`OhINhgpi}(w(6lXyD9f; zTf{>%1lMWnEGQE+?53{g0st@N(=}6--uIrj#B=uM_Fh@TeXvw3l{UzWFr)pc#9ZM< za(Dc+C2%ci>jGG7I`vxU-|ec4SFeh}P1>&My-qcbw|QYbuUT4dKB4PyGY|9eX6^HZ zR$$sSe$lMLnOk5>#(j`%D4#Ht4R*A8YCHg*dB6zGcMUsr%Z~`?0$*O}f9I0A!KX(ra`Df)i(+z^mnzi3)OHCv6v68y$sq6X%Pwe;0fMNh}eu}Nq zUcpcNb@tVn8jK<}`&V^zu=SNQoxrqAKC`7?nTc)sZkg{AjEiN{M@!3)Tski;XSQ%9 zmfBG~MNgZoo^1v`+tvU<2?aMQ;5YfT&FxfeM~4j!ok|iS#Q~1ZJAYZDu6XnK#psY6 z5T$;FEyKU3QNy;{WUNnc_4A$XiV$gjafgUr(jN@nOuU1x6RqxnK{wV4>oPN}QAQ)F zoq4{?^rvELa%;OfWXdkzg=QVi>M`qdnNK?G`=$9pA)x|R{#0*9Lup7q(rB(O+vFLh#*gt9r6N}H@)VW7M+^He|Hfusa8$Ner5!YztkIHV zPeSthy%TozDAns%tinNCtgWxWHeSn#tylppGnGsq^G3H`s`-%yQURuDxPh~rO^TF? zGbi*4@>VfDEYDCA5L_EBzh%OS)ia!!Ae8REAzDagax%ML3mHnU-zVzKIFJv6_Wn#K z`q7x$-df9Sm|~E7Az`nn)OeW4ysJRAyZ)r1lnX@Aceg;Jo$vAM$wGsb&Y)B^GL~rh z>B?p;2pMCzAOyb&nI9EdOC}EnEARJSd7m3iM6|*y)j}+L;e)}`c4yfzLTciU&OQ-!C@*2}nqL1)!DIve{F%ZESE#_ze3 zeHFuQJ(Iq$f{6{(uY0mn=*E|I1m)M|b+bK`++kO41-#?=s+;Stm6VjUtAyFl;r02| z!m$nKdobWygJfDeEgEE>xIBJ{%my>JV}?b=Q5SIF;G3$}3pk;ft#04UuF9P@ZHslU zesyNeTIy$~tp=D!;&*D>Uj^bqy7R8}6B~%zGJ~J8;r}qTmDbA0@LSG^jpPhw zivlE;((`y74+^CrE7Bc=`}ExaybAdy>P zOBW6&CmVsKiJ4`IZHD+Z8D2Sozm?Dz1~KU?IBa@U6`D`#`eOmLuLCH$TmHI7l0xQ~ z$REv951D?WDt-F$Bh7wQNrkg-3?B;z99)Xhy##w%9U5V6ZL_72jlR+U9CN@>W z->=b&=vy*ziCz78&))e(^Zgvu3O>$XJ!Q#eOL`o_pPt2-HSKLNbcUk$^R?(qsKEdZ!+XH9u>7)UdKtL4i#9Ao%ybm(Tzxhuv1x%{fq8~9E-IUr+ft4uC}h^(9Z|_j}SL=u{Q31zm(i*NJ0Ld zS!eacFd~+p={!2{7^yX#3h6afv|qi$r>HP==R?@PnypOHak1IW`d&1A`8jtvxljWI zhl7FaEy2$3wk}SC$0L~Ek@W9aYd+*32zig(eW84-zwhO*D2bMGmW&A+&hu??3C+RD zR$IJ;$%`SaA@idj=Sj2Ra&?hWXJb-dks)Vs#*K2LAN%BG$=oScSd+K$l$1nfQ+GeA z)oi1}M1swx4fHFAdg^cvMBP-$fsMnW;KaP%z@{7tMtv3eVLd{DlL8R_H_M3MM-Dsb zM^;4=AKK=RVTd2-=tWo2^sIYiL3{k|%BgZi^t!23G21{N<*Q9+Yd`K2rXpxX=+(O5 z=Vb4;0xPoyo@+?mnjlY&>$y&dR!y_D#of(NBC_SH629 zhaIfa`LkZcYt|3WWZ zel==)UrU2sKtyc{T+%uj^7O|t4Qr5J_?5yB2Fn(LlU>d-zdm2ig-cNUYG>yC_iTK# zZ67ZDnl{+b`sn)*Yt-y4j=ilaS^}PrTKWUOXPy^LW*pM}1-3kqZa*w;sVSJa{g06S zkDHxk%Y`lvuM2oy=l*Nsjd9e&T-%_TLrXoQ8wL>=Bc6tjcjX5sF(*I&QQUDSleyY- zzisz7%_U?j@+D2W>>6DMj(3E-h@ER9z<4Y7vxQ1uQKlZ5XiKn_XPdP>0s&s#ie)Xi z2ChhPDKqr22qnmheV>p(wz_psx0>(U0Gb;~bHrEFao^|I;+^+J$mEIEr)wc-`q@F} z)&jqz#aE2{3`PeO&6rbVvQuqWsA2nNS6T5F0^5w2KIzy_Rx@dbO+BWQq-!3!bUXNL zE#UmlHm={5l@o$nIrn@Fa~DNA<<=tC!yp`bj?@cM)e)t#ib#5&sFe7Nv6U{$0n7GbRiSl#@qpWJLxM(ZK&Cg<{}%U0d-h_`ga2G0GdD34;7WgF2Gl^#KSLov+d zM~qgm6b);j)*2-R6U;tfVx}7etNoe!`(~5jO6Z+?udZ-8HIg^Nu5NbeJ2W1XA!PG*I20_!@mX$m zf2mgLrBrbL;;wg~+Oak1WMed-=`UB~su#HVBvvhz1ITeSVN}#V`Xvp5y?u>m)UBBi zVfGxUuS$(oO%}aZ(Ghi{G3#eC`$wacm`!N69YO(C^%s)8H1y1Bk5@8l z$Konj7`nfjF;)s6wuiR1k>y$CEjtu7D0o8EA6!n9*oaiP!)nZ?@tt8A(MOH8%lJy+ zaNGyOJC(ZVyV6baF^O8mZYlI!X(L163$}7PhUdawq4xsG)%9Gw{cC$hAD;<^;R4&?SN?ivng4c#r}BBm;K(D{dd(Yf4SbdH|%)?m5ZT- zDRiAnQ^Jg(Y{UiqTv`@~eCbPBPZ{7nPW8MNU?`kSkd8ND9?7AcJ0naP=3ogE7$3AE ziZaMv3K(CUXP*DS9k`{;JEYZfxQ5;Q?jLtG2NTlJjv=T?8KLd$Yu zeVCq{Dj5eDnS`Z{|4sBY_Hi)t@I(L=a#i|#jTp^N4Tlpzyjlwjdv>Rux!*^Y4>j9S z5bg0$?mtk04j6Fi-q|Jwp!0pAVv#}?yq%{DyAYq(ml8k9#(c;j zL`Viw%b$)Q4D)Oe#P}7iWN%eEQHo9wE;zYcaz3V& z3RV+7+~D*`e(F!9*7y>d^;PM?%*|x z-idRK>%7wb(3w#gsai zOf{kI^kqz#9UxBtQ$9Q8ZbGGEdUyaRvx|+vzXs~QWpxA#$)AEG*Pf+876x(}gr-~K%tE$> zJ8h_GQLnEYo{#))*@QTAb|fk%x>Wdrgne8zBYsv4ee|dN9Uv4}Fq=g`*d+3^v}5`Z zdeZyzM(^{-GTF-9$y`Itbe*~5jGBQUoex_x{ywl|Kh65~+7Lf4g!IU5#gcgSMg7^Z?^pjwKuW zjYF-`q+WnkQ4wx%J*~-L&66Erri8)kcnPU1OtR3}PIM_V3;iY#sKgwQEx%KQP6I%@ z!mFb{bvB65U7Yj^LoY87(tT`y%4!DDk}Ky_A~twPyt7wr$olL#S#m} z{JshwFV`f=3POeI=7YE8HgeFw;xCFs#efHcH11tPBoURthzT;bo~_s@7ZOdug!f&9{Oc5$=e!1oWHC=qbbz^2H;7~n+=oe znUan1BlTA|wh#SWFz0(%j1^l$g(;+{XKMgxHs~502LvQlfJJB~@3~&Zz7m?hh^JZbC^0Kzw3{LTs+KjG+@ zu1@M{S;Kmub#NlwidLB)nRNzf84zJoLTEOj6W`Ty=RdtZlO*S%Z+W^R6fkvC5wu@uoexx^nmOo?P^EG9{^SY z7v=|E;3skliA}ZyqYYu8QiFL6`GFBvxF#~F4=8;+nF)}Qt-z4eAl$(ZCIfcQ4NiX7 zUp2lU8F?0uzal_x<{CI`b>O~Ld+iOJFKcbl8QRV*bu~X>?L08f<5SIFD9c_$zbQGE z#ydF_2$1Kd2t)QJ%x=Cxb!08SUcl20H5|jj8A^m3BK}b7!B}o9mP%QD`C$gV8~E!A zr4rx`o&VMSKG@vK%(s8!R-xg!_?2=E9-Pju8Iy*3A|WOJR;L}|8sPI~AxO$h@mD0> z7B>Bq$Rf{cCysekh0-npv$Ai}ulzY$+aKyhMqw_Cu@(!^Rx{-{TRTQ%pkXq*S^g=x znz1kn^5j;X)(t-1xGXlPV;srKHT}Iw$F|`Mf{#L%p;p9_+$Ac9TmzJ zcS7S`EzdbFP|7KEjwik7TWITvH3wmif9M(B{V_{->w(tfi>+_U!h&QaQw{f~# zDkkLD1q*ii7a&8@8kPoTVbhFI2vKHlS>EZ0NZxgxI03+{j3>$tk$I)CYIb78K z?<&i#Y!WL}bd55hyW^*7W{EHcTm>8CY z&@(j#6D??I+y;upTgh0Rg{JMOwn3{9c_i&1ita#obL~l6KUL=uwtC6fuh9v`_^C^0 zeFae(?0}80uxZM4%4d;pW;AZOf}#H2Iy>O>eQR|O8gjK~aaB(Q&n$p7-a5N@@0c;0mDUXjw4iy>`wp^Y=Ktd?=+uljEz zK(t?0VkRcgEH_H4Y5AeA6kv-+Z-KcSZfm-(hl_a~`2Y+dX{2R;MVec+U)MDy#50{l!Ec_%Cuc*WuZ5>gYraIpgrzIc#e6fi8u>5<)qv_0Y8$}#k z#1C|Q14E^?<<*rB^kb|I#%u)>=xJ7Vkc@i&%YFH@)x0s;QXO=<+E22D4F3U)AD zufEXa&Z_)lQ3joD?nDCA@d;+pqeja#mXE{q*lY3Z3)L?y98G7X1eWo| zMt0+L(3hLmM?31pr7V`+MoopmeZyD8m%8ee(>sP2!4)@CI0&K73LJ9Hz{AN*+ zpO5K(*s*VNk)bJ6|G%~NQA2uRoOPn-d`jDxhh&JX3wMyD699@nagg!;u|RhS#kTaSZUoR=!|pPkLl5rx$HoVh|~-72B2us zm6TIeNICFKmqS06-W-dog=H+Z>5*Wi51e#HiX=aVYrh zm%g&yckz%rLO|#d1QdtzXpFgx&8C`>RxL?NsQQ`cwgCd}U#K_e8sJq-XMo&F_jdhf zQ!0#U3nB(X0J#UnV1$K2XYw=nYOqlE)Og zFJ$jL8>D0iuWz|KZlPynq6u2f9Sb29Q+~Qon(kJG4pi`N89vXRY%*aY#4t z{_<8~;AI1&qRw#{f+%PeM&EI1g0j=M?S!Xt7b|{P7@8>0ui8#L_Gajd--Vat+e>)KbwMU!ONJwl|qa|j{2(`CXTU+(6 z-C9+fq7jKzT6?c5sz!BKm7rg0wPw*ojl1@!QSRsZJ%4~B4u@RV`}29fUgxPPpr;H( zo!J3~zow&}W%>IDB{%vqOv>GCZQ(2|XFGdEpLDV-WVa05ni<;B0yD$Pv90zah#=h& zW8oQx4+DC$A>n`3kKHhqG&RhTOhkHu%Wl3;FHh5LRnLOn4tDTi8Ca6Q$pvt3=BoS+ zUR~BIjLS;N{-oG@G8;?ZaHUGp!Nk&)T7|F*I=vO%x?Ric;Q9zk?q*cQa~WKf=E>G^ z5_RQ9pQPIO7(m&^DxWMw`x`os>Tv8EyifR?#p@;Znfo1VcqdQX3wEVwcQ1aF@eUQk zazT!0%vO;V*HG?_<|$GGIPhBP9?l-3=*Agi8Aq86i?2>EhZENfb+m$}Fgl%x=q{z>3 zod3h=?%_zt-e}Ty1Ey~=wybDtuwt>7WuN@7h*7a5%?(52mnCzz`LMzbBKWoY6!p>LW%jB%qNk#3Iw7@v+P+m3Q zVeZFZZ)_AS$auhJhPucomhK`*2z*WzG@@!Atw}>|kzetnvh70(OboGN68{^#4fHGh zDCEMzRQoF&Xt)2#o##p-OY3~U)V&pm(gFDmN6%Idg%uM5!c9Q#>p6=2woo^rMA_jG zqV_r9oia4M(PIOtO?1q{X(>?~0yf$=*=i$Q;=(mO9->87V}&zQVf4Av{ss4RS8LVX z)S-0v2zs9hf2j*qE27I3*N6K$xbSxy+|L=HJYwbvGbu^oevB6k?GuBt(GG%()+I;! z)h~$*;+W*xgySVt49eWmL_iVm|?o6dnU<961TXp2Wq?m87|$qxmFR__Bv1j(s*S zq|T2?W!XGPOzKDA9-vfT!-pEq0q4dPe(JCiuM%eeYXB<-vr5H&ct&|~*HdAlYWM0N~@JhBx zSfKpl3-i_gCpiO^5|c=0BGsp=mif<0K?d003;2r!j!BGxBdDxAn(ku@iS{1)IcA^9 znTtZP11l9XqoRhYRm}{xb#b5>hL|$=4+Zlm8vP+t+u%Rtx=5j>6#XOvOa1pmC3s)L zV~dlA`+2G(viMq92Wz63Vh)X51lBzpv2L{H8&&=IP3~1Y2J+zXllpq)54M5iKf-u^ zPtfvN`th@vNS;n1M%nK36$*a8Me2=^n5rT#e0x}LQwT_9ofuKfJdrj}ZpvP}ubbVw zId~pdRsa+z_g7~pjl`|J3sT(dcmzXwdEoQ$n~X)|i47r{&ti2(eC)h&&T@}&mklLB zibudU+Ww&xc~EZ<>CVTK;w;TWZ*kJB9RCBb;Iu5cNw6*n%=1Z?Es>4c+qX1y1Hvd9 z6Rk1D;@5`LH$2lr%RgIyV^@mi0N>AR{Ch?YLI;N8PvvM-KDnFI>=`e1nzeYmf}vRD z85t_O9^Bx4&ePv47lVI=l*281iHr$uoJO6ohKb`*OK9RnAB)Ptr{XuS4=9^xRozct z8zDv#)eXK&x9%A~v?Vry5SZNBi*PC1a}RSPLS{C!1T7$I#A@CDCYC!za3bi9qD!rF z(b)fh@rg4cX|?p#9OJv`s^z~p=Q@N_vax_sBLQS_?n)ieVti8o)b5;Dq&Kd=A5S-j z>Gh`{2fgn2)5g_K3_H5p=Cn!btQ{jN@ilih#jtQ2=*N|b_bUjB1X*YYs0;GfZ``@& zk;lmje!c_qyl^?cTJF`r`J#KtCxh$8mG@mgpzWk=sf7&(GmG(U>EnO^y^yQ0{GTJM zjx^2c#BbB^1Nah5Pxz+{P5j8W78(-}$`HIWS?zV@+QleSU(J}h`&5s#Gi2>&V29CI zW9|eu>ICBcH-Q6{uV+U^WroZ{`B*K-%t;1?ssrP7?D~W4Vt~vmYpOn$Gd2d-sg)Q#HTW^8u;C3&gFVl}g38xNPv1;;gPk5Dt_3#X6FjdcX> z|LdxH-^#+=Jr~Nz9U$D{E++K5s~AM7bL?ha+c5+pIH64r92xdr^gg!p z`bY#^OTkC1M@;8V_B@Z(`k)?3cso`#oNL#d6WeBXPVbbe_+M^3KiK`DPW5JRlKmgX zk#z`dYm(YdueFhga5l5{$`DsF=n^hYdl}h8Df);VueoCwP?G*y#*SZ!aZsi-uh4PX z%i%zEJBAAYZ*K;?eNy+UpnAgO@lFiL1h?iE;H*qfwZuvGS_T8;Bl-^!a4IAZP6-rE{2(HpBhQE#27R;(B3n= zblmVx;aqBQ?~9H`AFci_v`mWaxnEnwb?xIXcgdy6Dw3avZK=`QQKA>#inD8^C)f21L3j; zZVwPNU}K$UsO|{8*pKpyj@*C6V0LW-Nl>kX@w)#3ugkJCgCc?cZ~1U2e_lD+YQm+& zzE{mAB|pfbZSe?FGxI|r=)}NGm0sg@FXX8YYVo=FSqv93J6P9XWyVaXzy6q^+LMxsIOIOeV+v+Zho{)T{9pfBz;O z;ak-W+%Qd8T<`fO7i6m$=LZkr);HbS^g(-_As>e{N(voF*-@88<)eG9Y^8Zj!{+o# zkFxQ{^IdAdWeXVpazAEyLQSy*2Z0VYyU%IUx5HMSHZ#O`y2=O_8kusGLpnu6P3j2b zmB6z%=k@*RQ|MX$khcu`}Dm8 zm5tOC=ed^tmTqXt7m$|RZ?UPES@cPm70fLTV;|u~x{XN%IpS;Q&R^AP8xdb*7U~_N zZHmkqYt|NqBnRV-{tL146|Cs1n ze$G)dIwq>Vo=aa_8PWM!bskBR>@pPjdysU0-JLj9xD_QnpQB?PiXogY6w~Uq$vObgreYFKM{Q1ILpk8_QF>o9uLOo!Aay3Ao+jqN1 zX%kF&XTQspey~Pn`fZxrM99}1YWrKOzZ`?v4uE(ct~$$Y6U1ee-wbs6@G8!%eqvmD zqP!G$gx(`Q^=IASN3-#yJo049O%F=WYi-^4(sGE%K&XdPOA=W92fy5FtIv;15O!(wcFr}~YH=a=}Y-4!04 z_kKTe`zIVE89 z&HFSS8HYf)8~`7?I*U0w@vZhR@(>`~GIJy>zffhX2Os7+vj?8r!Ou?YrnO4mFF6i~ z9CghKCf**j&F_o$8dk%cKHM+-x714bM(fd^r+ge!qChyAogQthOM@2eFWw!+e-|`o z>(-I6<636lWOnwQipA5QBWDo_HF}mWlcOzTJD_ZKPPd`F)JsMC!|IGnY{miPF9SK2 z^|6<}=sr;qr&%xMAu&1{qoQc0$ z`!20SaZKTW{`N|%!G)GOR#jy<>OnMq1h9IPf8$)6JLhGs^>l&9HA#XCKFp?*%6@CB zXV*hY6Nfi#n4C9E{ z5xzr&+FZ}KCJYQ3THVZ`Cc|fIn%N9oqEnq|?q${Np9{>FdEEPN!MB5==J}jv zvN#QIICLflN_g0NY3R&3C|Auc5QGZV^Xd=u?&>FuO@`eyo;$fJZ!4P}j*os&PE_DZ z-06?dipyfw3p0C^&08kHYDfAa>=ANU$1W>5a^g)?&r1{LyY#};rYWFVtS-^+fbDg) zV_P#0x(Q&ob|bO^Y`HWmr@Qsyl(^bS%{4kToePAcZlG%uX4TGXCHiDji29S;AV%u; z(*u;yc?GI#b-)xVb(JT@;3;EEQL@nk^3}SYv}d$@_DJ{2`Drb&=aCkc^@IwX6aU3o zRB*H6xy`vhF$0-lyj~~D*6#2hXy_B{3)y|+P>Z{KS!M9D)?UF&N7vymsFEeySn4^g zhDi#&SWe(pz9zc8;-Mck|JxzZl0qFZFOeLTcqpOpx4vo@Ei zq?O^n&*8rRIH!p&woY!hulNt_jJ}1m<6lVF&B6*e4*^81=(Br=wMpBG1N4V3S*&t| z_MT0pItFK{aK|G;XJmXo!>+pMq`GKh>Qcf3;Ww8-s4(Xpc?l6gdYog?)Wh=>GW$zf zShwv=U!ABEuM^Ashwo4zw6-@YHUGpqG|j~CIRNsP%0hw`ANQmafOE~+yTIQG0lcj4 z99xd$=kCmD`SD_HZ^a%_G@^QiVHS~BFJCvM@WzyCb~bZNyS9AhS%Cp*1(H+*$}JWj zP>Da30%y3b_Gw^8 z7H(+-q2ApZGxOlTTcJpv>>XesUNb_?GIk-CPdN#oEcqKx8G@f zan73VJ4%f_ZxXoVQsey`wK>^iUhl^a2nCLrJN!3#CT06WhiED>U)xpfoB`MXf%Lgn zgicaAHaa?Lj<(#8lIvWWfiRcKHv#LwLmK^V=RNI-oruk{^SH5pM)ec6V!ya7s*_wBlM?_Tn7^dan8xmiNOpu!h-E2JyT zb%h<|_{H z1@LF-Hse9&bABx3_uiWw!%-2RxGRdTN{kE1tjVu2P-{dzlpgB6OV0quf7mf!;`WQDTAj`F#=wL=c$Db_?h8aoAt-=*?_)q`d1Lj(jH(-Hlq2|3@mjoeyNFu9g4*hf zFiY}3Q}?D$9_T9n<|)kvo9YOE-r0*YI(^u$!^^{ah4sqg5E+xxKEL9jL0mYqGuMA0 zM(OSFHCAKRaL^+|+nWNh8RE+Vc9jFtaxZn=2GyAM@&S&p%7AyaVDY}01>bM*m<|tP z^2&Wz*oH`@X5+~0|1FETE|$zJO-M|S^Q4_C=FZ74F5mhGd3+Xoc9K`lFYi+>km;X= zj)60#8d!(~im`{&GupQS^K#J({iOnTc}wa4K)>8GD2%WyMGCA7NvnKkfYGx|S&L_X zrbY@1vSji@b4DrBuv*wV)`4&TZ5?~XD~rlQc{%&0ONzIWX`2zqGN~9Xg#iA3ciwAK z8;R~+vqW6v`I)-s+M~2sLcgxFCqr8yi`S9=N6memnynf}IF&L3d% z^O{@Tzb4FG#<%PE#AuS5@!u~YkB@IV9_!fTiiV3>I%6?1UE~ju?jpcy4x)jJS{6ZRGH1=2=WF>x<)lBZC(at=j6by@mW|8U2y{x1wdbl~B;I&|}~;Hpbt?8yDQae%A*1 z{QgD7G9~2|!QGNpsbkP0Vxdll%`QLOc+D#;1O(X}@^+ECaGEcrZG1&W8*7tB?hVg{_@(fW)yPhxcFs%v zWsjBoIkI67((EHCidIR%iNNv02dJN3u(x|9i>lVGUh`0Kj(!IWVt*$d$xHbj)hOIVaC$9Ws zknqbz1W*7?c~Klt{Nk51N+3tlL%vvvsOlbP>B6mjhX29Oxss4iS*s6du5(dDF?A0` z-4Qxc+f^rVTTY5@N``FNl^>q!2>r%rXI>S0I51ZI;kwWCi`ymqTc`ndf^y&pr7-3c z8(iqaQ|c`%bwQiP`y ztF-}3Ej&B#X?vDXj5Zgs4ApLMMXeSmP-@x;8-UJdpLw!v!=AiLpEqR?`I3;u^5+wD za;WLiNZXhQxLdN~!1QLqc4>d}^4aa#Gb6K<7LKl~=a!m~y|0^ZbPayR4*GF+J?Qdr zeqWA)aE`_gYzrQ)u1|Q*XQ-!?+U>`>T~g}jugw~fFD}|tii%QKfl3W^8RzKL?@IZb z8YU{G{oZ|d?v8(&4<>LyYNR>oL?@?P^P*lk*A&xY8tv}-EwpmM5n6&qEEiJEl>L^TVx~OM4@?W0BOf7Ut|iqf!e#W} z<+@MPnoV!?k4zyTf7WsQ^Co@~KHzk>K}5jJ>T&;~QI*Ojr*_~(NjIz812W1h1vN*= zRKWjG@%_v!&hw-T9e3;W0QpEth^d^f*!u?rE=uR2y3KVmZ3_~$)fH^7nl(4tIq+(u z7;!2wpK_MLCt34r^FP1V(spJ*df1rj434@(ktv~;l=;^iWa&~SJyHZ(a;iG5Qsrrhm!^`(o z{~cxSzVP6FZSx?^2wox79ARv2avQDDue+e~<3@AqcRQ<-xC~avh?%Wz?Ah11|EaO!F8IOa;^XVa{>}Op3X?CwQx^ax|6b~no+n^cktrTk81ey zfCGl|mw}B>PZ4M?%sL7#oK>>8ZxJv_LElRFOw#y_lAj;LUxLV<+aXR*9fDajYoMZG zZ#e|ztRE-vVcaJAIvyHTfL;gO8#4UQjW<`?nyh^-60CK?KEH9aYR`bf76)_=o0G@lo0 z)0D-X$HQfR`b5ETM3l^)I~-cjeIp>0r-ux{QifM=Y=C9;-Xs|7mGE>H1$fDBN|k}Q z!?2hU!{r%a>SR_8EYHIW-SAWI2J78GJxXRe5NptL`u$?HcQ{Cq-Yn1BAI=uG7WCrl%YU{jiZITAeFk)1c5bZ= z9?%kSu>F3|U#8xrvC1$_Sz679`PP3R;ai9YkE5ce6qvte8t2@s%G?V&)#oTCzs0)M zEpvvg58X21{a2dUTB+`==1IUig^Fs7Li_{UX)w*dkGxbaC0;1}c3@_6hi`%)=E_*k z-Y`jujk}fq_$dki0dWTorj0eJPJGMr=yL0{GreVwnyQ*XKikM((IlocCf**~>+!hG z(-hFBIrv%{`TOenDORco&24h_)aEyeRJYZfc)2dhrr#;(f?2zt`x)3adahvQMxaV8dQ|R?vuC#2S|9A!L$5#5G=Dc?pQxbw&9%T4t z`q!M0gEx?zT!&id#Mf9w&|r!fiTm}k^5U|E=u27^>xOu^sX@=QF~6ru+Br!w#PRH0 zUA=`f>IcuAn(W=*s3F(9CuvH5H*C@mM)0kqr%vV*+YFn$4n)Nk1MwkFwW+5Rtgz0{ ziVAv@i>lxYC)4J>02b*U&-X&%6!Wndq_3f6eRQwc|FA=ER6F#m7lUJC$F#x>q^@4X z#5Y_Tk5qgF&ypeP`wKzFR42LDiG=2)yoy=gN_vJk8vjEO>pp_q|1210gs$PX&rwDj zn)ZX!@0Xr8DCjc&-PiEtc@kuq(a7-Lk2fpakWM&j5xy94>tX_Xl)&Q;fTqXS|ADZf$KH zMA*n^|8224WoVpzXJH&Ib&`I#vO%le=VF`xYR+#LRhAfx#*aQtzWS?~bc5G%(W9+< z=lp}gA5r6PO>;U zk~dhIw&~TUD_z>^@xIxvuQ^x(&3=m;RgVt5i9Q#DYL8w909ZnN#FyTl3ITPv|3C`T z*s2e#&Kb2glzA~jsn#KD>Eh`ZB~HU9T$0M6%zjm-pfwEkm^)8W?mWS;fKnEZsIX&(4&k zq2lE{{FkYSEqz=2OqjE#?Q*$}%`w4^iT|46IEz6-z_ca+4@i?RhA$HZ_KzLErl?AX z3`J$T)44vKZ^v9rC|j$MkpwRXiphYA!|Yshx)952LoX&0Jl77{t|iyi^u)sti#z~% zMh^n$RHu#IW$Sh0uo&%g=iIGZrnKs&rFP6!mj|(85yJNJANeq}YK~+nIFlvY(||WUYIU8M0=+y!wDc`^IOp zMOV=zYnw&Zy@G5Ta-K)TT>>-fJ?-z|d;(By{by^5LGArBx=un?n{zjm+hqipkGnAd z^k|YE4`i^#l|Kv6xyvq@Qj2*j<}!rwwEMIuOFD_YlKaYB6W1tfW8``iD3 zTWIOpn}L(kA||cWo8^iI_O_rBx%%KY_Zu(#Muz<#(mi^=mbPBW0f{M)?(YT!@J=c& zaja(f&6#v|&N9hFBZ~>gnBvC>`KmyADJCT?vvaJIJi^xvyPtIvw2h zb2c))?PePCU9YUJsH^`yLa;XO;NB1XJqj!FbFCBpgZs-} z8s?L`ogF)LV*T~fcB|(+qss7tE?ZHa=Sd4KD9B*#-}H|4E;a^VZtq9Vy+hI{NHQJX zD>b6Ie`@20DrK{!{qt@Ee3(1o4u_o?4P&E)wHFL#&#WH**~Ism{EcbGJP(AUjbgB~ z)YJVZ>Xm5z6tr0tM$gmVCOUEIQ;A)>nx<#^e<1i8M{0S_&BSoqh)=l=yI;M72+Pkn z)sDcy6a&GYw9lyfDNhvGYb$omCqNf@gPOKAiNQp|HHmjD|HxwG93H0DUufbfk36q* z4pKQDfvT0No}=%Gvs^&A8iOiBEjZfwkGXbHh)<(+mqxW^C8$`q$fHH$ynq;&!(< z#L5jI@ANy2gJTpr(45$X(&@-5CV4)Nqe7K5XRqt_$cwWrkhb{q2Y@8W>SBcSO?s2e zpi!gjW+IOemccMu*Q~{2 z|L?!IahR3TS)Vp5V-AN4UviTbZ3=o_eCzo+Eq<%tvhg$0x(8PK5wfM}t5_p4$+ZK> z@YY&I=jX#FhsDyB;Fqn-%T>5Ow#2wzbcrf9omwJR3Y-&;Np-``E8&5RxS~r=h`> zInK=ZxqlR!wpds5CthS9$sKbH*<@Lb*QmUD9WVBtA`i6o$bEWdUD}pGr?*x%VuvH5 z6YeF%Fq#>5NlPL%nq*~`%Dknw?4cCw z+Gwk+>Do>5|D2B;hcv0Z`#c?`80enhqBm^BT1D|*B#`r~3Ag7+?*H|G(HZdWGKEX} zDFS_S1DBu#s)^}Ab8YhY1X;xd%*4tPeZzYM5Dkncom3AD=xywn6JsbGd?&0_wZP$j8IWyU^~{nX9EKl&qKu3i962${u&Wj^GPS zzaC*PcEs9O)IpvJ9sWXzFq^$>?+Kq1xZ&#PzOn`6et+OvCp>naT?aeHeW~ z(aWE9ckNMETdN1k`IKSve@MeYWZW;uX6Bm;hym;4|c3ht^KKlnB@?B z6=!)k1rwX}N?Fl%;h~Q~(jVG~XdFpE%V*-wZGJs#jfx?S*EK?6 zUZ&NKR1l;W6+ZyXFI(f*Bz%Opg6Zgq6tC1YZQv2c1&Rrp3#M-4_s()_V4F|)CaW)psY>*%kyXp5Jtv+JZyhEhmk$pezYhl@Y{AzYanV5d>wiCdlL6PMCK-4Yl$0Sikgn_LSdrB9bTJX4y+A0;j}X(h zL8V*L;}C*~c`g`rWB?(oNGlB-R20(?C`+q2i1C!0n$e+SfH&VlaZ}`>NxG+aWvTe3 zdt|NyQhPEG2#bABiki0%KDNKbHJD*<1^X@tJnBZyLo6{I>FgG2kTUlUeYEY2-N8?3 ztA4s|at+xrrd(>}AD+dP6`_MVNbIF~PxCPi2_ZbAY1Oz~1AOm&VesY%TK^3qT^WC(N1%&nO|RtBs(=kk^rC-)*7D1#gbm-$Hi0>4Q8*1*$TBhuL@8#j>v9ZY zLXh&x@BJ_i_~GEwzeKXRdfBu9U9m&YSmu=o9)lR)8K9}1y+Z_)|NdxAMeWn1VonES zrBJbr55s}WEr@Zjl>waU$iwQUD{%>JJWYv0ulzJ;mk!fmt7KEf*$bG&qH6QB8K z-vw4g!C&9_Tc(^z8|5%Pn@}p2f#Cp^L{!&KTy#|Z{Jtf4J%6?4TkS(nmy`}$6F%=s z-Tq1JaS|>f)yS94e$V!`pg6?ZS~P7)3Z;?koJoaY5s-$caMkvi>0}$dw^xEhD+ruy zQZ_~Y*r}uQGdJpZ`zy@a>)h!}!i^N|9t2bY*MwZA%Kb2a2Q%!>*;zZjEl3hZ(#mw}+wCApMvT zO=7+RDW>D%0fCh*NcqpWsD8!&K>Fi{CST(>h84*K@JiRGb$wP z9-=T&eebt9W-+i+ZEft2PUb$H{XftF3j0YInc+)%9Pot&{C}oYF2Q0lXLgSHg1?1U~w!zOUd895uN>> zL5=bUFe~b%47__4WUI&_^7Vgf=~2<;i+>SQ!2ofM|ElRoCwr}9!!O+|P9-&$dQC)g z5hALJzgW7pSf1Uw(oL?xA@ptV&N{n$Ax@nXk-!u-TFqvu5=t8C=98GKk@>+jE3AHB z#|_=Zn!cO(WNJjd3ov@W(;17Z>t@TiAi!4F0S{m&hRu9xUu_E@vw-m6GpNvSn70}R zUBnpGOMGrX_66O3_5Rbk&AODxw=>PF*&}h050|JctcppZMV6f`!v^8n|C{5~HcH>$ z8;yI6M4}1$sABuOY&@EAYHlijA4$q6k(s6?t61&??J_@t$%J?9WKKNqA(UIAJvtc~ z;lxWmE^ND1C?PT_cxPvnn98eWOlQP9dfH7YbzfpJ9tNGE7d?)#?G!^F&g$p(f(z(h zx^Kqa7R$nXY-t2eBM}P&HlqYm&js&bIigcp*I|jaf~JV#;yI;;fsl|!^%R{*VB>ET zpETLqNYR@1Q{@uo*0FMfD>TcL4zfB<-)1Zfva<`L^Q6t~pMJ1m#vB?+?Kkh>bRLm- zDZyWe(Te;xpg2L>9VK)0~y8^fLCrPv4KLr4->SZ9M^xEB@8wfFY^XPR7<1gy>_2 z*O^6X>zA$(Yjq4IYwt#ZScU{+gyi9SOAbQbh>ZzOe%s%x1tp>4maUA*!;3Bw8-0l2 zV44u1MB~dUkvH(v|KjdL?Kly|;b-PCn%u-6^*d&*!M~HuSjpiPT z!%XbT@p(pqH%=WOerl#UM-X&AVWp(xUi}zb9!gpsJz&%&f7>-kt15IV9fIB3Za2qV zn6K4Rxb3VU)62*kS$i5uC?aOuwUrut3V{UGaZic5izu!g3muJ|?0;rMFR_T{3rH%< zMC4(`2UZ|m6kxvU(j(J72ix_IZCW;;5<}~~SI)xLP0XU6^?d0Q^|H0Iim4SIDY_>F zAdO`V2xgzBDu0oUmE`*eCDVFg)(f)~Qy+C3!TuqM4LV1qu__~@H;BZnytDJQkPZ37 zYBlkOa?%e4JxWHLs-~JB041mBScw}5M1tED>;WGGd#^|kW>t=#^bKqE2UjesD3ihW zHa@_F36Pta`K*skebw&g$R9xKCZlD+aaE`3B2i~X^TH^$k7M=8KPCf;nQcQfc}@wz zh1p^{GWHI)t0eFL(sZHX9OR1mFY8}xhlU!T75kx@s2?m-@I*4D4%jxI9;k#0KeC)zf+) z`{3`xQ~y%8btAcMUA^9*#VyJKcxY23@KB2>)Zn`~X+rLC$a0r^`$wf)@GF#s;$UAB zVdEb4Pa)qRawCnOpu_7R1Zc3%SP`FTFW^r0I$?LqEGJ+ZECcfwBdzK#Aq$-=2?|uU7m4 zX&YN>MrBiU4&$Wpl&bOuo%b2K8nF~Pqn@*-KkGHgGg{wL1!^Q4FEVDvnX{~{Y>gj3 z8r1zpvZLxm#*()+H=s$;TNCwcs{A9Cy4Hg~{yrVXs0qD3d2*63g&0+O|G#*VkPY+( zWKLJ@%7}H+A1j6kzbl4o#+CU-9s8};mqFu!L4vit`)^l0SzemkJF%b@EmwyMa_?e9 z7N+)Vlwc1J@l7P1X(>*HO|0Wod|a8@gGgc??@^NHz2|eRyo!jI=y;7--vtp{E)2yO z>tWEWnfivX`AE$WBbxP7>$A}yQTKddDn^(u#JFfO7b>Ir#^dAY>j=| zD<31B&w#tpPe+)3%D4o?OrMwNN2O>xOJ|Bsd)obg`KR&koV@qm8aveAj1jqZ&_=Bn zl)I_CMv(}Us*Z}f5nW|Au*@`SY?T+|nNWS@ZT8V%$sxJ38|yEOHR#&wIjp;9$CzO( z7u0#NWV9J1yT}D!Q_b4cWKSC)jb!xvN<|MIuj)xZ5(dU68DOQ(k1M6)L94U-Z$a)-u_o{aiMza$L6`p8s#BvZ9l8>fk z^3AfG6Oi=!cq$n+h3V)%8EWxI)E9CFp4|nyaV?-sJrx0&UwW(hpL%lKEb`OS{sU>c zS07o7XIXcol^-ZU6rlbcaXE8jDYd)v79*(AV#`c?d3A^v(ca(8Dbx*FSfX|qH?`Eh zjRE3M&-{guoW^(VO_T}DSba5)3A`*iLkrl}MMgKRltB{OVm^f6%8yD9i>e_(Zo3CctS{#Kx>#E2e&JEp^wUf z?otx3jFc|~QiSCX`9$%nET9M~Y3VjjsAJpYjG{mI@Xlv&(le@7M3bVPD(3fB{|6ciT){$0P9$}&%h~3n%xKf+ zM8kWHBdpSmNkL^%JaZ8l9@o0UX_Sr8L;Rx~G`5n~>_<+*g09GG-dVsoX1fYWic%+J zD;P=W4jhc~`z5*seyJ#?m=CB6h)s20&&q*V`C zt7h$3=xLF!Y8NwQr(SXaIFhU#^l)gk(5{+2Y{sH6H!Zav-z%o(cG(D9o&z}mAMQrf zJ6p(DhTSnyaK<4RbXHS!p2fyXK#?L5`W59FgSlBaXPjf_1FP&mgc$B%>d4`09N(m5 zK)YovQQ%24WUXL<&C=!nVpqvXv)0Yj)5ztDvx94K2HI-01>^N3BN<@YvOD-{C+eg z2ldLs^J34?G=TV_9ljcss`F91l-VVI?t&uqpup1A%9vIJDq5&w7(X=Ta5j&fKzKZM z#L9HFnow~84x|q}u0p`|D!&YB?oy9QNPmnHwf&4&0kJ_c!oOA799q8jO)-)DQe35- zO&lu^rk#dqUFUDJ7E_OlS$0GqYh`a-w+VY-W9+PP?d~fPB-{2XZPgJMm85o zvMu;`toEANlVydH9eFaNYp ze!zECYR-obeV!GYrF7CnYFLa2(+mQbGf|}b9Q)Q+`-Cgm-L%rS^y9nw-6*rm>4vQx zrni0GcC(}kGIEUk)8W1JKass%Nr<|FLpoZ>3o$g`gpdj^P z-@(=6FzGRA=|k2Rj({yRn`2E`l!Wl`KXV+8AWX^F^B9-b*sYL&;Xr4Q3bxujtR9N` zn|}85OUUKo=$}TV)aBCb<~VHwoyO4fth@Q?dr|WS>&&AqywZ_}?Xda;wsbR-f|c<{ z0czynLn>^ouVHQULJ2f$tmT3k(k=lrn_<_wxI>1Lptz#{(>kzR-j{W7CR|-0X{r zIqcYK_8hxYo(aEDnUL$6V>Z{2JVH?~+k3E#$Q3pJLJOF&jCab;kb(0w7wEj~=hqTI*sm zaNgP(^~74l0Y^29$1L52$hE0%l%U~@8SfQxE!)3Sv>ls=YwMb#t6-HW>Wuw7;h|}cCA)lRghRtx^EM$!0a;A^bDM>QV`S{hv+@p zKqd0#zpTj7RB^gpx>CLHx6ubXU+kuK2)#(ep{w-Z>zhL>EDwTcJB`0SnTb=5DWh5K zUmejg-7F3~L{}W-_6*g+;I1{F>%j46AJE;DS>59!XvvLCt?N~{xkf*(F0hiaYpQ!F zACb0Xk&v~XlsOxBq3m$`GD6=fwpbOH46|Zt|A-ACXS`zaH0Vhk-uF*Ob8CPY6<=r0 zK6nPS6BhV*m=W25Z{-Kf(oPfn6#4HZ&trJ$342V1t(FgCOg-%GXNZ(3)=WOv8lCzu z6PHgv0x-^$Q8JMov*RZ1NnCd5+nJV$?1IF*RK%@E2Zqnu5Y8lSKPS$L*DpwxN!E*R z`o+RLQyTJN(bk_7U%7h`8oIMPDAYp|0%&VgTDJk8rSaG{t<3?^`gD>~J0O19)YuRV zlgZ`9DK^Cug~!~Nv!@d{r8^o|hjsl*We2TtY-+A~+9`C5W3_7$W8ml&v0L10`C{v1 z5_E<&OZxS~-{24nRJW9vcH{}QYPRChJ?=ocfKhVC_+%Ts(ouySpoEP6y~P$Iep^H` znNlQGWpYdTz9vi_%VA9ae;J5e_7T@|wlSZa1Xo(Wr>5`cJ+=QpZuyb#^{Qe~tl6HV z@$2#w_saQ6YpNW9iii#xo0__=1P$8^=*gF>$zX=8Qn`n(Hl+A0Xz=7T+Ql z>xNV7JE+DNvRsNFc@4L5fiT$LzvI%My2ipemh5xk5t%}tFk}KA3cM@^=(ISCZw6yt zaf0^P)Z$Mv#YV2d#8AykY8g`v&$b5USCs*LfvB$b&y1wvn>M#RCb0huO!ru=HO>0D z#I%uB@}vViY59F7Q!@kQ*n_ehy>^h)!xB7ik|mq%%tx+;S|^HaGcrMD$}uS`VNF^v zUPu{ca<~eU%o!1VU+5gi9=g7f%65+hrvF<0Q8zf%XB+af-W1*2f3kzrkv*^w-N0dB znVi-i_81QIcT*4^*JJ!84|xd3CXzF+^RxERj1El}>p|_Y59^!?7QT zmxG_YG4hu1hR=OSX0UIeP4K!#e?pGk0am_QdJ@abHDyEh9hhskQv`>T>ivb;_#&H-`O?Cqm?zBUIW}Xl zjT!aZFNEARg8G_tV!mgu>ehCIWVFr>dl7M8XOP?9fd2 zg=P>rX#{fi1jfL}5lELXyw@W5eX&&Wj*W+t<^V<17_x9-xuy2asxx~=d+gFPozHD_ z+Qz9>8HW@1?QDYxodDOVi7%h`^1k{dH%7*3XBO23=7=2{XP)Z129A!g$=ui;{nBH& zE5L0RZ4x)>HR%EPxkMm9{D4*cC0fh~QF3j<{&DxTb;9493@x5m4($NlwZ|pR1;qu1 zx4-3PAF2!V1xGYxJY^4o<8^o+0eG$dKqwvFhYme81Yt9D3bQP`@9;05z>&_#GlJ0^ z%>;4V>2{x*%ybi}-2G7{_88m}_Sw!IiA88UVKBn+f+fpUMD3A&l~MnGxM zR^ON->+r0v2S8QB%fMCnIUG=KTX%w_WbK{LMg9Zb2fjQu^zZ3ozj-*h&vbY{$$8?I z&6Xs|vIky%9BsH>Qq1-~%qKvPIgs#?ftbJqZx=wqtx6- zrFjH4D3)6C2sgR{f6fzw&h&BZXF0Xq4C+{p-wB95fZ76|M`+&$A(NZ-?fdNe?vs*P zNk_of!h-YhV;vq%4`JpzPl7&sl|g^cD|rq8cZno0Y!!I;0RtaINB?%aF1WCdAWdpNxVFuGmP&u`bs1MnOh{_DtDA zTkyqS#%FQ5(M=z%1v2`zGov7~dUEZ$@_wPflwqS(>mxb;@#2|uKG%1W5IDz(wda-> z-58ICP!{;|M00km@QmDbKY7?xkWp9rcVaJ~ztbe&<5iG}-9za2U#tDxp zs+y+QBDA2>b)JIEZ)^dMKH&{i27L9aZjmS}e%M@YV@tn)$;}jN)jUq6H*`LU$~(6NWZV zcmZ6p`VaCZb+Aq;t~yl`#?8E)MiAJ=bG zcJ{dHKP7 z+^|&ILu%ZeWw(!W^Ok4KfkB81qri)7Y1t+S4Z3fqa?m5g*n->l-hX2kthSDH^6Bzj ziS~n9Ui^h{6z8e&f>_w0vFd2x`J0-Z?}_)lU+g6hT+_>3xfpD#JR)CkqLnI+%@1$V z=V+0pdi-q@r77yD4JOca5D-@RQEd<|u1!Cv;E9LFRMD2beXAbR7-Q=y#@YRUtlbs9 zqJ@9xBc3yV4m5sm$ST6GM-)}sZLQK=1$VEjA=Wj2W@GEiEcS@eGA^F_NQd-=&v-np zFaYw&;m$N`S<(Q`KJ3Mld*8HVGL^dEYA&TG-Fwk~ua#u|&Hbex6h0_#earx|CE(PDM({00yWx3=-EybO{yWm%Fj4X34Xx`UxN1|?WEDKFA3*%d^EMXQgBi#|cuRx1fVl2Y7# zzGSk$+(2<_E71K>n*QCF9!J-dYB%n~Tn@XR%)Qn(xgg~4kI;_6oc}otQ|Gt-houF6 z%>hm~$n&L;X+o@zd=Q&q$EmAh>Sp9zN{Ce0dGSdBt$J&*>Ft#&mcU`-<2AqW#~3(A zW0-{}!85XILs{&rO8xL`?D-+=(YRKLX^viJ)0L0p0E`ienu&;@IbI{%3myHHbWrNj zq$*df2k)?*fM3@A2Qqon7k$b(M=Q0@M?b@tz$@$n$WB6e^q<8k?~f)(g0q-&VC}~- z_BuvV6Eu4!+-MU#rHnEIe7HQ`o5MLOnJ6TzM!(z+oRuqrry>*DE7wtIVdZe z-JOzaf(Iqps1XjU%+Yw^B}gHdE>8DHz3)Y+%XNFtyLrCi8E7Xe&nL{6H(|PPZ zyOLvL37NdW8}j*C59|xSN5?boQi!~nBRPZ66F6}4jreo1skFf07{EX)UC7Npt>-(! zz1WkXmR=aa&ZBqn{wbj2($BOl_Ga@kDPmO-S;~{jEOb}?mOJHzGMC;msLLx4If8sosAACn z4}@l_?yBeGIJ8bZ#&}?f;A2lND<3PJp-nzly1l5dMlR@HQQ$k_EDkt(Q7ln|EuoLE zHdJFj<8@UkewGG1aP=B;ebJSlPFp?pVg#V!#u@%2SPd_}O~cu-x5G@}Ja{I?e10gt zC~Y(yU=j#7+`={S(4)c3drC}I5rv=hJo)bGVG?guvMQyu$_zrZbKK6b5z#+No6q%a z`9e}{S;e0^+%r#AO&V!`0hCRy&s6*#2+-k%YWvjF%SLBg9_avgX}R z3*L0)8nb=h_#*kJI{7k3j15?1_VFZ3-SM(l-uC$DrH_n6?qd_VeE8i9-?B z9yOvhi&TKnV2c4If*8>NbT*QC>RK~NWX2GV#Gp+-5s4Ny(0sr`Bhc!~KFHhHNuU_` zK2Y9FH7g}C&9p9ZwoykcAwwJXrgxQJUAAK32~4+T4of9JbT~w)gIIQ zL%|tso%ACsR9e%A*5vZOHZJfybi=$xO3au4BrYpvh}q*zXoop>6?^e)p|Bulo=Xs$ zD8I4Nn|T##=o*I(-WNicaB8g6%-vEH==rh%YYZ9?u>Dtgz{~CgA_^=b!z;KukvlFx zw25}K=~aiF2l!s$C;NGqi0WJh$ylzwNZA`Xs>B4RBpeyT@sg@Vti)!jw8^aVy@1Y2owohllr z>I2rN7x?)7-BH@)19O`%5;FclZ7)PDQk_-X50-H<-S!X>kKdzHvTtL}zXdjscG!*P z?oYCDCBHtc!hLjV7Y|$n_Ap~bPwi5ToOF;#Qj({Vs}ISzIjm?$Evp0iCupK*>?#91 zho?b;GFpook*cgK%QEUg%p% zW=YesSe8Vpc+9NiCCO_SF!e7!?i!<2xJIOf6F>^|d0sX!N^--BMPQ}{rkh$i%aw!0 z9k_gw|Li%7(=ifa6YLRF3J5(}XX2>#ZL~`fm|Ah`P)-tid8=u4T6Yt9*?alr7ky{h z!c9ca<#+2CegW+_&D22u4W|CJ-q)yKW4=|r>*bkGZ{U6Mb%{3_f%s3B9iz$&e4?zE zSunSTpm#C2Ee6iv&=cTM!Gc$!Oa5cU*A$^?akl2-d*i}Br^|(6%7v4e{2To@0;_{^ zA_1wAM0V8GAnGS24)jX{)eRixu`@&LQJh%gyh2 zq%SAg3q5rHyqsI=pbOrc*BH5Yudk$^^$)BhYsT;2ja<~$x{y4(8^7nC=RST@Z*}V% zrs!wS2QgDq>sTwRhZq8qm4Juon;K;Yiy10z~&_b3Nkalh`ZLR zwEt40>y6Z&j1=Auu3-flAa zEJ0|@5GuKFN{*mrlBqhz@Vit8tZr{Q^773BwJM^+!GN-X ztFCvVGa2Tju{d&M#)9Q&cBxcNY9)I;m*#m^#8_@FQ^ax#fA>(J^3mc0AQveTx&h>$ zB`5NxD|ieCoSe~jZXYv-(&*-oU0+`WLT&!;B|#k(cV0eE)9^y__gOd9NJf7(&X*EH zkZY~`n5~|31wdQ-oWo3k2l{Z+SxaRwtuV~tJ!$``Ri6Cq{s ztozZ@nDu1{&4>_r260O?<@iXCw^8fIIBPqMhSUwyGHj#aF>AE!JjaL;b$bV*Rh2K~9# zKzwe?(ZPw0ahZQNKkH(DJjojUevH>@U`fxnPK3~qq@TXQ!@Q%}7qol`eU$h)k^6() zjbtxRN8cthk3-tCWZ}OV`)ImW&v!4Hl_xK^5}HK_@yuO;c52Em*5gmf}T`)qt_tBeCEJ20!J;V;eQC?S;qf^q~yxhy5F1} zX7mj9*j?oOq!&qqy*G!+c*%YER^|dgCAqS;B@xO1ququZ_tD1q1_WHowpOYV{a zfUu^f=uIrq_@<#LZHs8GCI_2q?BZKa&_(0u&CcSWc>Rao&%>|RzQ4x#R-w6mJRk5a zMFfr5()85b8`y(c>@g1%+9~-C1p!5s+q!{g&oEtMW)i11@H*xf^KY)k2nMe|ZwJ zC~FU=bGlesFc7Bi*~7%}NJArQ{QD4?nDU5CGsggvM$s3kpL|PmxJUC&_EW}%ip9w9C7@6MzYCB^9WqUDj zJSqH|N_d%^4F(+}nJP-rAu^!m+M}jU&JXS~*_5cjsC8nwlfTr1{Xd5TGt@bfWmX0_ zBX4l!x@xMSc4I%3M=;qmP7>7M{*VHm!gA-aas#-P!g!cCUm}$HD-bGp1nzP z&ppnRItv$ubvM(DV4SOo&^yn)*oOv22f_1#+8p|{f$vZep>U2`0iaFrGyTqU5qC$i zVn?{2{XI!z3UrTAnHVNoY$8VerlTiS34=EQR6OllOOQwY58U(jsnm-zLA5ivD{{+i zr2a!XS+3-OZdUF=Jn%QCg`TdN$^03%Cb*ROZa49f?rHXvh3tS=q3oRbtJE^_L(>r* zB8y^F@htxfIO0uB9R`=wD`&KSdAjx)$tMLZ&FyS1<>mLBr!NlnyQkFxIiS%9kIU(#wSHyaL3HcgzhlhLVs%I%iXfE~cE@gfJ)#Z6L&$aoLGHXVv_FdjKp|LQAu9%`RB6R~|S_XoJui)_9>+9e@WK z%6GRkG_|w(%tS17E@q(j6}dvHDY*5$W^wFiSZrs4R6JgYZp8YfBp1u~^a}}a z{tHh{X@eNBt7k;i$%YU^^;Az(yoP)tKmtp})tWB4A%GuZQQLmU-w0Ml+G&yyIm-iY zu?+6n7UBVPU%AwKQn|_NO&b{xwzgt=l*ZJ)c>jfgj>D5XExkSFHxSJYo1XHw+l_6W zDlP8;t=)?==tC)q(H#j7M72+AYmf*zD+UCK{!P|5ucRB5X1UsQY4dE}PVFeO4FHkx z3xk<1E`!FM%8(3_WpW~Z9KCJ71jHNkmM(OK5UQ6`WPA9^tekRXO;DS$Fq+jh;QZ+l zew{}9Pd*-Y+0ap5YrdK&QSKzlP7L76EON`;+R?{n1TdYg*5I|j+DICL{{v}aY?zcj zy4XFC$AC5ISLurX?SYqE{dI7Xp;Na|Mf{j)-S4%7Ie*NNmc6vvG*alW_r>vGbiP~O zh^RP!Z_4gm$L++GIp_kW(LW*<^6%50%`4yCIo9Vq|MpYtc{+-fI?)}q?_GEm>0%EX zR2Y2Q!pMW)8IzVPl@rx3R80I(A8n;7%`l*%wv1!khfU#q3-+#%!J|P|X zm8<*h?)%0__rEYEoCAHe&;Q1fb!BG=H;KjSa&8{N0jn>R)P1d~@!u*AOG-BL7G-<% z$70)i3vH$5@MD}5Q43=e2te8*lx30s4J%k#tTwi7xv9}B^5?;7sXwcF8cR;q7oikv zU0oe=q!mB$loJZMxTw3qQzY~Dhs$Sh-`vNqpCzc>v-9XvvW*SxBCX-KJeFkf04@e$ znnfTQj^8vk1c#AWLf>OP@mPmog>>q;v-{US{X3`@h@UCId&|TVz30jUx}T5P3!}zN z_p{nNA-@5j6ZETw8Kwg>b*!Om8iP4xGX&G3o>uP!6@WC?&ap4gi<)De%}#MASQie; z&UCf_PZ&|0qB>ATB+m-+nx_w6x_dV(zMFRydm?@oM#V&*a=+Xz{y3~Y*;kOn&t3QIo73F@_W+nyh%uC|Fun`OYlSJ!N-==b zC3sSYN`vX|RZEa%Yd+EAby#Q#bOXV6;y?M^HDH*X*%@j)Wlf+$U}9l0&0|d>x305~ zHqHng{P5eV7i!4|X1*ho5z|Mg*EEkLXNPIqY~RtP6B(^vZA5VIkIh6#KNU7mdEb^# zsS{EctsLZ>m_#rwWEA>)rqyP@swrJY3FUJQFmW&LLaq1lm&S%y^#u`RW{F~b)XcaL zORILH?JyG|qwrC{ZxYJ}voXhApMtM50j32o2Xf)>aYnf4Mw&O$lZgkz>r1)kw<5Mk z^Zy42BeW^e!>Ps6Jc;r=Nb3qYyg)5}zpw$QCl;w-V^1oi?>%iNd~2m;$K+QmUHVUo z-BO6brX-B+X_v^+J(0Sh?5-i+^gJ=WWYuwVip7i17-0uk59Mru(lCx9pmP`+U z-*XRgs1x5L`aR`Q?*=av$C&aKQcZeb(Do0Wr0bti#!gL`A)r28zvk@s7&TjOZ=bTn zatdj+Y*fz;hnqXV7)a%?Z{GYt@A-qad~yJEl||YkUP<`aH*mwidCU_A!d?Ow7D5!C`-B!H^zmITn=)tWnu-X zd}scAsUC@+abk)(Ls4MQ*kkh9LHE0F3O`0Q%Po4=QzB)+8d-u!t)EWNow>2NL;n=+u43`{%$tb0;DUANKavA|*z&$g{7i zAZRf&Ed8HtyW)$i${Mz2$y5>l^rr&yvt03u+()Zb%=Omyyw*t>0(L`rPRPl7a`=hY z$0G$VJ4%d;X3Nm54ORmK-7g$BXF{NnDeHLV%-KsPt0s(?fnhvd=!iCV{(~}}Ggx(r zR@#-Cd-tgY9w*&&84-bBKb2hDv#U?Vp&JqOk2pIXA`1V#fE{0)l^tiI9X(t(%CgL9 zzpTgE^_62gmDolg;0=LiypNu8(WW>I*L55>&QgU_b}Up06!M6}G{57masDyzd;#XF z@@F%?w=DFRV-~`|Ma-`b`4ggNOL-{Y#2;Mt4F7Nl>-VR{H)fgUnN&>hBIm;8%Mbbk zYc|ippc1$OpbNO)1x2v7E<6;1NAKO1lFlL6!xeW0|B zLq^#tDM~G#e9*(i7sLO84D6ZC)v@j2BO5)asj6=JZg?rDIM1#!W`weuTtmC z$+FdlycjVHVd=q^qh@Pc9}_jDRbN$EB5F?hf_5h?wdJhYWFKG*gLOGpy1F%)CjMeE z)`j>y$v;JS`47r8+nHkQTW<70+}yh-)HXkE?i2RHo<9uNL@HDe-rcO0`TQaX>K=$U z2l+5+oScijs4L6&&z?L9u!@zchJMcIHeeoUwIPKUh%hWKp+}Xf zD@seBTD;qV&(IjLZID40z4(=V{$Wyg3$PB~cGVAAQP(jLppQcY6~^x4FAB=bgi~4a z3ky(aul?2htjjqasoB)|&z@C#5r6gxIRGAfaBDHM9z)gGkKO5vUZ{Lym^l&K$slYO z$Gj>evj*C$)h-RB42 z3o?Z)*LSot=dqf7Vd0o-p8op}gt`y`QMw0fnc1koGr*!(2x$jcH`ny>!9PF2gJQdE zyL16MQtj97H*e<0x! z^RGbm@iIk}?Mme^GZgq|M*vOq{zLB@1F=EG;*)N<{?%kC5H&WNZ>l)6Ti@M~o`zMCZ19N`G8A574p0Xju=itM&Q(p8urV zaJgD*2H@Ik+^P;H=`)mKRB0K7!|>yUfUNyh>o>;`mX~((EEKP$$ab6dWwj~IlRn)a zfMF4S?KD87q>l{=6AeFU}T;=z8gr}r%Di1(coLJq5Og?8_u*V?ud%CZobp0af6vh7B* zpO}Hv=^GToW9yDNNiU#FA|!O1_ zf<}x7a64H8i`zKpyh+PvmqZ~>8ZzF0M3jqFg_zsRf1hOkYVMn@_gw6=9(=(5w)PXK zv|M&dPrIX`GW%QbcYP#vTybDtQ;5rCR^RNu-ewwMK*(?w*E9 zG}n_+28pt-n^cr4u{4W{qkGydK^Z0RYKCBgmp2bQX+-(rJkrs<{?tIPVP@T^q<<>4 zQ_-KEzl!<9I-@I(NzP+>TJuGNy2%mkhY#cCvS8spq$T3E;@d=P^hD^psK*qI^8<#t zQN}UlMHlKF6)Rm)7=t znn^Ye4u>jsP5EJeXZ;6?KZf;>6y)+HA7DJqx9ew+Qq%RuoUKCQAwY}IfoD6Wp|xyd zXo%u;^ckQ65QT>|mVvc>fRo$awq)3agy8x{b=id$!bVJAey>5NV{%DJ2ogcm7|_Mmooi_ zGhoL8xT^b=8j>W4DO;T4GhzVC!C~_)NP}LCY4$(|XbjQh$|jlTeNMKx-6sr+9gdm} z8i&UUUvqI({_S3##tr`*on(J^nbUinEB`ubp52(WZc6Sqlqx)ftJfVDg|}_SIpw(p zFT}0%=&mU3bnKrs?vI&;!8Zpepyy#I&bJ3L@a2^xCEbSg9yTPH#Q628%ugGo*yIZu z=2gfqSjncgW- z$r4A02gnT2e1YCQ20anaU7T3S0=idYC0z7sF;3#AnpSX&r#q)uzQGx?&l3G{6hy1@ zlfjwLAOQD_sbOM3o_OqVc9YFS3gUK)<=PrR%tHWErOV3}vOrlsW?Paqd;2^Y@f}z9 zFtYuZfjD{N1p46em5C;Do7P`!QSd=kUMfsrkl(GJem8%Al&k34C`;opNCgIBpj^4i znd7l6R#?K7gZh%A&=FuN(=U0$$~s?qZNQ+ETM{ez)N3RLKy$dmO{x%2b$ z%Xz`S?ikv}p5i-6^0TsWx(A~C*QADbcjWB?|cn7Lp{F0 zN%_@h{HNm$rpNEJZ0BUOl2&BV?02vIC6~K1f9k*_#w*-#4BWI6&{cHY4|6}IGjLYmWDQ$DDd-2Q2n$oYKgK0!8 zrc_n`Dd{W%clyW@nr%+f0wUAy1Cr_Y}m$%+clk{U@ z@rlefKp!}MB4k#iS{lKGTdgRQl$vf7-AuZgRH9gNWqK*QTEmql# zyd|+?Sz8NkJ^sS0TR~>RE*Zl}o^#uNx&VHfNRL|qGvHLWrun@1c#~5QQLF&$Oivjj zIzj`CT@)Fg()a)Q3<{+`(QP%PLMc>NTC_Tp@+iPC^ob*!-_ z>(|J08{moDc#(wjdO!rfdbG|M7t}cP( zkE4+f+Qs6k@{#rVS^< zo=?nc0ovy1(e}LldvRg33x;lAuGBaWT*U~L1pM3Pm5>-++e1oP4kuHyV(^M(sPf}n3#Wm_EG;f4=A$A9t2fsv7dy{Jcni6^4wA*jh7JX zU~Zjl_x)^cIxpq_38VZ6IAZa2tJs`@-1uPcNj7HiD}PN5zSjj^hk>xe)7~oGqH7AJRlT!*g+d!^*o8 z9o_~J@YvDM2_H>V1@+I>V@xsuYKX}0@-ErJNW7s_rT>GTmsKN-GXUoEATS-h*n+Us zShu;G{-(4Vj$l*Czs0B_`|N;AdwKWk){4M6i`v?t3K^!9FqU_35$YH{eaAAOY+e!=*;;=Lpq2 zA?v^3oEY)}`49HqN)(QdDqp=kIbH9le7BZ4`1WrlVW)T^YoD+VyQ9+qq*7@MctA`EIi}lDAxZZ%fI~Gae?OyCR&O(#L~AcUv|YDi z^;Qkc4%@uv#{}KG^|xWZ4DcjC3+l;n<}#to`iVzy{sta@ZQdrV@(cuR_)fmgj*R`G z?Pn&H!7LxT!DH+t-Tbdv8{)_V>}5owFNy=EK?C^0Gma80=~bx3L8ad>nydE0uAbB7 z_H9S2tJ`6*179r;ntXAfj;YY6vh+3Rnf10k%c=H_4zjic9~b=LXtd2v;5GODhd@Mm z7Z+_Ms^wGpGs}~>f4yXpJ3Bo$%7ZI#Q=uPBg@$ZcjZakNFQ$51oKTpD8-)rC2fg0n z7!Y^Kuu2*h>9{YGWE@Z$$lXeV1j9%p>1||7yVR{n?g1Jw0UHZ<6%O+19}3rA#L*qC zr$X)Ga%GIH0x}zvKfP(sZf(!r2AcIFR$4Wr4>Ahud_0YU=_xXNiTXKAkg|wEjotr1 zwK6oALIx7yn<)#sYkD_UDYa`KK;OU>?OmBc_wP^c>A$#VkMGdz7So`duAOcq92os0 zE+IWF< z;NgeYs^pWT?yHc=n9^*?{##8dGK0-k-3c+(KI)ou-E51i)!sUj_cZ5YvtNyNDB<|0 zl(m&%ixGuqkH0xzlllYzuD@xSlybjSAWg?YQ*H-%a4PyA*!8pb@#q~) zsPA?zU+RPDWx2Clv1+TK zvgPmwPW;x<+BAyp-y;w@EW#Ds!hpl_x~W1`#U8j-tO)=6(_rzR!9zy}Ko{)5Q{pYSHcoL%TUceSyAJZ2<&aHll5T?ihP z)p{|k+lth*<;4&&ru+<(#raKxue$oUsvIB-@I%F~MT#qeC&_cIHO&KdJl05NN9m#d z-QBG5F^BxBE|O4^?JQkbu54YeTp}Q`{i>Cy?Y&n}xc6f(ztKTAw=ENZP3iUV0TOqY z?G+2!dsl8?!R4%tfC2(XR>th4YG)O0Y)D)Vpc1GeG@kdu@85K<>it`lH)i=yl`gP@ zpXid(c{sutl}z3tEOfCDN1&E?v==3`oLbj>CZgxi8R*g#F^R8z&IMMjQnABdRWrgG z1{jc+i4KBSgL52F4>FBa7~IP!lt1qqhXJlE{f_eG%SH`Q(_iE5a1-ypTx#m9t-s$0 zxQ*5LGqE#|MNezf?Rm|EkYG$vSVlOGks>nopabd!AFoifNi9C@mADxuXzS3y)|59R`)Ug9~d1US}>X7 zJCplH+k;ModfDRcDrz6<{QS;*sQ0`v9PDB*s(V`4M`II2As@0I(jSPLTe95n1uKl( zt2U}2_svO=s`mvZr828h;N6UTGw^iTU#9t61CHkYxE}2Aa2?~y(gaQOPvB~eKisIx z5?*rlaaBtV_(P9m?w0L(mDlv8-*%90$GD)FC(q(Gb5W`7XeWtLuQ|-GrsmW0PySgW zvB$tuC3WWSkM=Zfvm`LBA{PGGI>9+JbycDB55SEt55}>wSm_B%^QbZ!BzY=arQ0c` zim8PC-Rvfxc-1^zPLzyYxi{d!+|4N#rF|eZ3NEv2^vd+}@tL+*`p^(r{Jd{zI1DXD zFf|tjCF0)s~6LEL7 z%U9xF{$1BE`*D$Os5~KekP%WzcaE2$miTPDEjbd!A9dEe9bqRLt(O|NX=pCIQ~o_E zoT<7T5%Hu}z`*&drF|is<0G$v(T#3ubnmj4p+6y(hkeWbg0g(56rwZ1;q7llAX}_{ zo9U&siCgK(1YvAC%x}c`hr^U_r-8np4&m~7Q3Iu!x2jc1l)EPW zY{plG=$dmgWzUt=3z!`skk*W<_x+AvKpEbnxD3Pa=ZPcLJXuT8mfI1$!rKhc#hFqG zbXt7T{l1~RF}>=m5@g6BHUt{l2k?1n-me(moeF~lx1(l4!)2W-J3B`%-(6P4JG?p2+NSd+#|f9R%N#QN;#vR6T0C(I zO<;DIbajV=-0&45v73kxfO9Qpi4H&s&|DLG#X@7B2C559ain8ft&r4UkOTBeDE%12 zp#hF%%JgVH{r+K^rK7SmjF_SNvFxsJ}?-+0x~ z&Io0E%3T<|DbNqhXi6kazGpWZv@6XY3aiv+4$OSAkzOQFG&MFPLd&&`Yn1xe&*EgT zRWr8IY?ZYs+Ui15@x!+~F+NzXZs$gEXNtW63}weZ`>C<}oLUrcVAD|kl~S8Cxa#>R zQuS4vi1_tIHPz#;4Ov^izl4DOElaB6s6*0?W?!t!3yTUF2)rE24! zwSMTV3vkxFf}}o#Oax_Qf+RaKtbMIHE6PbC^5vYZK`#WKXL*x#-I;I)OBHKy5ia@- zXTcsuk67h{sf&)Z=J=Q*SE{JQw3&0d(*<9kq_N7D?ODU_TLGi=VUw-ZLi#{z@pSmL zX8J4+(emJA#Ij3nK!9lx{F0~%gZOxq)c1E3r{b-|Q3K5xUfzsdc8ZZ`QYbZp6p(X( z9neEm*uAY{#~ge5;sO^%JcgAg{6u7~Zrdcih_4;aqm^;*(Swm3E*Ls}7ddBiX#Dy3 zI?hRZ->wYxVMO!1*_B=ko*r}3V5k){`dQCnI{EdD8C~jeNNOQUd)1Yk57E(}r@w}@ zl>1RlgJi7`GZh`;fcr?5{kw;l(|F{s1dmRxoIXLxDoJ=;Ub9=Sa@fal;?EzSv!am6 z#5VMZ@RkBpSgkhvt`M7IfGWNfB>}zTuiA7f0um}oPs_Zc&~>Hu!mM<;uzd}U5&@L* z{4b4uUUR9=ug5GCKQfUoPp(w8#%LnL`X0`H>HFF1=g2UVNTui?M(h+rWXdPQLOBf7 z<~AHv&eAS@3IRqFl)(^L*OUw9~Pi)l=mtOWeqgSQJ5Uwd@dafH_C68?NIQWcueR>{JZj^uF)G2*tNs=|&7epW zwz0%OA~|F0jo`b6;J$@wJYh7vJfaNA*snO8{!uOcTj|2ps237{@f&xEJpP#}X3bn0 zXm4DVq47;AZJlHJugR=G+dQ@X_E8CbTt=iRM|*icemA4ASU>OAYzdkQ!^&gP z!`(TWPkp#|mmBsok|i&vF#&(wq;SXB-GEJ(o1QyOJ(EHh8}b;1JqV|j2yC1Z3Mg8^ zJwj=-2WVfMg(H^+d_ziOKgp9$dHod=V)W~3cSl6gtZBY{gi>IgCR~CjOIt^b=FUtU zRWqGgSg1$Fu6@lRW`Tp7tKsfG@aBKTOs@ZgX<-oo+7HO0I%8LwAC}B3(_0HDvZ-F1 zQW}yB;JmWKECk=bywI8UZ6=~|HKXkd(!Kuo2b82HYk>X9;wh}GaE;i^Zg6HTrx>k> z@({B9=@l#zzr#%38jXt?GjnH1gM=ya7%@Cm<=*zWP9M7$dVYW`KE5ZZ?e4%TN{Znw zORiFTv*EiMAA4aKy1rR4-O0C+7)N4*$*!i)+}<%b@!0Lsxj7wX$Vr(KI%NFeM%%;{ z{D6rau#4fM{a)$onq{9IF~5xOFL(S|fsvo8#e7>DT->0+W z93qw8PR+>Q;iO?jbd+~;34W`(L!%93J)-iO2vUo+aW)#|&O97jUubA< zN8;D1%d0v{(&z9dqqgf6>5%pyuvUpoYa*~qT9rD6h++<{bgmr?wmr37PeREiw0Mdz z-0uUysH>ImVDw{sH|WtKqrNAvlBctJOqGW9GGuF92DB97)WB!r70`uB73P>c=CNG2 zJ|5;YvnlFi=2GP#~P>%xWt?Iy2(x02+XW>p)H6{r{?81-s7qwaeAe!HE zJ8}sfD4FhkyLcpzp3T_mEdP&Hh}1|%OmPj{La!EGTZ^Z@X+8r-XNeEQUj%rAXWESZ z$I)5FHQE1dc;x7gAtN^$k?^KF#^^2;X%VGCO1i`i|=_JM@tfsAYlDVzoJ>TTH(u@qId<7Pvlxzr&`m(kOy2Dh5Xsu z4=y{?H~-fBP*&BsfVqGuQm$UvBT~5fnQ33LxF^b|EF0Rt6&W9Xa}C+(;S}T|V+_bH z6Q4rtHj_LGOmgzeIg>c-=7Db?>whzoY=j{KG%D-N+r%xh{K?N?OGM(^;M6;Rr*_@n z+QPZazja0*&-30hGx+@Oz*JFPUHN#t^`(ETFdlLugD$)&GhF?++Q9n$A!uL>yp2zf z(|(|-J9xj@h^JL(o)VaJkSN5ii|`T4U#}8{HPI+4hxPuLOl~9-_%gY|IIxr>+{) z%oE93L+C(b`^q5L5|>=+OBz1j8Tz$;S)dZm+C%m&3FPA@Wt?holsq#i5W9wkoNx3# zeR zsI3^?t$(FuItBYAUQ=qAc$oiMY>b-81VaHyp-M!h2bot>kGM;+KiB;O`wJM?;;nK> z%4O8pcIG>(G!AxW&1In*55t8qe*OG1-LUzCeEU_Ktb&z2F8$1+L4WOstZF`w{>XA> z=Ia!FL-uw!IKI!ZCHICinaYN3KAyez1~Zpp)H?9h+}Hd~&YjYtnMzC)cgKs0x@}`BLM)ss;o|~@ut`B-*A1Q#Hin={ z-Ln+`H_s!jFfCO&yNWh`Ruqp=zY3TJ_5)wx+$}F@{v%C286w@b6PMdor`8}p7DttB zaTx1Mmi4(V)G#o=&SV}-K#Qoc7mL0>=k9iOvw(1?&Vo~j1#W9=rP}E7xkeo>S2vuN zc-+>iOsB6t*>+~qUr>^Yl7Dk$lisJCH|Y`XL+ng>_8Q z?D)f;x_Uhsmk$YGl^=IgFIugUrm0jrkiKNZepij<)t=|Ao@|kkA;3I->CrYoMQu_q z4avF|5Al^49|!O%B0Y7GMNkQa>}Vym{3*FLd%z&w6}`yu+d9Si*hqD>a#x+MP1QwH zMx!|d4F;ikbpIrIe74#PrJ;&Cz7 z{BBQ5gR<5%)Tq2HUd}y{%wmGn2>MbtgnaqlJ<1)g4xH$g1WpabN&+oL$B;WV-7Z^u z5HcXE5g9Dy{}y%+FW{U%(j_%BaP)!`@b<0vOGh3%4m}F!35%0gj)QHxbHBIQyN|Oc zS-B#acCXSb+vl=@?s%yGTSx9Y()l)7)$>|8@rACUsrihbR>$3Fq>7e6%I1J7u}DqV zUSC&h&><=v*@?>wG%2M_%-`JMc`hSV?I3tz* za$D!uP7M2%kJA)w=Tz6aHs)^M3AWCGIFsFISNYV2;3IQ^3Ci?4^otz;iCI&UksgbH z_$UoL4C-J#JmE2&HMxgsZ+wielHK{q5IC#ViYj1GC)UvW&{(jPHqVr*kcd3@u$Q7K z+3P`EMlTwEcW5RWY>`4=>PO|UIR2d4E=@V)AcD6OWxKNY#0 zULBOI-3i``C}_-a5F#t_sH!qx%hT#6;Z^q^EQtN>S^+TE9wC}CtI32{te?g&G2h~_ zT;nZaihQ1OQ}o|do1&>qvh_1bWJb31Vh&pM1E8kuk5(pkc`k;WFf6uS?AZ3Mqdtkl zn??ssWmb)++Iq)^BYJ9`A&1K?^;y72m%^p3bxRKHXlK)W1#-URT2r! z_;Q80gh>vjk=8^PBNRNZ8O=E+teOXdjF?fvo541HdahTc4KI5Y*UoZ-@j$6jNgs~ep zjB;TD-UjwW<#t!JYe(B0r)ZoGOx%aL21J7^EkHecEH|OO#*n6ZJR$sD==8460nsMJ zAK{SAhjP2_{7K2J`H*QtB1-#bNF>#a#lWv>2J-nUY$kYj{PSxIneTYPZe4E{GImd& zuY095Rwtuc*B79SJ8!*8eg!TOXMgr9t(r#SWJZ-Uj>`@QiKbeOROJ|fv7h* zGWj@8FPR}g6Iw^cuHs*x$=>OA5uAYebazHv{jeZ+xIv$mTP|t9nvkh<-MZOplEg7* zGI=YUOt0A-!PbJ~CX;%tui=)pbmV$b_T>N3?g#?YE}d@0W1p(eE%J7U(xv@~$n!C) zqzC1nQu1``x!EK~?WV8A+KDi{X4n7Jj&V;)r=txVP5-=nI&gnlv=tmi6@PbcNE)Hx z8}S}w!O4_hA@FzwPObJuzH*44QZdn}SNbygnu#s14en)j=0~G@sY5m7_spb&lNJM7 zQ`BhDUqnPP8^9teGw1Cl!OT96lYA_6`-IWRV6<-UI}zrOP&W4*d#Zg*$YEQ4Lniee z$+~hCJvpC)bQcq5O^USeO$boVcFnEh+3QQX-iK+u<@-)uJ%<;bs^o$GFEQVVx5E^Z_>S2ESYP7M&i;4xh` z&l1UjxB}TFANntP@R#79bZ*^RS#jv1kq8sl~vRNv(hB=xt% zN{o_yT!yQdQt2Io`zJfqwa8SXugQ|cDCYbrLN3BU{Wf_9f&*u63Eek2P{!+jh4{4{ z==gIyU*kykqNFRp&-qZ%c#O%jiCfJja)MQvLKa1O_DyZj6x;vx{IkRUf*Sdm_3lUm zu(fd6GMz}2`Fs1t_p^GZG8!kF;GTI~VxFSqv-^!0Y-8tVR*Gqja%=yg==0SN;}A`n z7`0+^(}`(`{;%_j8QGr6k`?MD^|OZwC&cOkgM_U`=^%p$f9Q;?pCwozzUqf2+DX99cC$eC{tjlX7@hGqF)KEJps(4Q;RH0|$5bPU6>~*_k1K0( zY~qIGcGc4`>i@0<*K#2g?m*qZRrkh|#u^MI;IRgu|2=x`mV}5Vc{vv<0GFqN?{{rp zf`>j7%_v;ZUAAE@*zQhNks7dTolIq27IyI}5-feoy4V_(U1X&g9L6g6s!&J*igk(3 z)BjB4cja*9ob=)X`M$n4US6z$3{%Mk;zvYv`KUvj52s}fT+E>GXQo9-7;9;!_vYzi z$>alNtEIFzuF;D+9ZcnOq5jPO7zyrRVOf*r4N%r(UW^#)& ziq@D^4_d>Qqr@k($L^-dxSQ9*^Y|&Q-eU`DGfu$UGs)>TTkM<0|E&+rGK?Z98L^rA z5C{Yy*8tQ;EwLx%bd6NkaEN{XcHhvqp8C^EBC&W@8P>d?op#GghE{@_u{Bv%q~S-b zzdo8bB2ZD6QQSx$A%4Jnd-?I4GRS2Cpg0APweMK#+11FZ(GBNdW4udLUuX1TMU3_?;;Tb%f2dSN^(g+EgAv(UX-Vvhn zz#@4U=VPim1HmQ+b+}4TAva9TfV7)6kd!NU56jdz4BL1vcI#i})Q6D4tVqx2((^m~ z3_8!F+SFy0T@}RQ?k4`=0y(1Q$w25r982$FM?FTJWFy=~Ay50(kIrh!D3ShSJ@Oi# z!{#45N-!Q6ghVE1;CpLC2HLZUpF5=VvZF+!muz%WIV$eX-JFBz1i3XASoSkaa#$>h zCVfI{K@lKR>JVfU)2ea~%t)hh9c<1MZ0H@hzjV`kt>G-7{%?WUtm-B*H~^xjYqIJ- zx+T8@()hE^Gr<}z_BF18rK2(Fn5~gA6(4Y3gIz*{BA1?V+PD>)^c1IPLSzfrZO8|H zF55oxG*Pw zbO&zrlanuqt&i;GTBl&44%D%!_PCd$^WEI;P1Ub9rKApJv*$E*m!FI4Hx2@+Z_YLa z%O4y5vddr%6jT)=W}xst{eSY7bwc+~GAIi6HvwyssqPu)=**Ly$; z6_gH0q)QSm65Bm=*CM=y(n|`9VSCgX-kv-V_8xSgqT#RCl`2rCL8yn0yegMITw~Y` zpWJ46X7H#shdpOS#r|Ktg~)ozduEe%Cx_D+Zh%%QAF7BPv_x;*Ja+xs%`YCSIM<6h z?;f)ZED;i>i`{u75K55-nk~krL8ZBTHKzW8>?}$uaH7~@=^@hel7AMUHx-&+w4lrr zv|?!_|BSl2Ix47mGki6eL#e%SwHUa)20q=ic*4p2bat~070Xx#5e?^2aB~?%JMU={ zLsXBxe#~+|dYHfD^_gniknLiCT1J`lXMphTH1+uOMY~o%8wCvW?_Gt5mhd@PW)YZ~EeiQHjfHNEq{KKNPyR9O-iz zOfEv*qkzeqgRRHjlGgmy=%YC36dO$>SWIR=Gqrvn+dVCdOPTMcGIDzi4?pM8{kQz7 zmzrfw8UBDKX;DJn9G4RNIx_m&HhkHh#>9}_aA&k%<>SC=u6fjND5?IKbs2^6ua1i2 zJV8RrJnCbN?ZmbCNa>i(=5+V3)Wf^XeMncHllD)TPyr_~kSmcYyZrUgX;8M!_T-O1?laQ>pwBOXJSfC|hi!_~nNpeiV?ILg7fIDJteX z=u-=I4N0FvcX*4}qNCZ9fz!6lg9^_#rV|u8okE76`lS`N#Ct{S_wh=jU<(yY?T7fX zeKy|WUqP|mZS+Nx6|jDA+*)-Vv`V?yM8Ic=kJ5(7C9M4$e93ryonM;$m4>B?8GwdX z6MUt)RExPgYZ<7|)kFfrkk6}iHj`(iew*^Fx8#4OiP%|uBI+I_+bddudm)Et)Y$kP z+XmcweNtMP~SH8n7*Ub&Vq$hl^n!LYI5rQ*^vMHD_=_AkhK(L#B&&SKn` z&U%SM>sq(uY;55f?A}s1kVid1VZGu@B5@6wlx*Kxm3V(?f#aieM>jQk~?HL7AEF5K-o4{8Dcg*Rwfny?AfN1i$61~JlcH2Kh%NG> zR0ZA22WKcqr%_*j>96?+)lt>Fpu%VnS|IC9?goaE5ll%R2pY$>sX*&DrOqgI7k8O6 zHFg5_CqRWl#|qAEcKMD!rc`4)&%C)BcIL4+zkSQf$P+DdZr?D;k~EVwrle^d1oX;` zhV!);hgl>H?V0vlx>1}6Snj5?s@cSx2!C80gWHmYK-?$ub)2Svu${b!$if^=`mPsQcOQ!28rBrdt^545Z zrY7G#q4CNh(0T|?^7B4)YYmk_c*+nHNi4escBfe7f;OyNpf1xZC8I`)p|RR$eCo=k zylF4qaSCZ!wrgX;^cIu&p?(XhtfTrS2KP*-AghbbYMIcS)k3a-|3U31NW8Y$T0k^4 zfn5r#t3{|4c0NA8`I1>u*BuKJOM6`^pGL_fnhz0fykwbF#BSh0ndmiF8fcTCk>#^^ zbr)2aA_F9m+fuTY+=I2MWeo*3KPoZ`FV@}Dv!&Be3f+OM;FbA@p~6k6-(SiazV7_T zE}~tO)%}taOdulyjlZV&y9$dOGYli4?6C+ukTFA)4l^Hs07Q1L_EVETZ)0xH)ArUN z)n-vGl4d;xzIQH3RC<2D>u{3(Sf_)5#me?C=-tq^ zl1W|P^I4C=FWY!Z#q|@0INdcC7LIp%e>`wD$dmGkTyC_?78Dvq07@(!oq9Y!#GuC{ zPpqqc)pPN#-cIUgau0*WjamIuUPV^q$Sh&OaygS8Z(m(qxJga3FQf4XrgVuf@={|0 zpK515lX82oluIr^&i{ag#P2T%a+JE0s&p&kR#Q?McdAC7LciwT?B&sMkH6l*iv`kw zuG-r$Ut#^zZTj;UMSLy0lXXhkNaQAzORmULHc`4K1;t=9VMpN4RF;__OTWEF*9{_h zJtegjRcEFYbVA@!qzXNG81dS0SvPJ_=<`XRcCxo$DY5- zwml=`mD!8%|HagHwTF6=t38_Te)NORwI`oF8@zZr7Y^AV`N}4Ar17w}-x=Tjw()qb|ybLm#_)!d{Tt54R`F zviVYK{_KWz(H{~-`jz7r!)&>C(6$-oxNX_wzNg%-$a!4X6`;i{nlI)rY5F4GdQ$0O zGKl-~g91(_5_bJi6^osIbk}8O$i5ljSR&J$m*}bQvl>wNCaenvSV#xxvtNuD5yMWh zjr$aUIiXNW$I2T&rSnZeDoauthm9M4MFRz>U_=+4c-5NU{HYqFuA^lojHFA*U1hd> zGQ`iRWg)TvA4faz5z|G`AYRQv@A;>R7IT=J56MXAR9m~{M4 z#(0|;hv(MdX8>(^2}Ops9{_CeYUpUe2$IA=^-xWtni`xJD%v9o9jxo zluBes#}kJfxy~v30jUAVP3vEfGw3#Uy7;#qGlhUGIksgxJ9ZO(QWU0=6%u)c)3>yP zilVJ4vjvPLJ$ha$((lr#7R4ihH?_NfuyvBBsH3~Xd%GZ?RiQ58mLh>i)<4^d&>*{9 zuuE6MVx#N6tTm>%vO;_l(1;>$JCQdw$_+ir3urb(KP^`R06_RSz6qYDmbWiav0RQ? zr&=vXgRSQxzgcoE;m zR9=@KHFaA_otm61vRa3^+m?JK6NE~*q$B&zaUc2YT}O})xx_;ppBAOG0e3=}$m!Vb zTCHb$z}xVWtP-9x5$GXdA)GK@X+|}%4A^GZM&)i=FON9A>dv&`#FOhUzdMadojHsA z;tuzMCQZLc%B)>?9uo|+K(DG-`n8Mrpa%hf;u)c4)h1^kZ$LMzxWY?v^Am8_TLJDT zme;G#AZr*fzdPL-;9RtfjV)=B5rGpS{WhlHW9OLPCCjqRfq{YTq_F{mA{u1CDzba| zk4W=AR$pmupcI`oHh6i(kR#Hm`wvD~rZo-&#`P5(q7^q%o0du^65RM#pzcJavr&!t zVpEnrNgGqy-UOU_1lXp8YO#-OSs!{h$XD@3Hy+{NyM*!_92`@+JRdVvW6_oN`PNOp z!nhDVsw|z)F|mY-l@0G&$r_D#Zk(AZiCJ+8LSYzoV%yVoN$+9N5aJja6wp=6J};@` zL^Jg(S``!oh8+Y=Qv5^y3Q0MY3{>?Gqx&L{To%gf6p;%Q=BCu(OSiwEjOjR1pMpCg zz6MHrq=2gps6f(+ng~Y}R}c%Ppsm$5!aw|^z%4VzFD-wkB((8qVcN01eE*#Gs($%I z-@H47k83aTSoFvOZ)nhT5jX7j;<0#Ji014nO~c^zC#eC^#Wxu3n3ULBO_MIVtTqEb zzAwrK6LcdsHa|mU1lXj9K}rxa^a5|1%zBm|^Bt0ZP1-e`!p0I>RMB`8KOBC*o(iTj z5SOO@#V)tPx^zCus7q1)F9t3%PzomuxNK9J6fe1c*?=oXm} z6|cdlzAl?7(m|V=Ns&fQM!bxvBDV30R|$6cOpugC8~o>PASdFa!PQ#YRSu#as=$3; zT{-KgZWPXIJO<$w1Uco`bmI*ryS|SGw6xrYq*>|?ujw8IK;-T|xAG@vAEM(8^OlMX zc4Q6JZJmX?wik$3Qi05SFSyrKiQQ0Q1+;AE#j5uHQoR2FcL=j-)LR(i;T}?hSNXY) zZAz15lJ&OU94^8;pj##C_LV1qI{7_jY*{xjA|a8aG>6(9TJoH83>aNL0Q0qITfOly zscJwsXu0J|8l2?L{gT@!zS&6?GJSVTtXp$P_qmpv0F*=&%D9~{^;}TX@sjd8CCh7^ z0-BDXzN5(4m9xn|mY-H23U#tg~Yx60jA z4ybd3M90n}kMDTgf||+=l04L|*+k%x*ABj*%b+O{&1a4&p~cGyJmu;(=Bs7AN&wix zC_72;M0b^zL&?e29bJ&(g6_OGF;ZQBoc$=>;0<>d(SKX01uH>tRce8m&~`4dpk&9$!eyXD)u zZdA_9Y)s5S7jHzOr+}aN8M6S7z0uI!L^>Dy`UdMtsg8^EXpLi~bxHEz^v5g49Aga+ zDitAIYw*J&#Y^5)rU+pJ$Up{Nx|(Ha=vqu_sruG-zuEluM8Jeh6Vn#0NLzl|Jhv#N zo@!&$iwn&I66nn$JNb8Q^IOIe+uZu3=5NCHcg%|3Z_2)Sh4496Lk=xFXqu!WVn+J> z86upYW_N|?Fu89dJZRpKww(x~iyAb(gl+g8>os%ps2}Jw%_~%KDUsI~sm7glubr+N zeP*VtKvvDzS2PE1k5o*H?e!_*V+#ZF?WUbEw{P)Q1d@Dg4z>@!n&?Mq1to! zeaM$h5IjhC?~g`zQ|5S-9L#}<$T^ygoXP=%;etBH;;f0ls=G(xk6_Nd1$cP@h|Etx6d zHs;y-{-$3?e@{kj40~z>p<<%TGM2Jc9#?*QLbuw8_&PcRaW*w;+G7OT_Cz+{Q{&Ov z%pvZBJvxg@z==he2UpS5?I;V5DBfwynT}VJ?}Fp~oo)*G!*mRcp8{EqZVQkNUk%^Y zdj07+k1V!>yvzzi;=YIlrbs!_QN-=bBkndcWO5eR6&oLvVu5nwehpOg`PWlQNLAV62UrlLt^S)Z!oqk81 zhAcd-$?EiV8wg02?AUMV<^p!vshQS#5sWw90(2excUt2^gZ8M^WPOKcSLr!y&8BT^ z;#=rj9!;A4&H}zm-$ts5m-dVZZO#JCL0w1 zFBci`H)f3cEJH$rBWCcj9S7WTZESQ>noGQi4NQS{{}GylV!4I#yZD#R2__Fp-UGF; z#yA+8P(!Qe{93$5WN>U<+C4!8Kb<^Ve7YugUj4vzXLPEtuIlCc0$%MF6iB1xI&A%8 zMUzF<>xG~szBeD%mi7Ub{KKNBmO_Hzp_Kho+!!TE#t%I{m%J~YB$j2!wg1uOHs`4X z$Et#Q$9|X0fpz86aDLVl8K!}dc*8TruKyu);j#lYIf3Uw)&(9#@it}`S4T_SM$d%T zupik^myiom3R0XRm*?sc`K6zdz6!$PBsi8GV&rC_on&!cN<@wMs+1D+E0Ym2MNJxI zCZI%@5hn0qyg5T9ntRh+6C+g{S|I^pMKIDah#32Re?*F z4nJEuvRjYGg@YKrb$C;Eh-!Q{C2a&Utr*_Q+^awHyL7X&_VllTdA&M=hJl)ffUMu^ z=zr4@#}o|v$34+Vf zDInyguu?S#c&M|r1ix}kQgG`UtL9WF?~ZB6Ftx@*11fV-r? zzO`kq+#1Lm3(rUAXlHylX?!j zR@RLWVaqhg&x`QLRm!vm_e2=BQUsj>R-4;Y+t1H(MxGpqsUoTxGA9`{KAJ5YbytBc z?;0;f7)g|T_<%^wr_(+l;hQ=IzioM~*G8%Fn7hxLE-B|lAT6IbXF|Lj`Xcx!^_D5= zTbm*;DKslV$(^cp=~5qxaw~|sNNuXR&kwDqaL{g`d~By^o~ibYzyD|0TBfW%vhkwy zuw960F)>Ufzel2fy*=bTs2@%k$_zRzh-xLHabm&^-cNL0Ma8apr&iN!gD&+qiM-)A zi^$n?;|&tzHx~ijhyPk2A4K>xwKSBDVKm2pd;2OQw&(4FbJk97Vn?%-w2*~3t>vF! zeq1Czf~V2|xsp>DSWDjU0io5s@N<}{x0fBb54u#OqQ&+*-?P#08Db^BdA}0veBH1_ z7q(FaXz7?o*vWBsnA#&U2{Elj`|@`%k^LN-!lvwOUY^K#xGNGqsO%a*(nqCHPewcY|d@jr`R2B)t(@o}$z$@w-~vET8I|*6?8f zL!%EyqBw8l4QuF@PolJyP_rg#l#&iJ+ z4H^$ZW}zezQ4Z83<1i-fIaBj(zGI+ooz^?SYQk&vYFfCwpT!W3t(sG-0{H?)S^G=opDCF$o}PnzBc@t3e)5PlIr^3_0)RE0t# zgJ1o!loD675UI4)b>k-KtLX;7BziL4N?l9t&mPm5vqqK-Mr&F23bnwP1uPOaVl|M! zI{!NHW%aifZ(ph$BVU&r_~ZF}o7a4007KL8x#``Ct_3poIryl;2YHLxqDfA^|E7U1 zuwuX43zyM<;Xb<`0+)(ZqLr5TephBxX_eKQ&JP$WC6hr}eMr`1ToY&V?bgoK zPwCg$A4oD|{u!l|zv3-;E-b{KGc9eu$D;Wa;&MMSW*Q2>1_+kT9ij_6UIO7*>WA4dOanQSC%?0ORtoy$0V+8v4Tz36LW?kBQd!jeWDo?KMLH8^?Im@<}5)dD{3 zUyx-rl3Oc{e5Y7K3T`C;2hRoC=r8bwuYZD1JTcKHx2QcIWcAK@AJwq5SFIip8!!{v zn&Xi{Z;IwOGv`?3AF%0K81maiqVtz+0>&W{z(Hsl zV#p5-xWw(At#OK6g;#pe@s62>`K&RV1!|V7Fy))rljYr%BRGm^WGS zG+UxdZ=sKZYcbpZKVl{$MjxM6Ug#o2p1v9@jHY62H*Y;h9nj~WyZmL93wOA~ zEGT)t z(T#v3IozS_FUUl9j{r&15iDL9=D+#~ljK4eNd*kTZx(Hz*B(@4%7ST(^tBy0kXl}t z3-6SaW0|%%`elEE>rZi`tB!7(97R=2X&`GBT||_QAf?hd^LxIn=osJP0AtNBoLMC$ zvUTGQL9B+M$gi2yvl`K0HL6VvjfU7r<`@UHhyVfX*`#oC{i#XWKXInG*0}EtKMTVD zO{XXxM(jFYD-oiG3iwjmS+rR#$QNwSQSyO_e7>0V*Pp}`sA;N;R7zCYZ?=mtO4k<# z-EWVQ^kb8T>nL6#JaiC zvRiEVBCIRb1D4~?HeNh00XH(uZYt@|t%63XM{@JoZ5gSmnfK6aJB~ zQhbJDD%%cXNg}c1);|wBh-m!bM8h<$3==DIw-{_iq52#&BjtSD=}{{|WAittJsSVV z6>n=&5u8El!MW#e_{(u=zA3pB%dg=nbXwzaTNbs|2#d z`S{0mAvP@1qm%}LriOe^@0_0B{tFt+NqA*GU>)sHCaZpu(YGc0t;xgMQzBF22Vr{# zL*ZY;Ezx((#qHmfF`QZ=Y2*V%<|%ncF9a_#as0N~A3MueAE%Nnex@=i#}CDXA5ICr zJruR3&#f?kJO3(9JWMgJxxYP#>@4J+|DuMDD!mqIgA^BEb~iB-A`) zEY|nco#D&B-3dGmpm$w1XWlV(^A$nadbvJOPyh_Ggjk|xw>hwWo^S0RbQzpx3I@s) zr{s_8P^;E{*+Ds$aR^udu)VOAn@U(umG3culL;~BN6pW;L1g(g{%!Lk57bv<5;d|w zleJMIe!pMQXvxz&DL?~D;X@#1e)~(M1PCRG{c7HGC$#+urK~^YpL4DQl8qK2dkvK|3lmIOTUej&OEd%ZMz1#M zfyHC<)Cq7&;$SOXR<4jCFpRJo*w~OgQKA%b?D;45=HV)wspg{VVBrwmsV1WfjXzH9 zk+)0Dec{Y)s*^RWeEo&Ut1Ju{j_r!l^k}YP8_7{CRHxFXO(|o4K{U#N(=9@jl}*^a zZut+54ODOTQPo99T|5la_tWj5l{YxF1y}M<=Go4UqQ^s5k-+)hRpD+413QwP^}=kE zeE~L9Q&Slcxi>NdU=aL?aZ}9|C8p2dcOJgUv1IWOAALKc&0;E_u(A?)&a0d)n~k_< z@Xa!>>(LQ)*3^*>WyVA@f}l}$1zc0fc#4H5mg1H=dc{A9zL?U7%d-g+A!LhtF)sU4 z;hvSILR)r?Go*2^Y!W++HeO2Jcj4bM`yHah@6I|!$!*rb7HC?@f^ae@x6ObDwFk_R z#wNsaXPs=kFsW!>t`UP};|#c`G#lD%>|{`2XLWs%F=S(p@TYXk=IUxYZ;$u!9*!eq z8j`?d`?ca|nBux>v+zDLx5g=^0%qLjE}1^uvF2J^bah9BM{txiMS!}COq?|$jmAKv zWLAlm$z^bqHU@y>3~TPXTYXn3x3P}!US0kzn3Qo;Ak|dxI=oOzzj~Jopf(M6>FGCvFHZyKJ9d9^c7U;pZaV;9>7x z_<)%2vRTjs@x$OB@KopE%0kHcTbAE?TcHrFflwJnW^R2&G-!Oa z>Q$JX15hosOF{kZmXCau)Pqho1G>!dl~~&6<;OXR4Ilq#Ln78lY;4-Ncr`bi+%N5t z@G|WYDWYz7nstMsh`m7to~ZM+GFJH5#uvsqotJc6g6d@gR!`_qq^;+W^(?l6Ve!J* zNNuiL=IcuXVfr$0=mIPN+3Pa#5~(phO*|MLM z-`hAhdW5{xgEkzsLC?oDyxqQ1`3=d4p@?IPl^N5__0qG$;WIl<45b39Pk}5bF$BYZmmO>AD1mx7h(P~ zc-^eT492h3C;)$i!08W|O|~*890W`yo+49#i?l>hR|{^IaB4wGy4*MZi%d z$dQTNrmwOp5l%YtHdNHSbdHIR7bA8l+z-S6m<1dM%rC^2P`hlqMItaX&`wWG#7XOz z(xKE`Yb|0anGi9Iki)^l>l)+{0u&{VPU3N1 z-72N3f)pM{a?I^b`^cr&06?D3>&Gazo#gqkqysY%T?rX#bTVQv=WlR7*Uk$#Zcr`8Q|D;{LakVzp zD|vJftlHad?e=>hpF^VI`#O}`r{uE=q_&)`8^ta~^}rM4<0SdJ1$8tK`>?}8rKA?s zZrv32LWS!3ah<-n85xXNK{XZgmh&yY!yNq815_!?w7O8K5+-RA|efUV`+gnA_|B3pC?Snb%m|s1;EyrqF+U(loDT=Egh>C0_D1 zsPS7dKYnULn`ZMMnQfjg6Otd$5a1C-eWpDBk6T|T9jX!}g3*rkgXrXK8-if?fIC_y(F_-@2 zkz#nEAcNa1duXgRrx3d$pCb9u@)3&+?lW8M2y;ASx{5NY7&%Z(pd1f07+49IyhEK} zQaY)a>kt|TO}8g^!!YPL)L|ZLn;3X1+U@zYkf77BXdqck)j1P zRrx(xi>N&HkjR9SFaxi|B%RYfDoR4pl-`WC^O_CY?@>cjoLU>M!Dz@b^Y`uEAxV-&s4;8FnI6j?A>tt|a z^jou?^I`XaKDf#?ZB)F@s@LHOiOmC{AQBwnrPsB4GKG~2E#G@SRrjFpS=`MvqK3p7 zL9ZFtR3&Yu%14Ah5*i(h#{PB}F>YhV)^S&X3GjNscIky~yS&t_DZ2T=EcGCCR@@YM zfseqe+K!PlF>?h{c1~BY;|Tj}7>q!$A~ED-bE?jg^d6VVRJ^X)+yHO&>SoCjD+&7rM_MFQLz=s)G+*|a#o*5al3a##*RTZG8|=KjVF>9%j?dd2kHo2P zZ;T{w!vp-5suIEGW~0kH5Ih26(5UhKNnG!>(J_@Z)2(S7&d&@)De3I zAd903Wh>ie(uT7R^06;I>MxMoxhAE%at~@>tE4HcTSoHF^X~dfG$TE{L6DWQQdM-z z#WUJC{ik!~y>-A<3DuYsjeAhuX(R{%)@I6Cm3C-xG2$4)yu%GuV74NIPR=%lgb(oJ zz*#$F@RMo{oo^5Esd#DR9X?;+c0onkiR&?hXMZV2ytX}u^XhA4eDqJqCW{u0?Ox$B znd-;y{x+Zg@mLs&Dy!N@e~CaHAy`p~%ZRHQSK0Gp`3mf2XSYVDHtyKb<=T+e8QYe* z#h_)!Hwn&~V)i1h-@hLxN^}uwzOPD{l9fWzkcY^{`jRVGjeUdm;T zIDetg9AjO%wH!&w z{zHP;k4;beH&Ye@27u*%%%qurc|vjOfgH>wp$WqK` zp3;ksB$Pa=`6+371I$>MxGC83A;k;E`8PlX3>O`NjW0A5^wE^4aFZD5A_!=|OSpAG zRHWMmYCcGaMG=(PpP(%6r&=$7&9{&JQd~}BT?vg8XFY}T7VM=|-`AWkpaxlPwK|!^ z>1nlT*Uw&^Z*oP5xwTuR%fZC3_nAR9$>TfK-*)Fu$hK!hZqW>Dhoh`~D69hhf*7); zogLzaoAM6`7ZJ&WwxXaocp@1LMou>@zC}}+GB5ZEC@mvcd6kf>SwT5AzZuKhrSm;r zTp+=Nm+=u2=2=4*f~oAKeAAZ`S0Wlz(a8T@w9|WamkBe+2^O2A1pI1Ls79#$Yu0*3 zLmA;Rqa<+Gx}@FncEX=WCyD%f^`~%W&r!4Onet$BCAn#J+74IId`d_^ZA7hptC*kS z{!A`|lKGrwrb8Jr?}MA(ZcobR9kMgf-*+uzloK3V^K0h+LXKBvdK%O+~Jt!4Z z*&bbN_M1lVIU>3NwZM{kx&{&Gmvf&Us^zEl#&=7js>A0 zNRCDXR6-OfX+g@D4hIs_()E7N_ZRFqo;~;dT-SA;*ZI?TwzGvbFt@Kkj7=+e=>ab} zF;qp2OWR&Yisifl*#TzLLr_mWe4lc>7N8cC9*!5~Qzsg(G_VH<_M*Xs;3V$0@$C!7 zC?)?QG5Qaw%kH4(1}NJGZH*K0=Ci&f;2f7eCeIc2Y!ob8T@)Z^mah_3yp#18OMBr_ zsczOx?DT}ba_Mm;`=SljfO;3>roPhf@UTPu_1(N;ax`z0v345MvC6vA6>xhL)6(hp zWz`up!wXZ$1mfePidtu6N{YFKSE=%47@m`fi+UZ*_Va4E^HKvyPW>NRY=k#tUW)PI z_dn7(NU`eu#ayoJDe1GOv2p}Hcv9_j7h9xP!6}&+NYPtEz3ER%`qq1hIomm#6YP;PZ#P z;15Lps|s3XsnTcbE2ydTS>5Ltv1D$WB%s=dWz^R*b*Nt#79tElZVa`gCs`s8v3)Fo zj)tW(lz5F%d}>Ear7;I7m@w%(19$~ov2PO3Oqh)jq7oc>tWtJDeeV4rYKn8UsU?r9 z9Zw;9=U-#5@C8P0Rx|tk@cft~3YMM4UJRg}p-TmY4c-}2$~e2~^iXdD2`#_=o}7)u zU`wBnnJKOa{XBnXs!boBN@&#g{_Ip>0j8GS?nQppl5j5WOc(Jr_skN(WjX3oAe35e zrqHzD)YR2}nCwm>N?ogTte|NIQU(PK^k+Ve?86*of|0oli?SY6%O3cFQM-_aq`#QNmz|1 zseV?fy+!(hu%F=V+sDtS)Uq;G=E3p#eyXz-(M|e;4nooW28`w7HSJU=WgfYbE^J!< zwUS_(r2sKU7H+(rsQG6D@?x2s=ERqe9z__x@tbGN-Q z)}Rjzc$;);a?VQ`Oeqf_!3=Mc58YKH#t~}TRqwt^Gs(@-8_`` zI?tQM5_LV*a%U2OHqs{YKsZ*?;&CA$;70m-dxci)a?cj@UxpNjAl&!q6R zBfYHlD7SKK4WA;k-5HnytbhKO(ezB>P_w3ywzBlF>n`!ex|D@?MDrtFMy25U&7+2= zAU`n6LwZgfD|d77=QxI;(!gZX%ZO*e@}P#_&cd-+OOdicE>U3>!Q#fTDC6C)aNf6d zQy*=7ZmAoxw8DO_fi?D+e(SzHc7zomRXIgBDE5J*VX8=*lQ-?@>fJsN|946kxP?lxmAxZ}W?#(VT_0KZrvwZ~J6}8lF*=vJyk7Rqj#PM{On_J5+1(vl zB0neH0Q5GV%nFJD->MR6n9OJQY~}1mUu(rK=EX7T5m08n8yjC^1yav{%mjI1SK;5?s;rd-s}xTAZd4RoYDp%0p8J=9=zI9%CIN0B8@CTQn))N#l4o`;sa-J6w6>KJ zuz?TWX+3rifaMI=F=CRv_VW4VXTf(WK6=?!0iDKCczWGb za{0o-X#YkqN@x(#5BCpGhMK;YEgP$4v`P%)4ux(cFGEx_K6qc4R5Hqwt+P&hakXc$ zM}byW7=h?p(=6RVlg*|3{PfLjs7%9X6Fx*Q|5e)+*(!=k1dboJ?d6A;8IVVgi%0-& z!y=Gtfhrjrwx5nNbpw*F=Ottk%q9szew@s>SfVIU>@^0bbtsN$$z%`Ec%~V6Yn#g> z{sSdz9F!|Aoo&iD!<^*AjNgvGmi}#2V}H*svh)_mNjPq02hQz!yorem`&c;ZB0tHL zLsInW zi3bkCbW|kgotd@H=gET+5&3yC11?LfA~i`*?)>7__VfQo6+WjTlW(FDdH!k;A-L?> z^bW%h7O>-xVGy9Ngse^`HNgWl)^qu)0+;pM00@9+vDStxdxzDF62V$6Rk*d0?e=sEtltn>S9qx z4xp;!ih@c4kWmqRkY5sD{(fG~y#J;?1ddLExFg&sFZ9kM+W-e3+jh0_4>m~+f6ErW z7K*$$fPo-R@eWW`)<20LRycj8+;PalDomF9Rqu#tvmlkChB={XN13h6Ov_i(B*`U8 zc0wrr(EQ#+=C^-bU0k!fyM3I{pMZdEpuw2E3g;7_5M(6QSRP#1X?wRzsVy27&_wTq z^2iNrVU$M|$0ph6TDpBUGLqH;>pL*gOL?vZ*djt(YOqr5v)D$ID{eBUF$oMU>7Oll z6hN3@^hD@3W2;Q`>^8Fj7@X2e`b`New>+!IFpUCqvj#Ie&;nNbd_ z2;^#=y7mGj>B0~l_b(Pz1|(1OF>SU)fvXF(GqvaeWHh#rALb}7?M5x5|H>tgoAT


+jelAdXo2FV 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

dYsiE2N#mq68)lq^yBLy25_u-F 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
    e6`V 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
    Bgl1!L7=H|NLcN6>RFfR<~ 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

    >&CrL6oAi?g)spgdphm)ov%gPc!**mc;HWH;+b z+UIF;DP8zhM-&cM-DDPiwE_Ct@BRSMjLbsNYq7=N-mRSBO|Oe8a%+VYP3y>R<>jOo2WEKuLJ{)3avxhNW8F@L$_Qaz;m~-zC%xr!TD2o$bbJ zo5_EjAv8*`S`g_JSynr`YZ5E@t3GYwct}q{vOqIK>W`I#I(O`8Lf9?Yuvpzrb$8Kr zenwCYMG$d#8Xw+#@YFYIRoSdDzg{7uRRph}_CYk9Xwy}_9|tLp3iF>EQVZkLKarsH z2PbAccKT$i6>8}NDmlaIy|fvE&q_5?@}^S|iqDLr<)aKE{(PH}@Pv*l47{(YWpK6} zCKA(DXpEk7yV%`x3sg+ptdK*Oiq4di*0M-<*-wchgug-#uA0WUYo!TQNQvxI`N3yr zIS(HQr&HSKjEsFz&^}AXfH@O|xkU%M6L6LCvMe-$i#B~%;xO~ypVEZ+1L>EG-mIbjKbIq9|TjAh(+gZs!-TZmw zuC}1HL3eA!ihR>)?yZf z`bXWknUtB{A{#t+p{f{Wu?FdeY>*Sdn|o|$%Su`ijA3DoHE&f#w*p^hYx$U{ z=Opr5WlR4JxV@8m*~s*EFO@y$agxGNf-nU9Ak%w`0|@4suv4wUMcQ1fFFC$&r0=#| zi!q0Agkt)R}szg?QKGqyiCab3tilr775O>`*^SQWI)S*p&bX?STGD&Sc-|8RQj=i5lAr_h zCL$Z~5UP$>zJP{?DQ4yWv=miCU8TQVG>H4V#B5o%VN;%E4#1A7`s+iJviG zdNt@-z3oD|HWg5^e@Z$AcT5DbXupd{xA`6ZsKGM|zTVPzm+)5t-h&O%E$|;9YDXCI z`AFiH36}tfN2tW%jgl&;T$rWgGU#00^4J_1!MNJy!f-O&t)u}iX|lIIOQDSqRAw?SKLeRPwvzdsGA7B4Jj?Ox)$@YEYgV7){LXc*okyN^KAl)cPhf0HV zH#!zHf{YlAl1eEpElBy&paT(Jy8Hb--{1c`?qkQZJ@>0VVrRI1skoQRACsGk|{~f(11bx=WYbc zA?y2Aj^#@>Y5ZDX3VB~EjtDa)SzT?za{I9(4!qmr!wPg0y>k~sP#aq`zlH>aR0ial{kOk2X6P|`vW5a%SZQxJ}GX>-sfjI$zBmjdse zYB&=CzboYR@h(iPHD!`+Cez^itw_wlGmenIX78R$u{Dy~tz>J!;VU|cOA>(5pu$Ku zb>|H|q!E`PabjVq%i|!Ob3i(ZLKGG>pOTXj*|xG+c&yT}I)25)NaQj58ZCkgQ)tXn zHA}O!N$#tO#L!j<^Kf?yB=1C9!BLtDRTSEDV9>(}?E z*qJl=*R+tvV`KW1l!7&l*u>JUsHFP@Pu^R}v4EoW2!>Tdw^Dw|`e`<)zoeXzuza}N z`wNX!1!hg=PELCfnD&tasGiAN0SkW{St}PTZQ>= zQ08LX@eC#lZ?IkT8A{fP-3AbLT+SKiTLdGPCZ;1WU&ePfJOqk~YO!&p!T&S5J8(D6 zLlD*LyN)fa%TL0skE9d30X_G48l7Lq8&*syXJJEP$g|?xC_eCnle0@7t))fS$=Jfg zn*Cm5CypK)-XtT!x&}nbpTH^AGiEW%vjJqP;rxC(eyjey@a6}fC1YPu88l(A=YYn342RhrxGy|+|?sO_j9OR{pR zg%Pt1w${KE=@E(0+px$gQY%dt@0#6*TV`2Y@^QSNsG^QLmHi*I;et6B_oblpM5hom{_HkTm!S z+jBYe7j2hy(iikoOezxn z>O?DN`OBn*+A7bTxOAVyj-~<+#6BtKe zuEvJiix07FB*YAnQR9imaeh+l26eA;L91kxGq&< z3Qm_(f>E@ZY7oNLb7R=t3)~SW7-Xi^D08+6g$Sm-*O>dP;p|rdwoqb|9m1u+GyC3= zP}k;jVj922LXX-4-OLTby?p=0_r%|&MQ=T?!Q?|;od+~Y)KNFwzC+&#$kq&;I+d`{D5< zZCGuCF1fMAhR?Y1W{id3@%d(5(R<>P=Sm##Cp>jdHvP4oHN*pB)HGXZ5nk8FKbVuX z1m252?MBz1GFfZXzz;jecE@Qe_KX177!7~ECV%mhnQEa!9)_${U*h`v%p*zBbJ5e~ z68{L^aRqIV|Jxg;!HQ{()-wwG9GM_?NicM8vuvHzKl!(yf|;cb55rh429socs9}1M57ApJ?FJ{>Rkm{el*m@n{6qVpepPTqCVsA5%cI{( zO>ki)N8!0RYeAu!lDb;wn`v7?Vty?RdU#hd1z%dGmwO+lfm?L_1rc>_bD^miLw2{j zgIiXlr9Zj3?bWMW*zP74@tQLEQG()vf7(oq2G7X8kOPx~4p@kgnr2T&U+1-gEt!rk z&mgmoy@5S}y)VCzM15rPayv3rkw?sft-Mck9*U4Gx9Ah#&5GF!(`TK65uz2w;vW>3uxrjd*r%x*&1~4m4H4|h@#_dwX5U6Ya zmO!g>vRpz-s`V3CVMO);sPAd43-_6I*^LIz{tC~^3QY1Sa@EGj=a_9n#^VPzd}5-b zlF}-c(rhRt=09QR7?%VUNavreWB(WV9fVWsFREeRO{V^q#Q1sbqrVgWsyz&c8BqNm z_pcCQpq5s|(IGjgGxKlNnGpT171zH^-i;FIlL2 z>dK@Ywgnl)_?zGrsUrfW7T)@sFdRt*@SRdfT*lILC8^{b$t_PaA*=c()dAkU8(odJ zp`NR=a_=V4zV*iXkcSpbS;6i;;pW^nHN&|kiu0FT`@1Jc^S7JQN3Y~0nnKU_az+B-l9SV;#BT8sXEpr&&U?Aw&P#5FpN9rn(gR3!Rf<(D9xeE^) zy&;$+k*-Sd|3GI^QOg8uRqsr5*N2_PW1*h82_lkdw_2$2=qTl7ZJiQf9DkOQ*ekz1 zr#(p{MNhN!yE|ZC;`EN9~jD;^YV*}1Ju3y8qi1!inP1KZG6cW_6CJ;f(n_11f1;bTxyU8 zSHGP=#G|)#a=g#D8hi?zVS$x=&At-Ejy&m_okauuv@nk+Ua@c5iiFRg zqtxpQR7@f0CJNwyF5D{*=rq@a$YRXbIo$3+vP=OAN-}D3?G~lECJ5&6V!!lU%cioG zz&zP-R%mhOpEy&xC+I0=stuwI5<={=L7pWnDFc7{!gNusKdP-+zeTJ&7>AtJcey(O z$Ol)D3B*{}Dsuo%S1OD$cBoPtH$oH~PEx0Y*Krp z*%6~Ea;XtOe4eGK)#Zp3=xT|Pe`yp^{6~;kL0DeKfBTGI;2=%NzThYk~eAlFt8G3GJRo zZd7o)Nzxk4)R3|izJi|BM1eB_8U7;L!U=su24z9)G+ ze4YMWS9H+|0P18rL`6s8Sg2GT!UT6`MZrQ?XaSA0V0Vxu2hD&yw*o!0y=}=x`3nXb zlU3gyUx_VAlz-j%^~K+WSnaoI_YiT7s>^UD}g(r)0g4_Fr;;ulNs>%C+w0d zQ0u`B8eMKmsv}L930xP3iY`H- zt4_GUKia3wD^IRW$y)T(ldM+MkTQzUk4s6CVysb1o62F%0^|bnCaAS{LJf6=b|idgQHMKEKisgJ8ZGJ zr9ArIY4RRJu8)<%s*}CUqA!_j$yG)=Nlq`veWlg{zwDVvg9sH4#N+TYd8)A%qp_(-#m%Nh>7h;LaxMZ&DfV6Sw5P zSMU0A|6cm4kN+X6OW#E>Np}0qoxOrk*d+6>U>1U}(v%${gft3R^Ml!r&J=dY{C70Mm?~zq3?XxH*`G8PeaMr)?Fz9|3RiY|)fwIhc z*SjKyOX&VIy`J%pr!mdzb*wU)J6)G=>0?yp*4Iz^E2w@kJDIi0S*DBYebgKH_m{5g zyqP3FT!F(|2qTVrCJg=@y&c)pVfFb-vx08WhEIg> zOPz9qs#_u2+)d{1Eqe@|Qg$iHsGdsw2b!?ag+w0Tc1>4zG5lK=+V1<}5*M z*JmiYQ+@??TbhmQAZ|`p8UF+MOH}*^TA*uuI+W-f_-Lcpz`^olnUb*Eb67dOa%e#AaGg`h>ix!2%^dnum!N6;Q+T;6L|BJ4I*E2q zo9?(bHcRDm*!QfB(!?4z?q##8mg$U6M(v2T0(3|INjRXc)hJmWKi7hkAH9=@etV>w zwtq!!#Wui#)RQ7Ws~rxgL?!#d#ffP2t9(p(Hmn)lD5#uIy?DEDN6NQK6=gdw;&%tW z4LdVmBb~cdqT~a=LAI0FYZ2cPyv=D|iF*}E5sZ@(0R|G|f5=^7CQXSB>O<@%s&we$ zVEEYg162x@*1ym3x^pY0f1OY8#_FvUHs)gO++9LJ*ak&xi*bhQlX;m5gD?BQ)&H!d zf%22;dE4#bxbm&xKR?RscAGp}xB7fc9ZeIeh{>(ek~CcI0AgifK^sYTJd8K9l8y;c ziAI1wB@qx^;wzSNoByA#XFheEN={L#-R9%lL*ydP=~Gzt67i4AKacnyK5|lR6hec& zoVp#6q=OUehO?CU--}?fNQ=4J>ds2rgW+G}%9j_He^aGn8mJZgvL9i{L(VX)JJuug zS4l>ki^YMs2byzgWCkx2&mJWQtW|psJEP(;NE&_q5Yq?+GB|Nn{4QO%U5XnkSUK8s zM49~hlppK#gUUOM`(XhzrWifQ?OXY=XqrA(>j>_0TujP><3htySkGJ<8C zvp~--2)LJDn$a$r=lv*HG*0MNx?)u$Nq}$$dt@@ z8uNb{KsA!}Y zg@F518>SWo8l;;HNQ*?Jh_N{Hu@*+ogNFx~F1EWfW~~A>8Z~D`l@1#pxpv(9(|!H$oXZOF*M=zame>s}D)8l`Q=q=yg{a9)4p5A5V_I60L|- z3FpTy7Z@?nf)h=zRM3p#!KE!gPkuNvn@@{3XqDYV+MJmZo0(Cd+s36 ztEEcb#rsDS7U55{bbZTc4KBjws+r)fBqiC_FJEjLG=>K|e*HoM+zub~@fQ-Z4PY)A zZN4w9X8G21KBYH33uu4e{o_inp-MzPUgnj)1wE>7W^oUfTKV&-b2glbTAH>c_j}XU{fgR16lp;U!gjSql>~$7C)qLuK zp6CXbHZJ_c6BA`$T_bX8nmZFteOqsO8(1iGxJ^EhanL+1yq_NVMAA0T_8H5InyuTM zdsyU|0V|Y^l=4c{+oN+b&GF=MiR*6J*&_R0vfj_>?f3MxAI*m!z8)y-Iux@n6Dk*) zdCeu#8CSCtz@-g(zYNB9NW$GYANrl2_b!g`@ktHwW3D&>g=*l(Glk3r9)%ms)5ohX zr#hdES>U~fe}?c`Z~e(?v=+C}c6#QkU#Ey*`#v{Cz_Nzv-EK~`y-|@i@$rzk5>R<@ z`r6B|qhzW){WPSaaaHs*JKw2U%v(mTdO==qG)u`j#geN(sziJV#U99-$HdAD#f;!x zGMjfk7DR0u-IxUOzD9kzt)6{4Va9syFS@W>k{$Q$d6UPYQrAJzo0obbpII2`R_u0M z+?{*ZsN*$+5U9zj@Z4u}pOG z^QO#i)%5(>#PWQx`L?(6BkHon>&2Ew`nwPzM$asB#!%#{6#M4U4_f~s&bWX<)Bivs zj#Tb48;Y1G{FDrhp_1e`!MB3JsEhER>YDa<*r&J8UlFkXJ`Vn3>$TvT5?X?E_ndfU z1iPM9HA}Q!whrM20-#@~Jqz^R`f-!y0Y+x3j1;oT9&)dC3E94 zgr~>CwK6rm`ql_^c9q)YXYpJ+sQw`AyNvWbt?%h>dl4@5k=^^Jlu|s=5AQU-H|KK< zPVe6c${hH9xC! z@p)n84p*uiZ0J<&mvAEZI0T%5xPVqKe|80t4k(!rD>Rg9=wN){wl$ z9yK{v4pwEU0pIATWCzo|ov)0nCT@YJBf<_**y$ZtppodWvNgT)C(d{MQ69m=cI##J z9B_(y^~z8mrm*<~upNtp%y;mPM4JiPW9N_skBjBPQ&btPsW6RjvNK^v zhTDTqz$@UjA-zu15AWZX)Q)le8k00UL{}4ex9Xj}pwW7+<&)WYy1bQYC@oIWT}M|P zZ73f`7R>O<@GcV*-{K%eNcMu6WPssj7g&egZ2wWG&1ie)7BxkCwn}B})wt{;c5ADT znD@(7UE;F>AmX8lmodrNl$E=iL*<{cdZI6buhqih{=6V_QOF@mtJ$tz7Z^lG-O759 ze;M82e++3ve@|uef$R*(Tr8uKZecfmlg1QE>qU>sAEs`zuXL-8O0lnQaykMh57uM5 z0FuaGIX>Ltoc4Wp9a6+V5w-0L7?OQKMv-WuCT@q3iiPpoF`(0zH+JtP&+8W(G?{L`V+H-ZZA!v#MOo~_J#o8)RitS8b6 z;^Z^;L578aGZmIS_`R2;=sBjwLIpVGtd>H7X%aCwkG6ugvFNvj?xv4NyF84&_g4Ik zpzJb%srIC&3A#){m6F>3w!HFdu5s@}VW$5H{AZqtc?^vf{GHC{+o84)4{ID!y#BI& zIBmf@OQx9L>!W)8q=75;f#AT5<6S9di;+6!>3N``CBqWu(rQk&F0=Bcw$D;{6M&d) zGuokjXT#nC>Uh$mP|-He`o2-DP-k}#@MT4m>Q_>x4LX0J6Ewq)DQ{TZ&B+1zse7Z- z+y;|}u*9Twlf=ba3ZsF5DZw6af~AEO!Bat~0>8POF^y0es$i34t2avU0h8=1T@{U} zOuZ*FJ;xv8h=RzjOA*YOP8@AZWetz=j7bal1)HqNQAGV;LD7`2(?U%Oy|s-3OK*aP zA0XCfxMCuZsDz(ZLuyNib-|m#3^@Rk$gJXw41+*OXCwHnjE4w+*<29q$qHFW-;Qa^6oISn!XaYKDz<7XurhCavKAh@2R@|6Ct2D)>2>E_E$QHO9bqCb7 z!S^QxOzEt32p;muFgmS;IXgOZ{eceMwu48wtVR~`9P<=cZpx(PizGT^vgZKNDGQd! z`VBWpUDNV5Y9j!?Qb^t@cf{_|RHEdy=zV>H3W`j`+2a$EKuh`THs_9{axCEWn?O7|Yw~$Nn|vcl zN|9GOxLq#f-1{03|H6D+x%BYZxnDhMzaB_RhMseTZ0=7pT|uce;&i0wcF6|ko+X9S zy2wKBmL)uJby-{0F1{+J9rd2O#?~L7_^sWzoGb!h%da+B zD4+SRJge>rE&;+)LhzM$iPVUgR&`B%E62$^v~`xC?6~*UEukS48t}=NC4WIz4hrtM+r$x&zm3&= zRQUVvv8(o6R=4rUVERWac%tx4tBE%+&FsRW`J+~rbk(3LpQem;n%1q)70dJYm}?l` z2FC1SG|PfT_h)Vn2skFE0E3=Y^}HagEM9(SnB#|q18}604%;>VCnzrT{($ZpraRf!{{^j3Im!w)EL(-MIah zlSIx_Kqc^92{rlylGS2)L&x`LxrKEO^2S%v5QqzUre^R3X^eZ{qocJ%*(40^_{Z|D zB#P#oUEIfIW3yUd0y6YmYlZxb$5#z7Ct_O$4WGVBP>7N4%r@b(pY>)Cav*ZpymI06 zJD$)a_DyNOR6VB|W5wuY1zEx5COYIUuQ}2wAHV7mmj89TtqY3Eqq13((Xz1c zMo-?lix4Bj4z<22TskH;+A@?4sl0sO1%nZy9nBW*n7L`Ow1#t*&RnB9qdfzujpmuu z8wj+ObnHs~d?RfeKrKU@vH+`-Xh@LTA8O?=(H#)uf{BL17jIgj%CdjE^{&O7NxO$~ z0{Fjp`@9%-#wICp1OWC9{ZvxVX_1(Mj{Kh9>F1-e%mDSf9^jP%Y z(I^|!Z*4*~2Q z5*t}vfF#88qY4q6<};aZd>eM%dd4@H!^kU2Ua+= zZ{_Zt$sL}vtB|La33a~piuSuXr{nZ<8jU08lV!LXn}WQx^L z0+#Cnh?jqdbjdbLU_RBT_x;Ag@{E#R=%DR@MqL1^swr!s`*}o0Gufknad1oLa#QYd z3z9B1<;$%2q6Oq5Vyg36G2no7cTmF-IvL_538DOwLgw7suwZmj$*dfutz$4ran420 ztU$?Ua|E~W5gNaViP~gWY4<*fqpjHtC+bGP%_#AUF{HNv({qBLuL2zzqI-1Y>C#I@ zSt>thGR~N{KCnZ7!watbb#{1j!zv_`k7R_9x$pkwg7nU(dF1%OE)IpxrW%z#euImf z<;{!X2?09v)p<(a3J6&#FB2mYRiLPXz@IqKYdwpsLdzZt4GPLL!_`%?$tS|b#=hXUe z?}D8Y`+{sp&|mxC4%VkiE2Y9!7RIG$zcmynWSd7luV~6R*4fqR4qMw{p>f!9>NCb6r@^-4uTu<-FK{0@JpU_SrT*Anc@1QLZ;Noyk5#W<(FGv7 zlJDho)|$k9M8(EQr$3wGU{8+GIgOsiJunhHC&C`mL9G0U&qY~MfwLx?k#o;zwPeoB zn~boi4Kp$_!Yqz1AsY$dZ5Te>y^c8fTzUTg?JNga`3nM$5|41l&7TX9@n~N#J!p;WONNqM~QY1TymOXDo$p*=huV5B#Yd~@=w5t-eP#P9htR! zp+PJUlVn*;OV>EDXItB7?;YBfHCag0h`GNxm$r%=r}N>DADWzYw209QKbGLfu;g?N zl%~LO8>%ox=Fgd?3!~lSE0eT0C43no8pS>bu_LV$fZ=$QA4N=do!I3+UI|P;f@=_*ZV?cW3}4oFpNgww8Jm@i@71POFp{ z_j1Z5;3@AAc$;jo6{ar{y1V=xDB&7^~?MgCcZsm5sSqNdN^-vqUev}cTR9g%JGOqutb{_{TpxI8zR z0PY=J?>4fl%wp7isU+)~KppyNtx8|4rYq_wNmU789UnI;cO%xK>kKwBCMD1WBZ4n8 zgyb}{?95{HBDl?t&!J@-nH*jWBp*&jt449~1`!eenD{hFRY5qP3;P~7W)}9 zz+oCiK2EC1!;a3=-9|}~^jLPgox~scVVWx^3jHO4F;;Adpi0eWOFBC4M0Lhs;jNL1 zl{ZEOc<}CK$>N}(_x;`n^&I8qAB@T=i(pAq*NB7`#R$xQprMyf{P_<}HFbk5O*^5i zkrKBL6Y+pOtKe?`aQ_a4St&{d>d=aeu!g+)_Uc5o@sJS$@oJoB3F3D;5(+r93q zJY|z4)rq_JOg~DO)EYB&6qr^UFkR}|XgQaoe&;x=9(Ix+*fALo`k4Y)8jya&i&w?C z$TZ6;8|{So_Dss9_sY%?D_1H!b99n+Ws{2f0*G2I22G8Q+}m#-YbK;izHPIHgJh3) z77NulqpOgMn=}4wqPT#5QVo*{OvvX5>;C$udc9z33frgENQ6LR!_*y_Lq@3 zC2jFmjz9$dRyL=}dBO1Z#ZR5L9;xuOyw7n;ZG)tPoU=2<&2mq^FHZ`je^k40XEon+ zt{aOPOj!q?DTjf&QNZ~Yzs7`2n9Lk)pvjjdbS%nW2C;jBW zL{IL?Wk#(>(6rbb_lA9-@{GC1aB-X?(at8|DTG%pwr6&`09+e2Bvuw7!yV|iIu7iJ zL`*Q1PtU!pT=0>+ragIls$M$oCLv|VEC(Dq*oz`XmP%v^^Oh98*f!Q}nZ2p9;+>JU zNWQc6%jkh3YXI2hjz6W5pZT>_fVS>>>%F1F7JuM*pKMpXY-V@DOu)RUmy*FAnER)K z>j?sa9|Fk0+a|6E_oCLb>d|vn6|auMgDDWlHpB z4Ukw3vD=m~LgKnBdIE`E=H@JPnZtE2!Ta&Z6fSt)Ftd*@enu8N&A&l&+c1bM^HA5* z5+-aCck6-v3`pN(^8_6iI2@>M8<+AzrnoFjAmWSZRQUyh>y1Shx2W;3K;qe6z3(-B_4;OewObr%uf~L_twyx*`|A5U3vWI+`&7m0RYbkGq zCoUtnOWP1Iz7Xf5WQ;XV8371vtKaOYq^p-m@3N+MBOrL zsbobLq&SkQ0uJ=pA5^S7SU(Cq#FyM7A5GC}t{juuCsWmL=p#!R(AUi&Jty)F`nBJJ9S!3es+o-M1_ zEMc(WINT^(1Hq?%9JK7c3G0Rj_oAcTlM4{KFI0BZj%>Um<`WSUvO!G@kRMOs7Hbl0 zeL5bdGGsbY(z=X`n;J(&sSO&c)2@>TFsG)9;wtl;*Rfrs`-8iaMB@Sj=^T{grNN_+ zej?*i#drjVzq0&Gf%rH9DesgkAB4!8Ldil&_Gq(!jO)PD-dE4VQZ&-%gV5})Be$Qc zk)elJb|t=M&{}+w$!GOAX*HOAP+IbGNY4bjkb%SLb6vrO*l7qnVONNzvUDho*4L;9 z=u0wKXGLnE2NpBtJ|H9<#Dgnf7`)t|(eu;~A#JIVx{@hJv|~l(1pF@+QP3e-&ed|= zh;fScglMCck;(XEmvdW=;+$MCsubhkROEbK+`(}DC8r9z^2$SDbsImy(Xeh3)hAMMF7~6=J+%GYi)0A)A=9!`pW6VYCYm!~8bZBr8F0q;!U5v;+ma9Reaq zjRbSvekosDRNC75hV}k+3{^=l?E#~JK9TR&4B@}%q3RMNT}cf+-SI7$B2^*jfP7H7 z;De3vU|M<_0TW=%*ew$!cQ|NTzWsIu3JEjwwsabqtbU(T%9Y^h{;+4_`sDV5%xRn#fp1X3%A#TLQkz3CHP942}>J0XSgyk)^4H*&+L=DOg9U{Z%X78O*cIyd* zQbGM5k_9iR4J;#S?o8Hiue2Wj!%Jb@AAbH@Un)_kAxrrE5uks?kiucc6d&gbc~71a zGB>%0JGefH?>6;AV%xndoB4_p>Ntkun3e{e^`rn6NXw2yA-2c}J~x@;&6v{1V$`C% z?|)av6+v?wt4qsa&SzK6qDz#;8pk06A_={lyAD)u=LCka+#1u6kCsN9vq-*=Ki3~f z@Hc&|tb0vAjg!ayrEM+?4ui`OUP78AZa$|0ls3OXt$Ce@ti9dwkKY^O6J`Gc(Y?v@Qsb3VW&dLq?v7hu5HQ7K8rtD7ICk=;Ao7 zbWll#EU_-zp)-AtZgeMAPi)&{kHUVf5a|3#UQ(N6X4xp2A{aJ|{pTbu))4V{?3r$d z7;TcNCURzEgaLEvL~vKd+9vxz|&ET{M5$N>{Tm@5BO zNw+uWbR>13@*WM??McJ<9y zhvWj_srX;I6Dm|gD?!rXwl_d-9DW1(~lQaN<1N{%n5J8rQ+d!+D>Ni05Vp<-A$ z%n7aP)LEw3tA04xu4C+Lt9xZ$b)d6Yv8x-bmhV&5oJi5PoY9iZa{K&AAijiDA(IJ{ zDZp()U_DRG9x16*OFFS9A4cB7AQ<$K0DJK7`(H7?U}^r^Dt_Ht$?ZHLnu_`9g74qs zdd{Suh`4qYp)w9=G)VZI{44+}L0WT}7$ z^|RLrL<;nVz;NjVO9DLnwsz!B7YrQTg>i&N<`46c%nhrlmRbuHGip0>$`Sw;%P_w} zvxk@p83aup4Ijhg&arLe-X5=`{eTqB0FTX3@&5h>H!TOJ$Zndcpt?JsjKU-g!;_Ay zI4&ObO8pP9TN1bGvibX1D0a1kA*OJsyho$Y+kyF)+RFNMf;SKoCLgucAtv4^$!REl z#6FpHM%xh8xVt8MJT9*VqZ2A}cNYHQ(vBv7{qTyxJ-$$vT}bmD&(^w*F`hej-P;6` zeL)e?)nqmDhaFdH-AN3pN z;%p@?|46^U97P{Ao$PNxo0t+&8xK%qE)-8zHP7P6GT+Cljg0b_EK(55S(=~Gci&Y(#A;#=_H2bJpEF95o+}#}5`udlc1dLQiF4W0gTg%^OlH?K5>g0uJ=aXYC1 zCJt(Pd+Gb>VZi$g&{2dM6J_NVF_&VoF`;r?)M(uhSQ^M~tX5`iL+zc8y`PXW!2tmj zM;JLn+uxxH-wawpedhwH4x{O=QZ87Ir+1rM&eYyH?bBb0@Hx3k-l0q%pB33&u%VE- zGL8Q0K(Iyi_eZ{0(ZBN8uF6LJiAr|?Mt#`Flwj(Adw2dAd}K#$RM~rzNG`_S>g)r7 zAoEI)pimhJI$X+|4!j#h5dM@?WeH#Mk(Tw-@ff*8O_+G-~pVEyh^hHNL(Y+$lI zPVGj~zPechQLx*o^{;&pF7oJT{opef7o5fT_o zJs}EO;BvA?z4aEOS&5d^)@I4poDivi0-Wh}wnB+XP=0Wr8K;SOpQ!N=pJ>oP^|iA$ zCshUZ`s4;?=Rux!Bsj9GuEdQp!3~|VZBB6b9pZ87w0l-7H4L756r^Zf$Qq}CHf>y} z3gz8bp$%!gM>>bZ`|q@A8q!m6_05}yrFftcN-=#^ws(7B!)Tu4o|;UXgjg$)xO6_m zm-Aq}8%8eVdmm_@f^{=b{#n5_EDm!RD$?PLxgSqmkW=axcHveEj|C86?o)@XVsr65 z*GTO0y))f(ZILR{e+BpW^hHLoFM2NVoA^?2n?c7rGH7U@KFBi*Bw%XJ=`VB}A6=&( ziJ^IYC;{_PG-v|tgBNx#H+TkRuTOqo;|%=iM1q*-CmEj+wTyY*#EdBqGP85VBRdm{!-_rCU-Gc0v* zE`EwR#~{UZ;?Mtf_~w_eCiH&a_NKsyupETm)USF*N36S?41N9QyJDOPl)!jBt(M)y znRCXvz@-2P0nlG zS(*y*iJ-V=a<@tHzF8#?Oj=7NytXyau{?>hP2>W3$|Q2ol8;+<+;Mf6-#cb3rNYXr z6SY}wW|c|LRc@Xq&oh=p`t;%Qf8RVE*ao|NdDGKnRjyR59c`ueL3&$TVKCD=HN-j( z#?SHbA35~Lh{G6WfRbgH{w&!QKNQSXEMVKoGx0~rm$Lq-D8ldhDQU)TH}mURl3L9j)oyMxCpZ7l70>^ z^KB@Pvkn~&amaH|5^R5=rsy1^)Sptg3iWg)nTJuXk$8q4$@|SJ9dzO9HXn;jNg<=??6c{-zxQy^BUGV#{!|)YpC=mlRPT5FH*FKOqPmMKcV1Dl{o3I!f zc1aX4#gkYh+HAWr+bchky04W;Qh=S#0X2zHOnHrYfG+L3 zRx3aiOB4pM4ED}aSUQxCX6w14w$XT$-`!UwE>VG~${vdGRB;NZ+sL}Iwb)_?Kws^R z9H^q-{&+|SBXx6wW%Fq=TdV^4n4C&V!0^q3=feW7=<)*|i=c&Wc)zbn&hELAkWt4Z z-y3rq%^2oe%@=T3vuWimtO96bO3LDTmV3_w2=l02Pf64vl6#Vk;h_|y|A9Dx7|!UD z1Fy8qVF7e1r?9}vw1eNLLBMD}J>}Kc4sMXp5hgn?7W@40`|+hmbtwPMGM5~@BY|5a zRx^t#8Pn<@;CaOJ+J4(?Xe&jZb5NknO~(yO)nj9!bMb1xYL@cOaXd=iUxbgkMm-qe zsmoUHL70Y96wV&roM<`Uinp_*_wkydmnS7Y8Zqu%TYuDdMJ~JsAn(M9;c(s7Xq&7Q z@U#tdt=>}3DiNi!7bav7gm7>s)NxE=Wh8nNL*?wJeRMfs80OL*sP(9}Oa@vHrY;ik zWd9=4c2t3o4zqai5u+pIQf2oi{C9#f0M(a~(-6Xcp(M=XPiGWXYpUx#k>g;#t!=DBh+ znAj@NxlgEN#3nDc*+MQ#pg0$0`285kU^yCgzk4G zGs62d!dh%Q<+^(7g;p;gMKEb{`O5XM(TayXFw_%rJNcFRQ$5i_iRXI`>(@qws*xiy zm47E=O8MJKE_$o9En&h8gKfB6M(R9fB95S2)U^`F*3-j6r61X;eHt;}`$)|7m7~5N z0Y23iJ2>i%FxDv7lmROkcP00e@W@)L@%v}YN@QLPuFI2x@f=W(fq|9D>O6*wp+M;Q z1c$`*6vVits;{QT0Rv_4Nk}djh#p0PF1CIU(ptwV;EXE`Wkk}OP{yLW4Rw2pRF_-5 z{wCoVCR+tFNLgIH2u@<$TufPZvqIxk6J;j+_v0DHCPB-J6ckl{+#&0TWtUf_u6&qh z&629F*9WD`pzjY}%Q`YzEjLUHdZ!CV+Ksb13O~qpfkJ~9&o^;-5IfsAbC6>YNWu%5 z;7!WGI>`K2PdvWeXDmlHG)6DWp>p7{91qtQCTI_bj$XRJgmD|ZfSEq@MqXm13Od4b zgKbj|^QDK4sW%o!u&;SXQL8S-A|*pektsw(#R{H+Il|lU!D)*>cC8dWT|WEMe9e4x z?{|Wl{b(H(Z0@rxCSDf+!t7ICoEHvVY%~AWoVU#8uscwhX7_NaT3-($*;vEy0?Rd_ zh>#?#6M4HS6jya? z+CR9)iOdm*Rehl(ovxj>ypbY2W|yKsG6O>1SN4~OsZJ3Di?KfP%KAT!&NH6P_wB23NYnLi&)!utVBC%`4EJa&Xi&DE1qjp=nG?XZ6&(bIV=T+Xy z{gLas&-47A$05-tr#A@XDI(2ZK_r|6TMnm9o?b2>JZgIZ-S_erOy+N_Dhc`NNr9_V zya;d)OzM%~5q9y!Z44+}4N{AisRopY{CJ;kL}X?2dMB`GsT4|Z#*Y_+F%gdcCVw~h z&Y?LuF^}|qn1#D{rZI;tA)}X~U$OXxly{o2~e4 zarG>hJ7fs|1MHeOjw%cdXj&IwtRn8;<+0{b6y>Ml1(zS3RXdq3(JvD8BpRCTG&tmI z8OYY$h#izsH=!CI*K!uEb7ZE{{b|LWCk_R-RAX8X! zisRV5?vRe-VQD_SB(qopiC;p05+vT9C6tm;9g&8Xy%x_h z-ydZ@cIJX42jPUz`K zS@P^iGaaJeXiFBV*LF&FDMK89 z3dpxqJZ=vcjMcZ;qId^iZGC%mNA{}w%OrJ(h!P;kVEtoD^R}Do9j^{^nF`%=>Ibp% zL!?T-%3CGOyaNhmVf{+l4pjaE(N80<^%=r?VdKfpNk9OF#vDdWJI(v8JllZsviad^ z#~bpQ1D!EY6z|o?!loVGy0Kt_Ckmo;j18N0Q?xOTA)Pvd%II<}Lz5K$Ja!4|!iQ7L z8XK{$zH&^6{c#Jha_wXtS43uQyO?2<6Gx1mC3yNDpdhAOOUv&Qt8%ieZvH9X;D59b z&DMD?r0Fp;={9hzFllIxr}uK7{UYGA9uQR-Yg-&j+Gu?uuwq+V7Xn)%=4A2}OZb>) zmQEIXK#R#Pk928)*G}?Ww&IF5J{{H{R*k4Md#L~(_zgbh&4Qzr06D`EvwCia*rYj! z(QQ)(+JjCcFfvGVQti}HUoJm{%>dj{fRSx}+C&X`L2B)h@tEmfbhx+Fh1C2GS(GYa*q_&d8Qcxb!vKy`)D?@J+F_t7QNzd6!!(j zq8K~k1?L2;J(kPFbrq$_&(vL~nX49QkJE92i*{V(+O0g+k>QE_?F14dg!2WFAx$>T zFeR|ZX;z|O)s3G4rG7*t`vNuP%&_6MK~tM^o;tkhPe`5ne#}Cul&3E#1P+Hm&rcO~ zwMPB)e~-yR&?FHAdfMVaM`Z@?eF*Eg;C!VQ-b$v|2e(q}x`8u9{lBqvms$nyeYas3 zVP6H;kZf^d=s{ogs1v8kEEauuqwM2v9DU8Gm-CqGU8Emdrat4wnZKa!73NhFIaZ)r ze3*`>S?cB;^xxkA5tAzPHHkidr@LM1sCcTQO-#)F)VSL*zyI(`|*S6XivA4`YO=SVhHxhq<>T%{Z{rfg!wADey7k(XqSGY=FRWMqt{ zz24xH(BdCvGX~{Z`^4tz>WmQ(ocvw-I^=5KVw;sw0fUp|9Z(75@j-4g6ch}9_T!3$ zjG<^<%sAXX#m4NMZ0(dC5uG<2*b5owJwo4?rb6T=vf*mKB=dZGIP1?7xltUqKP3+Q z0_k}kP{F$Gs(YA4v!bG3oaNv9zn6@3-5`sE_#*pB2~dSN;-j1R60!Zd5(Pyje2j3^ z+MYIQVrS^}EY2NK#9gR;+C+zE%*>bZ$%4BJ-owqOw63gXCmH_6 zc1p}TXD7@O`-B^ZLQj0Hq+qOF7ZP|wZ`#4o(v)Q|&Q^Tph*acbu-D@=aLzGC6scJW z$XW_AN#5Pshz&Q{3PpOLD8#CC?0;R+iUZjPwl z5M_xlGOjg08c0^ScH%(AKLC5|y5=#@llet)s-)9MChQUM?s8m9G_IglR>ZH3-ix798AZGw3*Op2B$X!xQhLh4iR6Q4Ere*Au-Q-Nh=yp-C$&UmaSYOxEQ=s!HZ=k`Jz-W1a zg3RifTpbF<3&f(fSLVIQpf8yBrIJOL(^}np^;@vd4YgNzUE`TfH{-S|0z+FYwI2D) zz6i*rYXUY>gg;Hl`Jb!22*6kjX68KfTtTC0FNbb?asa5yu#sX04@jxZT!@w!rxX59 z<3;ILMmneH%$2{cW9rjYs5z=>=`Ziy@UUWdsB1!@6*@k~n^ed+B||7RT{FSJo^7?K$5=&B)tL|>ggw0n4)R`s#}@l`9^kyf!BOZ8I#H(x2Boq&91?PqV$5C(N=mm}F0_ME3+)^nDqth9J{G zJ@4xJ+*~T)IX;mJ>?%x0d{&W2K<;ZWsHr1KHhv!P_v?*}+U0sgS&tPBfod>(JP6l3 zi{fi3sc0Dl?q=FJCXWeesEyK`kK?SzG;IozgNN{TpGj*$yGm_=+26QCOT1(E1-RJc zSCRP;&`nLr(b68nMXo9IZWldj_wekLzH!eKS$NLqw<@+bKkcrX9%LZ`pO-q&iilcU zagQc!tQ8*MBVi_G-qc^pwjb zry;T@m%~|wnT85q+6SpF+(^YpX|^b>yCjqBhacup4Q@N?8LlM=SpE>jr*&Otv&UK^ z7j36vUE=7kJAC1hjora1ZL+<*K$E#q6da5qjGW%6{R7lqov)QvyVp9x8?NsUwSlsQ z9d2)d6-cNGU-;(lQZx3<40o-nQ1q#*aC7~|0jYdcmSK0Rn(}t)b)mME5_Abs-r%Xs z9=|->vbm3_%7*AcbnzqM?TgDZ*R^q%{M{Cadr_9wHF zr<&y15wA4pV)td{>$n5l0AUo7Byy94#@b5-hF0IG|Hgi_Y3>0?G0$=Hj*7x6_77sN zPq@gm#gExV(?HRc*mzPzllLcibC04?wf(O+HZKqXTz63=z1^fTfna7bPXSm}*;SQ@ zhp50;Bz!4yMhk)kq^zd3zWfBDt2;EJl9`ZMrX_`v6C$xDvvJ=J@4acre}!COcF$c}raJ*jdDY&)Uk}Pqv>d zO92Z_7>teb8TqDQ*-HaFdDX$k^`R-DLisMF1XvG+VAdfh#dAKX?y zK2<_EXlwj)2`(LL4Dm1!J%O|%J7#Sn19z{osg-6~vy!Nx5VZLR=>J4f%b?!<}G-&XAjqP=*1X8WVD*Fq*=XR=E_L<8xEXXNtaS*=AmPZI;WBe=-UeXTN@>hhpt$cwiJOpM*QY?o1S>t(_XJEEM z*KGp2;rbX-k0te{W9Xx=r|0H;AC67Wzi1Z&OgAq*JDtn(3WG2h8tSZaG{rZVijJE* zpS_Xkr=$FaRHB0g8+7KAxx*~4sIF|n6}q*}?01eo3{#{l)O>H1*J|#Wm6~9E=&qV; zp1Zm9vq3B=`!L-6?Pgqs{vFvb48YBIsPGQwdKIRIAYrE9W9#(G(61Q}=|xJ3_JIu_ z7D+bTU*ZpG7SSEG%XZANLwxSP?LDk|4$JwQ=w43pj)t{9q}{E3vo^W>-(9~Jg%>;3 z(FJASa_Fp%?>@*ud56;~Z@>#}Hn?O9Nt}vV{J4O}n?Mt(WQergd32J)j2y)jO6o+R zl0;iqmfxaki7J~p^vb;L)JelD*7V-5q9gT1X;bTxMjeG%1N9egV8tDL#~wfUqr4^D-Z#j7imv#2_^DNI z;K1lNe-Aw5Kf@}!!NrIVaTq3jbW!C`{A$jHzp7*4dEixUtvz&hXOropzB378!?iVT zaiab)FG5#%_zkU?L|JQM!>hbE6|sw~6{Sr*!RA78@fv@-+q{pnUq2bmQ&`jZlf!IN znpD8AS|H8k6LMtz3v=O1LMJ^xR{It`^je6Hng$Wd_HJ6p>ct8mU8 zW6*rkgMrl7E}dy2$d_`7(H^gQPtN$Bw*@$N13GwO^;@?i-b5(q|Mm8XacRx>j(Bj) z|5}BKf-}_jBqK_pq`o%!drbG@6A7;!^Qjjp3V-ffCCjt)^%HkacJTY(V3anzVJ2zu zW1C3h0KS;9pA^!HOOmBGJ+PM9V$iNwgHD+U{yqE8{7)gc!$ni7R z%jXf2PrDxP(MEEq%DbiH&i|+y8;x=bk$gA9(QUG{as9yg{ZhR!Rxe|dIzubw=w%E$l$0xHJb0w5 z+sAQKS@UhL_g>CF04FG~3XjM2plJYS=KC#wSVJH7w5}Gl&L#YnlC9C>k8C*qpOp(8%MvNJK@Z|Mo5?D`^PO3-oknpPUc!}rM zZVD~`t(gdG6#lu{V<(r-{DmKX?2>=zj(_X#+)%Si8B4o2Wc_j{-@Wqj5Hcb#nzMEr z%d`M< z<9MYuT6VR)ltA_H=338;N`>i9Sz#)&7-gB2!qE^bgbt3%RUZC1%HcAE<5Y$0fC}+k zI73sP^zL>M&MqO5W9uOur%5$qH)v--c(xmJ0y@4o33!%GDNO4(dPY%Kfe^6S(^DK& z1*b7tQLs`!D$}caMbSi|R}e$g9Mk8<8QR)y4x3Dh5m%&?;bZ+ zuBn7;3AR6Wb7v8wAMJ>*e8WK*iN>l)noubq5cvCAsM|yevUe`^{3swas-4&nB%$dU z%LVjZ7cQ}q){w$ck#%n1)Vp<`P&D*Q@EeO~gY2zp$wG&dz=S={@v z6IZA|rOFR6^Ih)N0W5Y>VH>pYaR4Vj#hLowXbi3P(d^yLWf>8zYV$F@ZwNFxVccW} zqlIXgvowj)+@kUs5L_#mi7rQ0Q5*8pXR?6HF}ijo)GCm{pV5l^Bn`+LVt#s|FOL(Y zE;>tgXsmZ|^e6!H&{bw%rnuRh)I);Z(&3a|;Tr{5#*3D-6iu!c+?#U4+$aqI>dh6~2nCSXZKW9&x??F(o7J)070 zP>l3=+(((P^RaNpn3$NoUixG+P;&OOWBQB9EVW^@LsYkk+4D!a(nBA0++=fSm&f&t*W(uUQQTJ-@SaD5lfcv}+id9&iQIXflw2d! zuKLcj2%#A`fFEgkFo~dAoRzq5**e#H#b|nQMC_>4f1_5NF#P8n!(4=2$SnPVa0T+o zzIk>2$W=tM>6Fr*Bb467@#*0B#?aX&iW;Z8a%?8$g||C!1kPxLN({pY$fCsjs$98F zmN=2GtB%y@w`g(IwNgK-i=%%4D~byN95mF0>E&v3&mNGOThw?Tv446_Y}aBEb5E6K zL2kdgbsgdwYjBP;j+$gL%VaU;$f)zUwe4LfAso%TeMz=^NJ>fCu$*Xkll(-jVvz9I z%c}hks($LOQ*U)X-_(xfyMJ$1usYbGUQ|UZngoZZ`Sd-7c6by17~J<@uCvrND~gnB zojRqCIG8NYlsgByW|A;ADg5e<#MIr~14L$q-htjii2Q)1r(*yZlzjr$H^y#e4EFN~ z@_d0WZqkfO$(S(VVX!4-_{#aQ$=N5d;b|893w!x&L3LO3v=H6*+w>0v!j$|5;e+?@ zF6`Ri7CoNb(B(f?UHzN{{>*1X-DgcvW#3$B?reCPhzrB z-K5a)@skcg-z;`+RKzZDrK$aV0YvDT5mBD}OH~4F?@k)F& zyf3N0o+Psl)Vi91tpszk0vf0?`+KfFx?r2>3_uK!;y2%X2zeIQcgaq`uqz38PGkg$ z!Wl{Nw_0(8Tv50y@I#^h5fiU2pyw9G&IZ!NY7dA zO8JlZ6aGwtnRD*AXQ!wD0P&T7_0NW}v5cg_B5bIu_Qph|_q^pdD<`(6-jJii6GCZz zw8aI)?_5Wd<*}~8>|XN@%ms3hv*LSMig`|i%+QJ0J|%}fa-?wT;NRj?zf%Gju2U1d z*|dy&SKGVP{WL%|R-UvgFR`1uhZO##Ra^OZ!(4E0qWLm~Uv%SynEgXlP_>!*EA?!L zS{cJa6XD6DF#hP|qpHEK!kS&-!qUFn+yf{p7x!(7^%T*4rJ? zk$>pI5U+ruhy*L^VK{TNdXW=_2%J!hd+NiQrS{ad?u57*Hwbl-@g473`l#xM0TZ>u zxZ;C=fXKC=c&~N32Olf+VlxbXS4alvQIneQsTuMDq7;Ln zOsBlNW8qN3WN4qMaTg>E?8nbQ#52mjw~CC!c7uqQWeSNdEQ4jEAbDp)*%(vam6*ML z3XhHICw1tBlC)l7M{>{Ei%5?3lwA@Kz9=!uj6B&InmXx6PM?$&UCM-~;tj%(MefN{ z^q{p_8`_re=QjMLf9Pe-6-9VsY3jI64w56V-JwaU6R)2e8A|l!GxzyVGmHo?^l+#v z7rvYDes<4K{r6O()&sbfCoOwUv1~6$pfX;D`7Q41!YM*p7J`^ri|3cr)mQQ?;J8f`krtfwQYpPq0P8$uFCr}>McAb57w)x0{fu!(ev9X4`26=-Dit7s& z^3@?!2v_WOxKrpoqi-a6B3S*tn~Q&D-P_`>sc!By0_n2&X-NHn#2;j95@w-xH@<_- zX070riZg{NsjI2KnCYwu))S`vgVDi{7O8E|c_Z9_c<9+xiqRLE0bvHum*5#I8w;Ii zlijH8ltEcSY0(#&F#QVF2UdC6kxwCPnbnQ`N7;f`-Odw*QEaK9>!Eq=T;AB6GkW^Y zOKQbq_Eu6{CaheLY&ZE0T~R{8!`XcLoD zvV!9gbjbo2)qf)jyTYHP@uC0nq*#^gn54|mK?}6vxV4(y=$#n3?HI$=)f+YZ;p>zt z#$&t!nruStH&O*-Puxuv0a-E8=#p}o&tZ?=1FPJa-B_q6*~3(da+wbE2AO(@Vc#sz z8Oi9)cjVO9>q~ZZ5MR<{-@D__uIwJ=7qA{s>*@Mn%+Srs$~yc(ZW76X?W{7Y(La7q zeDs^yiCa!{vney8w7>^=fym!9i}mI3iz-poj%mDM|AKqJ($ZR6oeV*R;muNJTz9Bn z5dZ<<{Hg32s}4Clz7L@?aUJuZ^&&t-D`~Jc5wsjycW)0@ckc|i1?S+1v{3oxy6r{ak_0GwTo8@mA$wYdHlV4t1T!8`nvLD#cx zr+7D*wt1Z5>5$=iW~8Uma=VXnF!1Jxz_Ifh<;jMaK7v3pZFcrxhb7mld?pxhXAHLwi29&-bM2<3#=@AGkf?p(yq*rDVE%&Yi<$k)yF9C45ge zer%z~ioPE4hJAGutE5UohVb8Q)DcjdND}BP$Vw1_bC2P_=cz|x)rk}5%dh?>ki1X= zaqlo3lX`)%V-Gz40Zh3!UNQw{7xXI{)TA<*3ytwlTg``X^^WZC$DRBGtTEsHD#4ev zZYd}yn+96dLa?>?(Y2ZeD zq*;~OM6N4rNXDApn#kGNL?PmJ%&BMN>kDNRx&nsR&JX-iI};}sOgfJTMg2`es1{0= z8P#+l@dlSiU8z}x)AaVKW^#YPdPaQdaQ^CdvHGW*PlPON#=$RIe66~sA_q-)-NFC| z%IG@zt!#t1)B_5iEgv*snFq4?CX$UL>Y7zHww)^JDy6ZfCdpEFZ9t)YdrYu!=V8_- z%x?_HS=n!hPE$t-19p6NBR$5{qf0-T&2th(LML*?D3?YW|7@&;0SVy1X=~Art#lP_ zlWGUb0JuxJqf^hrWzEZ|3jyYwQgLz`iuT1}K1w4ekEHQf{hi6Y(qS3%$1WJXUK47; zE=@@8DKf*UY5}kLWCRWb_KY1Vif3oH!)ZfJo%*Z4K|UUJq~W$s znuLiq01^^at`{gMx$DyH5{S6E$ZFDqiZMXL94aa9HG`7v{&0g_{{iwzmNFkf>6SaM z{E6g@3Pa+~ExY_I*lw(vY%19D&o8v8Wo82g-ry)B0elDi>oiUZn@&>qXgO|Tq9LNb z8q0%bLfNi-J&3@K)6EZlvF%(Ce6{nj!kcesg)H-6(!%IBUjtaE8kW8GqnOW>EN=|cEiU*8gn?3isU+5OH*bUm3l&rC^n+c(S5fI-)Y%%ZAtN)OjWwv?x zEEHx_)Nxq@yq9BySVmb~X^Fya=pBSqT%}yZLD!2mC!_LHi4UrG@98&3^_}ZIyEk$1 zK=WA9gT7kWJP%fQ)pi-QSg|N&VY%g^N&I6`jpWvn&%V;V#udl>0ltTW$?1qfguS@ll0eAiMw@`S%jn5N>cw^xAh~UquJ!Eii-<(dfp97 z@J~_!#L@~5;g=+BMCUL@2_;TB4K(w*-WcR_Kgu@6d9?=Z)HMA7vt{E7)6FN%foCXIcQYu(ukml>vMeT%8ENEXhl0#~v- z?|AyDjdQF2IvdxzFFpPK*Q*HLuB=G<)-B<8y8tH|V2l|UPC7xzd@7z2C6SRU?UDjK zt7zoT8Y*C8h(IWx+pPMrm0g(sG~BTok5uUO+2#>;{M!y=GJP*VVytv`@9aI63(sg# z^=?_!mOX7e44~KjSQVE?}TsFER(zOY#5F zDX0;cWPbg(G*#}ReDQW2+qc~S7cu4)d_zZpWGFojh&~~PJ;of?SDbzA(p#*{8seou z84PFk$TOi@)dWGim2%l%swPJtW=LX3CAai4u-XJ_Rg7u8Dr1$@8yM;RJsym?_#7f_ zrmS#cw)m1qWh4;$V`tJw`&Sm%7nRD(^uyhwNdqe%>?^zLik@s_;vKOiLD3v9Jd4h) z!d7Vqa(3y%_T<$SS8hIq1wEWCjb@1&e55&bDU>?K*dtfCi)o>3{)sXFup>~`$~ARL zqqkQDQN_wp$w*E5gs%?vkZmZ^L>}JW&dH~d8 zag4^Sv%v?cIUWnsx5jc5(H>a>=Jjs{88p_(-*G;d=72&k4f#a!R;lNfhGKz}KI=tY*Ehg5hD55zgujx%UC{yD zv^Q=1=6`edN3JWhkh(_omH7rP;UD1hR=Kn71IcjVCvxGTv^{YhenS{|VLKj14TGPZ zZ^=!)TvibxA?f-bgKef{j-BLc?@7Z9iiS-s#n+H0+r$nnkdB$rMZ&pB9?>E1QKtj+NZWy!yxx- zh&(h!FfPMypsD74s_5xj^wK@}U4Rl?T|(C_Ve(cRNx*a$wRu zC{v^*3)SPMyWLb}@<>QN;e;rvDbXZA(;^>W@yK8{AfTVb%;!^FXVRH#A0CwHNeKot zo`^wn`28=VJ{H^&%SabokJ|0!-sh&RnQKZ>$qxa+l*4J|j`9rX#QP|09%){Qoq>CB zJwv@)8Y;CT7|Y)08bt{b$p{P^P>RL0m>)e;S&^D!g+a{>Bd6eXE6Mcu$~8uR^e|~3 z@-zPRPoGsZt#j)e`14#wg<2SFC8#!01rr>!nANu2VC;qSKVl9b%M61?W)mtF76nC{ z`PX0G6j;rle`m0Z)Y%(t+XE2L*j58*ZmYZx8NaWCJRmJru3_VJuYGgIUD)};FgYW7 zVk|NGF(L2oXAOi&Ef!yX#fztt8BIZ`n; zfg2UZ3@;wZI@2a*eT@5a>Qv9Rt)U+aBUF(~ZpTN-Y>vLpk$C9p47ojL&xKcyxym=` zB8QJ)gq$8WE@#&Y=PS`F?UU4J&sT3~=vngQ7qY|yV(fekH%`u!NL@96M6>*3-O#T( z1>(i6O8Fk#fWJY+PZI`;QapYVO_xL2EVZj^Hs{biCOGty-I`1PEkPCD1~;5&i_d`P zxdT%Zq^9Ys0E=cYxAE9N0H&Y0alEeCzX)U2>lH%xGtBY7kSLw>9e6Mi}AT{Y%wyL*XSQJGx8LyJ?l7&1lc8=?}@o-V} zMA3FGg%UPYM3JC(^ubLhM33ysVpvX(>dzI>qt8hpoKMmo#%oHF_mh39TRFq+OtrkCFAM5*z4KZqA0qfj zK|K$|FM#3`$n}f0W`A4zuKAhh)X5sUFJ3i?Pu;BeB1cFYX8!>P2GzNx$@aa1X`B(W zDtOBSeiz_<>fg7U{ix#a7TrLmib#G*hVVAOGnx3qW1#4#Cr5s+{-fsP-nd04O3KE1 zj@N>h!zG~1yk0trI>L9H_zKh_MsLrz(oPKDr7MojQK+-r|#J6f}g(Z#~1w4cOM}fC0p@V z0b^qVPl#_zS<9EW_HlhjImT=(n|4J1R#u`kq`a>(y)9&7AKlc?257sE7IhbS1cW%MOEx&PIZa?dTQEwnY*r}Z3f~bxww97krr=WAIep#ZdfkeR51se zr8sU}^ic}3Vw4*&hWi@Hva2L!hScAMDcd>-RdlMPnn6wNU$O!^$*TgGv8_7FFCXQG z3WjiON0Nt89Gw&#bOOU3Q+JhVaS8<2RlND71ta`fIU)+-MR=>+6lXUB zv_3Fer!y(?vQn8YNskP%bF$_*S}2xkN-EG|v_;FXKZY(ns<#W0w%?fF)F^8d%=evc zodG!|9$v0^5Nh}=RjSKkFCS{0jGA=};;rD70{Aa0t>af8b*U*TPF71;Ey~mShm!)Y z6fHt=C0)wVi!bX`Z$GpzabTr(plLsv7Y2E6KoX`IS#0ahjbKYjhAfF8W_||!5y|Y) zYsE)dr>k57!SjQ{o>~RNm3h5O*HWXEz>{%4X6>ir2A}YLliu?>DN}wad7iV^ZxKhB z_3(y{v0niXHS~II>{rRmQ?CT!8-BzNA?m_a$G~C<-^|fT*6~JHp%RUr8*QTCZ~?Qd zt}9{8f3sQvBK-h6l5^-}j0v?+0e}8TMt0pjlSffF*S=EXLBQD=2}f9(>gY|9g6*w^&4_$cN*}9zy8b2 zx_#qkpPQ2TwKFQjB;g~SEaWIONkPf~Pm;ds`7^NU;gnG`%X6|SB@I`N&+3Eps)DX7 zu6ew!8&yf1_Jv>9G%5q+%b}F+{P}G$dit{@ET&VJ91ROPN&($mn+oNrq8gAJ+M)g5 z*0waBTrW7~TV}F(oKx>Uv6#YqMLtp?X1dxc|10Rhl$=2A5g`*upPN5zIpoqDb{WBR zLi|`mnL;8VZt`2{r6GpsGq8IhlG(VeX93tOMvZggE7HZnyAu>R;FRue<5cwEm`gIQ zGw={~#g81i@oPF&|K+)BdnJg~+wnR$WuXP7w6Qatm^FTcy%)ty=)KV@>E>dy=HCNE z{0$Nps?)Pmk@CFMM0ocM?yNZNW4p&f2^G(Hp|;4efFjxfJ)JUgd_((>QVrm^ zMHGhh5XkG&$xl}mGEC!(sB5jQVn;W{Mp`F?g3gH3$Pb<9HBUqmr*ew(P1sd$ zr79T4^rH%(OIlOaj0+ajMZ(-pIuuSo62FUAt}cR7>cE<2a~hlEIhyU%s?sa4a9?E# ziZU5tibtirEGoQCOy=VqGdMxLn1z?d;TCkhVi4($&Lllpw%E$>+y=#d+!PJkCwZaq z!VO==FE-5fRD^&ZS_`^oY@vTD=5${ZG$*txffMyYe4rNW{$4?Ccx)WYVS!9nct-`` z@MDFahK-{_E{@g(3~x`TqCr+3H>}}{4d$v$W(VA;Y{H)@<3y7w_r>PBZ#Q?e%42~d zF4rJ8SJ0SWxWS}_7;R7X%{#G%Yk9)hBq!Ak{@N(irJ}JR`Awv3oO& z4y>O&B`70iB(iShN7Wqq4L-j9hS1NH-SfX$gc{oqH|$qC+y?I@BdDa7hZJn>J>w?! z2$QK+e2VqaVZGf(^$-^*(}#!zgl(Q1WvqheEdZGk?Fb+AnD%f-fCi+8-+!W1Nr!qf zZ4LwVS#H+r!%o9AS17gj^b@W>DQ+f~=Vpnyu*Z$OT)AAoWR8qFoDLxo2R~1cL=o?& zbQs$0LF;ZOS4C&n7*Z&v1x*yVQs;R!9**+0N!(tSu2xs>F3?tpQcgi3fixg5G+ znxFqM4xW>rtw82tKzp52k5I3O>5pV&0#Eeg5~cwK9KTa@OVBrk`v&XyY5P4XO^w&0 zvvYxnbK?0f`b2ltO5|5?ZtGwbU&8^*yIV*eRRt3*Qpj7#$m!xyOMQ#fGayU8EQ;1Y zULV`U>rwS$SWy*U%bg!c>2A$`$OdSa*zP33f( zh-|U{sfFTUDF!_9nVy?#0{&p?aj=2W+Q>yo*cx`0X*)ccbuoU_!s20Zr}^8eiCSwF zN`+A(HW)@ICXJ>TYr`JjR@gzLC;!Kz7Lbyc@nrv!W#i==eD7|y#--b$jiQ^bn`hR$ zeZj@jT3)Af@5rNFUJH$~Lhd1Q_^@PdF2X0pUePnxk^5Qh2I8pJ!o|!ZSm@R}?&7{8 z`Hd;tqfwo>D|Kj8(-iGpwz-J2#IPtao%E(;jqRxF!}#t1*c?gEz?>i0cWjjPdy{#x zq)s^NLtm&x3aKe}8B{CWE=*6|>lMG<2BJvIQc$zX-vC~isv^^~-_Im%g`=BH9u_(c zDaGKg!kqDV6%&~3jE?y_=T9>zcIt+e?~{ivnduz5y0B7~@zV{G33b8f`3-^$_+vdp z>}XzKpwbY#+Tf`tV9t(uv|IfY(D9S3&~noPD-o^DT>uhdNEV2X_tf zuH5a*9@Hldo_KUq+>cVI)5hOeF>jkFknNw4m>~k@7WsNHe%80%o10T@^+;>S5GN_1 zlNvwyw$)i5v3AY&wL}yR{(>nUPVXB$6dHRVdttKnO2{sU$;9SVs6!n+P6~L_1av(a z+$=0}mk7r5*(d+vaXsql=Pgw|S`mIaZeHduvi{?}SrT18=gFP5y};7a4k$xF0^7CM zXtlk%BK23lIU773x<@tc>LUDSw(mNt+mL?$!024{qTn*KMH!b7VyV_%PT)E#%?d{OqB$SkP!y$>^`i8GTiZ` z;Vr%`x8@&5Qo`QJt@y>W`1Yfgy&=Akv_eCcO#qS(tg7?_4}smJVC}{?!Q{|!dX38s zoC))3V_KS~Xc$=!-X28og~3;t8qbL0TFlaAstEkT_oW@beXxSKqq_gJ&__A~af900 zxH_TId0r-EK_&(WAymVGZ!0dpsu$=>X)>rHsxCEwE~IGw!p^isgl<0i#7Bb9${7lN zk*NF2BCK~z{TUxKM;~x2)-8BPQbP}Ibs=5b!+d?SSV+@z5T0kQfkdP;`s)l?N zp4Gg-^Qz+gHD2roCS(%x?>>{>6GK`(p>!E$))nc21u?TZ=}5Od7-ckvs3SS1U`8Gy zR4*^fo;P0J;p5sLJmTcoBSWggx$rUAL5f6hylc<|L;CHqj*33K^_r zel42z%C{~A*3>m6Qd}D5a9e`}__5vkHf;B0t0ZQBP#ABy&MV9$utmh<<=B0xFax}2 zo56_->9-dZ8p^eXUxNkB{_vpu+`v>+_;EEg#-Yqy!X2~L+Nv`5#{$3fvIb-ty4Tg$ zaYmSen_?;>{AS|rkMH#h-c%etcM4cP z8E`6uSZF7)zJtVS#r2Y+s%?kJTv1B&v-p=~^_4z!M17HoA2TAk`u(BMvvXp7vvheB zXaO4G=#mFb9WzE<Ys8@Rk9uZgwqiuE~|W zlwo#uduDE;-x8IwGihNv420t%-Ma@6A3G2(T7JzOXFYfz4o;yEdlzFG3r9Hv135wR z5bRW!NzB<2E88&R*|)no&sm}OSl{uF^f>oz3>1*qDAewSKUn$pd{DV~lBv8=Pv(c~ zR5?7nY+#$4;8(N|nyR>ty5^QvZ(zc98*6ElGnr8_G~ zTA6OZ8f&$?qAXzzcu{af?ERHLaCjEbr2OG9FM#8uc$*&9!(W=EANdx`rlN?~VNr2i z;*oteRgY5yQsGETG$Lwdznu6*M65|Ov2`n{A<)&k@6*+h%S__7bv@!WW>f7p z9yTZKk9(+MPVkUwO=I2&VY6>9O@&?P`)6nuLcAfo=cl2H8*vkPA+$C_vz07`{ahoJ zwN^JsX#I9{?*^0?ocICL67(DvAM>CwPp)lnEy&{T-MDz_K_;Ar>!Nv@LS6;aqJaK>Ei4CX%VNK<5@$@e|(M+g;qe4Vqb%t9`(6i8`3(LFCZ`aZvWhhwNKj z7*0#-0DH46jB76DVWrYIZrnWY;3eZ5)=l?f^t);6)b18$X82zO3P31TZ#DOMV%m00 zjsIr&|jQZ22c%Ud6rR3^@_es^IFV-tYNj$ur zsTNX9nQQjWxy?)tND>~3kv8Q|m~;kB6!kto>?|1DNetJWh`(>vDNneF?kCh@`NaMX zYlUMLJ}Cv))#*1PL&$P1PpCFtKGh8B;1a{Oxctz4fC=_06s0}^l zmHojw*b7#x?;pg)&z%j%_!iS?nbJrlVjO%C%v|5y=XVBw*;*!Sl#-wgygiyv2kAfS z*Pa~>nG5aM-Uv9Td>cu$9iBrg+4p|DVE|F}pI2hm(iRQF)tRo+_ilCfIcRdxSg^p3q@Y07ahOYVJ zOl}t3)Mgv4fM#04YLA7CIo%;o?_eSW^sKJBlpp9qx^=uLY|yFnwAoF;^^_*eZUI%%*`*N8;x|Vk9dGim_WX_}%)AIJ4 z@hVUJ>!$r}Tk{K(nCSR)$=z6{8e%76jEBdXdKS5{C<9YJCPJgWH%Zg&$PP(-DL4oe zFyHO9{0DFd+Q@;_shJ8{Ci|Sx6;ra_r68bS%D~O^3BE*(0nbh*q4)8!!7QT{AoO;r zjItl|oaE{S@OHBSbf6jY<)h-DhWH9oyeha9&4#1KuPrj%Df6CJfE(E6hCK5m;BaG1 z#`mcNWkT4^5+r0Hx4AlId6uWL-y36}!(>#0P&%ixkQZtV+IKuIxVcG`HxJk5HH@ko zI0@3n?8kTa*>jhzIvg1LZt=SO0I;83nq|O9X?L)TzSJ~tZ{_m-C2oj{kCsoEGMNcr z?rfR*Pt)F@ua4?C6405nuy#glCz3**$563CLq@l3S06tRMHXqC>A9iaMmXJcV0oAG znsj4rq?+_h`DA{0f5&lsg??iLtbFsxg5uR9{Td2A7JCB(eXSD{U}x zZmVkYpcK-HE{e&xNQ3@wrf0H=IlF#P_c8pbK!AP0@Mm5(CH3h&nXpX_sGz^@o6Wu! zOUg8=UlCgLvI`e~H`d+?99@~&QzibF^UU2^qU)}>qbFTH=`#xdKLTTx$_r9={35cd ze&g0=?&Hk9CRRz5tN)c_t8vtHh~6N+J~tzII9Fe4a)^sGo{HR1e6};CM@y@6Lv%^d z;2}KgMi6exv)KP|F!F4CiRYf@*)I|%*k5oSn`bA1U%UH@hKIlpLH(JwH5g}zq$S8Xg z{XW0H;Xe0yzdx_n^Z9uE>QA>v*mYUNPnVvYil`r4OH0^5k0 z&sIb%wb>PKAG$W4?U9ma~^QV0kTnIU^5oY5FbS-pRLO zb>Rd|EdF9;*emWd%T(=c!OD>t&*Dw7k5hf5uVP&OkT=k>pUnW`i}ZCaEa|E9SLjr^ zyZ}cxuu)njFQ?IS-7^busPC?_JtXZ_!|S)A*6ASs4-WH4^jQcx7H!1fA#3J~O>|F| zd{?u^TjJL|jZ?B_>ry#ToD!{!7~a2`G}}LxR?GP;Kd@;#tFR&Ez2OxCwvVuh57fPp z!vHSsW$HbzoKh-m^oHhVq-tWo$f+Ua#qJnqo~vsbLK&TPu$3~=1HUm+3ap8;#&-%2 zFmJs;AnYkVr>FzSL8_5Dp_*Yr^zQ*q zc~Cc-*q7Bk+iZB!ZzuW_qY755rf(70{AuuaJrl3xd}nL8>Ktim=Qo}T6HtGNh8aol z;S(rIrh9@6zxfbo_mtO@_1_z2%&u_iM=P!#3p4l+78^#+$wA7s<3%3O=m_xMjzAYS z(9FvZaCZR&d&{SKo&N2p>0U-b3GVd$Jjc}xp8gSx@(Qd<@nO#UxX^=H@OnRf%jlwO zRRigWq}8Fdq@9hq5m)$%UvXP~Cz5uJ-mhC7O_IcAf!R4;J$LM1jFj($t(FlT&yb_P z1oFQ=kCxsXtx59Oi-zq1cYSuY=Cg_dKNC56q0as%{^X8^iRH{lvzby#yu(fk^^BaT zc+FrwujmlZiOxdg)cWstwo?&MI)w)h86D4VWX}d<`1)(rtDi1asmF^>Jjn1B7QU4c zjPUhs2WF|>wci_x*KZ&_MQuHNoHPUQ!)7Ej%2Lp31?|G!tSV3V5|!g0iU{YgY+$up zi{2uJJz8i~o-A#bh1Ym1gS9@ILIP1g^b7p6ggZy69@wk8yAgOiAcmL|IF9=^Sabm`zA%|Im7ObI5S7;lqDF zZ$@(svQWigm-+ET#I#f@abSKWCqq=@GygW!n^S}&g2SV~h`#>~grLJxbn_Y77_wIQ zG$F7MlD?|2sJsLwIXGeVCCb0*3msD|R|XD(I)%AZKT6e3mH|yc0q|WvZ+|P&h4=eR zp*z{7Yxg2u-vf}P9Uq)VSo2te8Yh8NnNe|+#s2YmpuO-tt|wN`Hlo8j5$$P4SOsct zU$f!x1K_!l`DMiOC=s7?JIjBi919EcEc7+%T>t8x*T^$Qd_*c3dZTrC&0b@5kh<>tkt<*feCUNxin-1wDk>x1wJpC8&pNfVlU^)Ay z1ktfNzh~rOW_f>={c&4Gyl9(jpXCcA9i!82bG8Kj;(59BYMv7j9KrQk#NrjsQ~}BO zIM6**QaX^y@!7b%xbB~+ncRZSLS{>DvHi@VL=11{TGlVT6gxj~Vq&-_ceBPEkzUCp zs2aVVFx_Pz0>XDLRnt0*$L9-7qpaKzl*yHLTSCW81WkxI#X^P#S83&5ayD!Gl6Br! z{$hDSezT07u4U%5x)dP^jdt0fyP>0TzUR?UBAEh2cS9i|Mz#EvD2N-CFh*JOUgt>|)`7&LK=f{m>iq;pw` zT#Pg;Ir_;VAaI)vbPHdJHDaft#+Gro0Cdfc*U{=R%kFi*j8XMW$(EU8cd(AvJV(~O zvQUfBK;8h$8acU<{W@*sUMhsmNusVyzKo07*l=SI<(NY2gVUU6(VmK4BL-3(-VB&t z`Oh5i3^WQ`8t@!4M-W3UkcUsy{6VlB>l2(vG$BeV|E;QS@4#g~BT=H+U25yxy*OjU z>xte@!+|N?qdb4(8ar>@6P`YeDlVrz)s!hIFrn&!%HtRcn)pEb4u!3!VH-8yi#gC=B*GTltllcm`2m=b^{ri5Yb36sxH(nGCE59&rZik3U&XER?DrH39GES$DZk3cxSov(V|mkOi$(yrxI_~Y-;Lq*DM5R$=;5L$taTZ?ruQ*GCxc<5xUM}ClGxbdv$ zyu6_P5<&YP$b>l>7~(11L_B1?``*g@sy&XYpbN61BZ7GHF#YGmZNASa8FPI{^#ltR z;xNTPc`+})TuF%r`rF-{01;QK7twWD&dxovwA~eqJIc#{_rG?%_Y{^s(0@HB!R-xF zab{)?XrcdL7!II*k77oz6Ou!*0nfgvxH2kvKF}^jbhnOl0%8oOx2$<%^6HrNtrQhy zOKn6}{|GQIcelIoQgm7KJ3%)(MVAIv|J0XbW+7vyrZAba%$1>|IXaV#mn}L;t43B! zWJ?u`<9y*CUSSmgbHu&|zh(jiCnY#7TdlugO%kJ-Ms!C+Fa=FfGNs1+Gio>5nH;6R z0sSOCTdyq}dR>B;TvLu+Kj3pv@ZnWl_>08@5>x>U@y=6X78~a@*%&D;&+Y&Awto-r zhoxCQfCNdJBq^02!cAjor<R5Q%wjb) zF{B^0x(WSiOJi)!Pqj_B>|d`K2^;vF!Elw2(&sq*&)O)A>)k_-6Z$2(Bt}p!F~!7J zrDB|^!K};qp|^zldU{C`TTAej=>S}nj{(I-7CDB^N^Br1LGpIg*C{v8a2Du@Wt<1S z*toyweIswXUk=^+nf`2`RjnTy${YD}?6x-A8A!PUi#ULOI=BH#adFyV>EdHOG7r4R zIu!lt2p+^CPUl2c3snJ-2NX)8skI;JjHHZdj1r461Vwt2beLPO2~boH;SUq-43DXv zV8l&+?uv|((#VA0n(I7!^Zo70od~b8>Ngm##JLY*8yjLPxi!;-GE<8}5Hq(>W7bkb zn)whZ*29;$j;KGQRtfdym4C`yU!|qzu*>&(lXz9ZVm`uqG3fAS-LChG0`7+|USXQ9 zmNz}EJfJ;r3wLG9T6Qn^-0RB0-S|WoE z7=@!&0{oEUl-q5oc|7OZ>f-(xWhbm$TFMy z=yAilt@oD-6;igAF3-mS9_gcve6QvSWe+kfK~)rm^@rRE9qYUE*IvgH7o%A`XvX&^ za&6ip#^t<0JDA(*ht$PL%a7F?3A&h4G3VkU;jpm(rha>mi93Ah>AnU^`~{nhky^Qi!xn2a{6-K{J`y))oK3shWex3@3dzPuOFUU3unK*^R4WUYAWtsld1>* zqD93M1rshgsi;Kx@&FEUlblTV$uQ`5(s*FT&#U9h{a5<A|aqZaM&L|Mr@3+6N-BwZ^n5l2;K)<~clv-BDSZ3TK zsE9O|<@9P(K7F>c*FLu_hm&O zDfF^Lv$)PH@aWrwjp;JR`#UqcQf|)X0sECi`qpR{#`Kh+tWEO$&2J$_H@r24_2h92 zdTB;wGoAN>fBqTzxHRcQT1@!5aq!A${rV@WG#jfRtY( zaa*VSQkC}l@h0f(g*~|_9g*CgF%?;Okoaai;`8X)Q~PzyV%x*b8{Ub(Ju^9;E#@oz zQEO~nMZj1-+V8~o?sL3LplWQa@Lg+5KWv#DJbM2vsHF14yvfz==S=T%8=8JttbLu4 z*viq2{p5ghRjQzJ|Ar5eJ=K)^?iPppEMuyQUAUVB84cL>80eqg?*6gSc>JX}rR4~G z^6XgRHS4#!E(}qS81TkMe5N_~&+JwCg{N*M@?s#4IFj}CPXAZXd~S+Os>n~CYaI6! zCeMV3aSqCj-4|45x@<)=q4dT-MSQ;grFK=9h8$9Sb7h}(vL*<0WNY;-8*z-ke(qPa z-I^;MwbQr&3nj1C#ushMNCpy%ABhh9l*QH!HrgpaynW(dKtuB*({KDV@f6)TKE=lO zCL-&aN5dxoS=bb-ejZ_Py1Ec>y!Ll|l=c(1$AfQ%J@FyT3tS33vn+3TUatEf0c_X) zcsSytD_3)_?ZH=|7sPkR{LFk%Y*lTulmFePZ{LXhL%o)AOS+Hcud z!HKJp+@>k2dd$;*A$6~OM5F7N~&|)ep>7dl-NA><4Gun9lG=sFewGK67 z?e5OxPHODS6R!o9$r26aocCk0$_MwPn(AaN=u@EnW2Pj2JZvSLk(nXz@-aP2Vy58d z_gE*lMDx9uZ=$8Zv>C6d{8d(u*Z+PytJ;GZ={vp|FkAVP!M|$Rb}YYTSr{;a-yIMA z-24y3AmW(v*gjq?U~m&(?mL7$I>*^=6T)|aXX@t8OIWE?Lq(uux~$qT)aX?P1sY%* zYp~@<`xh)OYv4Z)iaRoMf5}#v{h(JGuw@Vbf!|-%U@0CeSuCC>Q;u8x1Ldznm1O%Z z*|<0t3p~X9`~7Uv6EqB~;8wKOup7tP{lYaY0VA05w0s^WeIgfmfPxg|4_Tq?(x+P67`f ztjl$5Xk5UYdWl4%SCm)JqjulPXv8D-_{a5SuEylg`1!Si2I3VG({gRYeKi*%-uX$~ zQWa#^(-BvW!t_vklI>-?_S=0nbHSS=gH<{0JGuv>JG0C2P6He~BNE~ze|wgeE{9ML z^O+3sr>r$?R8ASRvyKVCn}B0XWb}cXHrfgzSqyS1!UB1j%2wuDFVS9G7i258 zE{BI692Wn_OFgNUp%fbb?22cA%X7t@#xAu$z}WG>UTx z)&YMUK8CaKQG{5&RSMR%<3WGwsU0~f_^1HxN`tX#)o+f?a>gXR+g*1BK31e%sgv1h z+yS%FMVkmNS)Xh~jjr%%?oJ+MG#5HFg4Eq8!*fxu^Y>EZf)Abe+ zqD6ws6MCAJRQ2uI`BbG=85rek;N2JEdUEeD?@UzFhglgjOf7aI7nb72V^xI=NB#O{ zQ1gHItSO^YBktddHB^UD6b3GziOg(tuo^3c@)GUEced$c;xhhrP-^dw+vyqb2zp6F9A)DF{mWXOEn$}Vw$1}*xg1w;dNmMQxggxbP)LqB&Ff+7V9okFTYh{0PjOKe zXAZeu3*o(oel~yX>c2sX6YiV33CV)H*KmJ$Sw%4u*c>)k={1q2M_m`^tXbT?N z#mDi!i-mGcqIG1N@vP+C46PqEn>QLcOX~?`Io4ASyM!@v2jj^~N1$ytQ%9v>{w)`Z zwiWx%G1hW<=Br8|f6VDxaB-@cq%Fflg~hcdaTJc#u*tafAphg@&C?V3dAIykVz;yx zluxkKW64N>2KJ{X@4+#wSa}svCLe6J64QNVtpE2DA~PsEqVsu7=mTl3$t5C6Y{+@E zB+1sYhoRA`R(aa$9Bq9H*&c_|>hrJ-Uiri(u`QEe_Z32`xtKJwR4V=2V=eH$VFAAp zyGRw;q7d7zH7T;WKkAJ_Ai&*1j?^g+rpGpCWBf8d2(9*o2i|Sf)!i*)9pro(q3!Z8 zD3sDr4ZL+qnjyl_dY20sf3Ib{DtexLo55YI&^?r-)U=a;E?UQOVQY9Bv5Nc?9@xUa{x&wldU%o7RXt6R zgp@Sn2+3YuUG*jLF;!E9GujO>4b=^}P!OrIS~EwMBSuWHmM6#$Q}m7ayeZgIYdZB% zEn-a3oK_RMgY?@=4(9E=QkX!#FV5Y0?oP}L6rDuSvvG@ez8&iG4ZpHWP%p+~o^Dhi zbkno(5v43Q!KdC@r+n8%sAa0f2R3?T4XNtVH~xfxwLHU_%d=v-Uk#Y1QM$rSytS(z z?KM!4b&l?Tv}PbLnvQ<19H0P)u;ocL$S01=#7vmhTj^@>@ zz1gveESlvH^Xl8=qq3{Cl`C^|;^#y6+0{(%B%O!wUD;E);bIXP|H#(gOHEkFIGRpG zUgo%u{@`wk?j3d&F_&4I8`4W^I1O3K$YM)s!`tCxr|2fRD5%n6bIlM{47fw)iX(I8E+D`N&Q-I=P(<> zL20P0ASldnQ`r_{CTg8@P+a`^iOC%eHg?^F?xsFstgt)p5ByfTRXF^kDa`!Jb%q^s z*)tU8Jq!H#nTO(%&kP)RMJi{{TxDgnXh+fe^1t%+4Hore;{8?)ntN247!UK3Jp;?24}r7 z4XWBbUnmSecp0zLQ32oUvX<=a13xviGMphI{_ZYB&dH+oGCa_8PWa^EZ4-h+wqt!< z^X3V1^Xqfr6YENfYYH6}eaj+M@~owQzaP6eiDat2Qn7x=%$?HszJlttibr?GZa7}x zqE(%_Fcod-n?(QNnHMp#sb{+PGM6;7R8tg0r1e;Sy4Qfr^h9Szpu6JrTfAMf11yCXBe?(G-{M|l)X73F9s-Rky& z|3Cs-hNlh5gh^-ohk2gWF6vITyIVSI_3?21n|e?yV@62(gi|yk+6V>J}92qS3f1O zn=#HqbK8Vz$mpbibfF%2_vTLSLdsu#|8j2w6d~2u_7Tm%7PwC}B5{0ckxi03vxH5^ z99%2QnRj}U-XlYe3k_V%AibTaAywJl zE2)PU_R^nHDCX^3-jrY56a>l!pr}8rjxeG_IOT8O6o1e0^Uc%q;B&HnC!J zr>T`DQIf>{){A%6-Rzz_(Ml|qfy#`w4;E0`rvj~-%(KO+_sBlk=Dq{gY0?yuJa9~x z=gY0glQlxKiYX?ZCcBU#fe!X4bVTcTJ*f`4mMUf1$Z1Xs;q?dpWS^tM-M7rl`nA!9 z-szzGo(Zhvi1x__jp~@)ebP-dhJt!FVRjA8>rfE%rEO;|d`Uguuma(U)~snNMvEImyEl5nl~Pexx9B(iy&-)GKv(llZW%R%&%V4`WdS)1J&4+g%>PT_FCYZx;k zYG@?BLBZCJNDE-9jHZq;Lu#q;u~G=PjzMY|K&-Vo>7!`w$NY-Rp-a(bX6P5xR#e*2 zeOq_^V^O|F%KfXshy2gtKZU}|j@7Zg_`1t`6ke z)pNznwGQmx)n&HbaZ6c?M|VSRC7GuQXh-xsUFeCs1cnvstYWNUmpHqhpne>f3+v+F z=;KYX!y=+_E0cH8KK(%D#y=2iV=3du|IXhVVne;==aQDr51D5yw@cp}%3lpK3W=}0 z(6%GU&QJUUEhe9?lb5nh{80Y6$R-7XMLd3>AebXTgsC;7WN)d4Y@(5i} z*cB;KDw6V~py|reeBp|r;0x8{?ne_<9YVkT*(%DOWcKRnPI^k3v`;nmne_#H^(KAL z&3SE0{q)xTD_>^Ao?7)qb4$*04R*}r^N*7zls3v z^cEHVUxz%Z{mWi@{gAWP4MX_^PMRC)sLNUy^a_SICr`*UJmX*=U#yzvOu3v>ncc|2 z9r(b^(>_{fIv@iKB$x`DgDklD*Mzm%EeY2Q6`glqv5RaRvwlQ{0us8J7s!W8!@BZ@ zMnZOmeEUVqtKv~U#Z^p;6v3iZ&&m}NF`Q^L@B1-8Rhql(qN2g-wv#YS#MkL)Rx@q) z4%1O6V$~A=fy%TrcpNRbOS_cQUDX#czFW+Px3x^QhD?D1k4kY0vz!>t6X81^*@Dz66xfzKNrTomtD3XeJo~V^!|Xred*5v z=|?+P1$6~k9`(BTD#Y!D31*6l(_iaUZ_LdPHiFvl>aGO4y2dQ*k5_9`SYh8q7YrXe zyg=bvwJSpq5f|@Oom26-g2bH#N4GD~CVz12aOjTK@9_la!b@R^4K+!pMQ3oQ9?Mhd z8|M*|{ALD+H%V67G>W2Y3BI)AU1i}gr^u*L-1dbfzZZDcj5wy+$>QWEnz zs=L|KmC?Z;c}TzM+8;t?eH_%8f_>NX)mh!yLn0=o9`H{eYi$CQ;Q)Uu^)t z{T3YZb&!9z!>zIT<+AuIFl8kXXzNi3ZUT$BMIQ)Fkepr$8adMjFr$z@P_t&_g9KZCmQ z4Wqa+Y1nM0Oq#RsjRZPEd4&#Q_peKFrd=){}e#Y=6`UPbVF@ER&>0Z~>}jk#=V`-%wV)buuo ziix2bzU;7q6|0kB?P*$|HmNh~r9mar#mj|)Lx zTrpp(x$8&!VR1tuV1q4#VK-I*`vehUawjcN?PtE#^8_w#|2!m!$0Ib^kD2FnmRjVHBKYVmtlEH=ft?7SFhrYw>>m9;kU<1ALf?_}OXIl1Q2+x5tky~!%RRwpAF z7duB%iu2sViT3OYS@CMG81>HdB70zPWMyE^ogE|mhMbRYI$qn}>w@;jA9=GrmYWZc z%8A+I+XnJbDyOt%5ZB#Vz3|n|3|yiAf3;zQv8Xg(8>*kOiYUYxE?$NQ(h287)txf@ za!8Wlu{gE3M6jM%(j}j{7rNljm#W)uVvvNBbdY4Ke#Uwp0F9!j=u=+}?&@4i((e^Q zKX1RGrZ|z~dW%QW#Tp#o-ao8-&K$dWofA~X`v~1B^R6Laq3kkK>mwD*N8<|%%Okg= zw-f1e&s6tYP2ze(w4CzVwQU*(crXm{m#AL-_T?fsB)4E(G-J^ zorH@V1Cr(-1I6zNSN(56nV>vb^u9Rr@bH5yc%Vo+V;zTdd>Qr){m=c&0LD-hS``9AL4btm+!i9&KQo zLeg$J)<fJUy`#WNSYN@mAh#6huR?R8Y`4a-ZXtvy#TPoUqXzk>Fo0(wP*;8jpGOC zbBvs>`ax0X&+oX*gV_N9VBw<9K4420m|(TOQ>8pPq%%Z78%yeH(zB8>J9F&)&CUXC zbz~{O*Ka&~|MF@s;OY$O>sCl0ScWT+!BB9O=~f^kgkO6^N+l2zM9RKv%rL93PB-h;D7f~!K$43$`)EoLP0%WL^)ss?^#3+E#nv4%J= zc{-cL$$`}`Nu}rmeMdRT4g2JH9qmq@9nMSz@;NMIU67Bv`#Lj<7cB23B`2Z=ob_xp zUlf*I0GL7Mw+Hy{o7)0GHR+U+CKW=iK5Bl$Vb(gz2Kk(ZQx9-Ph-*#^k#YTV%gZja zEWkIlVQqM|lVhXiFR3&5O!MDT?9iU@q6MO$9# zGxh$xHK;CzP>~aOf1~SU{j!EFU!ktmUEkc&TEsJpsTIW%t2NFiFrnqDpTa=JI<&&| z6(EOw$`CpZg})7RjE<)Xb>O>g9s5cgM5?3c0<0FOB?PMQ`~dj*;O&^=G{sEn3Rd-^L(D z@HalwS6ZWwWFg^-C=8k(^Lj^g<)K(-a%`-->#6rgbn`=Qc$?kP6HhO#m#MNU`QBU# zi%1$Vn^F>ONuqv#-$v19p5X29$##}6Goo>+oQ|!VA-j-9t0ZCG4tuRV0&6O_MM4B# za6HkTu6QcGiCzB0!;4K-VYCn7S3k%K*2!snXJd9Vm{qaq<8#Ucl-#17<0=rbDHL82 zmRF{VPQ1?6QZ?A;Dxh0yQ3CcADLhydIw&p`I&SUTONOjee0*glr|Abcouw%B4R;&d zQU(=uUw=fjl4=G^pvnjrq9rX!;K6(_dbTb(Mqk_1M)w095T^Zw7d-9_@#u{q9!sXR zMd&+>e(Xc5xfZ!?E?ntGN<6B z&tr>aRQrlakTg5B6?(l?O~l7c8ypmTr4VxK)hWir!L}IHonFU=tebBXs>Oo^*!44F z*xgPCzVZh(wXK#=u>kFyG~?0Rp@O$>gn5r~$^Ef;$j(hci9fT|`~&}?!Mc&zP;-~@ z7Fux60omO&z$1Gs%)6ojfx{TXKU%e4TwGkn9MVN}YSqTQ8K~O|>{gN}bc_yI{Rc9z z$|)^R%)ET8Lg|0^F+mu?IzZx0QD@dB>FTn2g%AXW{KacU4s+$UB|rRp;6!tLhB`*&Vl@Z|sT1VC?prQ)F8W4%Jt; zv>_xMp6+FQg?}9}wT?AyDmru zK(H6sV=*Drnhi*jpe z!D28sE*lkQ?x)*$E>n;-Jc0X z?ke_b$jw|^h+4s;6B6iP-EJ$^&778TfB0pghKf~Fw zd7E_e)J}K{y1GX6?8{%>eT@)3Wp814jiPV7J zXC$aO;IcPew4(-1*WxCPb24Cq#Uh`_L0n0$IvbbuL6eQsv%6xTCXQ zKBw@Q%; zw&rzlWoNOL`%Qejg%d_@cdENARqI8j^`jhdR$`Nls@fF{{G*F}Dkv67mYbN(5Ml}x zK;|W{V3RL2KEqy|4P#)~osf}>Fo#-+``pr0)lv#v>Flx%)&&RK3`-vUlE7`oHRjis z_!yG}W2i-UQF^Q^QfN3t8DSl_BoDGc9PlzWZf-;3!?hW=9(l7R-v3@w$PzO~{KWoz?8X)ILC(~TDuaVg z@nBRs{E%ZrL(7$KGzRVFL7Yxy5Ui)ca-3D9hi^fuFmw(Nrf;vLJE;*-T-03yG0TY~ zCV5X*tA>W^stg6*%VKylFWsBvRz>>z*YOeDwW29H`8fK-bRp9(TN}PH&ZK@S4kdwHNX3QB zmhTp1w5?}vNBa*qo-Lg7+5=5a{)4gI+O-E7sNm z$rLAiEreVD8~@GD2o$LvnoC9n2D=?)`z=JA{9fPhy03(*S%Yn{#`9)+S+q9V?ztvs ztb-Sd!<>oKS6rXictoi^mPfWZwdFUxcokXbFKfidJt1N2#9!bBlzW-k#aO8y^xYlT z5->GIuc1G%F|&@j<)p@_*5ASi1SvC5^=Z!N^ovy2(WO1FaLBo%qQTYcCuZh*-|@mT zYUl^D3_PK^W$~d&amUJSU-K(3PA&metQ6&)gJgb{t0&i65gOkQyE`k)?GH=uSt$89 zqWudv#Ihyi--|yH0*qdvtDQt4=_9p#G zOk!5Cv8ui^i*ynG+@rP<3W66di=UAUWV2bLC*<;B27*Lr!LzbXYhAlfcDz=Uf$;_!p0mjFy&nJ+XgA&vhne5=TjKT@YNkWV2g$P1)79 zTk^tucKM3EMlY}ni6f9rT%n<=z-&&WjFh6Hu>NfkDt)YCtFPwLALaG8g8QtwR(RAc z$!FS%KV_RdhrvGlQ7(lCGiWhyYASVEvhx#sch&}m-%fGMIyHj|rz%BEGi#*^Q_at* z81fUKzJ2O$$iMtVGjwO}x^J=y-FW{qKGW*m;VmLtQ(5cGI13e7cPbUy?HnkPH zH(1N!B43#yA(}K=k-1|9Pb#SOO@!FuB?M8%_`Er!)^CT8RKBGEfkvs;0@Jh?%&pih<<73t9aTrR>0PWN zhw!3+kNHB(N2XIxL33ZoAag*;LBIg|fxeIsK|T9HmWu+padi^(&sGjkTrpLd+I7)*AOJ{Jp#b_WYu4R|AaXZjC*gqskog-TVtoxTDUXR z7!E%RRPu;r>5fmy*W2`3;OvB2;1@qE9L$Z0-sWL~J>u7;aO0s`%_Nag;RpTiWGcF* zJE;*ZEkRf0Syr}0MpTw6=d|1w7S0~NwcF3lFNzSp zB{oFe#1ZD5K4nWGs}6q~3NUt9^nXuSa=z=M8Gi$={>6#hzrl76;A?zyss!dbGU=%j zCakW^D!igzOi>4ac{f6D_}{(fjYThz@|>2He%&fsKUHHc;{!VdnQ3=X_*cG-;+r<& zw~J88|3G%$pz|2gO`R)0(>d7fP=s7hzAdN~>}dtSwkT#X(bXRlSK*-DWB+6lBS9O?PioQM5&!nJ_KvlS_iQ0mS-{Z81%Hr zo4J&!g8b;yicH1FCTytDy;l-XPdchS>ie)+8ZjISCh6H%Mke0_w$Za|U1*QKu^Td* z`%8fE#FYL3hHab$zFgBWR`aGH<(){K({;7@wcA3kf^W8u*_fA6x-Mq_1GTi46zBLB ziP;(r(oV37W#k@-OL)m8?31WkMznQ(4Jzr7lrQDWYt@i5Spu^`qLWd^_&zznuxsl` zd}t_7hB~p=%9ZR)SXF)3oH#vZ4qb00+D{+u5LDYu>|U`X9OYi-ILqb2eOhi#vCA7# z2pDKq&WuSG}SVUB^fG+Zqu_#<#N!jgA|$DyEK zrWI}?vuVJo=^o{XnBlj!iV3G0HJ&MS}LnSu;_U@VcA5 z63kpzbZ2rcWpy*CqatHifxB)Y6CVE1li#EgH@?~l$>0-je#hzWGxz|VT9=)S{xPcDa~-D?O#vessAC;Iwt3b*D>2kH_d{y)pm@kIx7OLg zu)bufA=N{acvDy!)Mj>mGDvkLAOn7yr1wSeim?U4nzmb`uG0P$!cAv^l!0B+ny8h*54m}W=30V6njSKL zN4WcP?1b3MT%39T6=|a843QiNmgb=ZQ+`;0Abon^xxndAejIl-{z0h1pB0QxqRl-B zoDZS0a{Y(FKDjJaS!j4};JH72)SZ_D_iZ5#_hPMGCtj`hRhm}xI6J79O5w>-p?{3hSf()<+Nu>Hubg{() zdji2LV#`;h%IWkeedQs@>$vk%HmG!J`jODg{Vhl>*4{AV z-L4A>-deS}D2#c?>T=XevzB+x2N;DL(QdX<8J4mI=4_pal84AnBy{}~HE)Ul)zBZ_ z@$`G8=}lW?H&Mk_8_=e+GBB=n_!{idDCkM{uZi1p%2sg8I;5FNQr4serZz7Vc5+p~ z(L7b%tzNrZj`A*gMOBA8xhoUWG)EE0Pc?&ng7)l>jS68E?*B(%6 zu_5^OtL5rJre7fo4u9=dTm*N0N8>~2@S&Sw;PAJM$-xa7s=_7ZK8kf=U4e2$q9LWL zLDw9s6co{T?w)fptLj~gXjmH`VSq6^4p4Cn%Y|*Y_J=qmwV{=qSS#d}^6;IWrQ-L>JQD?kJ zCRzPjvnIC*m@HZbbdc8LyZ^`0S%)>l3`CSJksJ*= z7Bqr%V^Gr4GD2yT4uOYw=^Q!=cVFM@y3X_b^khII_SCw26}*2xOZ*&5 z^GZCg$8Ae-u$6dVs?jp%!2J-H{5B#79vAIG)nbVhM#Nu1-45ix)h&NW}n!n?163hIAw(=>UG*eM7j*5~dha90ei z-OoqhDdJP9gxl^{wpTcoscFqukbxMdVcPq&47r#ubwY>qEOeu}hPDx^eALWdz_3*4 zHiN~7vi?yC9ibw(g*&A6%Sm5zLv%U8<7njY6I8`LK$89y$E@dH@-k{zFv)W^-LH@X zbRd`hNS?Q1k`AbBUKsq-;UbelUF(rr>C|xLa4=|b5-7I>-dq-&*;*zA#K>aZ< zwDstwnKIh#ji7azab*(K2mO2*liJHFCCOe^Y||Dc+hdUab8~Tq$IKX4x@#&e<)`=W2Odn;(+||eNcTfm1sSh~MnW|o zS}Of<-k(0d@)z**w@P_uy%ygmg%?-KcDsX|2|Np}J=^H0{X#9P7{SOQt;>JV)3D|NL9k&VsOwt>=}Sz5?kFVO2{ejB}@5?i!RaTiQ)}} z^b$8|TGaipqxBua&PZ&bSY47OsU{Be2+3S+WY0fj>=Py)<{dE_F|D=dyqX{k{YRRw zD(_K3!(DW$$)(PJfS*cXauDO31iB@6f5)~n?d}*ybRZ-}!HbI1XosN1`p^Kg=9Ho- zSEN0EU+SjN^BlDrUO#?AumH-K&%G?F7&zp>=g;J!=rR|c#dTdb4DX$8Jtf9NJQ!hk zv>Zh;mVGlO>j`x`qc_womJtk;W5ANb#qyOI@vk+~E3M63PQ4tGPL! z90)CZQF8+SKzh~w3E!`;FLWI)H*gmi3lPl#3Yvsd#&DuwEC%GEzT>lkmNR*!=^PgyVN%07ukyOZN zD>9--gjKQrBxbJk|EoDd)MEXpdHv^>O~hKsm+D%#f9HGK-pSX6!g;P|&Y$wOW6`BC zb^aA?5){*Y+rKoveWST(dmv5b(wF)MKo>u}e(l)Bwc^B7F#SeZxSz^*B z#Yk<80+#Xd9@*$tYIj$V3 z;E}5{mQ}X%tv>AFn3Tcq%Uj*JSQqaDa-Ty3r8wdq{NLO1p$OL#?D)IQmtUA>TOvy3 z<378LpHTGp{rM(MS@t1mMI`K|s+x~6n_FD6ueh|=S{UYCkJ1cKI8iOr?_R5;f4O@T zXcKjrTKxHU+An#hc8mM&dPWsaw+=5#GG9ff!ugBNv=bHcfez6AK{8B>zT3uf#1P1T z*;lsN>sLRz<)$>|lIfNc+&ykMdU}O;)6#5exAOgYx#O*MiJ;K$qqwE6HeO~V@CSp=MbQOK0Lljr)(>7|E*^_u7i6~QzeICg>7-D=#V>^zd{}1Nr<1tRHN%$6puNdRPU%BAz0bp%HoK;E zX8!vfi*XIN+#d{PBMS=k$UWf6$&u8X#be9;8BTU&Ir1^@w&RpR1nPzyL3gnNk7;GE zlaK!awgzoYI_(15VW*#|A5|$T_;xoAoNWnFcT#ggfq7*ND_&&lpFW1m|IHBReKcy< zaPh?9uQC{zN%*O){M0(Uh4)v{e*koxOQpLppW^dxqsKL`lz-VwOqOi?O%iPs(iT!3 z3he>qNY`S9=`1D{h3+5(4B z3^o|~_xbcEPah8pD!j}vMnVC*{uKDCw%?v0a8d|3=M!mWVBukgC$B796>DIMckD&4 zlIq6S6crjfQMno|?d-gOL|J_wJ)Wc7Bkr_Ify(G|hqo|VGC|XpLoZ907?_vzTLM94 zeWa%7wcFTJ(dxu)X0@No^E6kikkuwnJ}g;T>tUejTh+kRwZL@#@lFXP@48x0{3Les z^qe>#DmjXO^uC|AZ_|;fjl{yDLmt3qw8#URXGBX|qs82sH=)?4tgJ(>lHoOoxLZFMlVo&*c*wt==eveDJAg}S z7^|HVAT=yol2zx>Y?4taWI)#P3_e^mo?yz%7uaFRaW|&F(_&ag2|+eI`~;2B7E+D{ z?I(Y$c^p!BX;0QZ@tg_6Vb0MSwUSeO)K9|zAy@9u=!}oa$3`_t?YY8t-wwo>9OG3#fTja#N&oe?NyGoURufQB%J)*o`?4%+#Tnq=^{tu!bqHQ_ZcE z9D$fF47B)I9ZfcSth*?fFEFBoIF{i{mhrbG$y8aPjGB#*l-UEK@&i=zu9v0>p7 zlN)1f_$>BeG2O^Gp6F_RzKyT*V$*^TcMco;lhda!%Evyz=XhgS-IDf6gzbzmoG;5$ zzHO09OzJXUyrF>@gx)xVHt*~F3gS-xpo8d< zgR&8B!ukiCBN1`{7e$fyh#g5!Vcp44!$`m%~x2ZGM21j?s`UTMV*N$PzDz9!uesJDSts;T zZQcq*+mYU@wstW07nnN!zK{VBE1OIDwXP8EkvaWvJF(GyH@&!k>mY(Eu)xUa4lmuy z?4~zLDl#&loWk?ud42d(IkBSpCsqE(YMF&*r^yNG;ZMZ~owCXe2*c%H$NJtg!Tvfw zP?zsA?Xw*~S5{rE;>bRkE!C95b8#7}_BGm!?4A}97sqbb7eg#w`)~a0m_lh7VqR`B zQdG%$jUEkZ1C5_K-hN`+C*nzNc_Tez92D<$jo){7*3=A1bDR=wLby1bZP2SK@SndR z8RfgRijUUvG7lZH6jJfDmp#9^gv(>iNqPbM=%keDw`lzzM$O`Cv9_%_A?qt#@=n{i z{d)+zC_bbR%^r5a3}upV>N&i)8rtj$2jc>T#~D!+oZlDzs`+y6^g^LSO7QV}i-PE2 zW{=V@u$?F9S)m=P5s{a68%Tw&#&D3W5mgFlAo_hpL^mpkr z(I7z;tZ0oI3)M5&-CzB}5x63z#uYB9+b0*Vr_1Z(tE5{V(D(4evavNzF&%Pz`;z&D8 zPa~C*nO2oOA|-WNO10=I%kz#}SA>UCQ(dTED^1xV5%Vz72e#F<*DZt`N=(#G!Rs%b zNDo1&)8UK_0(2Bb}Q{$h}#+CNK?nbA~dty*p~Mq6?n-@>HK;g0kbBi~cZokcyYF z$Qh(B*%0hSOXo3vK)__Trtm^&ztC)BMIn2SuP$PeMf5Xd|=HY()2vo*Qd5`BVTu&dF0IJUdoEd4&;w6}_K|%!iQ&d32rG9@D&i0EqUM zz*=S->jkucK@G|^5=jwLpF4P>k?`=1R1amqz5Z?&vUN<>8zGe;M*U#u8$RpP?LIn< zGQ=5jw`nP2eDTqHcc|`{`Dy|u`C0tO4m5sHPM!`9oFCR5gIH>=`hX2hsofZvvO#sx zUPvX<705BxERKYe#ohbLwLH^#}oe^$1dD4f~8*NLQ9MOY{jLEc2PRX$5YCy?l*$N(y7U9JnL!& zkBiQyTHcf&N?nJCeSCbT#g4rWant`8hkvjg97{(aIW7(+|DtRF0t&+^9l_AC9cQmoJGh|Dxub!D5$4!CBv;D9&@D0ma zw$Sp6B=%(Z?uuuN$QvxD3dFCI?dwysB;>uafh-)45Y<8yn&n1Ghkw1ag8jn|xz3i1 zwuqiET1hH$?h)$iA{iMMOwkhWVPB2fs)j#|z6`W+pvjR?_fb{I$<5QbZ`}a2e3?8& zt3=(mTJ725Loes)H%LsyT^smfR08y{pbK5vS*5$Vbh1cpDE~h2al8AaRX6YgP(9x( z9`uk!OuELG2Vo{ai*M8?^o8#b$?JSTmP?Ndp{SX6SB}Uvvx6w&p23GDk8~mHXPHKJ zd>1`EL*~7mgE2#v7^yuou_{XAL3AVx$`5Y5*rJvbrduj~*`3ELOZ|eJw1{ziiR4WA zBt$ukigIT>Hf6}G zjy#nu!p;3j2kp*Gl8349QDQ52u|V{3*K4j3VB)fcks+ggHc1-zi|F*#3Snn_=TQd! z_3v`*JnuCd9aWEa4fi80ex=KlNOFPr32xHK!n#?;Aj;`xt z&40lwI~nc08cB1T#(#R{e^;0@=IQ>gy1r??fOVwLkTy9x8BzRKxh#4z@OX_mb%qR% zn5znZwX^O3UG-b8!{fNsXpO+-EJNbekx@|Q+NK*T;u;7cISLQtPhq<06Bx=*nEBzG z+|-KPm4nFW{^^KRO9g*iQTqGyjw(qYxcXwV>ot{*2?tdR5)D6%SqT`Dia3Z`-y2Cw zxhkhZIN6zGIV8_@b4F0(s-=gOD{tgpZNDQJ$G*aBNUhmMA&L$eccunZk5at_Z!QwfX}4PDp%CI1j4+uIjn=zpUzVoQW&CU0UUop#4;u|@d>`GK z8;HpKd#p9d|DsDvtA2xz zY{I(BvWs1a%Z8s3;JAeJ0K{r+k0Ix3yDYh1RB*w=?bzKhDB}-qb8V8|HJJ2TC4RXU zKUVa<(e6=CwX>#)P#p?9;lw@7+kZ}IDJg2;l@{9HRxyWfds)6NpHl%Vss4|A!JItE zTb9n5HKEC4m1?dw=iz^GfC=%lf0{T%R$$Oh9l=~lahy_qTG1ZseWSgO!K7H~Jld&Y zPo8q3tKec_CfTteL%Up7Pb9KGxo0UT{|hK;1Pnnt1njOJE)ZGO4B8FNNPbo(=Achg zexw@M>?I1=ZR6}Zbmc#QeU=$2*;PI>ezwEklxdJ+_KdT!UkOgs?d2O2oe3eITHfs7 z3x|2SYCXV}6DCUxm{gwUdlDL-@&M7b07@B9=J zk^-xgkG<#oWmLE)<+}2ATyuEA2^pO*MUur}Vxdq=y9o~4-oJs% zBiB^@)(ydDyTBrt`fb~}SI|V40Ax8wqU9Ynz{VkU@DMOO6xw>ec~v~k1f(ESu7t)4 zH!Cq|AZN3QDw4hN{OvYo_Qd+TEv%jj_10O3qdFI0m|tZI6^-RxlztLieKV2;@K*5Z zEq|$gBpG09?HR5T=t3qW!9jCDbYbE3Wi%4*+jioSLL1~?D*9;9NSEwmOHAM7^&0N;6a97#6G3Qx0L2FV9yb+a84NEoG~R&q}_MivV$IKw)e9zHiH3|fVo z^tga&4};87_uu=_TxKPYJ&8NT`g+XP&JK~>t{0C|+i?_}kUKOesN}mBn`vq3qH=eJ zb5dE!3vz4b`OJ%1{lv+k;fQ{bDP~AZMuHo_v3fiq zs#p*ky7H=)9H5~<&VLenbrWZ#lfJNqBTEzN5TF5;4z%r|ucKBIKHH!pJ6_}^8D>-D`+FB$dSczY@eGACSHhRHA|w)OB% zh@S)exm;orbF>VHSLxjJDsJ&YJ8Jw)x9lm2WBC4>JhyD*-MrgG)cVe9&W9$|mYBaf z-{^eu9vB>UEQQ%bEmfb(a1ivL{VL-6Ay(Xh4*In9u8@|qvg%=IzS%WamaO!W|H0VX zr+jACh9{lJ$ThSEh;iq#Dr8rAmP=+Uc9Xi;9H@bBviM*yuy9WJrj9YMry!3xCA*Fj1!ovYgGBUM21S~8)hu0-oH?30w!DJLDB1`FwIE)q4!lUFeiFS+ zSLerR?JX^3BoQ-AD8QK)|J6tYxFNR5F@GhjLNdm8DGBC%HKpW$bUxkag`NVq?K`jC z&X5<%kwNjbsRI7d0c0Z1&tXbs7G#hV-z3W0a7+-haJ0MnhcA2qBmkj+C2qwwYNPfJ z0M8XpfU(&&Swml#)G8kFET|>+ zV-%y+U_(+F7f}A3_^M0ZBbC(x{;%8xl`Xr2ln+Gv-hA=O(NZ|S@*S_2+bHx~DKLD+ zOZ62u3q(24EeXh4e9X#bNg_RVh#h&GNUf0SB(!a$f9Hh6W+0XPHXXc5ASNDf^r$x{ zj_u>kEJWT7>Cx5q%G&^nTw-mm!n!d*sd&?vv3Ht!wyb!~%}BEtyO)+PxEc4!`dBQubnc}6By9+#-C(4+O1TRi+v!E3P;`99Xjp#YyE=7CvDSO%L< z6LJYoB%8=VD2krD@?WcaP;qF~*yGwJ6Y5v$L z>2ymC^V|0t4XZYcLUv6gm1A9byDBlPQvXoKGUn)joUZ)^xRM?c0l)GIGg8J3b;%NF zUZ>#S=Klezxe%ke{4L&9$)8oS9sZ1$id7>iyk*f|vvIYrEHR0~r+hO#2{xZGw1Jfm_}LAl%*I|G&$bl4*3sf)fuZ+sQsi1R zl4uVI;b<7Bq)nVH(GRF{aG8V;u6gy1{b=M7DUdRUfC_hQ&W9t$FY;iHd~D~6s3*Po zdFIKlFQI?tx- zC=XAW+J)G4ep{<$%m@@i6U*k(&XvI)sKH+k4(~pt+Yd?-1jK02Iq~`2ho*3*lM`J; zN^%cc1?D;GQX!6*UsV+ziS$-dfA)X=S_P9qF<37Zppk$9Nso(5Ij`0|tgl*ij#~9m z$_;<^N^v9aRI0kxVk*pCKweQiNnG^dTlz&IR&Vr5o&-tPN4%w=Q6A*&2Xl(zuBru$ z70EZPy~bfE7yXsyT15YD{G-v5zVE!DD&|sjwT!Lunpi9um(*c;ir^hNO||W(wlOq< z_CKTZ&IF(I5l%O+hx#-^4!^TT2`%{odrH*N>(}C_a7#5O{uurwxoDR{Xm=(JFMDU; zqAMo@MVOINko~T4#`zl5pXV<#EbwlljNOFyc7Vg7atNk~GUhI$$qR9fMy3*z*}0-h zfg|qmPW~K~ji`9Fe~R*Hb$~x}GUHQ3q-9N8D?{wVRtgzdqg=JZ?y{+IaM*TCl~Mka z29iw9_3UNX8_8raj(=ooNy<*wLaxX95*6FWBZFiCPqr)(^S!)H@5~r8Y0H>!?-_WJ zhB<&!fcT_kpFp7O(a4M!a{yMfPBX^k_aYXw6;>SYlszf0GWaJ{o1tdbQsRo5w!O zOp&|8xvV1Nr0jO>_pF?Kma6IHZ#K27k0xp*+XB|CYrvZQaNqF+QRy^NeFyv9y$GRt zFR;*dH!X)Jw~|~6r;7EjqF)@`88Lh*=w14J6~}P3+*HsBUs?PY(gTz?>{XGQQE=7Z zqs$xOQ`$4G$79SQVo@cN56yzA#ZOU&mV+_e%3+z}q)qBp4KCq&TmOSexjlQtbLcdY30T#jxZ+pGwZkf2M}F}VYdMlRT!$})`s0M zDnJxcUY0U{s*Vt*>`1UoPT??pwjH*fKd&`Dx&Mx-uN+)7JIIwRcJ7^=JI(^$QXpoI zKF50r0@{*C1vK0UFr>hbNgQe~f*^Z4=ND7-x`tOv1T)Byip0q*v}fDOxaZlk9zFxl z7Emz=s7B_^FtJ6*tS{{Cn$0Nda7!o=3iJvLclU^@LNzDIW&0-y9#R{jbBGVa|9siz z|7^E7F*v436o_-&XpnSXxm22wpqil>W@RT7drNu>?y4 zOkDpSpHagcV9;eKNNDYG;d@X%-V9OXz#GEMd0feIdga%aFv1nkav{iLJC+2ji;H6Z z+Ih566n&y%3?-D_FYug&vXKeN(h*(7x$Sxt9@!K}b&2=&1b`>1c!rD~7g9}VZwSjc z&2}ta;U?R$mwu>}Zr!(;>U0tW)*wlQL%L*0~@2{`z#MnWX zz{=Ze$*EXo<3gg`aNoF}OW;Zo%RXu}Hcgfnr-o7Stx~RH z@OusBW*7DBMRCX}KEO>m_z<yaqN1EYL>mte_c(4cmIsTNOD+ zUDbRpVV!SQ#KZp)Q${Vry{7L12*DBw5}{A<1nNiey7=!%w@=lQgzxdl3p8L~dzec` z>7B%aD8rcjX9xi1bgA3-Bh!08xAIc!E$8Lyf0AaqLd9+Ea{1Y$W z;9JnaP>{U3O@6=8mdN`$^5lnWe_q4wwk$!+fyR`>2w9+W3LARAhQU;c&l_hqMN2*- zt^)vJf;47C>zH1MSMQn8U=T5p?VlmN$7{s1PcK0^Tl|vhiyCb{3){=TqP%-?6)Vel1T)45_` zx0XAjexH(C3{wqzHEobK|MwypvL zFmEWXh&*pamV6X2_Kw2pwzm>U8$0oisLI*pEVqTtBx zTVejJUdCgVP1WZi&46F$5?@n>@Sc@PkfqGUZx2N$I8hGdHVnZ>$LuZ9j!e`XMK2_P zKl1|`ABI-!qt6vWyvK`w@Ls1`MI+1`Tzr|A!ak#NIc~cZVal4ji?3@ccj&tG`{T~& zZW<{GIxtsfe6qMiJ{GyxwFA6y*;Sg}5PV#O!9*y_Xm#u}>D3U2#&oeax89>XDrUyp z1GV`?`d+~<5y`fG;=8h5N}V1xDUg%jaXckRo5txy@94fK@eHOE-gEwBce{&I=ao#_>gj8QTuDqUp&u%wodbsrT>FZ2AJs@OG73Y>6Bn7& z_le+FQm05FsD|UwJ9BN}`_xkI0uK;`5{>6Ooj&woZ}7u6x!+1&?Kg|y%Trg#arZpS z)aajTQ4(JngKU$pc%5TamYOUhwH-M4%xdY)J3-7!L_;jT(J=EKKx>YYyIe@Dr2Fiva(?Uv?N&;=6K=tk9b?M?|;-wk5j_+icx zV}a)b5=Bx@3x_CiqpKw>St$ZGg%-|3qd4a_to16DI0FxXZ)JMJZeTa%A$0Gk)OV7k z6Q4`QCQPk1V`ZTj1@7$p=P|sF1r`$Vp{V5Ah1Qn9-UZpiFm1%K4tv%!SIW7c4mgN2 zMw?K#5- z+yP1?XKxCsXrC#7F+q=Dg*1eE>0uGFPhX`b4HblXb!3$PCHmriu<*n@anjomc2A$^ zrc`_8O7m;ii`Wq*X?(T9OLV;xgpzzPN3%QbwvBI|D^be;xn(wg@Ham%sLf9vPgK)& z)Q~sHBy6~W$uIg3&?IAmS7LO|p_*#d>5Eb;kgVyR=h+VXM%~OR>m_P|8co)`q`ccu zzSYc#Q|#s(9N*{!=~WKrVmvd+v21~c>t9xqII6hbArYEV8JL>;MIiKV`mh}6jlrf= zrgt4_A{tx0KK|rTvSJP-E@X*I8<$Gb6b46 z!yLA{0*N5H=o?jPf_!USUZub6)`1*O5xXq7(#n`VlZuGD43@}yf?*(Ugn3tMqA}U5{NRqfHMu#@V{Q&eVsQ}n=L%M@9`lGyvoKrR)kGENaF=R7i@m#L2~fV z9SL_e!*MDN5-ll>F*?vXXPhBr!RxjARB2kIyh!0zhZK2b1f) zmlM6Ch}FI0Se8`$N*G5K&H7d7rF!%lg?T24xu-#D2|Razrf5|_8QDvuM=Dd}=srJW z%Z}1blDO31?Qe;d5W5)fkl7^1za;N}(v-6IPBHQ!&8Jd&b#4j7(t7DeOd!nj*Oa-F z29t7SQ?|W>lcOxLKNKhIjh7014d_l;Y+|iW{SRQGJTmKz=2lgNpXwFduL@l#8OvDM zy`XT~=TO;%Me1pdNz_vEY4vtm5>9d#xg?yIQzBI|dZ^vAP`C;g+#Oj*U!pj=r(p1B zku%XsB;q!}A+;iy_cns>jU7Qnc@XO=`M^Ndi)hh~iCBbNbGFz%cr0eC-vY5kaf9TAAH_60 z5=mGRzgVFx9+f+;#@B41yEKs;$(|+uqA-dI?lj_(**BMdpINyUu7fwc;(&O=ewwnbeBY)3 z{;lbI`B3kBzN$rN=WTbXPKee&N&LMR797&LnU*hZBm}`e)X$Uj zhF?Qne7{`dTOH}Wbi=(tVm$qHHpRM=DCBQ96g5YxBmfZQK|diW#Rc4 zgAOfPK%<|vjJe%Z_;`t+KNSZhGQ05M(j77hQpGXds68|&{E*p$F=45>B9-b_J3zP^ z>Y+4uye1?3gP$6*Y$~NC!ZzUKgHTdc01)N54A0~DnuUL>*sf$$G^2>F{%nTBs9vKv zzj9u+gCecKsa;%^c}xV2*#%E6N`_eJl1RTFC-B)Kd8HmGR2hHf-#X<_qU6s>3f63i z+7bQkXhH83vJJl87vONzjtpNc%4)t)$C*Azo@Rm9mGPtX8ag3)+|%2(Vr z4Nz;hY}who6Peg)O9{J~Lt=8@BML%Qss>=ke_rW~r}yc=C5UO_sj8mV@^Dlv9UtLTX$A z$(MMT{$ZhDfGSjgCsb?MOkfqv8NV5C)M)zO#MW3#UF9yXL{WUlppM{D-8&^XN@+e+ zP3@wQhogjki=>B!tX>Ty&~coFULi($6yQA+aVxl=nD-eKS|iUN@q8R^zl#B!44`f{YUePWQ9veyDbv@*BQfR%>k@Kj!`$p_MNd1HR8l!-m{l{3>hlV zZ($OGLlZcv(u|<8m$-wr{94kB=)1ia0w~JhG7my${2`fOz)_-%^2{r9_FyhQd$yt44y?Q%O z58HS&w}9OJ#9%)cq5%r(f_Z>gtEiH3oygd7PYJ@=AD8$S3%{V`&d6SLSE9|JxD!awLAm0rVN223YZ}WXV0=r22K3 z`|J7T!K$0nTauGd<8#KH8&QZS5kgtd_YbBoy#k$}M|g)9T$Cu3muu`(DFo1CokJNp zJTV(2Kg&w2soe12`mwGYwQD$*d^PQ(=HIMdxaQGH%E*PZPN5_NlKt}wL#g! zsBRg48Eyu3M8B#I6Whd^M&{gZiIl%;`p>ys96T4Rs0guxiqwEEOJ4E{SdGV%=G(`E zzNiq$oiSlbL5_lo#k$7qYHtPx`ikV4J2BjBI3KXWRW(iyImvv?3Tj3y(+XPLk@Chm zHj_odF{;C8?##zAn<{aEelHM>0#Z9<$J)uL(iIr-#1y~$>E`?}pWJUrv*Dpl?!QPgl=zW0F>Emoxl zlXnZrdbrF#swcN2W6y|AY3047AQdYO0q6tht2Cj+`^=aqhv{1%@4{D#1Thk{)lEVLlQq!2}UW zR2DIjY`sM9dm)JqEhPYMXC@qs1HiWgLE)vhgM2^4(uD%Fc{T4RWtppR@QWoa1i?D; zmsc3tKPFv{O4Q^|WXlpd_O*>V5m&qi#u3l>-qQcbuE_I0tFl9fwvU%CQ}PJUlz=BN zx0wU`(gN!;c63IVLLrk;5WB4FpP-B^pS~?vceL=%j8Sqf7lWTIu0YeOK6o{C5O|hP zZwz*YU9az~m++@_(&*5&JOOERuq!S4FdQf<%MKFkAdLu3@qTk^;Ovke7ey$XR2)iW?D_54p4>5`o zS&k$|pJqvr54F3liILzr*`>N~7&+bxOvmW}*)>;uMc&D-6D!kK^?9~}8!go;(lgIbRss^p zBN&e=-H#9#0Lz#mnnta;A82mD{AFEMt@{qIWp*fvI0K0;V#>Qj=UW>h=T>un@yHAi zUGs!o{*nzeSff}YjwAY}li$`F9a_7^y5Vc|fwJqxyO}?z*LWj%GQ0o zM=kw+^zeMb?DlWf3YdE$;97mM-uOt8C3^21JOBpLm30y#{bFKGuR0AbZ>ojai=7BA z-CUBgM)Wz_zTeEY@0Hw4X5T09WxqXLa?19rp9$?V`Ng3HomEgtT~K-9nPvvsv5P&* zKIV&oEMY9-YkD&+Qlp6w_zL@M@y^cYI^?O8LvrXC2qgb9D|LulTE|+ktRyQ zd$%_-T;raUsO0$HkB-kO?xk8zC=nCVWl0~~)ob@}vfk6t>(kSy0Fl~6?Lg$Tv2T_C z9ecT({BepG7VelY3hiPQCaH73YQ7i>(>~iEn88k;x9RIs+c_qfo4Pd*p%% zdboMT`$mcNi+M({_05;X3m}+MSy8C&cQ79f3dM>VpnlQ`DeGst`5({(HpX`-)~0zv z`a-eOT!%pzJfXcyJY0)ZMGIwnKWVqL%ohNXb!%(fx>A7v1}@4V?P=DpC}&Q!YJR6E z2GHxvm6^B0MhNQNws38CNjBd&8lcph%Q%5d)gTkpR-DHL zQ|-6(b?C4G;%qt(s~K)0E%#$HQxRUr7Ui=mw5_z7oV%F!SXbqH;%Tm)>vJIEg*lEs zwCF9z#g*UWJY?53WQ+iVYgNY{cQTa#Vb6wztd{Ug>&11E+3i)@)XxPbs&rD*$KY(v ziIEt%;J$XQqST14Xpg_0rwn|L|Ftk8yV^Et7U+3)u?fJvDY$%Kd0q4Klel*sGxA2) zoX~N#ULva9Jn~0A^eXeM`3j8rt-0MSQQ==t)CT+q2%uMCBjNO^fLqS=eEh_5kCXI* zuvj|n+AzkmN;kO6lhIP|BjKIO{|4fX4mp87LvZhFHyiHIpBQ;3A*TE6UI#6$Qd1K% zUMK1b=I$lR*aX-7f;i@pMi63%zR?^Uu_Pmm#7I8Y=#bk}8hNh=>;X3ditK(Az&?hq zP@udUk)&$Ms{DOqSI1_B5)hXF`Vpy!s&LbmdOgOF;~i?-m=#2gM77gT6;SL8_XVly zi;naE07l!#IH}eb^Sew5K(XS>w<`3{yp&`vHc5zKJ2ttmV*?#uh~mh^$#{rMq*Dby z72>&;nR5DtYf<~UJhb}L;4)ltDdKdqqEYu;MQzIoPWrA`U8r7KixB7D+MuK(yJ=ZL zyTkJ0 z*jb1d7yWpOS>KStYSc|L8^8H#41iN>@fERc?U8-a2bak8+)EywEy^kotUzMDyd;Ly z638S7{AoTbozR%hjdJQot*&(3Jwg>D99*Z72OLHXGYTx&y_J$m-AyXlnS;g*M1DX& z3OREJ=BW>I;by$fUN6>px?k;xqd)TXILUUqXt?9QY4Xw)zj8!raMggbqs;$Coj zpL#0F@R6Ye=(&(0?Bd2TI#w=$3W7xN4xU)TZO45`4Ow+{A0YMJU7?iRr6(fptD&d4 z%4cB-1YPwz)+DB^?6c%A1ER!A<`7F^9anN;%))CL@wMWfzwo|v@;aQH$G3!)ByS?X zjX=M_wcDIl64j=b5vZm^mVV;H z`43Pt^WLAeB*&HdZc~7a0PC0E0D42BWUFlJUKKZMqEFHj%e#1I!+Er`XpA#$XIN0t z`Gw`*Q1X+zPf0oGIl6Y=2f(9td>D3yxh&zyU5)*urjzk60J89}w>J60>&pC;1ohPq z8cu5hw+`$9f@*s1$cJxad^_zHiC+>z+1>o9fH~%Dg(-m4J2u=P;`C#is&c!*8e?`} zTTrSHs?VBaaF0ag!ZhPhTcek8RlZaIu-XAa2TQc7l~|GtH?6omSGZ|z934pL?Xpkv zH=PX((DL+2Ln8;+Kug%utv*j$Im^lD!AIDkHAx}1kR48G^cNC^+-xwW)P5yKb9Xzd z$HV|Bc zs)_$?IyK{X{bROSy}F@frE{%Oxq7o=?9Mx5p&q>`Mm{G^o?i9LK*%~u8xvh~uKf=x z;(SW)Q^>=IKw;m+qB;0Dt= zpTgiz4}J@C&}l8RPa5Q?Ad?|CZT|sew~WPNj6Vq66-Yg3jC;YW!qy-I7AQrBUaHom z{i}X*!84iv@}_!;w1#D9QuW3z{APJm>0}dE-6gmZpcV;g=p*Ye8OQ5*RK>!2-qPJ! zo#|nU7$SF3(%GO|V^rXK33hPhc>36R**Dg!ZGPu}#M_9;mjoUzR!mHT9HDmyo#zq` z;6FX*B8v>K@GdD2REMeiB?Y+^;ZyyUi@ru&osj*dUoBq=&KlL-oNIQw+qnGPuDKaw z1wLF?H1&P?S>R(+nS`V)BsewGI`$2Gm`d$hu(Ol0BriT|<9%XAMWjSWl4Y*13#q<$ zVqphC5nic3t6j3MwWN`R0BSexIX#y!I=((wFUg-q&|LW-gDU>&P(P3`SF5~I4?Vz8 z>NWecE%1n}qGr1)0vWP%O{T7iK?z-!I&J=l@BaZRWT_t_O}{)-h*Ur^DES0QO+U(e zTj*M0Gk9l|vp1&6CU`Yj7I016q}cd7N4~2#a;3vmeTqs4z}}I+g1y)`J3y)a2Y5&? zm-bo1fJa+^oV2}M@?!WhGfqaVgLp^n==tyCsz`>mg=3tOB;($Db|cX&SN@QVd_~J@ zcV97lqn0=|fLx}-VTck#sUKsec+%Q$za!PwnAj(9yffM`q+QbIIz<&hdA35#p)|1N z%c`|9Lb_)EGb#H5yxi`>9$uVf`#Z?n=wZX}r=_Me@f{Wwr62x|j!RZAhZf4pfG%Xy-u(XG^3Bk;idf+&&~_Zd(^2;{Ce~ zCh4>y)6}BFC08-+(;a`_O$;F93CsEK|42ITcsBR<|Hq!Ssl5_g&DM;)V$>dWsx?B< z+SIDOX(SQ5HnE)+)mpVzj8dzIqBtl~yEbut_vicbZ#*7Zcdq-ouJ`Npe1Vc3--vd; zU3^8C{IdU_uM*Cm-%)!4XT$G`zaQ0G=fQnU%twdyBeCx9Rl%%z?Qcf34{WPmy}N~j z!>-Iu9rHB)PWiX``rCEg+Zjib-8!RuHGW-yj6POl8?-1w?%?|20(!Q~naHLi5l)$> z;nWs=Px)XLF2|*z2&^8ruD$Nq>?|Bl11s%cRu@yh`uiED#IP-U1+oYttY~ViP6=L< zUY*J_8MxIN=uFk<*!x54J+LwzSaF##`~2?jo5RW*iyx{Gn~t}i1&s@HImKTWs}=?H zPA`{r8X97<8sq9E8gXu_*N3I?*-xMLU!Ex`-JW7ES;HQ5Vll8g5bC@C!*~=6TK0c&qqX4rTl*R&q zdiM{68MLZ(Bk6XlUDmkc`(d@hJJRg2m0|SX?~Q1(M}JvY*0ju8@5dE{ka{VIdYF5W(-(z$3Q%)5ilNh zRMS{S{KfCIK1I;^(?6}_d5!0Wa9i!6ygd#}8DcN>O^CkfLBs~~{h4{Zp@~ezK0RU# zuwNUr=sKKCfR3V~eey5}yC7GKLnd!7YBbUn-s(uW9!M z?@hH-aOayIo==AEsQ$;gznap_FhF<+m zR59o_C;Xl0SysG^)6X58mkc+YyEugxNBQ2utjW^gotFeF%0rJfpD*Vt2Zy-&Zn%uO z|Gcn6PUfuo8l^qgsmya5kk@7j;y=&{B{o~4CjBY-Bk{5$ZCry{Cz^8mKz;UEohEbg@NA=MH@*YHp8NgT zgz<2aP)craX0U~61RA<|3Nx=fH|L-f05m!0sQ*AWq{^mh)1-{u%A_9b zzEA$~92e-7)Q4^;krbD#sK~}RPVmAU>YWX0l!?AwK`w8CaE6*r)o;2@u+>!*bjW4e zSOkL-;X2BaCAsVVTtdB3-55=x_%iAr6uKI?6*78`SeMy+)~58&QjH}_Sy)7csng@` zRcHzQ6r>H=XRp1$U>jW=M*!J_r9vTmJF2(aYS&3kPi z)91D%98w#stsqDCV;vv>Fa(jYW0e)^_-0&P0gbByiu%djz;@aFXyC6rK-#xircGD~ zgbq%%;%BiTK@}*hR}|U=_|yydOkS#-%le~)Ix~V zwHB$&s^w%jxs23~o#GQwV^GNF;$;35mz~X+mTg11YxiSsqlBAn?Gmrdpi`^Gpd{jz z5~uf;_O6DViSY+Hr2fF#D!ThwC@dG@_~$mnuzRfXsiUX4c7a63mt5tP(04-Qgt;oLkk;Ja!^AL0OD z9p)paPOq;b>L6LlW}T}(VxtYoJXK&P!c?D+sPQL8vfD0K&x+C+E8+v!e7yYcR-{s| z%m1R>l%UGc$E`%x{beXW`sA1ZL>Z7Kkd>Be&~S{t9@h_DUW$>4C5 zNdO?#Y0X#Jxv2H~1lK!P`2IfC=)-g0;;*?XXB2^*@y@7g^RA4uz5*U+% z?~j9;B&26|+UtO^2Rtm~;gLVPnAv_X^-olyYFij8$3Y(i2%5tY zcYvpn=g~>Br}n9Fd6|v9!o7ld*pF(ZA5izrjVV~M6+?nf$HvQh1uo-Zn)H(9QMZWG zm04s8Kg1bw-YK}AiN zs46A{Ne%@)R19BUhG{N-vZovkT(^(xqsMt2&o1m{OJ@^tx$(YBZ!=kQz0Ki9W>-~i zS4zITab6Uc;dn9O&3RJVdRI}^QX4VKuqq~GRPN>7Ip} zHT$nA#M6tzcKQ(?vh@QJ*q+RZxrtXp_ek%`HLyXWwV~SS)%1Hm?2Y&y8>;FUA0OOY z@~HSQa9jp5z^p+d;*{yROP?qKopO&ZMG(LhWu+ZExF4ViPH!}-mq-33ySXpIbAK8F zvyke&;(t^2qhfjE2Ycypi+}tyDOq@WmgOPj<&2E7MXO6KX*LuncC8v}f@mmzrevw4 zFDD7UeSuz9?7}x>q*xvq?!z3Ac$or!L=67qMtzrgle##V%9T+VdU>}(Huv*( zymbv30DW34ry|>{Y1gFDC=q_b8;sVn>FbZ{_MZ{F7V1C3-Tiwo#E-LcqYfZ9lbGV; zc|pg)AJFBDkpF9r7jt2CZ5yPXs{mej0=FBe3YQU)F-zg$Nhj`FaxS?(oJ zE*)e{&rz{ozp=IPyH5i6ne)y}82Y4aAmhI39{?qpY)g`J?+=RA%4y|O{WvzLJaJzR z1B-LEjw^2Qcsu_1oA5fP1DlL)<(!PNh}cK2dDN&f5Z4E>_ZPfQyIVMN)3dB0F8rvt zs-^<_yIw?YSX18}Aa8dAiR2nkc==92vpS1bZwMH!@J-9RI)+32Y6F=#q+;0=P#Jt6 z02^l!@w}jl(pO(0-vChW1Q=cD^Wn~-ex~D(n7yZfrqyK4DG~s{jZoN#J@x!+Z1*@x zyoPT6huqLb*viEXA8C-Po|vMY%^v2if%%g?`gq*^OhAL=kZ}Fj!^ENMEOJ_6eeeZT zpQS#gzE#8j7;OfwdT?sW-Tg8tlkwW5GQUET%frnglM}@ss?77CC8fLHNR-8fRy3FSRUWTcM-h}SzKeS{9 zqa^w)(B?+X;2M{kwD&`oB9l?Fv+UEUMzVD}vib!-aGk;2;@;|WF3OON5fd=>&R^8f z3WCMp26G_$z30+haQLJwf}a0$C<~pH-+sY_?HH?8c%{N> zCD?zE)UC&}-RmRrFTr!%xbx6WT9=#N#~9V@Kvt;l+SA^kp+*W>zCvak?0E8b+OD9J zu1C${+!K6-BbpQxI8bKy^EoJ1=8nEFBS0EHO5>4eOn(6?NJ}JGthB(i|CyT7C(9cArjxp2 zPTm{xI)j83?nmIzIK`)INjyxlA6HoaRG1+eK(37>@?|Gnzhp@oyEMLXOG`fOeU^CK zZg>n3qNR&-e)h3#zMOa}mr5+gZtLX}pi!;i6>&=E>#8;CN-k`xZAjalL4h<}+4T#% ziLN&9=r2kXHDps9weA0ilpE6G#uOV|2dR4VuH7HDv9l@~BNp`8>}*q2lsT%Ciy}Oz zeT#DrF+G6pLJ3?OiQhJ>xdno-`4lVai)(#?ETY zxk=c2Dj&sO{Cpy&d#_X6lw&0dNKy{n)f}T%R1S3zw&q|Z@~ev+5O3EuD5P&yQ=fyB zyTOHf{lOoq7Hw_LV=;(+5qYQIhCNz%QOes*RRXd(xc+6qq&)yFIMsYP7LXT1BBZe9}uZC2o zKM!Ldd6vZ_(wV#U5%DoS`?F<^c4|zWoU|8CU2gyxij4 zk&XI;T+-=^QFGR^aVuF2H)?+dke&NS%s;BA4xHvVQdCpXwIq<% zOJsIKY^5OqXmD^a4n%+36S!UVZ{~-mya8hzB~lIDB_B5%w^0QD*_nXMj`qxX8`>nO z4=voD_|isWX%qlb*y(XRKhUlR8}GTPC;63WDQzF3NYozj;w*gjIdeQ|N}n|)S*mGd z_wwD@nG$nh4ch1OQJ;d_lu7*m6jh9p0D~W#bx|-adn{>1?8URDq8L&x!cZ3BIAcUV zc8Iiw(FpENUH<6Lf!>HRp=bZw1z_7_9B(UR)h<)mi(FhH1Q07JZ}2cu#cD5CXU0ro zoIZ3|-!-=p?lkb@wB3e2tVsN`K~_cl8nq zI5v2mxA3^n@GZ7RJ2kSw8IkwdfGgUZy-%Zw@Aq_&31dcFQ*&0IqXiBO+z$LfC-k_@ z(~)^5ZppfOx$Is?4?W(hzF)#5BS5=Ru*iU|6^EF(g9C{X8!K%<-u18JWs_Y?nT;q>%2i5NRdS zqUTgtmK_mQGvnVL-Fb=W6bllc5zM_Os%l0m!7=wHvV?y_W3^^kc^x)uJZ+h}7v@%7 z=RPNj;ZBDuxFrz{_p23e@+ zyzvg77q4Nob#x|`fPFYH6Yn-di9n+W%5KFLR3Iwod~(DaEH%gdd!lkm>66x~CB~M0cIqJ7aNtmqVF8m$80V+A~nV)hUS_w_?Yh1XEKY7DF2!DrFImXOO?$w^HF=q zF4hQIiX5luIf#k~Y7i)=W|5^ZADHFc^7waofmT`Q{3!U=y-YZ>#ZlKQOTH!bORQjx z$D*Mwq{LT4iSQ-p%Ww=rdt>bBJ*M(DsXRGwD*|Vh3pw&X(l{5CJE?jhiw*y#u*Wb= zq7F%iJB1SDN-{HJM@CHCSkl{&zZdz;bn^3{;$@DaPYR{v6UDo^`beO!X?~UUS$$-2 z6cA^-${!n&qm28gQf2jhBnHOa2oxJ#cUCv{VYQ66Uetd}P}rL5vy=ZEd=t5-v~fF3Ti;*H7p2;Vyw>`?B8^YvB0x0<>o!>sSlTJZhei zA83g!ggBi1ZeCRO4DqYPxKci@Sk$khaBfcpeNx^_mxl`T=ls&kfKaRm6}nvs4(!E z`;-Z_%c`zPT4@{|MQuBY+*bK>kZ)Y?@qeIhZe?Z4s#I$>Y6Vqq#=@kvoBsGU=4s-J zz%bppGI4V$>h!yx#H?J1P!0aqU^8*WmKn{A9Dc?QTkSEJ3)Ve{EV_OJiFjweFC>o4 z7aVI}Z1X04^Og<5-I{SeWpN8rc1DygkqD*7H6UWcjzSH{T zadVoAUjg9{%uf+gkweWK=yo|$h&biPt}#-laC}q3h%s`CrZKrjb_TEqSYNRp&lRML z#@h{9z&V^I#`Br_Af1^H|!ThWs%~pe~=vX|-ARtg}RHn(?Jd=1H+bb;;o9R-@ z6*};d0S1;*D3LUn((9gOn-R4V^K(X|WG;gP`)hfBz3?$L1E2->t7zE}Mxt(H1fGWE zWrp}{bq7qoTXjL-Ah*hq-Ps_G>|!=Jd_bc%rN( zsh+4P6`3Pzdc-FdF2ZqFB(bnA^f{#+j%$DjHp@_6oG|~mKX)WO$Lir zSs@}b4vLD#qzsO%vEZ@YrW`}CdAmg+Bb@;>ec*g2mXcCTJkD0yJPDMyyT&A5f{m4NbA^sL(b zW@kOJV$Eq8Ey3{)ZHy=?9OV(Y7Ya0wXzcHq>0ZMu8FQItcS%Svu8(g|M#WJV^1)r- zWe7`);>3Y}Xu9%|_|S`NSHXT99o~N8%@k%;laYZ3M5f%HsBf!5aH&&R4sNVdo8EJW zRC@klgE(~+|9QbKw=od>^$MCclfqKnY|rpSg+C02WPFn!Mr2LdRLp*~WHsw3QcS-; zTlIc?mKkfMRITr44qV`67xJRK)c+$K30bQMFoO-bJA2>Kw1@so7u?r#ik|J;m@<@p zeNo=?%q38Fk4?ypHDJWkPP(8cS^pE%pQH9cA4T{6qStf1o(sz0) zkTBcK98WGMf(~?D`zV-@g6}hm(bta!qf1XY{I8IM@f^H=K7DaN+}NLGevz5L_AN) zPPp$5x4?gKg+Wve-F(;?`$*!x5Wbx1jR|mwWaCpgp_ziXjZ;jL$iix#ZhTDCHuxOh z%Aze}KqadMhQZX6{?(37(;nz$+&H~yA5r?>#AoeRgTu!nlFtU~o;nL~rzrYt(wWl9 zK%+LQr1_6ho6=fdCDP;*PfRr2{Oe*1MyUAu$qdrdtR2y7^SCDp|KP?(Wg&ORmcAvR zKW|V`>dzns-K8qnx#QeDpla*O4hQ&zKfzk#J~pFMXT8Z%K|iG=SH zW6=)^TUihh;05@>wO z&eWL_7rR@bh@Vvd5A<2(S*_wUv5hFPO1-xmx~}m|k>{PGAQFIbk>Kmcp1IjK$jFFzS#goD1$(#NRbmTT5ez*xrvrU2| zF4_cgxT|NSDJCLlJ7QKzk2Ee4t(i!JXjXsA4smd>FHF0XN(Foc@P&kqXMZcJr$qID z*v%?G#lxQNUqcw_cc*wB2}OKJ;*)e0Zzs5Nt5)Z(h4L!#K%SZNWD$=w%+UX4hs97( z37|%&4mAEb&{EWW#I;n8Ree@O<^|O~- zrXO`3d4;#6p|pJCNCU<_r3fe5d4FJJhNPodD$a*ch=}X7rMHn0mWguoNHR7y*XZ)8 zcDpvSU%1;k(YM~pP|y_q&n;uAj{xHRnEl2K`Xc;Y-?zt{k$(p3o*p|htx(GOJrLK(9S&G zz4w7}gwElX`v%6tU&H`5K+6)%4aL=G3&^KZqeM3Npr4>l22b$Bt;z$-~Bd>k3X@01-FBcECS8DhXS+Lg+h$LVM(gb{# zogZxCN0aQSP6rI=_A7#e8~LDDq(PYH!%G93bq!uPYkiU^`>l7j+x$@r8mm=e`)tk0 z8AUAZdiHtV5?xeFE&4Jtp;P?s1Qi>tN9CKIhPoH2I_X&_>i?vO{%aDthNQp&Io8j+ z>6|@gbkFqn)Lj&V(iVZar7g>!; z9&o>`*7$u#;AhemaC+Zx1?I|*Ij=YBj_zcP@7+O{)r&LGJoM5`C$c^byx%F0 z3nMF-j50I9kfyd%c>&4r3{`7=gqenDF3nBGDU6EYwB#18|2X66GhMV??&_xkS3t_< zH%f$37GcMecGs`->s%Q&9$1n-DB3HHGd<8(H>NW)?s!v*K!XY@a%^PF+y-BXerY zNp+B#vT*f@HU%I&J{TBCHk6}+Yu>$AU;I!cJG+}j8UfdcQgQ99U@3p&C`4T1d^N>| zr4WH^7r)C8ut0!INKR0QP&Uiw(P^Nrv*MTfrzc6(n3L*GgCf70tuNjq6o<$n4J$oj%bSU}((IZIm5O2(zaHLb z5Uw4qbGzSp(KcWV1hSvoD?*WN)PaaVbbvu|xX*3%uM8n$*gB7{ag#P5J=47!{GFpo zeBtRcG+q75&w>Lf;-Nh`C*r+rQ6Y-~KbbJRV9Q_3kSgtFZ{L3yL84yVWGmZzJ{jwB z$Hp-BQ3khE*`DG4uZhd)n~_r{7>Y{afg~v!87Pw$81rG9&rij$`~SQTgHO_Q@816d zN}!{&bKcbN)>o&WGNkX2yw4SHvS7&digkeJYS{QFx)FbAN_~tygIlt}wrE4bOA|L@ zz>XLLWHCm4d`sIVpjS6P08x5hWR&9=wR;mpn9*8J`218>Tq5x;k^OwL+6bTk{a{@B z_#kdfXjz~9%f;pIe1LIA#85zh^v|O-<=1WrQfi1rf5F4M(ivWZ*aHg4MztyRqi3vO znda+eW;DC}*lrZ855zZDu@}yJTYk+So{BedGd~oF%;*JTbk)zDhbc!6)WZWXL>KG| z_3|IV@1KU3GZuY>efj7|M+d@_F8^TnZ2p=VBZDM~^gmDuG!!pOoxdxoI;uS;2fgrf3~?XpUv_Y6~uZn zx}6!fl*=`c6n$WcaaU&FYNxbwbL8MOqf#xHvq-pAI z7!^xk&7%V1GvV=3zaDIZQKxICYa*J`pWwPSdQzCjT;;VRqd(QRseAUqgVIRzLee*- znhd%EdYRs%T2xt&hzQ{Q87hn)$ewvt4y?LXHV__4&>&bS6WZ`1j>eQgJ1%88M9uvl zC{O>(@cr90zo*qyX_sG|7mko$Tb)R~`vduwE+9d*ims%%Ob`c?ty9C>s|;m=Y$qQW zaXOlwz%v9MOvlhIYLN<7_@y<`^Q~5kk?65~;H#?a`o(qz;{7hJR;~cv=)-5MQp!>Y z;Z8R#*E(E>SxC^as6<|hDYI$C*Lw*4v;MeVOw5-2mfFbn1wQky)4ROya&;#UeU8Z_ zoh=nQANFwdw3-z1f83*0lbJ9c5yoecUFwq^8!6 zyDLFl;X}5VXmXK{{K}PCyayT|;N{YD%Ji)3QrsT_o_kbNIz!efYeM#xMEXW8GBtp)aSz%sS z%IBz4LWrY%Fg~@C>Fh2q?Z;u(akqw_rM=#$L2EApo@5|%gI28-WO{1BkhkLGVJ=8> zkn_GD#8mU{g9g61q|7*hL1romW4nONAhSa{T7(5p;V;+LPK6H>Txz5Lo8PUNy3POr z8f3IAv?UqwSpzl#{!nv%((TnDG081qJk{9rGng%R%O*;>575@6?z6MUJlAyc&rm`z z2x!Z2Nn9ht@b&LtoV#7i*uhALCPOB*+T<7DpFh#ZEs@vZM*TL7{s%dF>9`-7#MR*!nGDu;uBCBxg5SZBE`k%;?K#Df|U>!(M~rG^?z@oErw;H z0Cm3I7}OM}L#&(jg^eh1_l=GDt>_he#**S1T#0gN(PBZlbi$qnBq=Xr{jB-efn#6Y zGMo!)+B#z})P;)copRP2V=1NWek58ujaU!1SjP&13mRriZHItCciDW=tCd5Q5d!yv zQA-dP9o}#36ugs^&wf%}QA~#OGw@nWw+TOj5oC}k0cgPZA%#XYpE91|9f5(#_QfgA zDQ(i`xsa7OiUS={5~mWRndK(W)-Mjw0~g5sHcpEcMoG3Qs<7UobCQ~v$3t+TkQyRE zb(<%y#ITbnjlEM65D1p|lcvW0~ z?+i%p;MPmXvI}Ew`k)EC{b2%jsIwib5Cb;aSnHUf7Wy?b`ulk&;$kmcs~`!kw|jsmyvRb~q|Zi$~xf;~~Sp9wB0RjpGd3 zBG@#RsMPzLgvN-|xp30`3xh*Lj<;fcBn!vRam9=rBe8&Ib5pR<;wSd$XR3r>52mjX zr10S7yy-7qyhI|0cj<%{cb z?JK6*6f~kq_Eeade<%|k`e~XY-r_aL8Y^gFgj=F-F&UbMwey3*4?Pt=)?QI7^Ub+kza&aF>et~iGtxkqV;r{{D@44&<1N=cRZT`6GoB5B|24icd zm=;&p9Ote@SK6|bNG$&mOJL`1`xRb<$F38}vq?h55>Or&!lLXTS27oP0Q3<$x>=hu zHteZc%0L3u+<^;rf3xm`k}q%QjstUC_fJhpT*DTT*Jyr$M*T}Vata*K#%2psG_%{7 z>pm~Qm7#Vy9AcCGH-H)ss9b#V<#@MNKm9OpA}-T3cP+8h`a-YF-V1!nX3k+82#$W@;Fq+xG$HPMwH?5Zbc*^N-P=APJ?RaL@BKa-|P6yAKfSG`@FLb`ORV{bo^mch_V?za51RtZpF zllW0y(LzIaV8)?)iQMCDy|FZWCSMXjh<0Ipp$Pi!h*N6=vH0H!u0AYI35a(|K`y^J z<>U_RP(H@Q(bch&^0N$u8qJsa9J;3bFf5ZsyQvNJ!Fk&x7kCO${I0WnIh;jNXo8)V z%jtqlatO4_?^j(&zY76IJ=ixvUyJzbSBX-k@9{h-P%!z(NE`PC){4Yq3&Tit`X6XW zB&fl3FoPz_9TmUkJu*7Q9qV0ekqlBYsJ~Hr^2=J!)lQC^)nwlpG#mg8SnYZIEYqjS z`TlOFeBGCl(w=U$KI_l(UVL0%Xp2?Cb=uCgop*<;SDCNh@I+#JlwfE&nJ|&V8E#?W zf5uEan+602`;PG&5&0KB!_kdk9-72T53;Qg(K@?8Dv(zqBQm&Tl@DA&oLJV3kOGej z3Li@dDk}XL&CUoM70JjPfe8Ys)33ecWW}vTi41)-{wlnL1{sogTrQRbq1bJ3=Wz~@ z=d`Gkr#C z_Pk0oPE^=}ONkcHflqZ=pjsheQ=^yo%vH)o21DGlQVB!;T;B35B?uh%XKEFjP@s#k z&t?w)ETg7bG3U;$PjnNAy9qLq*y|#5ap9VEgw=_<5aki&xw#UP=7RKzY4==t1J{5F;rlnN-uQPYxh$C!2^k6PZvsDj zlNX>Ah)^Wh)r{{pApf$}1yg-Wo?HZNOdZZ(TkUKv{{B+epx4F~cR&=Nb})Xj>H{<` z_oZ38a1;A`;6;%(9L2p>U!=O3Q6|Z5*V%cT3pCDeDyFVs!4~-S`0mf#JJU8RCpWrA zJma(>k*fvrdz_b?u5P@i{sXbzR5gF`PE)8NIa-=FHWXHpM7M%~w~!lzp6c|W^z&os zWEQL|4tN`*9ttLe8%i^KWN$4eFyc|;7MSQtV?T=35VNm9U7ojh#0Fv1!m^6ePT#mAK_n^MNL=X@D4+Og@E`(@7%g0)p4t>XHkvt(% zykaL9(CYt+dXD}+Hm2s_nAcI5FE;6Dw;0=JAGzMVg* z_sc2U7tu&$>5d8w+fk5~bek<>G_R^aCrIY3{3MfuY<{jQ;@>B8{ z2d3icT%3?X`X$L)MBq{M55I4$BHdpTR-hvi_$}9<;L}Ni8l&~)`0G%R^xZL7yJ6c= z7Zx+&lHIFn&1b%4Z%yyNxE2EfZzHjE*f}$ad4ygIdRPR02=cKUT)ZR$%P3#qL}>eP=D`8O{d2?o`Ru%oBwM%C z&pcz%wP~T-cU|n%Gzam#+(V-;7L(k(YuYz+Df)bQ!}SDUuVlHhnxX^!(|a>EUh!pI z;A<5&nIUNnY%h505p2BcBVwr4>W655Dp%h8$1!9i%Oo+@ig8D%KkmJ1`djkKrs!TZ zHjyQ;j3mj8k@&jNhl2=Ik9k{xRf}KDuyCLGR|UJ^<4$&sT7Yzf2x@O>Yw_9ZBz_Ad zW@l2QZzQ4V+5Z&h#UNf=s!%Cb4DGV0&tO5?;K zieT~|XwGgEg)}pze#RhEW*;JT(l>8LEp%yuYTM?E%C6EJq5KUvB2P#}T>=2z_C7|% zF9YvcRW=@8`$Zp1#ULx7lX*=;54vTZ+vAxxXe(xpI3~3XRti3^*QWmzZJrr=HAQha zpY+;XO<@XB&yJ4IxbY3Plo^;kl0P1?0!d}j3IE?(Pq(-;pJkHqyt+~BPn*-5k@%y) zxdH<>-i?)TAxmh}y>>q=PvLPJVl)0i8DINgd@dC6^6Rc~Q-8KQrR<&C(jEL5g+gWv ze?oS5e0UV>TUESeW7(Mx`P3y|%l}v)H|1YVIjSgY#$oyIpE1A+$ldTi&?`eimKj$e z@i-gZuU+*q0&g(a#~(&3LeasG&N0NCe|hp&dRuoC!^J-2z~V_Aa0=v0h1^agc`fIf z1WT{Q^oJIF=ByKSW3Fz6Ac@nb?)c=U;HZ8Ndxlwo@0_0mzPz&k{s{f)J1lN)2D@wM zWNIoOdqiJc^D-YbFXt6K>%6hLqOBu<8V~u);rdX$q~SW?x}oZyU=Ft?d{G!wCACf< zh5FT--nD05#~F#_!OEf|eQLf}>0`6;p^c(7G67)EU})0H-D>r%IQ+M2n@UJ0;b&u? zPur0Fi<;`$;N3BmHd`fdt%T5U)ie~tpnzdbqQ}Ud|CSdC3V#LPU61bQspy@O3Y5KS zU5ZNG#=q_CFlY`x?Cj|IYej7T*Yr~OOEp=a=-1F}%Q-`yW;Cm6lVqQDp%e2I=ygVH z%3gBQMvVA>Ae#@xM}&t%%kM)je$eFly-{4b+qf{b@a}n8`Q}%CP0ptS8$}Ly+rRAZ zQ~5r>dvx2z?*IyeUa55kaJnx1B=f(LQk0UXlb~QzGE*zORy?390a#K|Wm|JL4~zc( z9`wNYz2xV(Lq}3y*|ZfKal?IB{Ql1gx)47Dju9Mgcnm$lC&gpn_o-={{Tu4xx7YOZ zB)dj0lMkk56jG`ipYGL`zYkAOpUI)svh(Q@SA+a9DmJbw+JMSVDX*1z`QtHan?7uy zL);DFdr}GCe;_Dn<8+#7Ady7A{a3H?Z(V6&OWe$<8dk^Ue-`_pi$cvT?n4i@6xBYaqE-JV4@gk3G zK)d}XHRM(O^L6riH05iDklzWyRqvMq#6cc*fiVXBb(@99KSSS$x;u~kqT}TG8VH0n zoL2U}I$_%y=IN#L;L9hut{=z4yIvO|KYGyp`+cQW=+ktcfmf5Yy@=7G(_uXGsb|e!)|Ok0eeO;haD{&qOI1ownG-3?Un@6NMxBf1Va)la!_-HsGAI2bz`RJ8g3Kh4dtywzv2L z!@J)fH4OMH*(Qho1JU0LtHp~nL>eem*MG(viRXjauG96N8fNf_W7MGhq)yv$6e90+ zj0U3s7)^h*O)V>m?Zl)hDC{gvZB@o+bO$3IPfp!oW9U!}3SX2zxB`1OU6s7)L6s60 z((aRD-5#XEKl44C0?h2L0wc*m=i=x)A)elED~mJH2GJJb+M(}*JN|xcZ2a^oV;H=Z zE5TUJn@2~k)|SbaW}gIHf^1mJmDed?dvU_ocjige(!{3T7~l%caIC(Ie!Y56_Sxfr z>1*xXOe(>4&$p~za_d{R_J23Uc4-Z`1z5Ykm*?7Ap3=5OI@9OR1Pjl_J+l1fMdD@p zob`p9C&eNI(PS9t?B%?(ZC11NFJ_vt;9uG>ZJFgd=FRvK?MfXc(8PvNMsP8WoId$F z4iLEinPtHbKU}D_Xnk>+l2R{0Y$nmkE4z8doPLD$C7&70|9s#P!%t@Tw8XrXu2+=E z{{mcGAz(ty9k4k{onRm0ZD^di8zPU92q!|6!nao(0 zMu14S=CD0PIASZ>cc~n^^q~%#$?i(ZH(@VG1Pl9ov&;e&_2t-=A2kc=&UyT^EP?|p z&f-IsmC+Tt#t;ot22KUSMV1k^X^OdCE{=8(w}tSDHC4>&>zmWJ-u&7+mM)A=ZY124 zS!@oWOUwa-+lAY;Pf9b(O-bZymm3tlRV&PK)9-1xqpOs+_veatna5~wYBR96JumkH z(FHnh6#W7WfZ!UFRQ`;%8ovqM>Q^EUu6ZGR>i#3wkwp+0MmKUMhjIo75$yf7&-C08 zNEO#u&=E@V$su4PO+d%7a`DP{0_5VmE*Z0^w==sNa3W^<2oDnWCEu*gtBu2q8A{(Q z9X^Z3Cd%wS)wu+k&LmRQd||ZR%_+>AZ3wHBUX3AZBX5`v>mDUlU0%xJg(gnrrJmaZTy2GBqV&uMgOJon4{9(tV&VV zX0qSrgnSh+FBl&l9^NrL*Skg}!o2p)qCeX}KCc;IDmKX zEWvxEzlNLkHf&dp%JNe$Ur$fZKi^#%5H~hQ*t%|Qf%BUvMaJIIDWfjt)o9?sQkGw) zj&JIV#v&Nw3jw-=6VQ0=z3W$d#!ZfTBi?9FvK=LlRNvm_p`v`JrQ^5MM)xz18X3Ij z@pS$2Bm!Pa#TR5Q(Wzci!}`?AX^nr9(sxx|MSNXGpADm}T`Tp|9Mm|>8d;Vyat#MK z-TP!bQ_Zk!R;2xfWIm!jd*12I~f_4=l7AU-J$I z3~9TUSis0)ZkYS(akAD6o|f@RKi=j(wnFZ zCBC2stCE2^?rKJ%2;KlCya=VgbRDd}V>nVP&Y#(xTK%RyOe;F{Nf=pccmtlDqwMrG1tL#KHIdv%SZDdXA>_VzsZdot(EU zz4I&x-=DPWW52}H>;C-R$4S|186##ppjee;9$DG6&Hd;9adaMzQ2&n~KYL~iIUIMk zjMIm+H%GE(k-hpLD=T}`xn)GzdwqlyQaY5gBBPQKIx;@Cv&ZN6{{H@gAcPv9?M#}8O zJ-<3DS!BvngwxLKB^o7#4RKyPPEc0wVg01Kd zTh95Te~aLGpw1Zs9kf=Fpvm=>Kv}c>uhVJi1~@Y70?lo*Ln4mPM2_EW5GEK(WV9)+ zH2-Ex`keP56)t%ZxzV*%#nq#B_uS1gJZUaj3CuY-dFPZZ>?D&1Gl%|E%;K*!08c_$IM+pkQP}$y1Blyhdq)%oWsNUrM--EcrxMkf1uDw zW4dqNxRrTcE{DEUW(Nw)q?X&7fRw4_y)?#kL*=AS(2_U~6$K15(qaWOIBa%Y9~$$Y zbHN;JRaTQ(^EBfFiy#^nZSr~}TXTsRKOc|tgfrg5{mFB2gXo|_ZG8zN(8n$(xs;zv zaaS5x{DH&U#yd?r4$T_s2_mPNNvE&_Rk4@r1r&s3LLnp28&#0b(Ojzm8lz{`)c%i6rSM$Mjv((r{s%=llU12IPOoWHc*i?Z zWP=IJA3ZL}*s@(Oloz*6KHu0LJwkKd=b{KGhnu3wJ)U*ayw9ffcv^CnEn+%Mrpl5< zr1s<^*h2H51X=pw7QxUd7=FA#9CDKcK%02!&C5)fM^hgN7P4fF z6b}u}@&gaPh>c|HS(wVBbn1jJl4M3t3G$gYBx(quadVpRQup3rqYNtj(32)92^KnB z2PLQj!V7ZBoKa`+E>4??ISc%mcOD=+Latll8wZTEV|9br?w2WPG;Y)ZF|?0VzAl}> zmfUl%-%v?E(2;)PM{~wDj5G#ob9O-t~t zz!{KwMI3E#4D1zgo(ecm@H$kB?^UT1Fx{ZEG5ME$6Xzf6tL_AaR$D{f3*IV59kiRC-f)UC*0U6YH{28c*C|vlmjj7@ODWg z8h7`WgioIjbJ+odR(yw%UHTI_4hu?T)@Wusx7!;psg*l*9}%Z(fbk(dpBX=`eLGF` zXHf!u=#F;(5EYfsVx<6EE;6Rndn<5MuB!Bk-v?rfA;US3_ zsWvoIOwRFtpbAKdB^}7V=g6LUZlbWpUR!bK3OH)rE!-nAM+}?VIJeOT$0G740YWtI z^j&O3r?bV(Zpu4$sX0z7ng0tCf|i%1t05?U=6At#bHEwyjh0g|QYny+tE~35cp+ESjHCJuy$h1;7+dRzG>M60Vksj4+ zrE)kB7r9Y1w~2iss@Zyy%dZ!$aFO||aIb-Gas2vJAo(4H^pm2x@TTp|=UVbU8>BV+ z0n1n10Bw{IHTi-9`97fs{@9(lZE1`7zJW|4&n(wvkWQcq5Q)*g-8}Rxa|!rPT?p;) zR~@HVIl?@!LnIm^79E{O~J1oZE{!?FlB`O&p{sNXt4nu7~W$PT-uCEN3HuEZ<;cOzukWGf6@_+$&tEUbB@D1iMy1xKw5j6KXD(LZ zEwfJNrL_p^OWK2Iw_9?`&vdxcOy!58y$UM#s*iu`DlD}QX!h4Ah;YnuPDkrYB~0?z zNzpUc8S=7r-WW5QC-vy}l)V1FjWa4g%Ain3MyO6tCeqT3>|EYMLO;L>l5WfJSa3#^P#glUMoaSH@b4mU; zg7-7fTOPHSf-0vM@e{}F6BLmWZ*$)VIu-yU^dBm}IWb>Qp3x=5E!>(Nj&Y>-Sejp-1px%`hYLd ztVCmu+rx^%U3$Xvt@6X~fnO^=3%%;T(`NvuJ^&irPUf^5N7ZhhI#>O$tj!6UKwj z*tQ#UFEy1)6sEYe^m$hu`Bk3SFcT7f%8|mqDvT3=9h-N#Vs@5q@|At8kY01Sp<{ki@+&_z$GF#4AC zdUrhQ`s(dOy?hP^G~Orf4{m(r(p&By5KedHe;Io2ZD@TyxRk_7SHUQf!w$X+O_UPp z@w9jPEUd|)bRh>WJzDQ$?>q77Dly>CnKrOkgwQ#*sgqENMf+37hCMQ4t;2`%&-^}7 z3U{Ks^|qFL@`qFa-#n=3Njo3CxAQ1{c!a}Huj@$hZs|dS60neEaFe<@w%1rndjb34 zG1`a%Ghb4gg7viM^^n}Qg&Az7MxsN^jEaEev|4)05Lv$D^GBb#DEr}eJjmy+!53jk zl=xu*d~s{nGX=doavocPu$0Qs8Biks)c{ZGsXFYayD2d!`XCPE@mv0*xC)7?qQT%B z*M*j%Z}xp9ei#0?ZOUpnMDaCJt)<}GXYlB%3ko?@0&&XF@|;PI+)*T`YLhmhS@bA& zln`j_08x=;?K0Lhx(0}i?bB#JW9Qxz)@b=&F~vUo$3H^H8(A>()~L&$3|1@3UG}$= zc32d~iN>NN{UJpYR2>-qh(YfBIj`{PjSE(EhTu?_?i^I0u_U{mlHHCa`&L5F_4fv2^d^7qUN(#p1kxZWUFFjvx7|@(FrlY1VA3F8tGKdB6Ys zv(EgrDH(ZlO@0mjd(Wi0*9AGlp|?jvr1MW?ClZX;f)Ru2Pt&iWbMiQNYQ=s)p}(r$ zqqM1mkeU>Nis-yribytTjtu8qPFMj4)N_voakx~(dA#95pWdcU*hj6jVSCCv4;55w z4bR+2+h1o4X)NiP-sj78OU?a^aJTn&yBmXwL}-YVZsy6bjMcgdRz2EmHv7^wHwM>J z#+;YVC?}wlCUY4$S^{cd0a;+$a6@pJG;jp4126`q0Fw#iXLiG3$1F*yW?CK4WxZC1 zc=^A5(G`hz%Dlc+k-wSZh7Cni(ynfxg8H%M>g4T!Bke<{lq@5!lbv5bkC+4R?!rUb z02PWqiX^C7a3{=m2sTS!V)$#g+y=tl!!*S5{YqR*WlbwkHRvll4+pzdns%GXfMHbZ z0Q(z$=qz8%+8T;=cRHzCtm^h>4QiO0^z$Qr{;Hq|-g!AHuq)@)xyNwuddkiO{uaa& zTgVhJyTU3}FuV^GMyAYwoO>pQXrUI+CRM(Ydv6R(bouY=6t*vgd z`+^e$iS>Sn(0p7!sV+Hn^7+VLeux@u^J#*YbW+{wT}3bg$A2DY7JPLM-@~GE8Qf-^ zL=>_#8b&{(J?ANWk%O~6DjJBOdo8o)ks4wP5^}dxJNq)KRa6WjR)PLY2Nk9yLp@yg z&%`R#6olIY?Bk#Ko1+QWHb|7_M8|d>U%cbLS%792_6biZ8!?955Hw+sS4z%ZVvaAk z47*6!O#T}~p*CsNv)x>s^{zdW5U?MI@23hP&IA`7QDeyVkc>qsV{UaX{j6#)EMB*` z_Lsaotukp1u~}IXm|y7;0K4r!I_IXj`Yh%#K9-~Q@Pmz}Ln#nH8807BAyMvdrq~33 z(jk*5Y@)MU9ZwL1mDuYm{f$gJJ~Y9I;gf~T-<)^U%1yf>VmkfZa_dPYs_9>PDBsS2 zHra6#6(N?MS(e)=Wvt1Awr5lt6uBi_*@^%B!PlfRCJJs<#*bvou!%|U+$d!lP$(j+ zjX#m?wc)`|X8USaAe;cp@^Ih zSm@3N!Nsr5fWlX88wce6p0+kx$=#D?9+$M#`Ukmx5h(!KvA+3AP$XXO&NDuW(UPAJ z;??GbI)GC?l*ROcFV}>ahHj_ZdtIp2O?j>Ts12U`I>`-?#y}cgT6eSK0SC#;@yGKe z+Q2d9G_w9a8yOg0^IIp#*x}n4W!@DLM$T;C4uFQ24VUq`Dru?^lOaOX3C0`uRq0!* z3uHiE4vj0W`8M+orC2x%oyorq0v!{)k_#ZK;nP{V+Pu+B{6)g)UKG%%{Rc8li}|71 zje{8e;*#YnC}NHs7Xly?_r&J@-VoN0{PAcxV}ZeS_4NuXItaKF=zJC#HuxgwiCHj< z-QJj{^*yG!k{bS4g{D;x)0r0zHQ39@OK)$FYZ%IWNy&8Vk4cyt?!f_x zD2(>-R&QpDQaLaJ1eJtvH#aO-9u{MPaUU=%FUn|c*kEN%;bjr+` z1~fdav&w?$R=uMqR+Ga>dPrqJTN4CUWWieISG|#cUGVkXEAxfMv(5`T-odl~rFsH_ zs`(3ymt)tPPje=0Q1!C7>sLdVkiO9v`TYy>1;+Dpo(=>z)1)B3tm9>?lW+VWD8gfm zCsllRx(R$gajh*dT%kRR;)R@r0hj@=>@mBuSVz$gK0;J8@@BGpJL06!f2o^i3*Pp& zJYEBps%$umQ$&Ah{U!>!Gto#?&F<~$*P7qizwkgme`t07D$gxoeJ2Q~qU}NM&A159 zS;;$4oC+zynTlkNG#awuKK!xADBf`nslzx>W(?<_;DZivjuVTnujEg5Atph z8w}4yHi9AAxJ+#@(xK{^Y=})q@;JJvoZgdbk-u$7q}zBSr?pozsGlGNOh9Hiz0#0J z2I*xFk6L&pL^7e`O6OSx{;H`+>7pL^TKV?R^N>1M5ZI(Cei$LWR`skTHn*|t(Ys=Nd1hR6P{k}OCySO|ZbAN`)@!tI3||D6PP zj0|&DpS`F68zu5YQ6YwN91KixvzXobfP)=Z&5=S_2KV?D6b=>_i#%#t!`W|^r1G2J z>RDJ@xRt8C=V`(!xJ20L1(wXdei$}X>@rdEkZRScP2m_eX@Se7kkQ&MU37w~=u@j7 zUd#Gur`#blJpATtPTNZAr$VM)#6V1ZVE*rP-*)GWqX{yLPvNoGUC$JkOgv9N7)|Q+lb_RsbU5 zjJEBsIi;5)G*%6b8??Gm$xYQ|MKRv1)3eRs;pUZsZSoKb4z7C12mf;GZFrtrkVNAKBsNAMN!+gAV2)ZO(Zp&(QY;ITy7F)_m z;~8r4h`AXrR3JaH*Vb(>&Ul@u|Gg)elDKX3$<1L{$ah{{B>8`rc6cC9gUjsj;Ketb z2Q@V&XzYyQ@W5Dot;$+Ncc6R%{62-!fs&IB#j%K36M$jAO>?L8m{;BXSk;hBCk0m# z--*^i{ME;TJduEN=-49P4p@HN=VA#hdHzkfkEgW&Av-B=i)|_x1jih7o&x-8@`s!S zK+CvZtc$%Dhg0H6rjZTe&6x;>kTLkH4~SfuX9Oy~@c~t= zZQYkj=Tep+?Ys|Lqs%FoR4s8qmS`kL$R?#OUnTiRWV~tNeWd{^xkXJNrD29gwo2!0 z436H??URwEHZhCX!FpoEA7eD6%#w^zN)v+0Tz*P}Df*o1}-;G_+a&2_29Kx~XxFkfx? zxr+ipswKfI395P(aTfY!0{L>2=#ok#KO^HA)lwvaS?h;}>LY`u)PAVvFC>8&eQe!pjjoS5O=GA}3hc<0CW*w(4i4;%1&V;Tf zW{~Ct|76`UcQmPwZ0i!;`zhL^0{omS#e|`nM8zAEgYha@1nQocmgw8iJfSKKvDp} z`)N4}Mn#H5+TXUB^HjJiG=(6mF$^NLfityIG^-Zh{?tMhO&O0a-|^eu_;$oR?bco*W=v%-a@^GF;m-V=vkg4@sZ#Oe zn2FcR$OE415>;ae!Y=dcZ=+OxHZ#`eEbS8xSk2hp}beP_>S8a-d#NJ|G0;g1I)1?j2ZfTWQp#9hAcenX?trY|7)9n zz#FI6d1_AQJ6HI_Ik@Cn?qn43LdlmUnJ@>ZUCCAfp6P)vb)qodwtr4eh1^Q;NJF3o zz(=(!bzn%E{T$mMqE59|1e7XXSgen=>=^RjRN+%Re~ExnKkY$khL#j7hxt)AWwWEX zIB6QPkGGgX^ZREDIV%S`8zRt&n_u`mkt^X(I7B{K)4#md*4pkY-JTNOO1jDI?FhZ> zE2|HW;iCfvL6i5)g+7|#UD&dedC-2`FAR{y6CX&AYbIrN9s^@cuq;>|(lS)SVg{|z z(6mVmzTHto8H}4c(N4&4Dzz<6ELG#8oo!Ic9z`H7!Zv6Q>G(^hKm#Z)CED+FAj(KS zApr#0)Ew|ej!l_Zl92n;>r06XzRP-t=~ENWv4%~8$&LSy0+7auEQji`3dMk$zs zZUY=PLOhuCz$k`8$qhVLwNuOi>ej+!^S}f*`?|J-7Ij^@(<=lfZ^W{BT$U${bYb&mQ@ZF< z)&B$8nK5W>PlcJ_*wYu<*>8OkwxFgz1UkhwaXqvuaQ1GoOYHxu!$i$ZbHb~qPznfB^GR9Cr;E%xo2aN$bun-lIs48#NIT1qfy zq?#jehNgU#OH@KFB@d*7SuU?jmOmcrmVF7C?NRDV)P+@0)_OfSYxKWf8 zA+KhW6tf2Gz_YA-tFX6haCyL=^47sTq(=KsE`V**FblVWO)d#2<6enn(LOc~2|R&R zS**mc-i3;`4FUt6+hf)%G#BI{2)Lnse&Yk9I2FrTuZ&UYjAz(q__cOi;gSi5C8*pe|RWZ|RsXL9jAh_#zv=%kTyvvo=oP-JdjNLq?7$=7`rrk$vEn zS|&D5L;9ucMNm=XT2*1>CquDWs!HDK$ebJ5wLjTqShx;CjEY==Sf~EuCr4Bi{L-AT zrgeRvz}02j=06w?8CA1a{qnbbfs7|l+s6=wuz}QiJunIjd&0MQ{4p! z;Q!?!;a>;em5F>J%|vr7@`}2Ub$3Xp90UmC+NqUk}*@wSfI6+7uJQ@v4ZUWdpp4(BFZtB6wpdJ(rlzX4m59G^(p+V3i|-(##nasB zfDuYoh^uEwX`9{CR}ozfH9D=(5aKtgZ%=N#H8xa7Vd;)H67J3mHw-l8NepxI5oEjI zfq>g)4xCY^0z7T*?+qDwg~DWi;p@g$VS#>3QEos&xyGnbkxQ^CgOXEBHz##3yfi72 zRK@-#I)y`I9{I$N0y?=+VpMz8H7J14XK(fQJID^Co!jpqiC=_$hI}w{)DbBUuTQh6HjP#%n<6oRx?8Yzv-d9h;Ds_eM&JpX-k zp(=Gko|o@$kDXuj0~2V=!Gr&m_u`@hH?r&;^HKsU3=L3QR!SGv{#JB*p?La@4^tR} zgMmhv@Sun;w^L%K$k^_^U{VRa);T##_VSg@NO9?x;muVO{G(5bm$sY&BX=K zI>b;7nf13f1m=@M|?VtMjKEX54b~-j4D1zZ)*)KTc%PYkownO7}4O>Cs zhVQY!JurDAr-Z%Cq*8{F=0s)W60+O04EUIE155l{nsF;WReth@jSNs-xNTMn za}d&e+9s9=CTr=t@iOj8wm*gp1`B(-Ek|f2C;)B#te~DF#x!pSQ+;Y0hi=+2Z66n^ z|53}uX>Kh=YkrT6z)qx%l*0}*|D9r~!?Yc(I5#K_y+dT6q>Jvn8i+i-00y8x_5lXg>zpkMJ_YGYqkz4g+!974LJQk9N~ASB%a(5 zUQAez*}nHaz-`%F9UwDB&#Fz^;%~gvrO~QQ;u3y5Rob;eo_pM2uz*Xz*iTCh-;%p$ z0ZQb1Fbx+|QPHa7#B}I6!PurmV+mfF^9|+9PCJr$OUbd10%<2sj4Lzg| zM94OQAjnvvd8Hxh`)4+lq0sx6BSQ@Hwl(ST27z=zUa-<{)wAA6W#V)45w*$F=?5wh z9g70I>v_+re3E$~gOyUviqf!@)x6#d6v*gq+tZ4aSDfXjT&b;7*`U_?H9+ei}g3nYaWPrjx5qb^ap3TDZlUL6ej z^19$<+|^IrnMEONC7KsNOb68bGSZIKGWF9D^hs_#bnRP^#m4yZs{e>cLy+RqgarX<$InjWjo^ncYdlIl2s zLP)AD7gbT5+jY)C=$@)g$*@p&)REbMouR`@2HQl(Y2_nQ_~I05t!Ar=hVS2PDyBB` zy_6Z6(jxt`E{e!89W7oB2>Wi?ha-k;n;p#UjX@GbVR7rW@HN(GgX$_;Kcqk{^`tXL zsP1Kz;LEB}KK$*)=lrTMoW$*ui&m2>p7Njh_da{(-+^p9XKKzL09%JetXRbe&TZy=M$cG_rAfCXI zj|qp9v)Cup#YpFL{_tIgxoKFvOLPhmA4yf)%(k<7TN}(fPyb+Y_K4<#?r8sa_7)cq zi^74qp7TVy3xgt0v;~j3su9japMNQ4d`&lejfsi zLJb5%VjGHMJ0sfvrn1xH;NoZO{gQM`2Nb8!>bGZBfmILSgDH)anJsOUHc3WQ;#Z1O ziNp48k#87yar~il5;}C)+NJt~$^mmT$C#Q$-RBim75eL$;Dn(h4b-RqIT(i}FGqUn zoNu$RCzTK8zAp%|k8dci5v(N>F(*UgcU{5Mg~FTm|494zv zS%W{EeRRL+aW+Ec(?Y+whe5Qu6c?p{uH2C_w?28x%tUixL~LQMmXLkDhA9dYt$RPB z|2ogfNThiSLG9&0Ra|X9Bt%CvFoCbo;5wQbGjyj3hNcZfYS!*NRfWJZ~RT+7)f7)ymwofc_D`4@O?+GqN7l^CxC78pQ88qe!6D=Z7m}BBsg^o6+ zf;*!s! z7#-skDzEd`iabzP=Yj06a!u2IkL1~4XPYUXa6f(7hv zSk`72A658IUJzk`g|2jtS3qH-2vG1g}II(%3IbM%Fyq#swILZ~=?qz=w#jJHEW8$_`#9?3(gx+$74zu$zDb^1x zH1-ntv;rGD9p6A2?%E+^9l{42B?#CGZzb>kceKDe%7r4;Wk`h!TK>`76xeFy%>1Cy z%t$A_LjZGV0<=-`bj`vry=+Fgt?i7kUkA4VWY0OLgw~iBSj(#JOzgAfw&0N6cwx~n z_W>C`U=940h9ej{T*p;3kD+u04zGG5^e83rSWQu z??O!fXfM|T=z2Q5&h_|s>n5M#vV9`#Y~v;UV*|w+n3(U+>0P9bW@Gdq_uB!mkF4hD z3j6dleKlJ|*gkXhFimc>aFBPaa!z>bxwUPdN09A2kEit~e;#lf zaS64@uvRC;zFF;=ToG(c%b^1HUt0b686J;xkJJ1WJT01DXLo-`Qo>kh7}+m}%7ap= z=RMB3SPEnD6|mV3Zr^3%9qap5iA+gIW*nu<*P^>5YG^OVa;LqxE9|ai@($eK@qAo! z)le`xv)8OYmgAqpfUtm#vyu`*7j@aP3lpmzq%yTTSUyhbjHef{;s zVCW;Frq!v7nM{%AYUtP+aJ^KOl7r8Mht^`HAAqG*VW~F# zCttJ$)0Z(cHgQ2k(hy=44~o+1MYTK+vVZ*djcQS#lV7+-MKu3rv=9ZQc9@}gY&+@` z$~>T{cif~glcLMf35ND?cTff`g^4mq44|ZiL&DdBb?I@8mzBU={Zwt` zBLh8CQ_I0DQTMY@cckmex@Uc* zZu%ppdu`p)uHZ(Bb8a*fr8XtYD7fWl5Jl#Kn!** zm>)GErR>RDF8qjJfe2qR(~9CXg@A{Y3$cYTl`Pwz;|g~#=m2A zw}%HDZ8%A#Et{=VZSaTg*>gJTM;qtTKo>hO%%8^@;Vk<0DmqsF5trYTi`|22GqLJ- z8yBgfHoHYe>r*spxtHB%)P_cKczM?_IY^D~+}-GoB+H^86cTvN{nV zCCl+GzH`?vE8op$dso)H>a?AjdnEYbR#tIE8H$h`N*Pq12})2|YYuVNj>2TGRsRPv zn0^-%7+hH{f{z)cMoOB$wWQMAMAuRjgNA%a3|8SKnwCPv# zd19O5E%Z%j0uZ|RIT?HqyqfRS-^os>PJEehS=V((XZ_9M)Z%v^51B>ei-?W>ci-%v z-F_mN_oCO)UZB3gve6U8XzcDofFWp*gCubQtEu)({yHtWU%Eis*Dx~K*cr@?AMI;szVVa1 znyE8J8s`s*_9K5W*OXWuICGr80>{madi0#)9Tfa;D>vlD{qs)r#(3+EfZiJ^no8Z_Nw~e``MZhP(UWv@d$(-zz^^^aS_2 zPcG6Nq?||jCUh>JrjXg!U<~DJ;ovs~9vZeWZ5}NdO+3Lz$M>;qDooDecRt$QEUnwE zc`AyZ^LcxM(Y5~S*ZqXMfxf2mT-5J&?(a+(T3+S2j{iBZVDZth#rMU_dG7<@_EE#a z#Dn97IyL&=BVqEJnAZ!pe~j%Ne_yL@wmGzLs%v=cJLGHtzkVV!p<0Akqn2HYVgEKm z{@`*;=gz$f);e2p_Q5{>;me`ed-0I%z?Kik>2G2u-b5(Bz9M{EyyPHXmEf&i?v?M{ zd4n6BmbCd4ZD`eP3$?YU3a7d`ZZ7jUkSe93gL1c=Y#aQZI7~!X`n{@iX?i$5pE~lo zxT%vqmeoaX#tZ*41d^rIEBkG5$>Tpz_KzYDhr-{xc^xWCpr$u@9Xsx?wvKg&sptk) zy{`L-_8Z!a3f$q9w6d${Sa(N0bC@TIZo3rF39D&jel1DWkHOFSmbEV`_KPCNbxXcZ zO&{aAI7M3Gr}&Lfsr^2;uU=mlGgM^PYd`trKJqjX_rcz~j|#sT!yLnsmVG~$?Sl+0 zU!F}T)wH?hOF@Q#5OY9kyxsTXHSj_W+}Tc`s+AoH#e9_ktw5|VG!qJm6IE)ik>8Nl?sc z0Fr2$HAupC@Bg*A5DpeD6h6oj#;h}pdbffwynHVNomWVT5lr_{ua(uwuMoF$2;4fKMPW11)*uu#fz{JWKWm zdxc?t;yd$i?}a)qqKIaod){9oglt!WKAn3p-e^kA7}Iv)y#RbFhZzEGjvLjr7ni4& z=JXK->0}_Lq4icSIR0vaF?iEkGN;jjl%Zd`|qmXIi9z_05*`@!r)k61pcMM=>7EyiE zsL=mh;Q1LF&S!yG?qt>;2d`Xu#=es>4^PqmA`RVN2=wyD^W%~bEo166O;y`I zqXvF?Yr)?w2_Z?!jLz|<39VyM1GMTP(KZEnWP`qnmRb8qFEeU?*!*j0<`u604V|$S z-P-KQyE1Zv*5AWrXYqE>T^hNnoFV>)=dR@b=CRx>+)wR$l?2|g%NxH~3jK;3mfxg5 z@^vb_9OTOgCSarZkq5#1`(Lrq;?(Sa4}^;rP`r*1Q)1jit`3n97v#pa2N;W#HrOEA zOHDsjA5Ym@6#6D(iBuBJA$j{d+kMxE@(siB-(-grbiJM6N{G6yg1_TrwMo#Gx*VP;3 zeO0F%Xa6tSJTFW)@c3DFf|W7-Osi-bvDEJ$BX6Xwe;%~;*uNnwuTaW3AT9& z^TVB|V}`1fe!Qy^M^Nl)Qk_~QzrFb1*%jizJFPbzrYrrB^%1w7A?7Eqox6^g=3&l0 z=_*<{0+@j~@0ef)8C!YU2b485U>j7dA|eqhV6y#!>OLMO~akrAiSm|#{Be|Nw&!OQyq%uOhZD8==^0rTwF=7Rq&Z~i-|Q~#N$1E-;cZ(LDACf z?}TN4>YH&j2t$OKJ|!m!#NZCs#!E^oxPo=~pBCZ@medhyiQvj@5(aa%WL3pF#4?vG z`&A_SIKhN{XX%WOv_fvGk%&Y=dhZR}a6O}Q9WzbWx^xk*Vz`@9#qI9gQL|qf%=`fJ zxIKj7j41R`H-Lw}5D#Qmbe1)Cc~H7pv<;oWJ7?ABbs=P~D9Pq#tpn7n^<;UYzy&_ZvhX@ZVmEy=6O!rhh0 zs-?*QF-vXP(J(_UuK>q&W%a?8`3CfGal46C;9^09ShOInf zpW9=tEuBUvX6I~1N@``mksFrH>w}IDQ z@HibX3U-@9B4xHpfjk#v7p`9K6lIH;H8P93w?K~xBH+sT+&?Wr0`=2$_Tp?V4_z56YTUOPmaUBLXsINgNX#Tm5+02{6s_?H{RrYyFO zBTy9bj9GTBxUN;vNq(hX%(tJq_hoE80QWTnZ+z`)UIc8px%;uTX>AVZ1#*-LeogUg zrNY`AC`<@%X88&EYL{ag+D?ZcD2T@~L41c*A7q-=fF`KO7R-rMEVpd;vZxG1Y0cG$ zVd#?{vQr!2^!*!VY$3J9^%8Ugk%Ub(<>A~g1JC55;-MC`GKw}XHp&utBA-x)8TO%} z0C(QodYTt@j2fmN5vK8-q^h`UK!@xzG^}fd*gxTS#{I}0PojTJeMuH?cw|H~Utr&C^KGpOMH%Ph>r;AK*e1BR5gpgt&P^}7LBc? z(SB$n30@)*Pu2-~Qx%ePq2=VZpq~;1>L5LK$qPX<^RZ}!K8^q}nPw$g3&_GPe`?7g z=3a9GI3zA~3R}P>vYThheF( zeAqi!PLIB+2!)1%n3G5Ff1s_zmqXA*q7^lzPriNtzo(d{~Tnu)NC1{ZqHtZ!Bi~wmTi%sWo%&(yS z)gdh^RN`cXYAp?W@zRAYS2GpvO~)D|w-Ir?h^&{AMSo<+`(2;^q=nJb&f>aJg)D&H4+NYZ^97pjZPyI#D+ zDwQ?}H9#>6J(E?5{5LNNDX9^9MFJl?&chl@Eaj+IO;TMwY?)v3uuvBv5WQ5+WGtXON(1<(&8R5d~GHlm(}*D-cOiGp|2z(9(8x}@)(uoYXmA6MXQ@jQER`Z~n_ z=G-)F0`-3Fw|j&II^b9g`GVr_w4MQj9f>hDV$ZXj8qQw{5|7|k+OZaEAu2?I;G|}> z?Rv?C=y$QqXO-Ue2JXa2CpKlF>?$^u0al~8r+V+Hi)_y~Q`6=%xg8msKbyA633U+X z(4}4w&OjZGn`m)&>uJrG$q*~v*ohv7Uai3V>E&aTW8r->KGR3alo}%&k){~o9#ZX% zWf8KjY4)bKdLcz&B7&usi~|}49<{g0x`OPDwr`3_!|9nUdoxd*+`g8690!x<5LQtM zVR}d5?Z`<*VKL+;m%vWJkQL_|seD#CW%b)PZuZ!@HY{jobaWl+rQWO?Z@&w8CMHRs zo+Ee7J=5&&V0(Y&QZ+pi6f8&!D zQ>qR>Dk{yHX-<6Ef!2?*b4j(T1H6{>BmILQ;^L0Gv6n6|^fRcX!Ef}0Gs}FlO&*rv zajz~`=TlaXf;em&mi<0PXzQuJ#7LG(Rf_%}rBSqA<15Cy|3}eT_%->qQGAr68yqs& zU_(+`x?>Ea8wEi^QOSXnbjR2jB`DI;A|R4V%LoN2MH&Hd{AlU&ecr!d`z-F~zRq>d z`JNX*m(rxNMtQD{Clb*78sp+x(Q+uMENQ`mirFsv^EMGJ9=D+M&By6-C?D#pOj8FO z*DIXVpxLNF&0WbQ1)Y!i6}ph%z2RE&t^4;?@PGwKvjTd~F;8P(M1NP>*p{E3+0JL| zY8?hH;~$fs=ixvfa{w@5x3D4RY%sK7gLtXrS?MU0t(-W|V!lP%x-?L;dbM+YK;m1& zk=HH!6sswWomTjH1YkobiJ2*4v<(KJ2P0$;9|?j3f%$PoG0Q$_FaLF3;d!x?q>aocC`j*92w z;-;(poA*Ogzw}Yx6OwchFWAIL6`V2a#6Y8FwCW8Aad43=W8X-PL6xATD`1z*BrNM@ zj~;A#)NdEQ1!ImgmL7^Q18i1r=3yV=mp?*sM03!~!%W|{KSE(t#$dyO21A49`Yf~D zK%z|CJlv7RO9gQIuM>e=6%}djJ&k1rn0svO)!cP4OQ3}k*o3N6qu1EK={4>@5Tkj> zmm=wsW#x-yiq;@?YuwEcP#Y5!S@&Zyq|bEpo;!hc>a}N9MGLGP#d&rV($RS+8xz+9 zeOI$`o*j{Qxd)W* zQ~g)`!rW)C0$%*Ssv1U5y%rxt)JkcS?61ubCTL5}4P%vtVFC!V)nMqsAW1Yj|88o> zz{=b}HJc2u$Y92k;erJ5msFz+wAMQ7`9QC5J&M`zKfbKl3rS;k;hDjYy9}Wq(*M|D-K1Y8PCl0hM(E3I|c3dn- zpou19Y=|;7$jv29?k`YPuD>kd(=3t^-}ueQMDQKCP{gpSG(ULS?)pJUD*k}SmOQ!E z!8!U&C|j4_z62c=KRpSb4qJZX5rfCFOuRsXwW2?}q-_r)(ylU-Sy7ZO0}9A|4InGV z$-<`J=AN!KmN?QCru*VMWOQg70>X3kM;uC4b!KQP&??dkTtg0Mv=>`vh;AQzzfWe5 z-vGv{m@fcAky+sbwYj1WZ;T8vD@R#27C*UKX0QaPS>f|EX^dvn(4f+aZ=NpEIF)uC zd6E8=f=Ee5GA=-ePZ-^NbKzRf6DAq!6DS+xknne{L$yABdw;)Wxc68t zzAWw0I7p(NrF<~8*D4nZQbYpe)R!Bj|BW$kvb#d&3227Kwk016Vp@4S-8bqru*derh&t5G5=`-X5JS)CXe?d4S3l^hw zbjM(OSigQuzQDpAhk7=gS|!u2rbvp{-9zJUV=`_$=Ao7v=tY90d7S(8xd#7sjT$4L z#MUn)DUYMS^520immVCy`=D2UJ=!rZ)Q>RvHt1KTF76CDXuRD^_FCtOy!u*C#r2zd zblDG2cvylA5%T)3mJQWn+Bb!B3j7$p%m!i>L4M~e6?416)(|2i+iS5Lry{!^vg;rN z2q8W|d-SY;$2u(P$(Qh?&+fDtiXenYp|vg}q4GEhJb>7`nz#9DqU)+VPxiJi=Y|3y z@}V1nMl#mo(jW%Df-NA78vm@0evxUS5qG<;p}d?c_}dG{u~I_SdoQuIzpV-V!GnKd zFUrDI<6zlQ%?Uw2TzHDuuRRdEk5m}U*hW);SE_GiGFK^q87t0Y?db6_aQl#&9EKHv zl5i045IQF1t;y2AA43ay4i%M)K!(aEu-Otff5{K*3l7-3Y>iqzEVwLstVf~u<+bx0 zOGT{Y4AKUlM4o|vBD{KmQL1qh3Fs$VX85D=+9e6aEY?|F@P*6g4zJ(k-b8RL&I}T_ z8w*c~XyQqDIKHv4Zl(N552m2P7~{Kb8C4`qEs!GCzQ0*?hn+jq)oT$R7OLJP`BZvxP!ZQxIH_iP;D>I(~F0|Wx z&Sd2=+~x1l==lM6>jz118kMvV!k1F9cH2Rc-+wywc<&b9p>-TqEw$)Y2b-s*c+}9= zP@kcv@DTMs(EiHcIeqxNUFrr-o6V-!a4gq^y7R?*fh5Q=T8;fwaaSp?9mm1YDKC5v zg>A>UEd+|sv6^J?!0hC*m8YBur2tgP^MiMRI#n;Q+VRh9SXz|H@Zxd!4uwSC(AAU6Hmx2o<`x3P zWZ|S^hGKHU!hmdGv+B^_9z(-FsT`}4R-3M7K;BHQEo8tjsST-S|@Akzx?CprzQ_kAO$%4Ce++ty2ws{#1zsCr}A9` z)L+Pq{@-!qNLr-FAEadlnYQF3oV>S>#NYD>uNVHrSauVuDJ#^}LU%B5SIH7tuw@z# zzf^8RE>!=ve(2HAR`Q;wJpK9sstZHC4)UMRAh;{0rW79ZLRE?+?@9v3R===OB!C;y zXw&4L%9W!Dx~WmcDQy!;XpY~f;ZcodHltAvsp%UD;1Edc0wfOa!cL?Q^@gbiRA>OX zpOh*cC=(JyDG3K3GX|6c5F$}i&SOnC@v6-zOO~A3GY(@8{M9GXS~jb9I_j^Qbd#ES zp_NC~^s5ExbtE=TW^bV#lLuM`)GKo>b5bP6dobib(0||ND>X`0`bW?TsTtwpZw#V( z(yNb0jm98H8qdU&^RXiG75%GBKyiHVDmJW5W2|wzSeVRdVg2U~wcl8mzzteo!OJee zVhPRnpOCe+gZvV2xIZT@(xqFzLo&_zYZQt#+AI?sR*e3EmV|7O9(LRXhA}HXs|V-p zWy~q1Z(P8^0zi$u*Ee;omGE$;Q~aordoPHFg-I;&B#0#}FjB$1&!Bx|`3PFjsmk-s z>b_VR?F+r2VoO&M0Y|eWJWJ(p1#iS(@{kYAx1Xw+i&w%Q*twr9Q;tk%KTTU!jk4pBh@CIi6T(5Rln&+kNjM+0srf+#Fb$u zh9LkzSPxUZT|5(a5|meFuAR1a9iVZlTdPliVQL|_KC5RliSB4JGk4TrhX{BwV2A6y zK>_@j@3o>ELCJ0mr|w#<GpDh|Jh3UNxBGJ=|0g zvJ|aAx)>Sk)2=!dK5niS4kA|Bainowv!Q@BL)XhBiZq$sUI}5qsVFzot$3}jn42b_ z9HC1mD@E5%bhP#*+1zJIx}*+gkAeENPxYsYR3D-1ydjv}paAkJJ0w^|{r4*NdeXgU zIkt7c$jRr(VWY9Ph4+u5a0zKu33;y8M_-U}OyU#zDNUTl4{t#^!4$KwJna4=$TvTq z#NHLoGy@baNx4^Tb|vPioQ=+3h{ z<0dY}r@t0Jd?NwmpwwJ!0;_Do0EKs>)77PdY<`PAGA^4xc6-3N#(0li_jHbWfa`=f z%L54%xlTDDMLpXiBhCdBupgSla;d`<5u>Blww_i&r7_P#G#zGtC`v8G2YtiPog5Y9 zm;Rc1wk)QK{G}(+rfbjPG$+Gygt+h)j)x*`Ys{ zJ*q#R-Mk5{1Lxsqi?x_IJA{x9J-Ys;luy>lG}I;|TK|D0494$snD^ZF85)|kIZ#{D z9Q00C1CJWN7z@h`lp4@9Yh+<2eoDBBf=wM0Da!8P{)o2emmU$IPDB>7JUMlJ#K5Q` ziKs)I3W~SEdSs$}NniY;Z^+~ol91wQmNI#5_4GIN&8W>&mn0)v_d~2%wOK=+@6w4q z-FyU*k;#|b>R0;*QWY_AuVh?iww;=?z<5Csj}9`3c%Uk0AN{=42*Jn*snix0`+~hM zCZRyMB3qBzn-COgWmhqj$1wgUtH{M`9)IP%|vr;*UsZ|a*!0ADu zWJmo>L@hJ&czNTFe74DM!fVy)j|JZWF|JvwAd~qa*|el>Cd-mHQ=Ye#33taTkma#2 z&KHhcxFNue>8O8@R&t9t7Y4N7kb+8e%q?ZN)ur?#AW$KTrAOT)qGdb(^n-d*_QP9g zK1hE@wUnTNecy?)Wipu!_@Uja0FzP5M*$|YK+Y-Am{vG>EA6~A-G-W9cYyvvHaT2U zZJrrjD5R4SM^Ei$im}2z-GVJ1se8R<;A`reZJpr|!hYrb$svbB2wuto?9-g$m-cNT zN$nHKibqWD?gMT6Hh%vxW1?lGh{fr`mm&Zu%expIxz8DA|K59{ zcPWEugZa)nJwUD9nm96!<8!sIH>HdAX`jc)#}Om{|3uT27T1>_s=;%r%0RnE*7`9G zFf7ITx~dYp#a5#DO4h*)qW;G@yR6)xKCBG)^hh=;TMA|4YRSklbe`I*#_31oKEhByp zAYlJZlu>6N7_ZK4jw9CMH4njHXL?o}3g6MF|4%^!j#AFmq_2r1<7pqCvwf$FhhNkJ z4YVhuoA7t4aCzx0M#m{WH-{LfVazmgTM!;}?mG@WMB}ax+39_B^J~2(Po99xy*EnH z1t=f{v6A$B>V^A8H6vdyDZD8Pz(B^KT2MnLH8Z`&!5B6PadXVzRhVtZUbbNhlC?~W zJ}FGAq-46ng;U?`QkIXXVEqRv9Y1^-7~n|>31YNw0vd%v3o^zH4fbL?b5=KRQQIO6 zQAwma#&aSO%UjUE%VM141+2|ddEsb})NzLD0Y|mXgOy_E_}H2;(e~#Y11Yc=`0&5tyr+f>;2X7t|2n+EC_rkoYUhl7f_LgQ22O z_6e7{dM!zlyf0NR5B$}|&{FRx&$R~h&T&#i9(8}g;ytb@O3iv?%pSz58?4+=5FiM8 zH(OrHcg;S>mAdBvi(7DWIPXn;d(L#dt4cKxv3nFah0;uiw}!sdwaUEvBc9yrq~NjS zI|we#PeknyUccsw5LNTpsY|UnQ2>EV5P7_>Vh3tkty05o4J;+eY)M9KYVI>(aS`G9 z>GxY0TKu>btlJso2HG;2BeGZp~es_~m>wVaYjE!JNUEGASm% zh8u4Qq>%Q$dUF^AwDS=Fj$&7Ue%w#y43VmCT4wb!0msRRFMjLghGwGN)TIYeUp_~- z-)VM^**Q{=W+KjBRTMc=T~u<1uhNlnIebcClLnP^Eii@At#LzY{hy|r9&FqVdO!w0 zkVwTASrxhpAbyvXZWNc7^=QH$9vn%>3$5UN0KS(3^q^8n^Z^@(!xy&a2A0StZoE^* zOz;bQvte%NwE?Tl&+V*`OKZggy%C%2pCePeV3T=1cb1wcR`gHb$b~c(I>d0Hn zCb1>e4&NAkMYbd3sAX`@IOAH`f$-SI7~@6L!W8W)PbwClbpdnkYmhc!p=mXamqlZ9xDg8_E}Wv zGSbmQgY2s0@wwkb(Gf~-W58Odh?M~Q@Utneztv6vJP7ziNj(C#h@rt7=o%>msH#l=Cpxq-w3C&}liT``E*FW#6P6;p2#wJvv3yO#{E@?r@0Z?FM8Xv3LiC3y z%ZhO8+*8TI%9d1V*lQ-u{o6Uu&=M*d5mI)$E{7S6Z{e5vygPZpq(F3`h$KsuXBr0S z*2NO%&~0!DWNpfJ(4d;~nAfEe6`FGj^EU&XfUH&eoy|&TRTM$e)%L}-DP!=%e;}#< z2LgFa*Q`v(#V3Q-Y+f@7Se{>2Etp(60e6;C-AS4-__&IXc89vPiHN51d#--Qv9#V& zR#mnCuOiJ~f08>GuI-=8Nh~Hd@?gK>;{cI2A4?vYKkyOm6fZ}{?P0>br77e&j{f48 zMOOf;>n52y*$fTsqk8?vuH|C)2H<*Hm}H87Ae+}0en%uhO;eZYanbegB|;W~&Er9ADT^GWq`zOE8kHOF^O5cHqyPN4ute!zRSAdt5a?@y6)Wdz z+`b-PSfR_&pEUFH@tM!jQY>dqvT4nwF{`XW6e{$8fk>^yzaJYISqxcru%XfG-f8gr z@Ik4b3%|d6KPD%&PV=`y1t?sqJRgcp@zyPx;HL;QOKjcuLl3GuflT<+F+93h*ThtT zfQ_57qId6g*QZ{&)wQ%kLmr0hCOxDq{@aHlW6{dB>w^@UzShGtNW#OV2|qr z+V(H`^d&&G>h`ufjEGS_4%iPrwx|cC=4iuuCCi!dc^}nl7+E3I2SIJyi33>7#l1G-5HWWKXN|~;Zy9l zg^|>od1&ESJGz0`xS(N}(=tWH00wAmB^v!ypW-YL6mN7y_ZM)?9EQyi0_ zIgJ+U{$NXAw2nxW3)g^SKv$@bT8KWoEVmWLb`!;t%l7>s#V9!}xQ<(QTtt&?5Z93_LX0pOWoWvk2 zb;6>8Q+SB}*e_}B39T@xD9aRv|tjxP3k*=p3*CcU*avIz<^!EtY5l8 z8CEv{+X(Uhp-cCImeA*d6~=t&;&L^)a3JPIrGt6kEL6LEs)~vXAL_n*J` zAz8Qhi_Exo$%7Cpqx#Y}-gB9`!V8Q_uticReSpN|q5x2u*_YnA_{CamTu1rBP47MN z+fLTTibq5MQP607+z-KV%vx6bJ+E&3lkGH&x=Wsa|9LSLw8|kg=j5?J<6<)2gd{QTDhVnk5>DE$`|={Jjco{SGqfD0rK&?~nx<}Eq-+=Eh}gja z(LGW~4NIv`qD)A8GDzRIUs8=`1b}M29E;XEwHGtuX5JusjNY~R6kc%V0GRjzIyyrD_SsLEuz`bBG#`?WF%}8TPmwT<#1|V z)d^7A1veA6pNVe39ikf8Z?Z$h9vy?rOk4}$j!%F!{li18Ja3;M5jC0J5c_iPVugGM zEp$ihb9L*B`m0LrWxYXCb(=M_Hak`fYh{N5aYw=?&tL5H(~zt(e>j+ZHOIc?5-5|p zGH<5sVg`X+=u0xjXDoIeFNd|PmZr4bywtRmEmyD1SdAhg-spE9qC$M+PR0xqaY!K> zR>LtYy8T|3AU;3O(VS2_@Knq^wO{hVmpAc?7+<^z1p%M0gD*Wh>WBQEl z%B+rF5eB%;SXn60wEcDzh%>AOONasumw6x`?DXFJ`N3h&(}o1G!tH5naxb-p!+#kG zDHOA3QE=d6CkXxdB%8q(|6^cSSftfdTI=K%&hPI^nJU|n20wZ~IWERq7a6(HI;g7- z2YT0&OXryb#WfEdLrTQl7?)$tQs9skY{sa*=>5{QJ4{0ltyz_stJne?0c{Y8AzLqI zXzV_>8FJwYWc4OT@vY87?YK?T)!%mXmX-MDF^7~me^xXadp*kR!PX<{)5o&J`;y>5 zS#{k#Q&?!4n^mni;M!iYnRNT6B}9xLUM(;&b?1Vf%H-W!77($yh;G% zl<*=If@+_)m+6ELl}EP&t$e^U2;UZ-=&>2q+*OOfhGpQ&X$y)K>cwNdI_?NcbtKSL4qsUll%ZvMl~ZUudk+Hv+18WT5Bu1HiOkkfieF>DT2j)*^kkc`mK?Z#aAD(1K1F zFe4?ckt=+`_M^DjBp_j5po8gJ<-=r4yGnY+US_4rXHTkr3rl5LI}VF>G2oRun~i#8 zLve0yIMvf`LYA#KZR#sb!sv+1KT!V@bbdESdr)eL-zMgq(ZVAp5(x&-tl0egN*Wb7 z0Mvj@F_Ge3-XoqWUJ#u_v(>%sYoFX>G!YsjzvArTif?? zwr^|OwxWrCPYycH+B=VCGRSn@$ECaK(2um*aq-~m4NlZM!sn?UqYFAaJGUt#3>$h| z@&Da)2BirNQ!kG0q$`D>6=K=MFy!Y?ta5$fKJ?-p+F+PB)_)3p?Cb7}uHLvN#P)EL z6YPYDu39|e;lCwgaQaBgD$ML=z~?rd=_Nuty&jp5)cB0~91CwXkz1ZIj#&O7U{icn zBQZ4UNR@NeVCDrL=ua={XBL@GcT zUnXw6?ADa7pZoPNWzy0hvD6-BF(_HMR{*{|3t`XN#o~AO`ukP`HpK1%Zpyc6t zM(8+D@?$RfbbbB1G6*Sgovv+`cU#y;JgR&GL7%(&JfvD)mwG{N#n~6|$n%V=4H}^O zHU%;t8tRn$vT__>&%6kWTq#2an9PS%?xZ$%u9cn2@3z|u&)r#Et(z!A5+%Ywg7>l2C6Wx^>adJEhR2uu`Tr z7^r_)sKY9I(0ol%c|OVm-2&@`W62f%q$yWHUvVU5-@d66U}Bi*!!~2PGRg(dSO=~t zhmA5Ll2wSL03jC=xj}r`cmY#^y32luCe3{+cL0{>@%;24Z^yiJo%`dX0(Gw-(&Yrd zy~n|d&CzG!={{wSZnYe0eej5y?*y*0=Tqry41*%;8hDj_J6|$ z5poCVpbwI0%jrKd+l4db9sKBVQZ?Hs#R)hnqki77UH18ysZRF3VCP#2d&eMF)|+%z z$YEt)a96eUf#9j%YS>vsu}#k{rb<||$Q-+?Kysu^J#!E=n8ZHtZPt>*#G2pEfstF0 zJ1Pwi3M~MNkNh!W4;)#x#iG(xzuw$cErB&Kjnk|bsbtQl;}FC8AJDUHd|wE)^ND}1 z*{B1M2a3%^zS382=Y2!Y@zOE=^w$q%JH?nNVBs%YP(RFB@?~yR(9&Q%9wUy0v{Ppj zxZkf6(amic&q^qEzREu39u%_9%5AVE?1bXL_{D#qM1c=OVe%err0tyfQF}UhO+FNSn+yP*RZqoc+KDh zj+WTAOh=f+s`Ma&M;qidACxR49Xj$khH}Z9v?}J~t<)KgH&{6mC(?9KaQ z@Ze=zdS(DExE{4CHdHb*06;2`upv0Fp_rC(B1rb{eDy)@<><{+Y z{b9qAT3%WE5Nwp*2Rooj%5iJ`@%ceaMX^|8<~N=9VlDz>D2LslKyl0A^-G0+pcOPy zwnPe-q^zSw#k!r#?cw&GRFyHDIO(+Ng9+NuI1q^R$$g5L`AUk<1R5`D4b~5-h*>9G ztIr<96Gcjk@ieUoWuNmE6jQ%Ii$-YC%hFb_D#-=%6`a@KJYbuC?nQK?OHe! z@)<0LeJl3ZoK}JUY4q4X(BH2k+)r5-b2#*Njy6j1b5?(H8_l1m2>Q^|F6~=J(k^X7 zc6|W~tR)(idK&hb;kR%P2cyB(@P>9H;%#@}jG z*#1sRgUsq@4MGg^vKf=R$g67Pa)zOm5B~10RISC?vQqTyO}Ek_ciRo`p&!}r@n0sY z0D+##yiEEiE|h2+QZRVFF=LQE0d0lF<@(tsBtB@%ag#+Ji$a5Wl?Wx7$UXf} zBggubPXuU}UA&((MHp5o3~cyznJVlP&K_HClb5=ud@x?XF#UE5Wi^2YZJ2I-tjPOz z#pb$O*P;NG%is; zH_Q&oX(vCRwUiNmGUr&(0&^LQ(WKGTv1k!dx`TWuf5?%<0Bh-N$GSk7X3NBBdTpfC zlRDmThS3y?jg3#*i_3dj=`l1d>PZyce)i0=T344IvO0k4j=tEtdfDd3v)ZA#!S>PyetzspANS!Rjc%)Os}bGjo&3S0BE z`AIFx*cfr>3Dic4%iMJ#{dII4%I>g@7rt|E7_Z7X;kf+vp#KB274mgo5I;`0ys4>T z(O|42z-uTZ3NYvy@2Yz|^FK*(Ks=><&}kEqWfLj^Q|KHtcQjSkg&EG*Y;_b*SvVZN zRV4`zi`l0UyP&o)1@z} zmwk3%pTFZ(xUGBLQ`to>^?66u~fl$t;;G#=-&zeMhoSEr^2ITC-`a zN5-HOGK1Jm6_`5ok{Xds_Px`XMEq#^{k7ekgXqk?x0jxiGa+bdBC7C=7o{UPqLN=4A^!Q=avfK{7mUUa&)Yoqpv6jAx~ z^4a(2x0@~Q9r%7QHJ|lroMJ6jk-eo+HMu9Q6>o7?PZ)J*N-2=5S(i?9PLGy}ET_ZuQJ?Ya#+K6)|ZRpq76 zD)T8*W&$LqOCu%yrWhQ5lk36i+Dw?xM-*)F|507nEE1@? zTG7kwd5c>vpP?_9EaRB-H3Rx-poc}Nuf=SQo-2i2Uhd&D@X%8)M%kiHJ9T4gwSj4& z?YlOufu0t(@0Y(R4x)M^yv2Ud{7gOG*2}VY{ILa9mTkrd{qsjAVAJd%$Cia}M&Wnp zEIc5sX}@Crfh>15&ca_mpQ_C#EiRGD0spWGXZVi&)tf5M_;#&XiFXFy+uch_-oA`` z==4|e5Zbh3WGUtSSaGmxoo~;>E*SIpTi>tWHzYQh!so8415LXUZrpse*1NN_>D%-} zS1tS9R0!?em&qG#=pEDX9~1@FPpsX?YlTa$5|YBu+#~lc4~OY0ceblm>ZIPJS_@9} zez*MoxXsh*e)XMyAa?ybHV%#!ZB~UihYy4h{BKMg*g_L2%etSnqQit3t2-N!5 zHln1N>|n+FSet-n&x^5{Hxj&}fBj0zCRy$9zcZ2KGlM5C=HG{CZroLf=!$RmIj+?> zu&$t1jMc9q(Q;H1k|y96Z)h z7v_D?`t#|b4qWA>!OKNNNW=?scXa^~rx67Vo##H2y`gWsn?6KU^z2sXR?GvekM32q zAyE`E^zb_E9ld5BA-%e7LGJo}nvI1i{n|s+j^GRBre88F2>NhHlO)p-?85)vpVG$$ zD`}L%Y$BV0m(!spCS&J3)HUyF9;GL=gS);^lJishoX*Q3CeEUlDH|}s%qW#VZI`(3 z`No&aXQ&$brjCP&O6y(A`dJPxzeUIKPuvEF*Z`|^gAf5T%gjipho9XU)o%1R=IN1g z!!yJ)K*zEat-;|KXio3?L|_oC}o)06$g!G;DHLeQ93|Llx*81_;KPh4Smu7I&FHpJP z0+VEjQ!BVH5#+LIVywk;Rq<54!Zs-o@?BdjUHpc;Sw>^Q0hl5( zukDm>f^!|e71w}C+ABFzr$qie^GyplZFTfj!TSO~RObQA!(Sr=j?6%#OJP%R%flNw zVNqbdMk%Ai!vh&Zd|2f^GJJ@xc`{Ar@B*6`{(3Is zJY&3?#!+-lUi*t82o7a7&xQ<4|D8)B(xFeXIA0Dv;(XqITCKbNWIYIxU5c`0%n z;C5Rcax@QU4-q0~llRhTj$-}-f7(8h=Yi2js!d$SE2t)z;!3Eq{)>7Pp_9L}L3aBMF`}FNP7&P!UqUy67LjSr}!1@6$SXQ<3@t?$WUvnpzB%Pri!GiMDI+2 z+%VPYnX0PDN|6#oV&bWY>RX)O1m}KUd)zieFNUjMUW(GoS`c1*;j(mbK&)~K(h~fU z%8?hOuLtR^JLa!g+r1`t5q9=ujYT>7P=Kt5(u%e#&6u6MgM$cs{yIH{kzEf>c^wT_lBOs;ko_3t&nWS z!df|rLl@Z8gr~ueuQFS6_uLuH9(2>Mt28tZTqcn`H?z0@`<>iod15XVXdDXi4!SWbQO%4^Z+p7N}kWN5~E zk#M&o=fZ?SW)i?&UuS-Vb|k`jOOwwqWN8acb;rP05#8X7gh zYewnnk<1M}e|^_%*?w2$lsH?O$NunSzf_u%hBRR6t=LT=x@)qja7s!vabMH(8Iyej z2!`=ro<|hf=_#%ZD)7)41AVzxZ;ti0H2&7)^g1~u_M4dHTSieEa$3z%h8KBMrOtNU zhf0hvsqnsfEc`B$!xiP(uFsGb8*h__pPbbjoh@ZM*5)m8-rG)_WJnHw81@vdPfGi#PojSJ|NOweRla4`9;A?CFh*o4m+q%Fn10M zt5C|L)7%$nWPitv+=984Szi%8b&xd8W7*=gI}g@Zcq6=WN|{_gxM*Q(hS=#pV#41J z4`@_j$o8@Ti?!z0YVzvL=)xrGTd_76U#_{msNI023zvc`owv&xe~0!|6{&^EOK;sA z{nNLdTHib3Ea zw%(WO*DQ_J9!EH}{louU^Bhy1rC3Ky$j2k9_Ds+Ujcic>UXgSt0DfaeFjOL|j9M(QI z1@sR`mV{uV%a6_voW@;^d*b?@xQd>&dYfgQB6h}N+?lB3Jog4x>lphjtppNX`nh3s z{c7_ZH#IM!v0q$uxekVX;-6hAP+9<)CEbB01 zRC>or(U@)B?b)6cP2Zt@E5mVYW`BSOYguS8F+as;<0aug+SFmhs%SivB`eM2XRC^2Hx#gu=CqF~cvmT8 zQV-wQk$N7;ECaFl(Co4Ti%_NRc*8>Kp%uwWqP!ZIcx=JVy3Dx7osh;fdetMKbkYmZ zn`?RM45B`8;aeLPH`Tq*6=Yur*KI9wSJ2hHSC01_+_Z9ooB&l06N|zGEQFJ{hZfkK zY-OmCbF9GqIn$|4i%!V}L|R7zudP22+zbU^4{)p)3dJNP_LVk`yy|s(g1S0j%KB4S zP$9Ey`y4^fMY|#h#N9&=th4w;SQFeexlCsbmWVj3ZpBfo3(xK1($M=wPIL+ux%7#J z@rwNrrYIaHVxmws?GWW9;wn^RrRi;|w>_=Lz=l@UdL%TJ5Hl7Ukgm7hGM(OH06m=X`-owtwG|rfI4ay^F1ecuBU- z!3ZPGDYDW7hi|}LJ<+z#lyu@K^=oW~7_udW&)WHQaRE6<76*wEe^<{jF7`^(?x}85 z+BJiHniE8%)ZcMss8AwYFS8s z5!+-dI?$QB4-3rm&3mLO>Fr$Lqb;3UGnRc5(bKTayYu~&(v>M@y_9>SAb9iB<0CjS zt?+rI7AHz@Sr0-y4Y}v3c6L7;>E#DqD57}642&+K*{1onmkkO;pn0;kA~t2R;<4Q) zX|qJ$MA7$8`Z|8os-(;G9DL5qKK~Qfq58!RQm+t3JfP_B=G)g7R3w?R?j{C*136o{ zKoe$SsB5lh2}C@ehuOQz1-_a5F!iOmyz4+UpRx9fuCDoAAa?E(A|hKXP9+%ZtalXY zqUSzT+@T$_T7U~*kQuMmbpAHgW%*F5i6!4mq=|MtUP}#(3km690V7o1Przas1>Ub$ zT@v^9fg1}t1&~nxfm#9+e>r{KxAYqMZn7WgQlzdrtL!GZ6ZWw z{o+p)yGS!rbc;Y*M!avDOB+EJ48PpilcKM_+~E>H2qD@b#*)jbhO;eh`$?SX0EG4FY*aAUXIEV8`-Lx+shdT zOF|>A>P-s&$BmyAX0(e`eO|Wx&TLQI@}CP-AAqg(D{0T8R$uvA219a1wDH3@af6I{ zi%F;_xS&aa2d(bP`-fKg4r^gC%w_xM2Dx42Xk%WwKCc2$jG;-9J|^AvUepa_PbDt7 z8u1FJ+N*xn<~zm3BSpLLQleB*F%?7OA@g-)6aTt}LRECrB0g)$W?`^RPHn619bc}^ zwC0Ja3ft=63CaW0Fkyt|&8cjoSY_And%S2@-)8l;3;!cpo=@KbWYFVVQ2uLTcl!U^ z9aH?ChLj) z_rW#vy<|#s^`+T1oH3$Pu-Kyrbz?Uz(k>fS?WY{L){m>w)B>_3d*jU{E9kVCgDHPVET{m0ND0y z#eBN5s9`t!qFZfZCLI(t)Tr4kY$fu*?CicP01kz(`~w-_2LQQwZ>Eb%z+5VlAC9q> zOE>f$oLlH^KJ!uSJ7l_V@OqAxhDxVjczT5RG#)Fr>bY4G%DCpc>LasKc~`-50bpCH znoc0GcM6P}&U~EEpG%i}Gj>B)^WS~G7a~UTIyI8&rc=a9)XZYJXg5q_+9{dN_m%SU zZ`nKze?qhIGF#s+iSV%@hs&3IlN*J&>ZPDK-T~)CMpDmiuOytnA_83rrj%H zxw6HfOJ?426Z#V3Z3kBK)y-f#Q!ScZQ2WO0D-}YPFnZ={&XS`<&JD-#TYE8r)sdn8_aD%z3n>@hxy6=5 zpB4>J?Ab(yFK-DBATbIQC9J+f6f_&mGr~@caaOsxJQQqOj2f;F?@NDl8T|)h@tPkB zi~A^1mZ}9#^bEH9q>CvLH=g)Yw-g84$@AY*8PosztH&eNc7=9}KYgcjri#Ls$Tgz| z#-47N2YsLlofD=~Vi;3ukns}VuW@?rNZ42z3H^I@Y3-Mad57v!q+Unm42pbt+ZuA!o-+B!Be)vlzV@yCFxs5=RqNeuscCYa+u#|7t z{JvT+51rdBRZHCGrwKYgRjb?*WnR#>*d{w=H211cUv_%E@i?-2^xz}=i&KB>Re8m9 zKcora6ZnWa^e=u3SNd1i+>w4MQ%_?yHa`dN5zj@5arz3)Ut`o$?;JI2GqWu9pkzO2 ztg+O21vfu0VaPW)=T%Wp(^Gk7*&-UPe)NX6;%0=A+$PylTEs7IfAdZ{tWbgio#>-xu6`+8 z95LBEYUnQWX9VCVbs6aLLKzes{++aW64r>dN=0{RvywYBrBkbb1EO5N&Ignlnbw27Zf2Hx5)FMc3b2 zQx3wZo)u~l8LM7t-xH9d8(zyk2636HsHr;PRlgccyS@#q6Fk_K+)224M_acNy+w%u zQo$a{6Q`)^iib;A6b@n+&Bv_7XXwa7g7YaC)9Ag|=oMr>m->?4b8hUYfiDf; zx-Ibr=F*E(A`}H~^u-BNDKjB7KlSVN;HG-D#94JB->K}N&o|~)EzPwHKI8~yW1Z<5 zki!F3M^0HiuyY`D+mT5D$uu0T2VwKgNe3#=cZqULmI zczK2)K-Zd9Nv@$mQ_ww%c|S74!bkc}5X)XMuSh zM0|c2;xV^st9~tG6yHY?F^=12H(V&O<{iHvVMA;vjDef5(bd3%; zW*n}p+JPESixfGHOO(LL3CxCsdcle>xbm_bu|7!T3ey@*fVfs_ocA_Dc783KPywlD zdWIm=aZ4WIdSWN1Q7uZAG6-GaF7VST1$UU+Q(X>O2~7UfyLdhW7JSD2_0Q?Xy*R<8 zjrY;gyifkfr%Pd(%-auYb!L61zD|;x9?l4RM`}2`&zZA1v=@Y7mX-Xjcx6(08~l2q zjJwIE=YDs07c+?}Qj-kM11+YWTAiQK9|~jL*`?Zr$m)U)XWrBZ7mUb!LG{R+n?=gg z+aW|wsvcLmYBFJQF(Eac-yC5>@#xH7(w#k&*tFQrCZ37gsmzp5DowEdFp0k)3yvZF zJ<3bJ_o5nLr%ZVKF+2ZDiYqeMdKcwdoEz%FweV|I=S?`N-i3zb8phl=E-wB=7j;ufxR#!b znXRgK552v}p48`zXl<3Fq8WT&ByUR_bKPO(a6A0=7`NLqNY~0#VyyfeHua6O!#KBNc0>w z1&GFj$EPac*Rp1M>fNZqB4p;2EsHr#r&E$7o_v9p?&mr2(l3lOb)g87nDK--gPJ7i zW0EjL;ijAqjFw?x7o>s6i7X|@`>#Rq!ox_`MQ*NTvm&dV|6S9Vf5%hR*xOViv3V^x zG%a09T=(2Uq>d0SI6$F8xKI2bhEq`_^Qc2>r!AymUCBemii-q9to+P-Fev;uOy0=~ zeQzC_Wc$nU@jL{NkLo$+I*n=b~U8Z%Y7X+WXDtoL1yEbjKR= zlG&};#>P8ts}47nqLGl#fjxlQF~w8Z#f{*300is;A>i?IHeqqjNnyR>8XZs z5}R^&Q#zRq`)oKB98X!LxyZCjmQmjr)Ap^fe(4WKXxueU!QSk{n-EHsuG!w*yL%RC zi?z#j+?5e*=Vz0An%){`v zE&IK4q{s!y47D-|uevrTS5+vOSn0Ycn1~u&`vw2(!6VIR(t@D4{^~THsS_Kif$`yM zJhri^HW9HHfe~EI#=%2?u4URp&DHVAnI;GedNGl6EXy$LSaGR#Q=j4kVbYnRZ5-}w zX*4nqy2Z0}Am-hAHy$rUs9q;ge{P(?ZjtEN7-yS0%HbuXglUKWnLc!-)=)fUFo+Qw zME7%|lj-pYRP5VsIpTFN$||bj?){KTPhahVSj$u^zk$bBF&ExLfUWH{>JcwT-5+cP zHtWyoBV&5%G}aZE^Dh3v&%Wxv$>Dkul{W$it*u8gJrDb?jFr}a8Mq(z8iJ%xtmCmC z9C%{!#S-)(%OQ=Lr^t&wSjw_g<{zTz?sQ{14_c=~hmP9Cy;l9HPlUtuxY@@jz0c9R z)4mc18{5NHsw=`i-n%47$%rl;)8(>vYRww_84SVs9R9=+GD{SmW`N!&9FIOaiJTH? zy$Ih)FU<_77FimiK6oEB47|+>gfZHy!Z0QM7D=d$#zpc7+C`%vYAtHI;>&Antd5tX ztr)iv-S8#-@;tXPPsT0S?I(##Z-iYBEYcfrE5xC5ykW-WT-*sg|r8wQ(L)Tr_kPu#GfBEWC+Y>UR3XtZH%(`;qqe1Q;HAGbbH^me@Z515JKT{*{clM?$or7lu;JF=(N}>LE_Z zlia#23$w2;*P%?xmE4h|Duh4NUf72C)##d|#I?e&Zy()fHuq` zb4R-OwA7qj49X31G2C?jV{kXL&CVFItxgA3Z=7XV2u;hlZ`wxxmS@o3oGQ&&QXW(c zz0ABRMCi{Tor5x0|3PH7J$vmG&-G_Y)nS_Jttm@ltun*EDeQ}J6s}pm=bnU100_wqw4#RF}{Q(je7vMav?kzNWE z1jRZb^lPw@Z8TLj$^2#^2OxMA@TWkHEWG+fZ*179km1+gHqe6KQr8teh*h@*kW@Y_9A&$Nt}+9DEf z;O@hzoA07n?16b8I>JO8!)48Hzh`v*`trc9z^U4k(r7sI{G8(!EJEa3N z+q{pckxdlI9H+I*bwaul?0K5^wBU(a|KqXs90nSL#IAo35>t}^RF49Nonp%?>qUZS zWmRjt-(jM}+Iu_XS3b-}{HPX5KdE>bnahz^f$i`xzKSC|XD6QYj2jg2@e9mpB?Ufg zh_2@8uND*(Iz8X))eh{l$I|4Ln{;VV=$DhE#vb+@#t=(U_iV7Rhi#qGq6jy!Pik|| zo^yL3zQ_?{2N=~5!Dt)jV`WKA3V?J`?G%x1p1%Bh@(0!3K;Ge-5)J6v6I@R#0-X;( z?^cmcV|e(Yt8ODZ>we@&=fnx4x(2inmR5Wv3GE>i{d1m1sUmO&WUQ&j`b)D{iBs%Va~B68J6J?2-Lpjd*nFf46HhB3M5Smnxy;r-D6e- zG<#O$g@BI>FquH1-VlrtS+g1^{@=wd#&=2{1kMM%U4t$pWTIUI;cQSlVeIw8G-v8f86T@OkbNMfGQV0`1y*0u`sXktl_TcPj*=eAmae^f zU#HKqNU`sIubqPlf2QgTKKt~Sf^;Q)dBNB_P9*fRLdP%sbg}M@ zy-Jq_oINgLjcLmBPO82DO;I7D?Dc8oW-dSei;W9;CVkCS?lW6-nk2*N<|Aaf6S3cC4kl3Cod=5Ms zT4Rrl%%LEvcO@QbH!8E-z<5sHP>w2}?2V(pW!%JitAo0YAvb)bb@|UjncgIG;nU#wCfa=+O1kdi&;1n)AJ^X~WUSP3SwP(hFk`n|xP`wK6xc5^ z^xmHoqN33i;4`@I2@eT?D~iS-8kOuxyS${Q1#bp%;zpmot`{MoF{^15^h9pqpP*1+ zEAj?_jKZfZ75#_f*r++==V)@Vcu@qysWN}GfK!rlDhklrsWpoI9%9=WR`KqQMp9yc zj&|j~ISF!cS`ISfZgFG>ekDV|z>9AZ;2y+6 z+unRl7iis&LN)5pNDBWnsHz+em}^%~LRjR{ob7Y` zYG8LC`R6Yf##B_U`H67^H?F!k-yO*PXUO@sa}0OHe3e0D`OAxyvVl)hEH*0BYjH|| z8c?t8DP4)DW<%z#g^>^K9)U~!d{c1uizByhyMT1Dr2vJN9W8qxky!cSOiK=HCBpB{ z2Hdhp;~1#E9Yg?AKhorTIXp<($c%#M0d?rz&Y?La?`ghIYxYf@!lT2`97rDny^P0e z&#ye#{r#!>%}3zc{z{aXsbsWFw&-o&0$_>*ihQih{{N4;_zP+#i@atGzlXUzMj~BN z@TV*@AzEgIv$`msfrQd$Eg|_qn)18SV&9ov!uPub{zwX)9%2!bQRuyoe5<43d%gmi zIErJ;oJDehJ(|K{TvsCG-ao8fPkuOf8aIKKirc6eg;LwNE9#s>0qoC4X0tY{+R|ua z>#uejjzb><(4LZy9u}_>YzLgY_Jl<_-`vWIix$xpn6pS6O)hGIe&*&U03+7izY|-$ zfdTR+clvAdodupmvXf&-8r0eOkB?2yGbU?lu2$MCo+;Ya#;p1apR9JN7#V~?sKmB) zo@tw`mftNNrOP5wT6tb2LiT=y`i>3-a85_hiotirIIR?Yff995-chBHP%X>LrSW{$ z@#Z+XhJp;c9(=mWqO8_6;~HuXnZF3@+~u{%(%O$q`J}Tz0KQ>znon!CrBTf41Q9o;~mnqPIxu6J=DA{NK^H`9beqya5VgZ}Y}0ujVAIWPZ;m zt$-yGNo8JR#*vsLj3pj|iHh?lfV}IK5z2+3_4^Wve4dOg@$E??9WfwM=i!T~UN&PY zfrYnPb7<7L)NRkk^)3anP@Z00y40F2Qb?O*q(B3wtKkXrvDF=4{xIGTUMXl=N-Vuoqm2pxXSFI0P^kkOcr*nZByF5rNq43@-4 zs;!(|`VneferFHw^eJk6fTJRW(Shmo^vf@Rk1fNtoTXe-@C2Pn`?3;DKDS(&-Ns+T z)4HtMs(EDe^N!ckdmbBvICN(Ud611Jr9>AMnC5o(W?k&>HTR4pfQwt!q!q*ah_BNm zXf2Z{G_?7t6F9**pVgww zhX=!)0pI$B$@M&!WL=LbEn zuXO<3@`P)3$F2TgbiR4+Gk;x*18X*-=(j!98NXwctN;g0aDu(RG&bL)&EuvdG%cLP zuXd{0Kp)Oh; zpD-=Sh-$T&HQ5`7I}X?3fjmd3pD?~d`E-c+pvJ}dkyk}(`>9j0QqVZcqD=S}Q>gS1 zWQYSAYf?^b6Uq==P!Jiw4bW}ckvvz^ZETQqt(u=lDSLxEYXqV){~`?|MCLm$3-1ag znFs7$^0JcmxURzOnnqYjcK+B;rXTWV>*eF1=Qm&YPomT6yYj>trQce}^*JdHU0&HA z)x>5bd%-xrF{$;;>iMst=GeK5Vk>CQLJ}9~O^Wzm%bRmCMMQM%<~_2Ew25+AU;+ml z8fO>=3NME(A8kac8Hs(zMukPPqoeOTs<~i1rlbxicYsGP#XWW&v-TxUCg(Xv?@ba) zP=_*-=KPeqxG1msw(G$ZuB$Yag37pD1vNs!rL(K#Jq3dEN4*;G8oeB$2x1-fAS<^I zcko_mV- zE+<2Hj(8ssuw$x7%yMKA+l;qVinE8Ba>>Jq@Qd(8DT=92TO--?G3>`od8)q`#^ZWJ zC4%Wb&l=L0Y(+X5KuK3>J*hTTeEA4O6(BqzGmnhtx6{-0Z|!jWC3j%pqRaP(UDNr~S3PS0 zl9Q28#|NBF3sbNgt$0*`Gz=UWY`}v2-jQfct0(=iXCTS zoJOK5E>&>0Sp(nxq6-B%zJZH7YF$6%n#|x#B&!*t24t>|%#RLz;L*_J_+gpb)AD;3 zO0Bb!LvjF&Fi`u|WRtFJDOQ#<UQ+WAb`o8PN6ByeIIMYS!=jaE0 zA}3jCY7~>ja886*nrUZC@N*gz=FrgDjNqU`Nd}7ex-(_89s9mLQQO6=Z5R_1UC#9N zouqUzN$|^6&5tg=|hQJs>|crwmcG*`^UXI$b0OmHm#CUrFXNQ zsQ`!Hdt<>bso%x@N9vqjf)`%v^su54LbD7ciz0>(g&6jj(=eX`trd52 zVOa_|kg3A^vzneJWO5*o$*gfUFHs`_Ix7c)I})&Tq}$2CSTqYtno4i4e^Kn z6Kh;5Lmwbzl3@e_`0tz(Z5Kd;ohn^*+(tUaxq;t=n5nmr1Rp7YHNl_B%+Ebm6sD(y25@2G3%unX{a z#**8$zj?vF5*w%4Ch4fX_A|UeAT@ZL3YQUZY!j`S_^+&l6%Ro%@_cZAibT2M%``{T zioCg%y@g5ckkOyR=|~NZX5U@<9!U!|%Hlw50xd8+aZ1a0I{30b&eVxMDn*3STL?|g zrMqb=rd@2Zs>r5ow&Ox;y$0i1l4JogeSXSV;MnJ(f#QcJ#hHR9dE1 zr8DB;yv9zN9Zx|n0pOQ)#nJut9&(pyMOad5ozdFnVO2p5SSAN?wm&>y20J7V-0t3Y zm*>l^CC&tq>gcO1(L5n>)`z^M7W}TDubz zyMh1)7b<)IS=QU+dtPhVO6j+q>L;TaisgZe8vQb_sP@Ia2D^t}u#vJmqW+OiLX@h% zwcqYAXf8TTjwp+mCf2Vt^{ko4F9y2!@2;u`6aGH2i`{7oVM zB4Z*|SSL;@9<#I^yNZoEP~XSg=otng`Q6GrYc$_=k!I6y3@xeto@U92f;~M+q;y7r zO5&Ia6gpTH?LRe=IZl_He^1KPi7euhS-zh;WE*t8Bx# zoejcuF8$UXd2Q)L?>4@zNrf1+g|nf)TM4Rql6(Zbq1?{yvft&^*?V1D-NN3zZAO)Q za#0u>J-mb*Yg|3q1)SAB?DC}j+&yU!tfKV#$xUtGj>2R{xo4FQ2Q-F_hxiv% zn1=8^#9J(}ZhRA(rOwgVrFJB9CGc#AgjmmdtY{-Z_>z>0 zcOT3@unr>1cLP0B`uSDn)QZ=LU8zLdX8TfS%aa{SFMFeN47mJNm@!vYvbLw5xsYOB zi|<81apoQgj8JyLtIXunLO~T9UCYu=wrd!+bIK1er^;w<`#r4h)lvDE9P=rNX7IK| z6sAX>(@>6v>-PqM!@_a63}fXV0D2t5Wu#P0StY=eLuSJnVK})v=N0FT7Mk@XmaK_z z48z=LU2JqQ5+zr)?dLZ?eku8c3Tv znqw?G^N_W4hUIOQ;CfU)$&^%u$=svY3)UqW+bn@B@?3?PhDtO`2Z|G zKYCqGaEWoowF}@jf)w$%wn%<|Tv=`%-V4pf`ts@W#rJ!pUa(+P=f`w6{11vY!_E>; zvK>u=ZneFOfvJi#_(JB z-moFf*9$*)mZSl}^wf2`<;@l^4u0lqsW8mKYaY%S!>wc&@g{Ls!(Y7qbak*8V!$r2 zLd-!jXK$TVllDWyp9}K=Nmoi8rnxs zKMUkezlJYzG$u;G=$$RNk8iG3Zp_@bF{x@cPj1OeHNAVdi{*xzjTaX#Z_aoKm6|q# z+6JyP-CjSM-b&cGY^^yS(!b~9_kOH%BKM`DiKX&@Sv100%TAS@(?cOh>a(&0QWbJ* ze)IJ}l{5e6ktZVBD&-{+RlXG(tPgB{9Vb-Jgs8W*_3)en9 z&C3{aCHmm*J+#fwr|eFj!n(W`UxzIi9er4Q$p0-@7$>JX|L4z-Pt043q8Ca5q%>#T zdgj)+s^ni(CRf#ay%nRe1Q$`0)IgrcT)Dv zzZCC$W<7M>g0}Xt;#w4*z0^yp<#5HB4+)wVI1$EfDzRK|n7zE)Lu&tm+KmU8Z`jv9 zo7g`7GcaOj``UuTrv9NOc~gqT?;y71GH6cmxyxdCMWKFlXO@I{RJXFr2#o2=X!_EM z-fyYuqA*#`?^-btSj%y@kXr$NSn;+2k63HlUlnr96+WmDsfD74{3>cjPt_qfNg>w* zW?-!UK0#bPn!-EObZln+ejsKHkh!N^eG|RhI(+myRr~12yCTI(y70o5O;JUSN4q8- zpUvi<5*UpP1CvJ6+wC`oR%i=IgLm#5&pzFVnw?PiacbMrX>-S0Ds`9NYODHoSU`zr zI68zGNQzh%t=84wA2dsjix2Z$VD`Lih+9TH@JoLKrLQO(e5rZF5DU)z;Fc=+-2ZH`L7a$;FLqtJD&azB)|E;(DJE|=5REgp>CC~G!ZeRYXa_46Yj~aak6Qt(b%5{F9p8hTkZwpB&|8#pQ zK61(u7awD~S+qM#c%POHivDeoBmZ5Z>S;in(W`VXdeyI1et8v1AA|bpY$>ZX+81BS zr-dsuD6X@%MI1l;u-jo$UbTBKJS6NVccmCbS-C_`A=Ll7m9nx(PR@MAdQ0J75M~Y~ zf!N&4;b@6pVWj65qSR(K_?3D9F(PjMdDS!n^C4ga)t{QVGT7CwE&rSLrsO5I<2L;q{*?%XNg;ZgBoQmsgR&c*QB$8p=1$ zFOKhfC9w2MoywojNk?I)?VUnx--Emt&4=>T{4z{RC2$;#P{tJqu zsDJle6{&zwOsG41L%#bL^rGsxiSN~jsYIu2oqdU4u(fNkJ z-D|j2A=weF7e7a}@F$&G^{o>+P*omYc31dLke+#JlR~yUFE*3?^!yn5wXTF$PuZC8 zkAbM5vU=O+Jfz)2ByxR)VOIe%>2DUDaI45xGMs+JsehOwwUNk9S;Z^Z(T>c|onB=A zUpL=5Mp$gU(xfobxA!1Cm~q)$d*w(?uhK$LYG+OcasGmRwdvdb37Owx#w6w2L+9=} zbJh(OJaO93lsv#iN-)3vM>0hlZUaz#X^9CN7vvH=7x2_W!U@roM!F+!12HX<>%&cK zv%~a@{fD9-x|Ob;E8lI&Q;fa)%b4|4++8B*RD#h*jhk-xaHiA=x}-k$q8e~7u^hv57=h9ftKKi{1rWE%%xw-3#r$! z=9uPe(}5pzwn8;e9v4WX-91~3PB*)o$w#IJhk>7xjcR^Z*Sm5~C@#u2wQ``V%#ebt z*wf||w(1Y=vn^3Dj7c9(gCGpNVZV`6f}<4~!nUMOTEhx~Sb}69b{gBOymIuEKhG?x zS;YH`%ehI;Eo`LGrs@tb|MFNR5zOk?ajdtw_GO2Vn|i@8(Fwo>wBLFO?}FZih%sH< z`eGZ#QroOUEkIj5DsbqqIqYmRvALC;pchcmUt{({^Uv(Sc_?%5havWr|M}89G!Qw$ zY|^(Y;-8F?iYB<%huxbgp)L5JbTn`F=T~l3X{e%D#!?=YbmR@cF2nrk|3qOjM-=(9 zd5c-(F7w?F*OAPs(Cd#e(>v6C$>&u9Ex1i);paUXF#$N4!%V`?v=vpWKb0d=!izU4 z-xrVtb7^G$uOr-2wh%95K{-b#jC*`{*C8%P`tbU~aSG_Y5^l)U7>7BeYPzxd5s4^R zgjev(b-q9~#mLu3eMwTA9-(sVt7CyAMrgll>=On6N;R=j(5cfptC6^_wdUaaDNnYr z-$!>dah1n-1lQTf0cSCC0)d0yql2IK2u17QHAqB;NXUz{ej*zFf|xHjBhAe|nHN(> zgSf+!J9+QH)8n?9;}S}5eXPj|dh!t>^Jj|mj7T0I?wgivMcuap<|j(wn-Mt(ET%IH zvtnOZ!ccs)Y3dcE_FT9<8F{qO#gypP^SQB<#*}iB8uL4I=E-g;lRv~O z!jc~xQw03a!U@I2U&I79WPCNlhCI_pAm% z)*B4oCq4FjXD%9{yFkDKo<_5@w;C1y!D*jE07kjBC=NkAXSWiT7JAHm`^CAwQ_g+b zexXn1U47fBy=$??Ah+Tfm1}CMUS%OG_xIeD0Dby#G-^zqNFF4&pZ3O`kNjS8m29%S zq%6<~;qBKi?5Yj_w#R@sk*~O8N-83lKeNhI?Dn#|g;HhQ%Q(Dm=O9=xjyBuxjV=Yh zu-dTfr+DjKUeb_ohVCtgAK45n$$t z45yjEh3+*P33OS(fPAEI&zC14NBorS$elIDz_`_D+| za)mxuYtclwiTzrJ22Cos`Cq1(a7Zhh`VdsrqKAWZ+L zuGNSU&@Ah3boaMD!90wKmp^G-Jj4jyEb=S`8Fh5V^C#14w*G(8>FQ6}L!FCqW&{=|oQ`0BOwB)cvwE1r*3!ezhW3f$+gC>@ z#vnWC%csiYvDqy%B}uP*kR zXOJXD(j{e$@iV$8kyltTTJZZIP0v_2H0?2oHCIHd_Rzy#NdM>o+eknC(PE2{?#F`Q zi2t!f9bc%-3-7a;w{GG7HQr`5h&`iOC_dTH&)lIhskijkSS7qR&7;Bsf^2|!s!XC( zU8hH;XAK?H7}OLMnHvaNu-euEz!#nOk74&*dt_V31y3m5B#5+o2@>H{#YYy5}^^@@7`^fuH>B|T~t_4 z%~lqtn0_EVSp1zsWq>2V-Fb~-d{7`92yiDj-w!UybI`hX2WJEInq6Q+uIh^nawKfY z1Ak4JZ@u3K4|U2nDfX2-DRAI>&b7e2asUYFG=eMMH$t(!b@rYjah6&1NRDIhN`ap` zf;P6gT98SHBOf~N;8~bDjz(jnPB#+tjFu+jfy4@Ztx-b~i4EWD^A(St{j_u?ejQFsj98vrKrIR_%6tZM89y2K8FE1gOWO*HtW zinR&`OP6o$n5O=r{WkXJ!tZq0<921d(R$PBOf>z*A=*9)$FQu7(BCC_QfswD^y)d9 zKPnJeS@FH@@asyMqWnVtFVCth1|SnaZ~XSP!5lWzY9{xhosr*g=pa5e$36as@7s|yv|eA`z$n# zH;>qKKx__aYMuo#<7q|d_hb())$J`RU&JPVfE8IMUPU;dftQ+{b8#>>i`TexaGiDS zfZnWUkjqdS&xs_U&`qXxI+VMv%mSlu{3 zEpY#6NbZL^FqK>%^)7if`=|B0W@~(=HI+XKHDiqdu$VTSFdd!$QUqGNO3B|Be zo^HNfXFWUc3;Hd1eRf<25P zrcuakM($#jqt6Dl97yRJvAkyS3{ZAbnFA7hQBlU?0FTl{opeZRQ?yn_G;7j-GIny@ z+?;nSWmZxlzg+G~iZbbIe_}H83x2X4NVxnMJa48q)Luxze2J91VK+)8Z%rRy@BFdZfnV&50dUNBW62L1jg2hCgdwB+B0!3q7LP zQA7!sBwA-nJpRsG5Xt^Lo%F2xlE}%g7W-Ha?L2>HuvgovAeT3ZYwelbwW__57KiR> z$|`lryTH&`4178&k*40aLoNKqN1BL#I8fOZ)hqwZVs=V`L}Q-vR|7n{5gbXcVpN>= zPqY_+gkow~qpMx|^*Uv4Ja@qq6hn=RRk1OSe5K^9bh?ibWG} z3Tmc4CQ`#2sQgKbUmynW9;u8N_7gB#Qkm)YB$87ni={@q9y_15KdbcBM49ZsaE4+u2NaU2I>Xn+=b;JFq z)?JPS*(mFrQkvy}!PmZ1%@S0O1(*Lwi;`I?w!9rmcS{qV2?eO0KEYl$L;cTdbR#I? z=>|TAaNDkbMdGg?_AyG0sYBV>H&W(EHH4Taxte{4f5|mwyCtXT@CLNp9y3yr`U@Ih z7E^0NYaFlr_%h6kc1F;Ui4t^dHT0phovS zY*0GI-ih(4-dvLOM!SpZ`$FFzomnpP@)xDp4@-(cM+cn{@}W+1O+FDmMy4{aXoLvv z+@kttx6^NHGiG-`qcTtMFq_1;@&_G697QO!8DB{+P6*VgHAy_lZjFv@P>kZ9vXL7) z8$MF;$#27V*y-y*WYMAsUW?Hf2FAVHiv@&h1u(CGjWdWwoh2_{gWpt4OmvtfI*r0w zI_T~RE@HasP;Ol+(vDiBL>*RU-A8s>)?xvEzKC{G4M&X|{kjmoVX+e45N7#EDFhO2 zGZ!^4j%stpbSY3i)Rn$HBXs8_nb@atvJ8s~h6Er*);NwXl9azZ23IO)Z>+fcFvqeC zv3NzrE(<#^peg9hce5C>_h%?H9@cSLgJ_VtMtm8uF0z;xAelc@F7RO>n;wkh`{!3> zj*>xuc$5oj{#ZQG5H%Zm#Z~DRxmPy?r8BtY@z$-KR4X&2EwJa9Q-_A3FCv#)*#>f7 z{15M1Rr~w;1EI>THno~v<6Qf1xeI?m=Q`l)j!&>|a+|X;p;%{g)4Jd&;4WOHf!rG8 zm8K$%2GrL1>ZW~|Pd_Xx^wqpMcAj;URk5Sy&m>fbDRB{--*10I<|M}Vs?d;7r|aay zGX;9zf_;kjen$1Ey1`yES4mL40dYbONf8i6)JQ|3*SlJ)KE_Z2v8MG6(vd6Ck?KF4 zKJmCQn?!^tu>Rh{tAZ=rvRWw03MK1HYV|B^7&E}Us{b+rPM&3A85NDTvCCDnmJMxx z98$IJxsbOV`{8cS&9&aR8L+3{d1~^Lmq~O*hB$kcCA9v|eJyn)O+^nQ^fo{^M#ryU zTFZr99jf{UrdQKb>ZMc5&;u3%;KYZzSEaV_rQ(3LXnqKi(;#+8wCs|#z`L7E$u})e zS;|pF7$*HWNXzRoOpsnGwQth7p4J`2KSp;~P+jGhE4N{#J?8z`-mP?c& zzbAtmQBq(2BOA0S2j#4}*nVBcfUBBcxS2>J4_2W+#L(_TLc();0cjM)< z&*bKfi_pxLk-StJ>n1IbIwOgCzw>UyHckFBRGPb)f^BWJsrKet{mhqTs-bMV< zj9Y+uRi*?tvYtkG-f$2&^|;LG?F9r~kpoglGMXwul0<}*Jh|J&ykA@g!c%isCHGje}|MM9s<$~(DL9rV>v|5UnUQPS|8XEuoU z1;_welJ>^o!}4u?BUP! zoC6N-bzuga(vf0o zEJ|bic1XmMprDjk5FrR8ZNE#)FdLdyCX_9vPW20|?9gKv z;is#{w4MTJB!`6HYjM{J*TI4Z^r)MPTX%f^gi@{p z;+QU+-SfC87M#2;4+)hh>UFlLJk%ks6E~$s)*% zmDdi{afa%L{0H}GEJht7yMrhKBtlijmjTY6;|!S(R`=^dyhT5nWAawM`E#CVxgKyi zbs`c{R8FgvILfA$egPH&|kZZeyk_^YUmT{SvpQHZq=W6OtZ*P>ZWbO zO{l`~msbW{+~HQd{6XqP68AE(T78lFKS*JJRQyQc$fq>9lh9~M2ED1f+FA6CyBXpw zPD~B6omRV2kw){?lfi~%xc%8rQI0{lpNRnG^0~b6mr{+rhC|bv;mYo8x)#h-~_bKf;Q_=P8QV`Xf6#drX zk|oOSLe6Oj%Piao4N=2$g@zs-WtYPj^ z98zvQ!at@NZlf}zZD>e6ME5;$;bl(fHd)POzZLmU>#BW5OA593-ImV|ib34i@3?I3 zQSCnc_Qzhh>zfQVQQf^!Z=w*kSXr^ymW))9%A~Hh(~0!{y%yIreO8lgS0}d>=7NHo zYbl;GS6*Q$NC{QB<63p+GGPHerv$sXDvDLi3US-Z7>sQLC`MWLg=@H{eQg}vXg3;w({yXZEevm2*It^+ zs(k0*TTeW&Q|(glbbhdr95&DTOk$ngJ#a9)NA>L~403zTsp?O!<|2E91Pblo!Xb5T zgv~h<;o;tu1N@$=L423pz!-vwnB&N9)|1K>5Ad>Y%%bGxYEO_{*80Tf10S_5X!!pI51s~fWKl`z2cRQ06zgzl!l4+%|HKsf7Jj2o8bo;W#L9LmXla27C092LKppbjsXf$L)mtHeCkuwm7B5=!( zb8;B7Zf|sE*Rt0duuu_brjX{lmh;in9=dk5g&0*;?@mu-)BA&{h#`s^{hOH z#Z2#VPVWdyPYd1pEpwW=v_EKJ`rt1JI31vbPKXsWKK<0p?rKZJ{v``GgAN?rn_NnO zZa-JJz{W7mU55j!bR67F$Z3rLrbK{++m~yHnwQY$cGL#(!;AF^r05Tkzv;R5~!Qp z{7kh(E2QA9;08CTaz(*cVknDAYN~*q_K!!B(!g>TQeFSf1nZIJ9J+}Hc*S;`DhgUF z(mjAY>Fg_iNT%CfE`U*=NV%{T(()}Qu2z~P3|bvHhi54=ylS`hqq@C>RU%U+B^g`c zmv9TD4d5*+k^?RIxkNO|GV75{id|#+xalXuFGn`x$&}ai8LtEw0j6m{ zH^}RVIq#6>)v)PCuaef$4IYSpCbv%=wi}9#C+b2tJH}Yx$#hW52qn3=lYr)<2GH^Nk!o!n zm_P8x4XbJtxE8Ua??c)yS5pjiOF*JP+=)fwbb41=oc_c4V71|0JI&PUvu zZ4j1>*Hq~NGY)3lavj)>IHfA(eD#fuU7Bxt8?WjcVQ<*ZiF;;px~RSwPVUi+e51%( zCk(hZGl+se{Z4p|SisOH5vyv-l%2SIHz--Gw2_{+`|h2-7)n`)0Bsc0VYMul1caH*w9i!NtU93WcE4^(;jybhx3jT=YRa}B*-?ufTzYd)c@T07 zZ zAvpu8oIJ-(p}3k*|8nVpD{*t^QokUCJaNHm5Rj2JYT8{+2+wh!&W5C1JMKB--N4h! zcT4w|Hr<-M^O0w3AwXv!5zcW;g*|UHCOeeSzm=rRrCuxyzLgekW@;A7cjN;ezX-`b zL~%XHp2Q#?!TEISn9t;5QO7GraSPBdHL14f-{l*?OjKgQdJK&42JYJ^KqSDRifudny zq-(E!>F&8>Ej-SbPe57~iR}v>PCN#{znpa63}*hppiXg-vQ1u9 z+6Rf-Vj5j$hIc9Bh3t^%SD9N6SaprJ47u)&ksvbRRe|suVJ!dX>hhkjmQeW&+i7e`j`Y93+EHHpxOOejvI%%v- zFw+PoRqPam=()np?trVexTl>FuR{+*5l zPkH1JwYZnCPMdZNk(YXvkd(t4*Z>!yk8V`|wupGMg#5aZn*B?lsLudAbR^zGIl)`9YUsA!44)tT7D&=Yc%dgBwpn6A;Nim4lmUPN#`Mg9o(fXTeRWDz8&vHl!xcSn}l}07nVzq|3Fg&%D`Sa6|EqurfoZhxK~S4FyDjto_SKKz<;3F z*qBxCSEbxe&mZd{ZkZHM)lemDbOy1gGAqMBF?!6{&Pt)LtgbtU?iKv;@zZdbCAZO8 zu<4T#E#DT5pXAGgVW(f_?B44+y*&3&V-4e^B zrE>1`)IXDEy*GazYGUN!FQ*69G)4vTXcbATgT$pmJlCGVr9#l+CrT$3x+;F25Bll%>dC38+l*!(1{~cZ5eF$&Yel^Ofo8Pe z_Or6p@3JGWlKFDB{ZQ){e}U8KTmrQU?=Ftb`=5Yj0Fe_vtpU zZO^U~0;2W+*ST#5i)pqVnKXej{njJil$cpu1d5;{5hCH-L)$OHQZ&hJkr~Vk>~cm$ zWYED>sHugD%{0BEzw}S1#ODmB6hPD$V>S>8PXIA!DtWGbsNtFhn8itPQ8;Yi!9b)T zYchn=0h!0fnPve{jz2!l3gV4}?jX(QBf9sdlKO=U6y4Ffqno-~1|ur&53_Oyx;1IE zdXPX#b#UF1*Cd($5|tWr-QU2c#}@6vthKOcW)fk_#zTc@&L|;7H%g-|%{vwGl%!R3 zV4-rzk1QQ}o#0G7?P2%Bpr}SDkryV(H%QL#c-}H}mN*>_Xb9P)-YN#za>XDBkm_YX zIPN(2-^3;pqAl}AY`?F+$IDgin&JzQK^|z}0L!?uP3{3Jy?I!y$(AJq@1U*C&%ID@ z&UBqhgQ|p}iT}tjpu`y8f?8-p8%jyGaO!s~up}muD#YWA>{TNkA|{QfeM;`#6yM+O z7?|kkKHKm$puCY8Hvog*@}o8|=D`Gw0dZ)#ePx%zcBA{8(hl4rW!Rt{N!|S8bC10^ zb!9ul5q;0)%=}0dI%`DS*7{wcOj6iVmMSJUY2H8SpH%sk=adH3(u?25{_X}LL9B=< zuZm7fwo0BdSMs%DU1QdRD@dA|6nOic5;dS8QRa zn$>na_tMJNLe{yueU`ntskKM&t3INxT6P&*>n)d}QPjdH>eB)XrD}8v1;D+4W=gfm zHY_|a*rYh_Xz<}WQuQ4Ntj*gn>+Jme$h5%=LmHf&^rvtYmO)tQJGMuP$gf|9?Oo}l zHg~MpX^DvghI>cF`;Fx)b8V^ z&&AO`{f+I1#=Zhix#azLEN2CRFIG!Bhq_myY=oT_OC)mG)Gf-a_C=_AF2_wHMOPqw z60efPT|fAPA7<@d6}?Kj?CR2a_`NV+{3j>H>MPwxh12kBjd*8XM?g9d!u-4U&``cd z_D0-ja=zrbsp^1(KKXw`j-&r+By-<*xQ$x$F83=E*-Px^ZW}n+#j)@xU4&Gty-7J{ zOEzC`Wd3sdQLqYFAN@C$)$jei(oU=neYk3WM_W}j1Ro}>|zFDCwWeN7+XX2`2w z!w0HKY|>aKGSKZt%6fc%@SX4sR92;D=cd`+?PpYTHna~oPKR_@IFogQQhn;(J%o%E zwcL;Y*P*fzYxaKZ|0rz^sRPf%Q#K5GH~o+5-DN1{d?OKJH1FY(M9@mOxW@yP-M;u6 z^3_x7Cjisy$C?UHR3Q>Rxx1r_#XrRQ1x|d?X{UjFZdkYK6ti4wH;9M88ZNN|EGF76 zzLCFEeEa>~>}IbR6T&1GX8!{P1Yd-7i*2B}Aa8TEbI%s35qSbLdp$e{mH%B$z^s7?8j~d|wN$M?XXm z?+JoqP%OO6nEWGATb@BvipP6s0i1z|>!AHXJHc|m0VDx?lat$h5$+c2_X2m96_3&l zH5d^v_tBF1wi-FyCKi7H%-j2!2jhQE?4>T9CfqMs)8cf~x1Gl|vujdQVYDEBLq6gT zzD9~2enU>VW^p03%?QGtm;U3MRAVeU_p3R2PY1Q&lGzJCqY!~J?9!_ zTs;Leu>(ZSYi}RLa`_*~i$d6Z(tLOyL>Hg(^&#{2mQtSp9ltz%4_(`!#h*L<+_wIc zoqzc3uKEuT3%}Q|RM^knu9J6>TDdoUl_kF(5E=d9F1pa7hSAS96Kyb#HA`sp75Jk6 zXSJj_H-|PKel07Ldwut-iI-mQ8V>dYBF2x&EjjSG4Z2UpQ{0RUs(X!#FB_EH)9-nFx)u~X6>Wv}__wy;d<^82X78*1W=Rk! zKygY=(5N|iqFPMA34>pn3MuobE*TcXj z*)m@unCKQ}_ogP<&7W3#c-g6x9bVQbqWPaTyaXlg0g3DQjTc|Cg#qs6Qf0U)Bh|oi zxQHoAJwQ1`vjp})w~EOkRx=G>-2vxDt}dWJyUJ+H5Y^|hzJZcZ_J<6G^cO)aW?w2#w1)NHS;x1+Bk}v2-T7Z? zDN@cTA_EwntlXH)VmG|+d1yy%l|Td^HtnHV;)17W_klF&gn~hNONZb$P|80zIiy<| z2;0st?<+?8Wu#&5%jnZW=F7I+4-LMnb7sip@PkRJum9{nJ@R^CKfSGo&TihdkKe`@ z$b$a5>`nNBMB%x=$Oa*>o13@rk>0Q?Z|l5;gm<*l{7a&s_GxS`88 zyAVwjQeBQ9$LYI9)epG!mcnt-do}va5&`Ps&N z+*Rvvmur53t0?n=7#9^A^WwGoCf&Q-iU(+=3|8w8iP=m~&*Lt3PA>%VGp=XBa{{us z9$bT$V;g2QZ#EsSKkFf<>9WvkqjY$Awq!DB`*Iil162!1+$QE=13NM-8{KGr$p*|&m2S0 z{HcL%Wi$%saOv1e)eyLd_xG2NYRWz(Zf9}#`>?tP$Nn0J5ojt!L^-zP`^`qm;xZUm z5r7#p`W!k9=n3@RRB{H=pk9ieQUd*I1r+zHlJTtz0B`Fw$b8*GKa>Mh%kFINj zN|$?6d2t0C1_QnyB0tlOe;m*v#q)V(6UQ-;45s09@1pQE4Z^kQx8a4ARGA$p+W%Ds zlwHhC?<>xHId@Nnz8VelkU`0r6}VR#6zLs&$mlM+RToeb8jz-85u-sq*qbCM`X>qZ zOUl9jc)8Um@Xpa16$v%$2m-5HcSY9!!Z z^#l|TbN`TYA6tUE{0Ca9DwwdXQ#4Ysta^lI9X`{|Oq5Pb;|bj6p!{2KI&P6Sm)jVS z00C#A{$ys9n{7z;iEpT%orz&FIEWZCDXIM4l+YlrH)cJED^Y+tc}z)Np)j>3Z{x1= zv#$Y(pla;V*t{X}kmkO@_!`0I zIN8egNlY?Kp|4K}3m@F5E6EaIBlt!5Z-Owz0p$-d%^yrSmaE*jX7F6@j61p)tIP4@ zg(cGOkkLZ$UO7IMRf@4+lC1~xh{TjZZ&1X4#Xmw1PKiTjXHU4h$qJeE#?u|PiYMz+UnVmH){|)i=ssS6Q zz?nUB68_5Z6~S5UcRAVCFqPg^rFFl>Gm}F}Q5Zt!A|L&-q#%HTvDg^WzLC>ox|Bca z=t|4UmUluS`t5#z>JeKI4sb~FqCti~gxjNu{m?51ofDFJWctALwy($tgK*rWf{!^* zu#9yCyYHpgPV9V@G1e1FcW5vo8DuibbkFecYupOM-^61z3K1jr4Hy%(Uqe|f5dTQh z4xiaOLmo^s|1+HXQM^1p^jb&ywIp{oCEv=T1&TeQ#R*EEu6-Cp;_HSgt)B_d?hWIS zo0?@3wUv<5dy{fXLbtmv)1)Z%Z09Ul~y z`{;^0i+Rv(4g)D|&*5GKYGF6Ja!j2#ZnhpN4V_RGkp-zL~^jx!r1df65D=Un8wTsEVzRdX_I*RYqK6lC8iN&6yY}sPIJKTG3hfl+T zj$0x@Jwi1kGt}U&$`lCIe|rnu@OB|N^mN39<#DBjdbTJRKYC;yVq|W zf6p^GNffHw!s}TeqJ-J4m6qATyuXb#)^=y%6F?oa{^1TgJ)a}P-OArh%~C&1hwpE` zp3eEIjMW?$t!y0LD{HdQ7px2~8;yI_Xoc@**`(qJr0oXs1`2Rp+uyHEP z?-#Gic32)?kV|i|O#YMLy?ywQebN8B!zO*9FNd*Xv=QA?))h|5>KlREB#d&ajHzOV zQ_ji(jtCUB8TwXFpC>h337U0vZO?SnKW{kx-OL>=RKAjenW{W=ntM@*sOn04A$5;7 z^7&id*4E7jB=GpWn8}kSg#lZ;Q4$}iwQ>Bb=M%oQzDaTn>T&dv{rBImt@J8yavpr? zt9USVn?d4VOE#ltN`YdP6 z+h3RN&AymbTdXntM$X`iX7%)Vp;l37^oV><2-J5yNFH0*J`?aO4>i09g4XiRX7Q_g z3oc;PpB5I~J%(?Gwsg)V+x>hJ`(tis)9?CwhU;zjn)T)?q&>O34gGP8x^)g#?WolO13GGwma>j@h6C zar+Nt9$@H@<4&tVp^a&)e`-GY_~d>LbgH=Gw&RD*)_?nULi=>$TbPsPjoBx;>uits zZsy_3cBgv$E3?)Cf+g!kH5FC8odTtkX~3_bFR?MhS0x334JMDHWOSqNTHpEM|9ZUI z`&MK|MznE6`8~wuQ;^8rYF7j7-_MquD=h|b?ShkpnCx-b>uaa+ z+y5AsO%0HgFl5^7A0*}e$MeOB`%q_df`Zo=hH za35s#A&@q@D{9=hHvq5ix`^!^8ilb)ud(eP!dkxu|Jpn9TFoDb-;LJ5xbNOy;uNG_tKNSW*+o%6frxx^FL5cxQlX5p)064 zI(gy3%l9UK$Ch$v=a4DQ`=0rcPtX1>rLwuzLVVQzOFpyRON@sHbTsr(iFxSj)y=>D z0VNw?3dIlKJ4~bQsJ^Q#8gg}B;d@LdBL8kvHWrtbwXN&S{x2v*8P{-B4QhWLI%%FFR&|^Ij!34N(*RLU;!k8$j#^kE=!e#>RRR`NjV~cB-zECCEO(7orx~S^Enjo^f@sCkoL9TM)g)`6y z#e-mZHs6ahyrY=xftp*uMnmVv2JOh%RHkEjw}56?8kpw*BE z@~M(t)d_#uCg+{l7bBsnHNW(1-PE@fTY|TBfbtRYU?RTv-{!lf?Jmq7RR69$;Yl2H zJR^=N2eIz_de*3b6N=!T8!WM2#qD@`3YZN9PFb3&1_M*dE&Es4Q|}DCypZ{;Pb}|x zsF1(|wz8hpPwiRXqzFj5u))#Z0jZ-&e>oiV>7x04Azk_^Kcx@?` z4QVABGvKS%1>|ksuSfLHv$hM-$PS@&Le`1v0tXGTHOb^Fz4OpW=Nh(=lROn z-dMRGLeFWZ9rC?Aik|av(2E`VQ)MRtfmA;K(wiIAgzTC9!68YxIc@w}e6#V1#43;! z@`g~$WEGn0CiCC*>dApVM&~AtstwC8Qvhg0468qMR{upE-H>G0v-XeTyXI?I^D#F1 zV4$JCE#sT3f20PvRr9ZS>+4P_$3LgVcJLGdQ?X;4%0NmO3~iBN*?$@ z57}p@D3X1Yq26l#-N)C^St!EqDB56`s4f>1qwKcGkxKn==2MsKqiSezkOH~t@iZ62{_0DdS#bV-+Rt%CohMQp#T(9J6WofJW6A@YD!qNZdi zQi}}(dO}qYqAB7nB}Ix%ejtkC zOVenrf?O3nluAI7S@U*Q_)goOyX!t>GpIbE7*H&F)S^l;2)GF%+^da8e!Dv6`Knji;Wdjqo;TFkZ_)w(=v?jIqnD=i|p#Q(t!rgh%5VH03`uA}M(7bH`TXpb2zC^H(3$#3bYv z3-9aN*v);4WgVR*)^)qM1}Sc91W&vu7Zj4E&*!YySWh2`MBhfBZ#@^V23|F>Mg00p zIqs#0pVM>R&ee)l<&Sth@|6%ps)vgy5sAkBbh0^`xafx->e<&9jF@ut8F#4BL1u&M zW@e6-|L){iRn6hIfbgm?!XaA3X1`ELXvSvoC5a>a9N~oY6MP%tkW}2 zrzj5_)3=ah(*lrN7@BL&eE~!cBQu3ud5P8lB3Nr!u zY^y_7L91)b&z1CPrMT-%xiZfE1+>@_-!*j{K}h485fVMxLY09~_f0>(2OdnAvN?vT zWBZKgPgsCQ95KPF(djMDV85GjtmSR0_=u6iqwWbuUNnMmkom zMC3|{6U)w?iaPQ(wFMYMe4#9`3-`);t3X2uX>I?J9kEA9%bwUVNSwwJB<7MwAOnHa zH8@>RWap_)oElWIO9h?6BY3+vzHt4TwqYm>xo3QCs$+;v_5rYrfiOZ+sk?b_eug++ zj=*A_r8bT=4+LBkSCy59bjwZGRm#M>1z_@3Nb76k$Wt-G(?&+gWts1DcNN+yj2cgM zVI)DH;J35#<&RbZW`6~(1R`_JPr>eThzfpGbOaCnp;CerW= z573!RQ=89kheMte>h7V>VEo997wwv%(uyg)4boX{e4Na7bE>34GIO=8@d~F;caNWa zBsvOF${cZ~230b1Z=|;dOQr2o9uzV_UKK~b4{5vKIUZ=fz;1I-CECPekR`D#)_@%J ziZ87|g1r;sGym3;Ua(en*Nm#<*F@k~8aUF6$-0c^KM-mi%5<&oJP<@nK z)J_vH9M}p;f~j<#kvr3&+-4&}=`M_fmvmcYrh=}XIRV^{V{8e}8 z#EUAKSnwE1gEHbUz$Cwr3{y!M?W`c?xbtQWLTz9e@Wn`#X)5%W-x3?l~_xkE&9 zLyd%qalv_3yBdDVw%W{pg(&!{1e)-(i-}2eC<;$M(D=B{5BeHCl`Ts&DT;wI=@Nh` zSyrmDDoZwh>!dMp#l`C{{NnEMT{}n9F3J~akSFUc-yH~vn1o|TDtdLjGl#BWm#|Bf z0%YL@0>KL^k$2stALZ~R$gF2q|9tg0us6UCFU7)O6DsY?>sx`cc;|5hE(nT^3i+8G zq6Jm*9&mP%$Qje2=$Lv2Ao^9hTIZ9JuZLy?j8$j{Yz4Uo=0UT}VBSOwl6=-IRw<#t zi9qy@YB6}?ZDq6s%W-Cqzqr-1t)wR~v{A;>>${7GL%g=OYdJu8;o?k#pYFsoI?I;l z`=aLp5+kD7?MEdos2=M}#N_4-dL<)}PU7q zyTh!mY2=N&Zh!O+h9~OP%mIq+s(kV2C(L(t>|0eulqR`Kz*6Q`rY$4l)mEsyJQ4rX zg?pY%?Cw^Ajce=EZ!?YV5ru2P;jIS40&2BPol9oaE~_N5F=f_8D-I&P=m`_J@?5)L z_vwyF{qBSLF$0k7mNGtpPh9qGjecsTwfp1)YMK3eA&*oOq9AL6f2NYYaTk_;@P5ZG zxuxPF&E#ikCM9$qXgc}|aLm-3|8(D8#Q90~Lm$l5e9$#GI|CRZ`d>NB#5FyL=l5@g zB0yRTcEk_i#BOq`kuLX$)h3NSxrH;-idV%`ckFh9AKeAjt8?TMx4jownSKR%tgmrzE86~0Ip_j^|R%nP1nqZR7!O`*?Dt8qwG zS$bY=4}cD4A&@vTWC;;;v({yQC)^_7+a+t z>oD6r#O0Pk(Na%t3r-dn+Jp}ukk&%J_6Dr}xN*H`w>$DF%xG9co^Og?Xx-Q=5r<1W z29W=o1Wt=Yamw8OhMFyj9Yp5YkB{va*GNR|g5s}(MrDBG6K@m8G#p`nx(ZFq0{I_q z%zn@1%Mcma$T#fz+}vU5XN{!9cKIA)B&j}=&7w`dMs@-CEUQlvq4 z1{5$atF-Bx9|qLd4a>npX}Nk|jl{PpG8N`JsMcCn@F))k@w6c}MnM z)PZeiV2y&a-$Xl%3<*ajUAGdJbGD&;!vpY3T7n{dtNoh{R0b&w`%M>*9nW2fP%e!l zD%@07K6}!BHF$sNW&zR-CS)e504z1MYVIsRrHh|M*T>1gutHYZ@6d#pC4PB+ya?Yr zfOM%1xuCNgHfQF!JrhpU`f+=$GXoS_%Nz7pbYGEEgD}t)iw;TODY$iLYMtXRrORI$ z=94xl=N5#k_~p>l&2tg4$twU_xr>oftrXIQr@t^@)t9i&Ec>yUmgO!PP8#TqA=V67 zve>xv(rsj3-F?I4ZS0#lqTec%@#fSEHbjCHYQz+cl}owOH0Q)Hu%6-^J!(K!&*A=j z^4;@9j565BOvrRbUprUlkw|WsMkT9LuN;^}2{^Zjc-7!(nZa_`ws@uTkNw6%5!&sG z5yzeP)T4j^V-9nadli3{OwKCLq-GwJXN?=^u0&t;2Tw1C*R%dr3$lA^h)W8D70U{2w9^q64F&kNG>HbIPs-P+ z&C8h=)6)lWC(>w}aEt6N|M79a+G=n;?yZ2tP0Sn>f{?y3h7JpuIbO~&D~#Hkj%6=D z4V>i?;rv&Ct7W*ZW`==s3xcQ#Umep}Dkrg9?yJxo=FN;qQ95BD=+$YbHcw)LdSG1m zDfz?Ue;^hoZ7U}Cg_<%tgdxStAQpFzQ;ooBzlhBO6qqv!YHP^Ae^r~W5sUydXsAwbVJo`ty4t_N>~;&Qixrok6MxlZ!Vsavpt2VxkZ7V3V!rM|h}k z4eVCp?N0&ORVyYf$&*b@K|Ew74I3nM!pYpj9Jq`lZcqI4cgDi-hW@DqM1>L5fM}=h zS{=K1vU9`k7} za-QEQ(1*C6927?058N9#%)D*zISQ{`l)c?CcslsW-Y z_j+(Fql&~@7H2Nvc17sbbJ{52P)bwI(QAnpVGSRxD!=SCvzu!aa{gPpOB@4Z3Jmn= zOx&yP$MDo2V_>PX@BdMnBj$Q)@Q}nb)UN+FYsqR69k3pDQ|<51O#k@yFD94-Is88C zthePID=tOjowCTujwX#JMF^?^y~br&7HR=p#9+VX4!E+a#s@F4I>R{>-KII48`d3C zEO*e=*of8HwrGHBKP`KE!i-0M>qL92+oe$H!D8Rsr1&b;YGG;TFd&SVZ!>V><@LC4 zj=yd20i>`jkefj;r~oOX&grl+x${k64{NdL!#m;f%Ewt9|;%(h`?~RnJe7J7Ucp6>>i&ezYqzWl_a_;TVmEO zEay@U=;Kbv@%s0Nq^MPCnd-VFm$xsjTOC}!mn!k5>*OwFl9Zt4zrd`vikKn{t_q^x z^B+I;l>K;1Xu#MnJAsfD-^sG2%5hA7lQW$%Xu8f9E!WXlmep`=)@)`~uv6KOEG!z( z6Iv!^P$Or+VA1Ii>)$#S>z7%;#gU;s%;v7=5vC)=mSuCBh4I6gqyqW~xvuSp4`_rb zPVHDF77EMXZch|EU?FReC#uY>v%RX4bvuePU&a_!S!JMsYv~8S2RZBDE*nG`* z8n^?vDL7jYEb-VZWe>QW?)9Kd$#f4}l`zk+4i{hR#jaMODJ6=`4be@4)2u&jY=W>N z9}9p~6I2f-<`@ji!HidY)i;G}MMe44YFjn_6qfr-f@Ost=wYFQiX`gwZ`$FWu@~7y zgQwcppv|8fURivpH@s6b{|p)2HK0zcq---Gv9s&&&S9JB>3f){ag72I19JMjY6fat zVT|jd1(Mu+iiy0`)zmv;NbQKZsK-*))Nr)Od`@qZ@<7`OXjJLx#cIK!E8+;;9GT7w zb%m#%hd~swVo))$ZR9@_2w}0uxHZpS)Kxkz-w$+QHA@;(B7e5jESt$WqB7$BX6EZpg=~6|r_tYo&%Un)mnTK6ElDNpi4ktU+XD*?d95ZiK;a*dJ0Mq_n3l_IXzomnjNc__UE>oztS$WI%-RLru0~7b-}EWJYL-d!A$$)oL|OvD(8YfVQsS7qWF* znunfS@Oz=D#(v?8jdJZQPTaC5wu(x!nudic=#5lSLO3~t(o-GiNn>-Jf-n<+g4djsHk zzsQgbVME2?m%8%(zac>^!S3$PW3BI2ZKK1?iXa$Oig5jzlomLHH_jn~^ zH`L>Ah+S{Y@0pSXEotYFmv1*1d4`7Uz@Rr&*G|an13 zcrBd#TAsde1#fb1NM*)TzheH`Lfw*25HKdIoa?vwYF_l3dWe(Oh3N8Nnbw1kMg5Cm zx2hMveQ=-l>&8h^ns$Sqrhs9uR4M6SigTqkujR+rFC_2eB=XDSEo)NUn!rcazmP+N zjQc@RE{7KzBI~pFrM)}8DdoGqrFcpyar;RE={)l0_hGGKPTjY4reVT0_>vNBP9+W2 z)}pZNiGTWcUwZQCwm+7ccvI0s9RX7E9y&&^ZueZC3x}_xc0P#F6$_L~*7~#gJs<32 zyA%QsEEU#1llbYS`)dN3i3Y*z2n{}s2E`X^cV^aO^u@N6v0A{&#ax;#6);UFY?PI z(Ck0i1JiQvfq5lBnIYCqf`_<$cT;^+>biXQ=%b40l1g#{A`bX7bhl zn%m1F0hIh`>Mgt&jG5(K!CyZCbyZTONoP(+nQTS5MRrg!kNv@W4HJyjhtDN0w9V3v)tG*3$Sl)#=k zroQ~)uN+gZVc*;n8mtPJrhER$TkGYPmGx9X$YXK-uU?$F|AAhAB)!^e>=2T|?ygw? zDg*+980WmWJMM#&>;_t%8H}z{H#-@K%#j>75D_1xeD)xVZdjH>B{3D(bE(mVqD(qk zVYsiOcSAw+&mDA?VR}yByRJYIBLczRosB#65aN@s@XUmCSS_H@31~6}0Au`$ zkasW9q{Eb_X#|EHnl04SP?JYdilY{BK_3*b-@=(H;dwy9y45r{Ael_h@c?i@|B()T zi%a)p83+L89L*iVai~6{5g9{m-GaOeDS_N#_1~XId!_;{Yn#QL8M`FiG_E8zK2AMG z5pTS2IipfY6m~T{Tu*-+Et?1^Y`hy^=|T-k3?AoF!O*qTu(25R;A!T^wZ8sBD!Qq` z&{^dRJLa-bgPzCZOQb4#TOFSXO(Q*@GD!;F-~?Kx%yWleEYF7V@Ux+Zx}S}oEyfRT z9p>Y2v#Y);8@zlUa9||XH%OtMBs30e!{cEPCcT=xyUf56%MJ7%PP zeha^v=M=odv7Ravyf<#u(A#dYr8i^}t?2ryeF$CuZH^nQw0apC-8;qeJEu?tqaeVW zo+aVwv3OmhIivW0|H;BHzGdDSSyhw5L@9Waq^{Mx64j3@_Fa$$0kTIb^MB9HAl`7R z?z8mEQoN{#KrbWB8X~zHdaB_%uB%_l^@m|MG9q{bc|=(ZH5NVbbRW>_9uoXLbvGbs zB0W~@0HPoi8bKi^p+0VciMr4Su0f~>T~lz4alhchAgwvhLA8>6W`q*8dl3LZN=P3e z>Ho+Ap{oOVU3lcXg}Bs4g9}0YYQ=wmZP~dPLrE{Y9OAikudmf+%W{NtU&=T?xA}AG z0)@EwY5jK8Ld(H6TWx^S>IqQ7qb)8_yO+k6=%g2EM&~0K?7y2V!Q4GfNRm#H7PRDTxrEUy_-? zPv!5XSZ@WXx=b~BB|50NNPvZjJn$b?xrZHLOrTd+*Ef_cg-cYb3|cxR99+R@Ain-7 zj;kMk$wmDRTtw7ohm5)czt1&}SK5)TlTGeoJLQIv+U0z6$)ip?v^!Ny( zcV1g&i}hZDoM|A?*$&qm+?U$nW$&oj=F6%Y`-Mv#q5|!Z3YIZNjhHX-Auk-bQaknj zwxi%jyp0`B(H*Kg)L#4=9;-D66afvR;7(M8J5zsIc0$r#t`g4>;1u1c`YPhV*7c@8 z4#%VC6T~qESwj~U6ygoEh8SKqgDo4LwB%?;u(Moi9is;jAJSk$^Awb1<)Za@kaT9B zsC@Rx&}FJ2^aFMKJVzb7LXdzWLpOvH+$~02B5<&06Hk-E*ij=A2u0L_f}qNKE_DgEKW$@bEzBHXqD5H2^lO$H|SSgC5VoUpe^WChX3L1`KUQh4cm!s7> z+sH~@Ne|o3jv?7ZxUnQ<2%7Jp*$!IcVq~sj}T__;vUPQI?C96G@#9i zNk-mpIVy;Jr2U!7gX7~c3mF~d5*2ePQ+<~rfTbeij%c*=eXVC`-L|w~?50ZF1>028 zAcN(d_;d;nTO1n*M;KTb0B@mUmnzrbc6A40myC5&Qql{k(Me~%Y@0(}Pa$H}a*eqYg0y7IWP@W7C zZ{m<_xoleh%EkSV14U~bzbx4LXM(x z)yKO0ZCzl#9N$ImM;&H!tuXi4!u13)uH3Wvewt0Yj{`S@H^%Rsbxn+_*b8LKWgNjk z15_R&?sN5OR^*;wmr2b3&d=@=^Aoi4;NX3z+txt&Cz>2X-O}sT|>QGGE*CM zFOPQtlZxYON!@7Y|LhDba4?)^c0yq2Y~ZzKD-*zdg_bJg41tAv{fiJV%d z?O@5BPde;tUUOA;-5Lzx|HsjJhqJxEeLVIoVzfy`ghXvMT0-p^qgKsUTbs5vwQ9s3 zjSO3=uk#hvH+b;zVhN<(|) zt5rjN7q<}aJ^cHMF(x*1_1=dyz3OA4k|cTPtg`PCF9BJm0X*dZRD{(6=;*6@U3(d4 zMO`HFP1<)n1M)#COWryOUS4wOK&-CSNrN(8^mmA&!B)G7~<=yV2Gr*8e6j z+9k%|Vts+_RM4aUKxsdCBw+Z|r2Jo3VEde1px7>oI` z;|Dqq^9|zs;+H6msPcaD+%Hr;h!t2-h583Og_pfz;O9jg@iA$ z&Yjb3@5tZrykdPL(yGAvSG9QK)P?@0wbRpj%wGIu0oe_U%McuqikOK0Ma;N1SI;v# z;J4?W*Q{#&rJ}5?Z5Vc?RIu|_oJZr_mdg&pO$H#$NO9;c1I#x!*$;_&D=q0V&F6F^ zD~h4?PVffK;DTlJ;IK08{SWNCMqp;eZ@^VTw-a&(j6742x1}~HL|r8Q;$Rl3T^a@4<86;+w&Y;X0V^+*hn6R-VvNA^ox&fbaxUOCvYzi^Ba2n84$ zSJKb%(k+I5Nmc}puL_Xq(s@mC2B1!SWOG|f<<;4o72cF_^(g*rC-L8<2Q3oEneH3(K?n+9O%`3|gw*N2H5|X$4OOL|afsm#13{@yHoBfB>oBzj zQg{6k%VZvss}7Cg4gxL7?~PHTf{};>tGkTjq$une>VmY_Dbx&=@0UMSV$iQVi>8iM zH=Fcg!oED#@!WAd=oj zPup8O-7WS>1G%``=Ywh?cBC9mbJ8lCuFX!+r7O{ONA{=D^u=en;U~u8NIKY zL09edf^UHcSLHJ-(!VpkkW+&3Mr+VAS z&mlo?gon8@h_@U7ua~rq3isIhX^YDzp)R`{C@(THR~N8QolX_csP7q%y%q|D$o2`h zUU=>bm?{aN=TPnh0NDf3w0M5BRXe2)*RoYswOBg7?28=xFiN;uD`a@B_JYC$W?Lmn zq~m^Pu+I`A%FGt_AL!8QJ~6wtTP>wd6OY%XiBJZ0z%)Hu?8PeSMBHBrHFSVq-%h z-c@Oon5`zt%YE9{I=63RG$UEHO6_?A6{KmBUVb>)^$3C6LL?yy9yItCKRh4!D z%jTH$_?cB3`bI>v?OAW|vsCPnI?X_;cDDI(Ypa|2;^H{SL()iz{naz!Q9Yb{o|%PqwGFM5jglMS3ozLQGP zhhl^-_wCI6u?B}7tsuJ>a{QH)1<>b;xvT^5Ck5wa>PG&ugRQvi;u~Po06Zj*?jrZS zQsG;w$nEBw3dYcqNwSaN0MN8J@!rhLy)_nT2DNc>YieaglRcIXF8nlu5e(|&oZb>A z1b-7<9<}5_Ke?0-t@weYq%E=wMQMq3dy8fgP7^t?^njFdpi`?g_O%DXZY5;_bG;5_3RrHDVGKe*E(xtyXMzu0^;CuM5>)~0m?0|+>A=A3bX+SUsg5>_QsgysmgkP^ zgz}(QdA{qK4EARG+tvjHVFU`r7!scFet?{=H%31oEuY+rMrFzafgVpj`YY)VooCkz zQm*cy z@M<-_riXtMvl}$f%GNwu=@Aq_|~sI zarVg(+$a@x)6D_ZH{e#xu>&7r9-7kd-n1xdti>NoydL^Y&z=~M!Xe?R55 z1IMu;9XuEpwSWPZG|||nklj{YL2;B`sa>+cdaR|s^YhIEQ$ZES@{?82FMOP8wEG)P~-AF*vlKd)E;)8aVw zk*c$mlZys~css=DYP>kn!nWmXlt}A6ilJ`uiQ{{n24b|ikv~y^NZV!N!0W$h21L#m z1V?Yt&q(g;SG^8FvgxtnWv>hw-UmqSpJ)58mRY!>c&` z&!XgL8oq311KhBawU0Rw{3%N6486jNRzk_W`lb91W8p-ybj8fXu790&5ewnPvHltV zJ!rZ9)mbgwD?lMED#MAj!))$?(x_iWNv=M0Y6_klgG-BdcQ)Vqd{bwa6m_nuY^1Iu z>{0CMa2DSsaJ*x^t5nYstIB=2w-R2XV7_ptHC0%^_11(|Qq-FWfnxL$s$?%l#bHE2 z^|AE%GEH%WKYw*`+EJ+qzhYu|b-EkT_h2G6x8j7c&GNey7=OgC0@X zhsY;b3czm8FaOXVm#$@xoUZdQXQ_UIcECn|+o8drcuzKH{}=yRHxxqJy~whu#j}~r z?CP=F4J>iwQN-yba{arF;is1VOc*j}tlWg9ImVMn7kPjP#XPkp@^G|+&)nKt^NmBt z;XKu*&;XGC$_@7*y7NgqyER=jDINUHnQ;{2)EgG6LLJd-G-_m%FQGLcM#Ap%c`atd zS~!|YvgHZpc_RXq(4Ybo-uQ;eTkaeQZ>VuWQnQIvJD~OS$U-32~?Y3th>d$?VjR)nnd2%OTOgu!~)lo@wo+2ZK%rK0}d}1z3tT| zLEQCEhw++69~?<U?ta)FIbzsd~qLr^gTLJ zxf!1|3h!G9J2DTpst;OGI&ues*G@JP-)w;^YdJnWVFr;Fz7`K$fu#w`zA4|cwHM0! zSC}A-H`#eQXVv<}u_emBE2IfDX8>k=38ot>W>qsB!%WBAw?vVvz_={Ca?h2XZi25} zH(48=r|iZ0v$T-NcUyfe@CFpYW$C^`?gzx%el12_MuJ~t8Xh)R(yHauK1%+b%gU?7 z9k_I--AvNfv=Ul4AG0tM2zw)2dlCBCCN+lIvZBpKw5Z2YoDb#xz&i$J%du7*Iq>i8w^akK z%~0fRx-t*YYQ8JC%BAtXia!gru=DykBgI-uF5N@3*fBh2q5S|A;A~CBDJ~(ijk8T@ z+P(&G`GT4vn%3juqzux_(aNpc99^I5JXnlymwq-!8aBJBf0(VRUG}?!>+j`@6^Eo9 zU;)1|HL{HjmEohqC!PhP6NsGvbDOkzsk8-dV0HUqe)VdT^tvp$6N|Q(qayc7yNX!W z++=tRLsp`wbc_W&w0fz%UY-!?y~M&g?-%JCI)-hMcJ~}aaJ^-In&y9=_&4Fj8C9PF zQFOf|21LLPA?4$db(j(Bv4v);k+3TfrAKiz8>uyPWjjv9qLdidy!b)64qi|B4f7IL zb%#2rG}KAc7jfLu#|#NK+9u=Ed~onvbJ;ZG_a*MooP^m4eQ~E7r2>?qcL@uCfq32U z@8r$RiUugq4(}H1Qq))qslCWee)U|&jrsaRaX>V)*F5J^{52)8)vvh!A*bAqV{q{u z>%&Y(TA$7o<~B~)>BgJV)=m68-{aV1f#*K-{oz(rxz=%iuI;YBQryJd);XUEtQ8>j zGK&FbZ1SSh2$~A0H+#Je;N!WeeXL&3Op`LPv_BvGB$mF{J7O(g#8&T#0n#>mR#%Qa z4gt%*;>$9mpgUfNmD)dh?(IlQrFrg(^u;84Uq=V7yyhJ<3MKXTFV;Z%h}A^_$!HJ> z=vu;K`rqa7d2byJC~vK%p!NoIZ=Hw#D7RsCk`cZepR`XKcudJD(nBE<(gZBdgP@!I zjP>K-3K2@L7Q*FyAFC?Zg{A0-%+=m^`QjLa7hUv-)B(hf@MckiW1;S8?T#ga_3q`wxBPC0#Y31+U@&AE# zhi$Oo`@rSYRoRx}av|&G+OtvIMp5L#Us=|p7$KBlLzVNijTNV4Sc`v10zehspQk(GoKb%~S ziufEGN98=6>Nv;jH*>xn>>cGb-K|a^ItS#%3$4 z{ZTT#ZSy@yqPzsf!?P1u9_qAzz1y93|&}0T=wdusIxQ#dT8Gb4PR!xT)j_Xs$EMsa=U@6ojw#FW zzTN}m8@&qgyTz~)@6}_pmd@;|&1$+#4yQoih@zK5%r`^!{%O$P4Zo12vsW#~IIfO; zWh24zdED*i&}`DoJP8DG0mnk#D!73*fZ~ zE1lacyi0+o^0TdL`)=v6ooO*|_~d{!<-(x~+}Oe>*k14Xu2Ke)S;M8l|Gs*DZQlFf zq83oc8vHY6EdTE|TTOm}g?;l}&JMhYdB;K#xG5y2`p2?-ug5z25_J)}cT^tn^F|#U zOrZS@$TlB}vb`3~r-jjC9Td&G@nPX1f$Oj8+4fD-D(n*8nJ^_-+?$r8RaP1dqcgBl z5T;s~3UqNI-kP7&g+icryV6cq{2CcG;hw3l@0&Q`+Vs`;g_zD0;VgeH=fc7k7;yfY z0%}~W+wQ~u`(`;ZtBK{Pt2ULBnAPw4f47wz5B`OemU8Vl(OHUv_CxmwfyDkXblLEgDOb?a7aPP;3r z=K1>LIpw-*q2PDFcKggNi&|BzxoE8B)=eIs#{XMM7*mt1Nkdb{}5^u&*u zHxWi|9|tIcw-#~A{o{I%3@SN?a*}p11o;*6Ukq~`%f6#ZFJAjFEay<1K71-V+W5Nh zjpb{LAHMBRTLVP=uYagLy{%?qqVJct2mj*tgK@f(?avBjj~9lne-nSB4cRaip4Z-% zb^g{$tl_yx-!&hv>DQ0XdW;TFiW@#fc9%1A{%HNQAY!p}^iiWRu&P|58rs-Dw4>t| z)zJYvJU2v=C7`S-=p}#N{aUA7q3Zw^&X1=~p{ld@{8Pu|LbqQvZ9;Op{}R8?m7RZS z;0vZLV4nB!-ga|PpN$TkT;8 z7vl@T#K$sR;v$7G7heVnx=7lPgE0-nf1vS;_nnKs@=B+&3Wr*4-U;5jOjT~YOBnMs zDkyuZayaxnpv6$=uc+sntzUa}9T|-D4L^yE_Y-nuBVu_KUw_-!l806&w8t~j%}&lX zj3m{+YtJrQX}-ka^hRnHKe$MMU*gf41VtzgN9&gpl0eQ|wX37!XM6$e%`Pz|Em zr+)aaPv@THi+@b!Ka9P6((qa&E#o)moygp^NA3x(N?L$6aq1Cxo^ zC+J0T>z@meSvN|dkn*_(iVh1_yPF>ycrBi`7nIkOrav+NiTPPo1J*hvm`Dt#C67-s zNLzh*1aZE|@Rex*V2=_W|`HTEoy28@EnG3*Kc<+ASJ^5imw&LBtSt1()Ts8<+Pr_O@ z#L`}$D{L>kJ)$jWGObS2y(~SlacNmd)?8BU%%JKpr&ENzewQtEq%?gj#^G>rUFj}g z(;N57$XKOJ>-^OiPxr*v-`hP3WQ}>@n#PAl_SGa=L;QDh^SLM2de1S$GVz_x3wVnd zrj1EiR{tB?vR$OKbl}c6QuU@9?|ZKP(Paj|#F?75s(V}^*YE!of93NfjC=A1_qWTL zhIw7$gnb_%|4_lSYCK1*ggcQVjwqE2I2oQw7U=q2B$o_4Ihuw@Sm z?liksv>+0{mv_y129z`DBc3Vhf0_?oJe{Q174O|TkIq98{Rzt9V*)#IDX?MMBjZ)s zD(aJMZb$j0icZ*>{KkcVpD~lO3rW|{eh89*$O3gYUr_BTcaSE2&@-rt1@!Zb-!pgi zu>!-^Nc?#%OAcGXW|7+=aGwB*b#O%9L<3^zO&oO{z=k<|0MykkYQ1aNzUn#*^%oQ^ z@x*~{0$2j6lZ|zM9Y-brEgjbL$9^o@bXj_@7v@eu$dVek`W*bw)xjTSywzIFTzM*x zjnxQo08nM$&_Yzxb45pz$($^@%vJ=S3KbrCjRoeWkL+AhQuEti4H5xP!HWZYCO-{l zb%A}#4N=}l6Ruz1ehRbpK5uvPd+L7wL_Lj66nzt&32K~x{gvx`ymWbp<&%<4sauHu z$F4c2zPsle;TlQ`lV8EV*I9VO=fGWT%10VpK6z8$Ov6C6gv)DGF#o&Mn;dQ8Y`@Lz zGA3qaTj4_7bsXIsK?BE^@&JQz%iKl>*I~!3_HXXX@1xs(@M%jH9p;2Bh<}-V(p=1d za#96D4fOvUsS162La)>w;z37<7{e-*gdm{S?e}z3{lndIxKzFuv`OnO5R^oU=Mq+F z)jP9FoEP=3HH1X;E^JmG^33ij1y5=vX@>EpZkgf_vmnlao;Pz!2I?3i-j)+{IXKF;kw!_%XiOIqL`nW;xp}4&a<2c>wep z=@CRjup+taA5x?wJgbY#MkX*rA>Tmhk}G~0QrD{)pNn3iy$HLy??Vz@+Pavq#jQxbwk6xya3aXmyBJ<2rC>ptHw9ooSM`tVoDT;mj6N%}B1!%G!S*?v&9Rol zKEiQUC}5QnYrmFq5%oQKtx{1R=Eg{rJk=($`|h`? z30|!DRgT3WhjdWQTIyRAo)4#tiD5>aSMlpc^qtS4SY3aS;yN@pbS7B~GDwuCzV61S z@z>s3EL7hFDgSG3{~G=-9dbAT%L8WDhm{ix$giQ5Y$T-II$t9sa(7VLP#>-~+J}$6 zue<{$eN-syZ^a9wLF(8)-~DvLvE%>;Tpj$MQLK(OPI}Sa8GQRliG)}f6=LZkmQ{Z} zSzLAKZe_JxoSy|B4{zLSBCy$#Su2}O}IXU`b=Zt=C(E)o)073tq=D3eN%jg3;yE=_cW1yS& zQqWo%g_IDj{Yv3rhl{T)CsjmxNDhl~HxC=n1XT$CtQO&A)%jl#F#{KhqFzHq$I!ig zVBH~P#2|OtlKL>dW46F|^QOc5A~d&h-&!HeE8;dAe`WB?iq^?KL2pl6fr$t09|NyG zTf__O8jDgPMvu;B6ZkO{B6|)9iVk`CtIt#dw=K9KUJd%{TMi6ua-HVfa^PGBZ8BC; zzVAN}XA{0sPUao`!R_Ad4*!Sci|^{31^mzT`bJdBuk%jU)f&FFn$m$)E0s2fx9Wuk z9PNw$P=tle0e@0zF#fyl3YMLj z>7^6VebY3A73lbe0ig-gT1p*h3=`kAk=DX}ezQDpKV}Bu|3D*OT@0yeu2uW;@b4K;bZ1hvKJn9UZOt)QXeqOF%uxRa z`UO{BU{CB~OhAgnfws{;^HQ+*nYxqN(e}o*cGNJ862u$%p?7i0lrVkfV3SS}sq2CHpN-eEit|1Ha-)-MCmOjT}D%bpd+EUWHPA_m* zeTJ-#6_7c#PK&4b4hDJlkGR2-INTXk$xcT784)ln6v(X3% ztN#gb{*1lhQ=>xA^t>4{N1DS}Cv8}Hy+<|UW^OWT^6aw>7i)%2p9-vM;J_4dr&JymRKBFpQ;D4r*C?HWBJ?Lg( ziXWE53J*X|{{z*oM?NKnj%#OM3HFJ_P{vR5R3SxH*o!)Ve7tB)!smh*=q&yl2|808 zW^>Ay{h3wMwE@t*UC(I%^>Dk+&-EmST82nM>(uf z=h?wT3dR^px$KWr0My`dQXiV@1nJ~Y72)xBv^^H9&zvM``=e%YT!!OMjVRPMS_`*d zDDMwC*xr&(6K$}U?_?K7_~OXC7Xy~EnOy(YyUlk06PP2K>MW+Dkv`2mqBGj3B(XuM zz<-j$kJS^o>AvM(Gi)cv`&%p|H<^2t=HRwxvI&BUx$ME%^CRG!ViYk^s&x@6Fems~ zV_VweDXCZ5Dk5p-Y_CsKUO4m?fN4PZrVC{mTMFY6WCJ^P>6Gq+2VXr)soPEBJHomd zsEgL`f<(}sSGhSp@&+bhMcM(wZ8$e*l=elQ$h3&}S{_m5MH%9jeq+YU>DLyMCos_pTB%U2^=lua##a? zLN~U`miVA-{cyE3n!2c@_H+s+9J4pxcf5wfs#Wx-3ANMLM2G_gCM^|5gY3K}7f@he zqA?pbIlJYQQetN*pg@(Tb3a{nh2p(Qt|P9<_tkn01&KRId8+ep2XYxgs8cKWude~; z$&qsZ8sq+I?Rh1%7BvbeB-ps0(K_3fXxwO7fs)}-L-eh3EB`7~SYeMU>z&aT_Ii9K z$rRU@YsK6z-eQGH(-@M~X$8_{{huzDu5!Os$YoI;q)>vq#9tKXn?#u))71ZlWfy|j zb!WLO?4t1WbbW#)PgCUoNzl=L_=m@0MSVS>K%I9k%hC7XpaJ*?6eFhuUq~Zu8rOTD z+Bs!J`b2ZBu(lb^0a+-#p8QF9fsZ!OXLEV?zdBX6b2AwFgeEPC6(}_LBW6&Ria)2a!65=L znQpvS6@Di!W*j;ss$J3W`D29uo^BPS5}sQivBMeBR-x(FJO^fPJYuJ4P0FpvKc zREX8V5B3-+>4jOrGVEZk`#g!|PrT-{NX~STl7W5lbd_35T%n|t8PP;6=jE3SvdELU zjfnKaHlHGSUO}pSzmC_BWObx{aBYN)G{bRPn(BJPH4cK+c02{oI@VXn`JMB7l<5D z_2yRK%?BVpGlRKu1A7;&Jlg2>lI=mh!WdApmOAvfLhP|vF3akO?)9agU0=O>ey(ML z?x)b#2DI*PqZ*AV{xvdi2+pIx0O7Zctm$ID9kzE7-&BQ}wlh4AY~@u17m|wp0|^1g zsb{WpgF29fXjI9GOy$kjX(Tc|x3kJw7Y>9uRSr%X2jSEoP5PPeqw2rGe|5XqzaOLp z(nDkwMRMgxPKw%NH*u=Mb3I$!7@*T6_$&pRR6J-T5U1A|gTZ`Cleteq*&o04Gfk%n zl}bbPk5en|SVMIbZ6kFcedl`8H%yFMp=C47#sy$rjOTnJTyBthB~Oz8Tg|LpH|SkY zea<2pEl@JQ7_mA;!QYOMSxfJuLqEoNciG2;>eU&C96{QJF(Y2%%G3T2pnH708RaN{T`3S|lL%rexzYFqV&>Tv)56xEB3lxqzf#J?JIEg4w7F(SCKB!WS28EzQ zKa<_{0;a_*>F?tFo|o#{@iWxo#_|!=3C)bn`#R{e^-dF#>(}_u>Iq)X==#a-h9 z_!H`Ipd!H5W;?ecC7djE`~6V-%&iATrRcru(~Sx6dUCK^O)JZ#Oy7ulvuK_{-4Zy5 z3_G+a`k?tnb%@P0(b_oJXNA^kbb)Se>9C{l#=k`W;6Nf|@)TxQtFp%c_X%-P;#cF0 zmu=CYn)F66GbVk2kL4NrZffiF9k09n5W?=Hb%01VA7%bAgUP9$XyJX*u0icf%uZ?p8X6mIa`X_Z3}=#Zoa5k<~Ne{L2n35oX|X zHDq49)`E!E5Ic5yp`~B^f4)VEQ>w$$B|rbnXyfRQeegeqMh~Z+$oG$ce6KFyv8T0> zEvvj)%r6Po%x=UObt+9(v5~bANsMyH5%0~CUm3}?q`i@UoR8DEy|iWfyUz)V*W|L# z3>`w-1^gg75KQ_(m@`{s*@UuAA6zy>9Rb8DUyvVTT)wR9mt4%kzJw}-h$PIqswxeae_H zZkAwT{`~oF-k4Sw9zQEgtKYk({l>ui4FQA1UGpX|V7Qn#LcVpeSKgDmNf#OGnRPFJCa@)UkE!Ko0QIZGJj|HSo<->*y}q9Qjs=jms+XEV30I+TM9Ti&&^)sN(#rwBnb);^We&{#8rscF6?_m-ub%s88%D zjn=#E!id9}{xt?XU7yipsS>-~d+e-c^mZ>&i{{o+I-;^m5t&F&#o7`8 z6J}Z>$d76-J`~E;&?+7M#d&>Xv&Wx%&`%6YQ<0|wk#`iNxZ{j7`^VA3_uN*qG%LCMrJVa;+vuLe|v> zYSI}=X+#Y9WgX#V{ydWT_rChB4A5t;*;TLaqjVEkMaEcDYrg;2rZ=?L=08v(=UOZX z#|u#jE7<&tLJfwLij$0_Frdr!P?)ys2-JI^5JrMF&j87>sR^{J@CShlpGqBZop;`A=k4 zbJd`yQ`*SqFPnJsgh6sZe7+vLjkH3bt}p+Krx2FR#n<_ z`R(0~K0NSog9+Kh>%N@IBu~()T3z_wS?+mas4aE8(eEy_Rl+h@EZd{$KY!|J5UEJn z{s-q$J}$rj(ck>o5EEgX6ze|#L8bJQsR$|_fXZ&I(xg#ShbHvCr_n@Ut{~AJ^4iBo zB|Im@Z(*W%g~6;3^|HG4N&v6L%p#rKB9B_@NAorr0*&Q|M~XMvs)jx}c=g%0xGndT z$#<>AjGn(nnmIB3qxQ)>NN9Y59_-~chjFqap0v03{ZMBnFj@Mhv&2xGh&sV>8tp9FAx`d7geSuz?wh%J$A9m}y?L@=S`WAC z&yycm+nyZ0KV=#&z{RQj?-aYjR+pQqb-=)mb(DmpnfHbFn9_BE^aI6XJ%4ursDG@J z04!P4O+~^4(Qk1kSl(&6Rh)a@8&!q2C*mkk-Sv2V?e1%AZgDG2s2hXgG$YkM?NSp$ zpfRVHO=zp>|3KM0blMaD6Sj0Tr9RQA>zLz3Ki5;W{^7L`_z6f8vrpVbt%O&MBdBSf znye%}mNiHEPmTl$j+$hU28r6N#_1?g5U9DQ_-=Wb*Ac~RYy28@(7~kTOYH`^Lhfc# zy7+*^_He9Xe3Q21qX}DD&?vGDCg|fvET?W;U-lUsF~;H)i`qK{d+AImtI)nqAw9h} zZ^rAz&=@scYGy-Bd#-=N4#~Nu%Us-C=~i9PP<50EvJODzkDj#(_V=(aJktAzo#qp|!E zaG70^B%FsA%pzgT>E@NC8FsZp{F0yX zYz3Jkq>JN|YI8%2)Ay2n2~7sckW4)r-`lv@dBzqR|ICCl5JA}|I80rm5@7@pa1h_9 zcGBtEcK8(gA1Dt&Xfh-fYXGOrae3FV1%sFB?H`$W!i$&Q7-<&q|5zj;r<`U>?*}0T zX|<_fa>Q=5TgYJ(OG5X95`$C1axr~fFP#`P!#h?!%pZ4sMQ2(}&x}=c7t%T+o|{M$ zv*uD4hqVJidF?!CVNQeWDXW&}nj$=Na-wfSN5=3WOW?gR#x}OppEC7S#B2xGlyUeJ z<~jTzFONBVu40zcX#E|}+v@ULQ|74={IMoc+sDnPeP|^^E;)WSVUkT;{Ee#HbtBfa zyuNUHm3GY{VdmAWllYM{xd#f%z75+fR(rTW$fow8`NCF8kgb*IHjCO~r~&y1%=?qn zXX8aSScO%=LTTabZ`^Kn;mMM?tvo_@h#|(2;ORc>wiy_`+qX{J5d~W>aeS5jf z@j%CB9lUZ^Ili;bzd__@X5w3RJd!Tm4tQXZz89{yiEiGxEdZG7ye`2fNPss{DNb@wO`rbzjJg3)gbl?n+$xJ7Pzhs$+yP zYI0a^N)1tZ?)6$M zhpk+~!^3j_{{HakcV!e@BupvgVJ6MpzE-wLG0ybkm+&5mx2mn4nXcgFr`h z@B6d`A+5fG<{(kmvVRP%^(pO?y{wok)*w6zuXt{aZhUCI`%BT5W-!enen%*?!wwhe zeXN84Q-T#`bav#Oj#w+XqNBo3ofWT3>;bJPa9@5e@NY81A|Pro{pR4CT&;@&I>dDH zeLM<;&u1)}r1(q}@aQ*FZ0>l$$q_Xm4+9#pY^ElElA?komsL-da@ONYN3G4n3lr#>HfA~RQ+DhB1A8I~RuO8ge3(2Dz(J{;{w9e97PWyG^ zHm236m{Xal@)GByA0GC$-sVF|X3sP2X`kzNG0*>2-R{T0 zZq1hZf@^N}?4~sXKsK*syKuR_&tg z1N7~n-6zLNXkCg43d8l~oZ7(bSRDc^^Lq1VII@rdA;&zjrH7auV%r}b+ICp;B&xJy z-tftO5vyD*_Do^4m4~4E1MO9O@d_`EW&;1PnX)!i82`G{NXAC3=OK(MbTcsDl= zIH;?V{*gfHKAAOAp$?%MqyD|hp}xxUE5nsxv(eJ~O0CW3R@%m>Q1D$Pi=liza2K7^ zjo+~v5%j#&xjw8Ifvq-nEo6Mx@DQ7S5=q*;>!PP75ay-QuAiFFfH6xK{}XAZd+#sa zmQ+5*y8br9Kt?*k1&YL-su0{Fj%KcF-1qODq3`j+z6n~x=T&n0y?LwseU)n0IwHll zEueRs%$SeE(<2Lnsli)`TAEq{RedcOoxUY>Qc5jiJ09p`564B$o5~^g(hx#w;s2#Jz;vv6AxA>-Dq;z6S#q=vuEhWQfX&S*!z*5{0Sw+>IzuWcA-q+M2P>@|D6OF| znXp&=f5l+-27y-B^dT`C+H5C^Q@q<0bUEq1_{iRN#k()B-GE&Y(OZ0PKUNi2YGi3k z%byc1pvpa%vOSj*a+qlMYKqn?3Cf8dKFH0|)!c8J-OFRlE;$xS zPbCfwx3~%S(?yZ5Hx$H?$vSAu2dT->$yz5jsB|V2#%xROGt^V#?5GRUOGbunmG`0^ zXw#MJK$da{$_kDxC4ZV`Df#;lM^DDmp4h46@7PMy`j`=}9~968@#WZ|0v|Ilx(ANY zyMNgNj$%O@{O#rk07I02u}W57)D36r4fS3E`m363x#jiHcUG~+$qY1H$+q)J$st(f z`9tCdlzTzA)EH+p0el{z&+KMG<_&Lph-ocooX)|Zj?_ljT|1b1|6x78v4_u+-%Rem zgZo^s_zE$soXH(@r9p=UoP=Ik^pryo-gHx|?}nS;$CeP0)pk?3K0K$CX+y4euWC!j z=OWr65OOTht4!+?q$G_3w+Onf&`ohO8+`bZYHLuJzV{#Ki{HjwJmlKibgAZt-vCq6 ze*N_}w&h?{ZJvXuTU)H$ld_F~>D>eGg z4`DU(m6q(}H?FS#&;V}oL|oFWfXDfy#iJf*>!O)9J6rU%2b*cWwqaCwP``f&PPwVH zq;5Yqimz813maxJLiXtj9NPi4&>DK?)7AQUcZz1la1Y;cdeRI2Z!O2mlh;o?NB%B) zz^8pc$ZI#u3W2`Y9mEbpy9LX36p2xt{(u+o^(ttvhgt`xB}%Mdj9)|#%w;9+vg)P4 ztGXNquGFsPjF*X(yVgeAYdq4gRObgrWi*p9ltAIAoGRM2DI`2I^jw!kUbjCj_kPHi zx2?W1AIjKoE?N_)klV*V=d^#J#Ci@5l}g!IqnYEY51b9b9S-!-OOqhkZf7@c$G&!h ztQh$(g)u-NyuZgamH)pL51ss_IYW`A(aP&LhA?Rd6H>@3z}xSqUS&?Ck*oe2C==!g zZp;wmFUaJQDd~Ny<01MRdIhn+rePuPxD(H50xg`|&4#c`xc zM87#ZHJKpB{zzOhuus*w4VvSga=Kg!=&x&}r#@x$?xZT+dJjqBmLmB}nQT3+xotK5 zhD^GZ=6E`ycDj-B;lGLB{4`$r%&HtS?ESL01f!6bjsWlX$E2nHnk~h%`klilJu3Zl z36o6h7it?Wx9jb_?+b$BG$P>DvFr)QnT>KLm{sS1nHsQ!EzoE{beWUc@5l~6x3!i! zwFWo-A=ZL8PI%!mEXAjE+gvR9>YBFJ1}k>&qpoukINqLpmsIZgM9u-0r1P zX$Twz$okk1cogyaF{jfZb{-;Zm+DQ%1p%G^W9{v`eB#lji7jS~D}s?vE)D=58m2M8 z!j}60lFu0A)Y(VsrUjm;1p3vJa@&Ch%<_+rk7)BqY2< z3v>wj&o-DE=1uo9<-Ll4ktuLTT-efP03BX&@Y$I(Zi_sYuHPO2S20J*1p?yq8G)5n zM>BKHG)DqRhSTMltSDTm=qNla;S0iBr>wft+Ihuk1*P+M(Hk#ID+m69JkSY66S z71`@mkY!-6m_FLg7DAvS7iVbtX)GXvvqNvOE3!n`^!&^(Iz#2bLO-*|eU=Mbakg}= zz(0ROXbLNJXLu-hW|S3; z@$891#Cr2uW16gIju*e*4~(4$*G^QS<-)WLU-6OG4bxRm*_BJt11hJ&$(1Kp3;=WU zth3h*b@%A^-!2w}r$iiUhf3eD#+qgd+&4+AuXWZn4}{@YbCfoZMoDHyH@3s@v!Q_7N>-s5A=wQ_j9el|O_rGzKkXS(AV~MBayy9Iv z>pauIJTMRy%nx%Cw*Hv5u6P=Z2|cg)qcUL~Y;|W%$unz(PWsj`?I7nBnaw}801G5G zeLnc4OZ?r|8%+x;yXCq!1S5COusrOpPlkz5EJkC3N{iP;~yLe?yPfsi+bSQQD z_m!@uEmp*kOJ>0Hf@%PUg}h;#Cb*e_RzLs#H|70=|BTgAQbm#CC41{u$@?i6_;iD? z!ic!p3b7VLq39|`X|ed(urkNg`vdVfSDQ1JmLn>NAl33LSara|!r~sIP}4S}V+yiM zt7|u6?S-N$Z+7tJdkps8X5=NYMXh2H^DC#N#dI$(7zx}jMhPZ13>Yn_dI%Vo(SiPV z03g!(4Ycap1z7!o5bd09S2*k}do6hB$Hn2a_dY_g_Fno&SYV0xg$yH!$@1^2I^-;3 z%`6n9KzJ6PmEWiElQZgJLd4n8LCVpNEs#6}@`VEu(j}jnO{gpH-9#q3!6S_iS~19~`I^ygVWieXW<}ML&vpsP6oR*q{5=84SbqLD zJ52{<4dq|L??~S|b^1Vp#?Arm=ZY#t>+vC*2?>c%rk*j>ioP!6;&OCoI@0*+8}2YC zpoPUKWXxu+GZ)q0Oy3b0g$x;E4AOVfA4niZm)puYfJ{!3ATCsq765gp`qgdj%Hw&- zm!i7$86SH6kibNiM)=y1`iK#AJw@zJr{xp0R*bdPW##aE`x(8FX>JNlhr+n#s`Qe(2iVpk%GUL^5=rqp9CD&oW)nNRrM6TxwxlBh8$!a%oGaN-JSu<7Hx?BOJ-l z5v=S$AdG&qb8wU4ciH(dsFtbk(>#rgqAzNX zArbUNHxq4r1|Y_n?lHX2A6PhfWcvmQMj9auv9B14iXzz(qgh1CrjueU)lcBVxgF2Z zGMVB=G@`Zui@mW%oAxFc@m^^x9<+oq(ykJkU?KUk6s365@X7Axpx+WEtlj+}p=Eg^ zPM%g&k{C^Eb3|{pB3gG5@!vB&&1($vEvnsPC-*TRt|hPgk?`DvaYGKhCrZ?|-~0?c zj`f*pvGviOMC2mZE(}vS)MF&!*MUCUT!3^`0rt%C98S(PAP> zHGIp2#j?`WR-(f#j@dlEIZsj9uG#l?s|rL8%0G~rDcV!-n|$;#j7$>K{;3LHNu$B+ zPSCh9UbXZrK+ojB-4HiUgw2Ra_#q8G;V8WqhhiVbYpZL-ST>xTx8`_zt8kFtW1&d1*DMK6 z`nAJi0fB;|m>YXXxvGHNo+}or>L1=s_X2 zF?O*p@z*)F=G%N|>~=7+q?&B?-m|XQB0lXaxAJE>x1gfc3N;tPaQA?lTp{lFIOEG` zHNM`fLGSyuzM=>D4&JM;iue;4X|q`#t)+2rKxrkkR2tZy@d-y9k7lQ>Ve=_FMmh4N zNvT)F6TQadAslP~eWrO=-=bE&@JFaiK5K2@qYn}DV6}J+z@A9#pZU|EJ&>TBbjOJA z70nWEBxFEo)Z+Gw1cQb1`Y}a$Q6-t@YAT=>_Z^XzRk|Z;-6MvCjbzV&yM{c8s<)b^ zGcpG0A#{-d%Xu6msjzqblPHRl5!}tVmq*~YB;7;5*(`q8cu4JDVtfFrS|B1-i)b8k z?l+LrGcN2wpm_bA=xECGSJa-3P9JQ*#nyqIyep}z zh|dT=yePrniMntBNu?#|<08pMJSZM_(U@9_*3Qd6-G2}Ve9!3x1$_NJ^Y8PcpVwYS z7{$y!)!rq;_pV~Oy*INYjt(p67e&5ujL`av@ayW%GYY4-37{^B9_0Rj+E%xZOQz18 zvjKL)X?O0d2a;0HuFD+xjy}Vpz`et9HvJeXFJKM%lSfiw+)$Ef+n5;|CRQAB%WjPla#t%vjlaH-K(p9u2&)gJQ($xT7o41> z{>-CpJf{;ceZIp}$Pj;P7G#g*AW&D;!K9vbWoe_f@sc5XgkGZJbx}v<{GO3R*gn^? zYbek9v(CIcxgE~wDHBlO5Jq8+2kPm;FIlRIee1%|xAwY=w_9Nx-LM$tuF7D$z07_g z+V$v|>SrjdRb^i{ffguynD%o^ut4j-(NvMH(y9G>!OlmM;wd2LVz#<#~AS`R4^~fj$B)**u@g_ z@$vj}thdG}$dfW^y4Iupg6^xjF@iJ4BieKcX`Q*G7me?6LPh++fDwmjZuBBg-MFrH z=3tz`0w6WEhn}%HnC0R{F5KR_rM%%P9qy|PDlA>pdR*N*%*FCFoDFY5!0x$1-yA~? zfD3T`A1pMBL5m?SxItuPn^KA4`a=AzLfdO$_aA&&YKA$G7Xb`eH<8Ad4#Yj=YM*(y z8uPk$FG>jp16_GDXL0X|#76o;QOm*sU}KjuOZHnWKIS_+$uOP3cy3LF(>AFZS;c?i zn_KH@Slk|@rd!{ts?$U+0H+L2|LuBNPF;3sv9t5rP1S{Dg2`UK(0#5 z(X5(TBMr|lzT*67)*q0yz0N@$2#317(F!WVYv>@2p`NqV|7&-r$XQ>DFf?i!+`F!iH3wQKgK0hCXW=PQ^U4IYAidtKv!ZOY-U z2)?8oL>MKBz^ZrBm!I!G4dp7i+H+>-w>ExdC2@`x;p8pSoV5FuO|WYIj;lS)y_$cn zNia$e+2;nK+Y^+0wg+>yRL$#4Q%2*otDeWA52)N`EYoT>$g_pa8Yq zPBr(<7^Y|Wb=Nn$K_?+@48pq6jw~EPd3n)?>CVqYnU*!D&F&k8pTAdQQyi%C;Dj!yuXU2P4Fq0zWPHR?>SRdHNqndN~G zn(QsDz9on_sr~#!wd3;@yU~|A3p4*f=lLZ!XKoHWOMPv9BOvTiOyg%2p3+%){SS8U zE&ob8E4qHCex>l&4@Q617UnSF7?zjkHRL$vF__bO=<)I-cG?1%8l@=>L>N9(-EQn zKzU$F%@F34TGwD4={Rbtfj8xC>CGN+~wT>Y=&l0?(Adg#qHA@7YmLoiKp z92+kU@KZ@h;mikfpIu_MAfd7Or4{Q}F2|XyGr!Yms%<WMG9ZiA+NH zzgXv&(2<_X=BAO{efEafJyGiI`eCkY@Xny_vv=}Ujm_qRch(EcuHT$9Gc&to#AA#a z)eCFAcJ<>SdvL9CjV>zs!PBZs9*srN=%shZarq{eq=*s1a&+>%oaA4WT<8rOD(QXH z-J4l$?|}(y&*jWcikXqgx{=WJ-ubJKoWyS{5t=6)2L~@$hz4twNRz~0@3M)FZaB!- zB0?7%Y@BaE)@j?dPkhpTm8rmNChsK1K6hoYplq#Xi~9AB!jH3icTEnSzMr`9R_7nc=8h0T z=T*M7ctz?=-dBfrR_y#-wX{G-qmOgcC$+UyvVx`&OI)*osp1zgvrIzoUcGn zUVOxV9ofRs$TvNXfM&I6eYwfMR*!*q6<{ODeZYz*em4#3SPB~hidyVK3khJ~@ zKEeI12|YH9Y`P>|zyO`h5U0JL^{DV*rFd&=b93TE-UvoRRHnddsM<%t-jh!08DWmZa!;@Pg?a@fp%6j$?A zmi+v*RyLIPBrx>PvGW9@Nag0Qn=4tpP4%UP>T?lub1S4#$Ho!CFZ$v7dan(Oe5Yp= z%TX(3QXqygid?@)63IHUJm&1|{PS|&{m@7m{i|s#bO9+iVYZX#y#-%$F{!B+VO3Xe zBjw*V@(=dWY&VMtF%$OJvw&qB@x?Dwq`%4_3;Brh?vo+)fXYbdX63N3?KZ4p&Q;^nH zb#Fv7kc5R8c60j+M0iUv(<2JnZ*ctsjS8|QP;{;(+nEeh+bg^>|FV>KrR5E)fv8IX z)&G@^T~&(qa)5Q851)()%wwj$Qw68PT>5n>t%>FB$O}enO_)vVv@#=PZ*zCl^gp_r z99^kiUVWFY4;%gm##k0$8ha*)G+XsT}$~mD8iaC)Q+b3 zJ!LW3O}VOhzUy?#jY~u?V0>jL%#=08F$A?S;(WvHdBIA;(tn0Q`Zpo~Tc#TuCBInn z2*W7bJ7>J9I$~=S?>4H@`+BzQBs44$XKVZQX^E2^!4V{(kDNiRFqtz1h$aYQ)TwV2^#JuToxijaoRP+%|b ztjk}tJ>ilW5f{eM;@T4lK3op{CYwwr@Yd!!*|O-9qH}>1&9bI)u+h<|L0j)#ozC;~ zvvc+n|Dm4max^1HpBnh#uct(cOS8{y=aMj00x67JcRUE`_FCN{b)vdKhoqCx1J2b7 zV|%W)YpnW}xw66@!Klqzf%(zV^O9@Tw7sT8Qrh03KFY(DnO?Nj;JjrZ>LID{q)$j%E`KMP?djRcsO%J(b*AEa$kP4^i5#*?|^>iNO3Q82W=#<*YEr zBl5J|aP_??pTljOkXo#j*xUx%+l%!hkD9b_5iG=w1WfyGO@tXMW{w9qSqs%{ib*Lj z;^-64(&*EAG^k@KYcnfo4m#|nQnngb%E8fUQd#j{dU@#>QS65@M~*${1w5bNAh)JI zgE>P!;NLgr__UT!fu7tS7kl3mKWi7UOV}<=`yV!p3awV9fubD=R z@KYZWrK)~h(0O){B;n~A40FSZEyg(@BiHb#4f>J;F>aZ1iJb%ssOBF=1YIcOSo>`` zp=quhcgO9lszkmkElQ`MZB?lEVGNHIb5xa>Dw+^AU5MYs|5G)8gho9qA`Df5%2`w{ z+#tn*sjUDU9xW-i$laMWMp zS0BZFr#vSf#P|El^VtUTsVL+7J*AX#NrC_;8!;*VbH#~|TdV4zWZ0G$?`8w6KuWGY zU(Y%6a!S+io1$QOW}FcBLnclu^dNVSUB}7|{rSB{5r}FL4eB`hw}1|+zbb-HAFP~E zQWvirCF1$I?NDlU=Z9{UXkb=1l8t6`5aBT~F0jIA+oo0n-W+tUxE%|-E*uA7s>P~p zl3J83$?iB%4%;s&hY`T~nwSzTomff8N86+2OO|ft3urG!V?$?KjTDI0b9DlY{5E&? zN|1EX%BqSqB9QYE#_&qjw+_-x|nFxu&At&jpHHYjr;|4N{uJLKi z0#cHt@I$+6JO$}y?f#5fEp+D;I^k+aieqx_SdPt` zkgU;UwoPTJ!9K1O&{>BM2_1dIm5X?Fy?%_uf4z`b3`u8_0Bn>lM90Ne1a(>^tmPGG z75ZmuV3^;8fb>h@xGlD+)#nzy+w7R-6a!sSxR1x$U^WMj#pxfVadVEl$m@T}`BRD< z3Auu#ed$p?Qqshsd1saZY>TN?J=fP=Fj7zC_YT_Z3$fGehw{?0Yyl*G9l4W$!$$H0 zS%k+!rga^({g}(V7WeY>QXM4s!NoxnWufiRWID+lgI2TT{Fxy=mvdeOG3MkJ7jPri zaz)%)=p_?N1>MlkHR#xBD12)+VpW!Fc|7+i zUKq`n8&JK;KME76!RyYm*ILZ;mO8<$r-3$;0FAYYd3Uf0IAPpko^ev`{0_>n2T7y+ z##Fgxnj-QYOfn}_Ou`RqrTCM1gWfRJAMF6-2N2KhHVFl?ZL_I3iuf zY2d4Z{z3|z$ZQQ^MSgC&i`3#bLe+^voq+l+G#_eAT+%_(lFKi?>MTV!kApmyn--J1FZqm^p+=6o0eEI%6& zYsV)ERyvl}MoJPF6dfaGVJycY)qEmCY}SvOjHKi;gnLr++Ey@(eEhKRo>RQ`K2&dB z0$(Gr#1gz3T6Y5W*}KH|59C1t>qdBCOMU~{c1HM2 z8dLqpxPI9`T~L5VcJkT)V@XGY(GxISX9)g0)Vzs)%O0Km4PE3O5d|q~rLOom`$PR0lC*Bl zu5Mh=lrivVWBuu+*TqmfC{WJArTtrp4cKg@>z^^M@1ZSXwBAT*4({H0nlS(Zw&Ky> zlT~v|UMJ55)+3jzU!3Vygd7|Jr|-Eo2|AbW-@mVYxTF}P!5>~&D3*n#O(-r7ArC~X zu{A014wI|))$OOMa>5n^(<5Op{P%-3%O{4LA=FCaEspqoVfc5>vIwTXIn_OMtIv8d z(@JNG^_lh-p*aQYJR(H>Res%QAi`m)VGGL=ZH622bF6rh*6h+3u@RD^hELn} z>hHp`&8o-kd;JeD`8zd(5VPRZz5mt-dcEZ+lz>V4nYCcP`ka_)G0)LIP!}djifq_c zOC~=XW9!%&b{jm?3R@+qTai%g97D1>Sp7z(&l}oDOEDI|po!7KnxWqfdBjVsGNaN{ zxL-NJ-GeQ0e7BWW%XBpFt#De22E}*hFu!@|;UP&y9GeG21miVhUxeN^u2g&MHp}N$ zxS}PLttS0Q82KlXN++3^gsoF_%ZHK#OPw6(AB!-PyQ%QRkdCHU5Au5VvIl*j?O7uL zLZAQdwX#SEc~DCDr_$fpe0qfW4|NKq(pR%E-nfmF&C&bigwQxcw0W4z~jZ#NtA`@ z*AM@a&J{?$SE~KT0vqxrK0kAXXI+8AsylF4MTS01s&%gAVDZ>(8vxtx>swUrjcjmV zrJVliI#Jc_oMjw|<9lrN8tooCExCjD|gZg8Gb)-_vAFTUPZr>Prr zwXZQ-b^gO+sPb97x+GagX*JKDJ;9X&88L`1`7u|W1f61jbpg~pa{;X*14Muq@DU%B zhf~qes}H^CRP~kvD^l5@W#5Sq!HNei%u~bz|7Z;#nIUEgs>vk`bJb*e5!@rc zsG?9B!bDA(7yg~}_DGThlxJ+FzjZu6J4=ejVSV;Z0aA-USUZ+fzHS@Oy<%};pc~s( z(&9SQm=g`-7#y`E|ETZh>Iiz1h6TS@?M7eEg`N{pft#HHMYgY&L$FPIeqgKTLCUQfyN)QVF3tH|Xi~hz zn^Mjb-y(vIFMP#QW8o3>ALui#Oyg)>k`Pv}7?{oRkt?g$i~^j|lmu5lAx3|bkVaA` z574spfhBdx_V+a%;^h{*I{Al*1AtD(>+CnoX|%Ga<%I8`7MK|Y&tZ4c?XXk ziw~zS(lbyZSOq;kUFoKa>6)mf%}v?z4E3UWo8-My0T`^`t451tRb@v|+qfNkXJYD= z3hV~O3$C$NeE4|tP<=*yCyMu^%KheAUnex>Ff@(M~@I4Ou2Glmk6 zwMx&JZq7!cotx|RD1&4X>KH3i>|kc4SpBEVUM65!4=7uX!&aouO^=op%lwW%cw4KX z&ywQd_pL`R2x(^#J?0>ryI(i(G`%n2@SP_T>04R^C%6_jjE4|boMsspTc76m&S(QV zW;7J#mO(@Gp?Pk5<{E(lXMK;=gxZR~&48xLwaS2Hss)lt_4^~>d+v4lLcz%<#K4^L z<0%F$Y|$AjB;oXk8i<8HpOiCKRO1yna&1|?v(q1%82a>X10A#gl_&dNRk9NC0-bdJ zU5H&Awfw|(s>kGF=0=5){M**vk_8%J)sxNw=EYKU_u%;8arn?;&IdPjKF@bG^(7m_YtemSjS3@X%w~r_X8QyBV3lNASZT-B z9&(b>D@MLBlW^=6+`moM1z!3~OB9zlZ_v$iiE@YqKP{S3bNLmpzU)!SI|;djmCd^& zP!=Yj`x8sq`5P^a_^xxULObu0xavtQ9Xd#z-XUy`ogB9olASIpyEgsav--Ko1=E^6 zvTQ1!uIBAQI!nhUM?8Pghfb3Qe%&AvSxDzZLhvpM33$-*s4*AKnpaXnsDnqs&nOxgzjlFsA$L1R~54|Jd+z z*FCxeL4|Kx1CiSQK-8~Z<~sj1rsfwt#eIe{?BXz38en4{(Pc0JY#|&dt*53VgXh?V z(s#BCkNHn2BT*qkp(PWM4hC@gDb+0jDN3O19~#%VW+9$Gh1tLQ7&HotrLja$PerMo zY1`X(*PV=*i~;z?zo$g>kpBtw$X)ne+4mM||_>hlGGs1(>Tu%gn8 zeZaiDXTOws9B53*a13dJs=UAM{M)KeMvZ`LT$fa@3uKpLa6vCJaBbeEWlf7_jD zpPzxkW%NhbkKiXsZWe!)Qp24es#cQ@g_NYNFCmpKrZ}@u3gkq3rO(U0Ki?>l$QKC% zF@Oc%2kLnYd&S0iLn`kqF`^lauw|B8qm6-=B=uGp|AACuNM`MM@z-T{#BlyM6R=6b z=5Y?^E-lp2o8})pi@u;@)TB(?F|t% zvNaNDbm9rdNDIVAL)@q*5rW%TV7C;UozB~eb`!`|LFr+i+wJs)#&=B8~w2LtP5xYNm0^obi&0ssVO4U$2MCEgr>W48J0q=T}b5z$Wv} z=&I~Qd2wKJ_>*%^vKWx&(;~Z`Onp0FL=dw&<_sGZwbJUW>mKx%#pQUMOBSl9O+rp7 zRg_xV9CBth>`oD}XNcXFJZrNZ z{dQFTqYh7MfxWUyY*uTIHNq7Bo_8b*~Q&0WnbOs=A8Rmip^%9v2R+;6VFUcsqp4hJ4 zV~%oo2BZ75b@je-ZBDRy_vz94+YjpYi|s3#MZ|p*MN5h67iHAo6pmuHF+vJyBB8wv>_V!1fasLUSB5c&~sq92ndmG-z5#8T&l6m&ZHv0G_DiaPL*guvuW0t}{wOW+KG5V4oYxV2~Fxnj}_yo)4U+g>1M>CXJI>%m?gCAPsLk zXsoTW5dk_Fri>oY$9Kg=LPoN1@op(6bc-^_Dy2+E_AUI1bA>HlYJp3@g-JPX8--Fm z%L~PGJ8MmjelRg!Rzx~^GO5Wbj(|>s5&nc)b9LhisgY6c+t?-zmG0V~m+pJ8Ktwxj zmsyh&i^Y@^Xi1x{#)2qeL-+G#_lRwh210`xu5azMptPPy> z{xPqZ1_z?~qX|tJAQ)E$IOj9PDAs&B=UUy%-6ddyNY}^c{poo(7&)~De{03ml=m-O zusKxMSVu;@V@}~N?i0f(feUm8eE6}&{)Zap^}FK=bYd4_PtcOBPLFcXzi0vh2-D0> zU^bmFC&p-NfitpGyEK2fPH||Zq3LQFWJ?!Ze`McFXot8QQQT$+#6Jzq_hJ-i~saErKwP~deH*Wk;FW=on#laM0<2+rEE7q(9Y!dn=O{=B#xAsij@4^*iT z5SnD>Xz<{=jBPECIML4S4U^*FTMFXWYBlSU3=%8>T=AQ2@neYhVv($Ce_8&f0NCXc zM&`xF4%e$=KaCVC9$$ptTfLjDXfX$Tl8?{7a^tGXeJ4hJ9ZlC-Rhq2LO-k|hgbU-C zztE&P97ofiKIOTaRSla0e(G>I%+5C1sjvwp;oJRSuA61UaM?qf?GR9McoO953v*e( zDJ-ww6+YLgwfGJJ4%q(@*`!59S$fLZ;;^B)fgd9Hzg@FeY6<}R>i(2(fds(I63)^r+Hx+wTfd;?ZU^%mR}h(7 zg2eMh_6drXNN08 z=$MnjEXnGon;mVhvfo>s3rlR%SO=#1J6H833*W48I2{>A6CrbQs zK+H$erY?=Wd~UFS9|iOe^!SB-!rZ=*ISYZ|KPKXa<5}m9vYxJDG)*b437c)nC;P+i z=?C=QC&d-p*mRghXPk}4s5v`co|EMBf^fO88#Bq)(TMor8e0$8Csr<6Gu#Lb>Bw_( z*nfrLEENF%J|vYsmi|Zw^+XO0{+@9n(s6SD36Iqv5eU&*701jGU-#I>Z9cv2NjQd6`gU2pt%Iec{o>->dr<2pKew(|gy%HOHzEGGCCAKLE zAN^Fu8o{K~!2((d1>yGrF!{G?AIq|eTnPzvrIIOscG)ZZxPa1VfPTYtdaKtupMxZL zGo0SZ^U9{cO0d!<3D-i>dpo1E2qg~J@*9bvtXk7PctYZ5qtDWJ$K?$=!T?v}0UBPZ zCNEZhT}=kn4>vd3xp|22kCJ$_R-rIEXtu9h1g3Mi!|>^aUt>+ce@UySc+HZ^Jhrf{ z3{jM|V;NPiI1LnmEIcBeMQK@%A-y;?p*GsdMIM~)-1?FGDD6aaQo=-HQ4G`LJA!ZD zj+Wmru^GsTZJ@c$@KguM^DldUJy9jvxPEVY1DZsdnxlDO-i zRS8%44$HzoFf3`S4=0Y9Zy_X1e6QtYm6M?AJxAc^5(%Rqfq*pI%!0C*{W z&tgp6$FEVdAmIAshewT%g(tzfmLik5>=ODa5nqKxlgD|+xDFZDE2~KT<8J-|&9M1B zlQyHx!2b5PR>}%fQzyX1bvih9_Vn01-HXY&&6xBebZ(5)QrSkI_pl$yvx@^oZy!=? zbGgw!|Fo0$rsEy#yd50QyaPHz4#+~ho|it@bG~_nWKNx{6e zV$qHC5&ifYCvJ5@I6xotP5BZ59*O1v?%UUR0M19uCgy{5-tEG|M`G=pC0^o=h6}|m1>#mq<{0un&=k=6Br!m- zoobi3-a>w&?z92|X1%ipv@yQY(~VOF8aRegDdx>_PUfnO%^@Ds0kj47GP_?YpHwG3 zAFv8v8sUEZtZ3ryX#++(^o(;Qk|Vl^wg5ZS#NK_O+dMFKnh#PMG9f9|GUMf-__|pE zJ5DHIMM&!(9WRIGPV3vk7@R?UbM?x0BpReJTd{DF5|YN#_`Y;Te~!eYRteep@OOld=q?RSa)ARBDK`pc&hli&Uo=(=Nrp0t%%zWFpxaYr))5_b{pGW*~lhQxYN~q{)Tx{J|qN%B%-X{|&`E z$NgYC!8Mz-dD{Q|n1K{;wH5E>r_r)iJpB`QSX$P0{ZhPkMVA$8t6c!bm6XHaGWmAL zG0s27pz`#goZm6wJ}bi>mkJNI07GynA<+e^A5(K-2+;-|J4bvmR%mcNYsBsX6JD3$ zi1IwxNK?ANJrPC2?1hI&NZDTO{Jr}ylJpP6e?muYct%>5RrnpWm%3S7E&l1q`F{yT z;v?3P8&3K|Z%i899Ji^1SZR2%(9i|UA{T`ilbf=amC*8A%4oJl`ORB&&d~s^50+&w zt-VFx}#VjmK^d2g{Elja-P zC(u~z0VtD1Y&Tcv$B|8g>4wN9VzqZawu5u5EVxmUygeaim^Ex^2={2X6v-c!0TT%G zk5vaJ0_zVsk|{gND=L>2?SryNy4xpb{r)6?ZXzmvaMM5hzL@?qq^KuST|(DfJ1{~= z**Kg84yCZnk=3hey&KcKABP*q3v2%`tdldMhW6m{=t~dq1;Oro_0o)T0hPrsdIca$> z(LE#gE~wVCSaD!Sxh8&Tl0Bv)Y2wVL>M{!Vm7!JSu|V;|3;W#~xAl&otVIaV(yQ0^ zp$gk4hVc%)0f_pp;#CMhH-#+^)#T`jyjb@~W*s+az8bj0uqd^Q*9QLaJE*)(_S_JC z#|o6|Melx38EJDiX(XsQ@!OuQ$B_zoUnSW6WC)IaPIap(q9 zQ1j22%i-x(U#5ANHo7@(stF~CZQ}7oN^km$9DCrYUXTQmDB4K;R|OE`W?#a$dl}x# zApyb?r6cONQ9Kt^%;~b!cTtlKaCl4l_TVWifq~$5cxi5|+&#>#)Crhg?yxGO`A1EQ z__{BC{!o#P!Q!Zr@8-=_>7bOYIO;g#c(|O$)vY4s1i7FFd*3%?4RwZ~Rm9(1)6`Aq zOy=jTN~PbN2+0{Fh=na_nQMZ3iS8tbtmCUs)1Fh&$D>Qpx*}QZ`d9dAtw#^i#ZqXf z?sBV^j=obKyE)Jn1x12a%k?wx9gT^@zl7(X@gsH1DZ!f>vSs5+V-gJJCJ*8CPWmvE zjjPzTIWOq(T$czHsFt_UMeaT`EWtFFWi|RZdWTw96BduD!Y`mp?CO5QvzSnU8*+)t zNWrbq+2@9u(80@n4I}~ehy(X)4tPba;s#xH%6W;pG}*Ag=X;mCdPHCUx)UZ&0C@(F zE-g!zk{6JU2>Eu>I5 z_sv8^lu#m?eRuew-rls%=hcJLow(R1IdCAs^$%n)KR=Eph{=oEx-umWL5}L!SEmp} zpWhP_C=#9!ziy08VEuWgDX<;4w-`dH(6PEE8%h{P@9Lmyvf`~D$<-#&H?M-&gaJTP zs4DT<0ZD5P<$-O@NJw{wTeV+#(*q|^ghbcUX_JJ%MHInIhb}8u#M5*=Yi7gk28~Iy zOPP;1VEwEYh)=7WK~HsB^`p0o0WHG+xZbpwoe)_%rMv}8Rd-TX+@W@8P0gsSB}j== z-SB~wQ&1kba28gICXudBE43S7?Edo&5s+1`M8Lce^*DY(3XxO03QU)5Bv>n6%~JEK zyuCR^T^C|8ue2B#zvB+i&%b=DzCT5SQ>k07td;svYS5U+YFHM2FW+k)cuMdc#o=S; zVLeL-264M^nHL-wOs2M1_eDJTF91k*p#RAAC^#FQyEph)fS+N8eQWnLyF>})m$70B z72s~?YCXH^qM$S|aj-ouD5_&68TXps?5B9}4Jeb^Gs(AG%qzOn%aLm>#QCHDoxxQt zO~sx4ykZC(Z*i8v45U$P%t_Fgl8dsOe@c~dvJ%eBXzHcRpI+raK2?J_AolJm)<5kf z?ny{npV{3U^qT!s6>nkE7W-+GUi|TWb1u*uP~#?UHomN8F)15w8dYUt22CH#_+SJk zuGL+x>wjvQ)in;J>9RFFf04sgCvDc7e=6oU%yZUg>1(OMrB+ag%?apMUXdc->zeU5 zC&ALpoK=29ZERX-LM~u$G#rf{-Q?$MEj6kf+RZhFCR1;&&R?S_{R3xy|ZQ087^eOzTRXEBydD2U2 zAGSc-MjoTJ68K9GR)CY7 zc;FHt%G7Y^7ae&tNY+u{I=uZ@-HyildX{a4X+X>|IZJ~yMX3xU}x zmCl6)Qbxh*0L`WFq=IgSFW+)Yth_GXDEVst`{15|3$|z7z+dgfUyrWvkJ(}|VR-D} zw{I=kTYOR!hj3>@G#fsCK=pF{+L8=aXAv|AJkd+o5&29U%RAd?jq`4f3T3X{F*+h>x8s}+?t znH!n(ropDY$k$@%ji8ktOYwi8Aq%rF&pX%NEv97ZU}JD22ieyIQ{cNK5_Wf@ywj@d z38+YjfwPf=HXQYGlP;kz>u4l8WCCaS*bMWe28Xyq$7bZvd{Lf3iiwLQy8ErC(qby%G@Zr`2nP68W zR7GU5Zs$?%UtgWPj%96^JeRJSi8A~Y*W=GXJ+(%Dmoha(UBykxZ5Ak~#Q#ki z6)e>Z)L7xr7L~A9yjdX0r1Ol~=Y&L>+Dl(e;g>QL_0BqLFS5219$)#;L-WU0FgVIK zh0a@z0L$I^l$=Mv*G3P}s0$v$o=x(OF;3f_JA2!LDDbrJ#h}?}mc>`Gzyfk$>dsHg zCKc0RCpM2|sQXP%?7Y(Gprk80TQjiq2n|o*ytUav?=qRcM;Q=9@@CBe zeB~ZW#THg8S#YSr_BZP(?IoM$u`{_(XT};NpoUe}tuSiCxV{n$j7OXEKsXNCn-@=M zaJc=oh&HoHZjnhTVdOT>4Q-Pofsp6cRn!|$RvB|(kiS@EiOGAx{PvTW?t$_Z-ADRJ zP;RjZpAb`k*U|&InuTx51Xbre_{E|6@3RTGjVKI$%-xek75g~A=AM{Xyirz_Bsg1H zH_Ex1LHv=om`)Q4#~65F>aR%PDtII6Hg)j!AT{5tftI^)#V&fl3o^r920xa3P9$vp zww^UL*n2ZrAoEe1M|<^9L`WG^vSu0}XMyi5I%LnR4I|}roZ=GB&ol$`F32XWt9yx- zO2D_Y-sHoQR^xT&l^^UCt}6A8tAw;{G4KLgUNIy{HRiQ#(@9+m+=JsJSdqnsf1&8? z7)*IKuP*yVO=20j60U@DPhmLBF`|fwbZQFkrSQRGRwrZ|#8yaYUK$QANjQj(GF~hr zh)eW}Fmqd@$d}IrS&u2&M~i1Cp=rkYx%U+1JR^+V#B3f5m-jGe<2ENwCH3SPz2%xP zPhoTL=nbWFf<&+pVEKJ*q=ZUyJ29G0^iYT~QdzDgtY$|5QPIUe8FG&Q$I*HCQ~CdI z{BUft6*=ZPwq%sO$8ip_XHn#c$|ienI*xO!i0n;;3We-*j3TSd(4m9uy+6PE`}+sZ z!{a#j{eHc#*L6LwEe;hdPepO22O7jvD&7{+d7$YtN}0EgNj<(@B^>yYcZ%<+WI^B! z)yQU}g7acpwMv$LyBs#tg>sv&1nmVrpYgzZZbEsmYKK~WZku?Cv^8qn5ht;PwysFh zRS3r!bqa>n2PkK(apqlLl7HR&XT^~J-SBEI+hW)Z<8`WAE<4#D2jIT4B38E}=PW8UKA0*Qi z=YVPhXYiTH*@0z_QuunjOSWDP^VfWz=++>wiO(7u3qbx9=r{79kbrMcOIbo1CQ}?t zgu)OtddVn<>iV)M=01Ze84dA3z(aGH2pDasoLLSPsB&PD*<9ZqBcb;1tKeDy867bG zt#k#Afw(4hzc(N)GoF{F#;#S!#S%fw!D~I?rdwMWblsSANZ1zq;L^Gi>`69Q0P&?& zXHt`4Pht)!nW&~`7Md=jF#4XH->vo!cd3Xs*&b&O$?U`=ne}7#?mQ>d%r0=b{c;0( zC`NEcBS!kPU4KXS44i+zTqj$DnZj!aW`378;DSK;+apJ-Iv!ki((E1wkWFcSOA7S5 z_{_#_ZaK2%MW_6DBAW90yC_-3TjC0p!jt_$mqzE2&0IXfI?&Pk<1}l0uiKwZ&ayLV!K9Xde-|G#X_zAdW4S`s zyoiw~g+5W36Mc`3JzWn=VyG&xZNP8u5dkD{q*%LUMCh0M`#*hMUWPrTlSe!`m`3(E z{|Ay^=r|))NP_&er|s|Ex6U#)5_Y>M<`CHxS?X20y5i5b<^!emXAjY;X9{jcy zL&piR{F3btyoVOE1M@7$?adMhbCF*|Qh#8&m~($uYg@s0zoPslKDBGsj1gEomU>-d zGccAYS01=CfAs^Yr2+l6Mx#zBrPAR;F=ntF|0Qe}uSzPOT`!vtXYL(bFOn_Gfh2IJ zothE>hSJA4E#kgzp?|Jx0F1+}dy&GaSyEkd^$W$^eN}knvoBTR+VBc!h3rwyPBCd z$Gj6y-Tl2DG zoAyPPnvj{t)b4hMe@b0(%y~2<8UW~mV@XwSCKZ=xlw(+RQrn~*dkuUtZHQN-;?ijr zRbO1YuCZF4!*y*#+&2_sa6f+Z>J8$irIhzQ3na7#kr?ou=qiv7Ja%kng?J6m_hiqS z^ViFgX9`N>o!gsaKU@#5Dg@#6aR5y$ysU)o9m#WrtTN+TF3N59Y#H&UsQ~_in$Hs; zoEDjSdW-$REMi!N2{q*J|1P!PAyCu>aRP7~^^jUg`zag#9DlJOYt3uMv+#s`6)+5My-K>9?;n3rY{q zCjIV=;XYq>?%W>-C7J73K{rh9L7W|ZePXz0vqoTyU@#^%T1T#BNzTypCG1&GXnm@) zqs`%Vr|FG@Dn5;7>!ypE${ez?x8+*076Y8~IB1JQt+@0EE5>If(r<#B>5q9LWAZZt zTsIUAigQyuz}@m=lcml3P^_pc=M(y^0z4uMT`;q-Tnobi2n zFJ3rmbuXt*|1;rtabe?C+a)wN&Zo#RvN=N&>91<*Z(ZnI<*aQ^ypVSIB=y5QTg6EE zaoePsL2Z2b>$}`wvc+1KAI>KhR-yEmg-K^rU-sxtnglv@7AXuS-(y~O|Z@^ z(rcY(!b=N`KOaV54i&~!|M`!%FTZcsxAUn8k$?8Q{ISE&=G~Xp1;5w?(ad4qKE&ej zsf`;QWcO~M)$93hThfd#f!TgChK3$a&&j@ z$5-SdS&s zgk~B2O1>j`^zR;E8{3?q=wmA0)~Bm-aoSvT)!1w(dOCgI)1pzfUy6S+6r+AMLiR^h z=`Mo8O#U@w%nK98r#BpayH16z?rZiPY8RFFrSE=S({dV*nH18ii3y>-b@wI6_BnrD zh3TGa`iY2!>I-!h-|0Ll!+iVhAl^cQ^Q&X-wDz|(knou*^{fM!{2OG*`0;Gi#FtRL zWYXsMVLPm~4q49Yn&+R?5t1oGYaB|%eBRG#EGxr8D0q+k;tl8G$DeS@Is;_pnK$1X zybrl6^Xq2jlz(qX`liF3I}_=KkNjSXT`GxIKNE{JWJsro90t?35IIL2goU}wdK}~Y z40FE^Q48$0mRF1X8VPCTp7-or<(&`k`gy-q!DsU>&&}q;%IjCWVFQvs+<5 zTSZV^liF#{Eq(8 zS0;;RJ4jsG3Q*WOU;Fx@We~n_{L9QjUtr4{?6!VbsK(qC{@+`rx~$Dxl`mX)3*W}g zJ-v>GeZ1vssq#ZBTbsM5_V&S{7dMl{4c#D>We#_pJ@mX|vP)vRuE`2iVV?csV(iO;_L-;~z1o;R?!+B=|%ka4QdRdn!Z=z=1*anmitypc}?0( z4|H+R`rs^^XIIv$%wZYFe4Oh99_+6gcDK||g#sTMGSB6K8z6h+zj0QJgqH@;*nr8T z*tLWK_te?XLwxl-w1IS5K;c=LPOD#SNekJir4R2uG$R|@#KXr=c} z2ITLjwxNi85lQUJP#zpLH`_Q_X05Lf^tmjKr0O%aRk+&5&oM(@3f1pmg-Bh=H-%*Y z44xVu7*f|8j|#SPh9iE0kdnPkcB9af&Jht353LV`5_+GGuPo*byl1sGG7kPAGHO~i zhM;;ti67l$k8`WX!(*(`i^=3pSy7kJLX8OJhhEQ(9#g+Y#y8|h=nGGngR!3%&yyTg zGZsmetVg1%m?d%pFmynI1{lk38_CwA-HmniA~YiM4ej}*OQB_SHMlB8aL9Y6n+gm% z5epI7=f;9$;s%cF?15HDzm~>y)T6OIre=b+L%10gW51BYPb8$57TaH^VL?7?r@24w zS(5XyID$vMMwA~K5*3>{6hx^%GNPtVoMd*>a?3_?racWS6<&m5#U17K(`G9f@5Fb) zy6?Qc>sul39K()HN|NE-I91voPh=LObrT4d)V5M#-;`3o|Na$h8Uzcbq4K#*GluAk z(vxY0xH-p_R7sB3a=tp~HKan0AMX|fi*L3V(%0N8951j+URXqG>c*Qnxa z05rcBB6+L14UDVwUWyCyO6qgxxw+xroO$J&w19?8Wv4Kh6OV!710m;nQ5SLB6HU6% zr0M@a@9&Y~+DfOxCO{TvRfBu@axG9Pvc3IBzOx$_pi_CN6qxVTVlxOHEY~i`FGv&Q z8YX90kNwy^fVea9?YL8$3!sZ=mdXD}+Rz&I`&dbb@*CiDA!tOzjvVSvX>DMhKYq8w zFI3NHLrx{qBVGtT8u<^zsoTdA1$(QBG$lf_GMD&kcw`$RB={^=tEaSGD%RuK~A)nJ2YkH}SIjoyvPZHNCyjWJt z@6aa~qe>)3Pvm{Sf31wyT)zA`3LI6tt&^rJdMwP|)e!n*0uqI2ify!!IwG)12*7rk!0ZLO-& z?8|sn1li?&;pTWExrLdgn|*V-bO6PZuBSZB%6tuk!dV`kC@lRCSdVZoxjtDS!%pnD zDO#PW@NzHJJi=_S^Ud&e6T=}Q)OBr!uoXr+T9?g--tc?3I&Bu&Lu0|z%u52frZt6d zlOdS38>NE+m6E0Z=q-a6n+bfL1qA;^Av&Rh{`vI}vNwcf1JGMWk?#weH4z^#O8Z}V ztMm^^d@1rWVwJYaC-R4(d?vy~O44F-;sc^}LZ%q(X1%?x0&yc6>KZ2{_A1r)yF;L_ z3lMD2^dX^TR(ae#;?V$}b%u!`a;fb2H!~FSyT7y1$t-gvw?kRlaDZ=$eWxcHqkgj1 ze3#j|ow);iCjtIKh+XoDY^&Nbn$={DkOn#U?X0i+&~W5VTYBzj{qXD$)xq#7fjn+Q z=ff~oYD~T=YaIS>ff}T5pwE>J@mHJ9uvP z!-*{o#K7FKphmS6ZeBV`0hKe%r!*~Vi=6?7<^$D>M1U;bBBXcyU_&iF*)d=f7m$@4 zX7FG+h*S0Qi&mEm4Lvug^(SIl=L{Nxm7eYb6OZ|3OU{HJF3Mhaanx;X?+s-~%b+io zcl3?Z6)ADCSn?D6La?clh?gp`2k(=jJJ2RbD#*+BWjbk@ooQVyM7;hncBVL;OaID- zKVOFADGTWMKv{?9MY%V;lmGD_RTr+NCITdbZ$v|B6=GqoEF=hM%P;X= z93_}Vg%AM!ruv3!FC2y|bl-TPDj6Lq*t@~J0 zW~ST2>HRrfduSt&-<^^%yhc%@MS@rBr0&QF9)|v?yip z>YHmF)+mqS<+;b=3LdJW)_dNnK#>3U0AmtkqHl@2L(O3MsqI8Q2?{AJ$PX>iW)TZ3 zL^hRBpoT=9dmwxr+hfQOX|;Q;L&Z#=F@mN&*9Z%p5dZlx3c*|}I>;MWhB8=UHY zN((i()-JoBKRmb6fg@NdoS#t0#RN}L&k_v3*xS%gc1PXd-;@;t3bb#1igeol57gLq z_e_8f2@+J|ycRp@mmarw1DamO$Jc?pTP)APQFUM$fyuh3|PX$ zeAXam+R~F=#&K4^=0A`)Tv~}#X>zDn?W^{qZ!Mu)e_+5EqA-k5;_Dzx3qASOr!*6r zON*Lo0THn#=&IEi!E}^_h-BW>_CnzUYIM_YnL=tF&edX3x8zT1Bh0?NtO^p8L^;1S zKtB+}W=a`P(}`Zoq|BSegx}p`zd-pMt+gPmignEq(=f@_KZi_}8>!ymxqg=qRh`vj zh$Z}F>n{%q*ay;Pg1H|}l8!|(3fF;ZrO*^BEl5;|Xlty*qIiLR8;OOQ5c?kpziMKs z>D}h5o$1_U`_08l9-rtlQ^}yfR=9Vvrck3_qVsu}1gl3Y7tODWK2dz-t-b*{)wnRO zFcXxylb@>yVr?;J(f?%Uw;XA#npTi3wCffPvDz%V=+kjqz4gQuWW+on|MDC1)n2 zdzqEPdFMwdml3~d!09xrUn*9ajaPuy!*TpQC zTNAi-nl#G%wPeY%Y{cbDm4bFE=WO%kM1e~1wQfBT%9Dp&rAI@M!Xl|Hq#7R$OHQYt z45UhHzGELM6S-5$$+hD*W`rJ)sohL9kTNOrL!Sq*1`nLOR*2n~NvyG>{_vQAwYO1v z8S6vhmDcc7=1pGz&M#3}!ayNo@v$yNH^bA@$jOACZ^9UmTj3HOMG}jM)gh|UUUxE9 z$X~6Dvn0NYf&%P)Vfd1P3|ca-2D`cWVm4vAP_+OK%q0RsVa2+}Q|dLh>q$;V`Eu{Z zkMPpc5tmYH1l_`f1%(MWDf(xvWO)#Vl*{OZcAppxm;I{EFxft%j{=hpmt!5P8QKUY4Gt!!A zU_|x6IgT=@3vO!wGo`M8F`!#6Wtn3YPe?rcx#7HhzEkkdgREvs?DdDXOcbQ;F{7yI zVU%_;;jhecv00ORYH&YwKGXJig=nmJhA@1^Tutl&C+<};*L2H6??}H>rbV+O7<=JN$m z!rXMKl}Uauk0Nc|p=gW)E+?CAeQ6G~0x6VIeP=99jY)}N{c1Y86s|u5C#9vc-{!L6 zgY8F;@0iBfTJ(f?6k6p<&juFp{=}Y|tNV~DkzuoT6H2&@fHgX-Z+SpGe0PAzr^cW7 z<)(mo5ma2)-HKyeLvc8$b5E0p)+mlYD45dV^P%&-uag;zO-j4Of{6LMGu|@~@tE(M zf=2rS-W-#eJG+a1c%SCYF&KsB?fYUBF_MhrLm$Yd442F>-nJM&U+?r|9J$rOOj!!U1D+F4X=^|8H%nG69QqKQ4q`4>Jo+`0dfzP4sJ ztPA|L=~OVY6nV}_bViilRcYm4?1IFPUDbFiAm0C!yJKS<(Oa&^2Bh7MGT zc(g`;bq{Dd%wP|G=_jW7p0^X>OJB+a^};A~)7pq?Swi2`*xC1qj#Q-Up_`}=h+C?} zV$oN5y}rICSuM%UCr!4PR`5|99T?B-is3J>RO}z2voRA}JI91EL5^!htRO71@GoaK&cSgv}ip-E_cUWsPgV=6pjTuhQa5Yx7hi@yHD zfl)UeHNBQ;W`W1r8w}%&xpt)Q-+{jG11(DmMdIE_#1s%1>OuPN6~) z5N5m#wnRwg1J&%-izl5*r(A3Dn&|GWYD*SMy|gj^)P_$f`E2ML>Wm@rTVE|l;rf(@ zn-jZ0)DWMp*j*RDgH-htBY-hX|ACS3j;-a(Hz&w$(L z>;&+*QiGw}mx)GnzAq6!7&*Tf?jYgIB+<6WUzcClfJiKxK*0P>**a98=;PWA=Pr9j zpM8Q6?qR$wmNQ{VioWQP8U5}0rlm7EAni}i@{*<{i(U2W#aCy}tD=5cpG9;q&$T@a zZnxf?&&R1HOB_V0zb2x3y6j4-@cwx34o23SXSd}%tAdgt{?Ux)BbZM{Gp!@GTwg}& zg9MSw5yMYq%rId+@pqi=GZ+vV%&e0?n7V}azM$Sn8PnPf6y|r+amPV_>R<_s6B>GD zWt91Z^3_~9fnN05@}UTd@&+q-ofS5p#pObgpiv8641!(Fs};Yyk=C6(ryy~y?@y0* ze8=}aqy`VOwl;arG?X6)RVSO_vV}`SiG#T1i{0^GqW1)Q*!e|IUSz?PYzBHfN1$HV zg|#tlvrzn!Kq?2y7wU{&401(1 zx}s{r?+vNYbSAeo`79TLOLXRg8n6cFIxlXxWkax*bE}&OVd32Wt+?JmKZR^*NXlRz zy{EYJK=fi^N7^Ni6w7G8eIt^~{6;5n%&Fg-y6aSp{tFaxXdr0w+p?s|%I9;ZWG9KA z2@`d&Wbos5W-(E3#tdiJ*ik`+7Ya+WAc+)FWZfbg4MQ?8xJ3^*w$5(Jy{X&?<4v6A zT@3)-!#c5l90`&&VzSAD*?B44#s=7y!g| z;r~EGE6}(lBRdUHl;7_7(Z||GnbJqr+71bw{l%{WD_hUoqSo0yM;j9Zo zU=Zqko;`=4gGbhi@cZ{k|9^@>1TW5yFX75<9pR9gz(=|UaVK;S8)xkkP>1i%VTbyhv} zyyWN&4}DwJQ1dey=h;t%XYCsNq~(KxP>KyIpilB^G1qK6MxK?0oG1XSN`FM|K_O!H zw_t9$Jk5gXrY=|+sOq)K5jCEwRE(L(Q?4#fE}O@QMVD9V!B_Jz2?DULci}vaVXtOY zIJF8RU54CSk1Im7=348e3qAC1Yq+)rW1{BO@O&dH$1sG2)PPqhP3;g@ANDT?_Q(Fm zGFuw0YM`*Mf^$mA4xFZL_V|qeF|?5C84%4$h2B%`jetk@;NKF^n?sV*L@)qL`1b>A zcIW@wUmugy>w<78;?e;@yV>^VkLOfldbfalkD`3W+V`>^<;D+G>J@<>b>aosK^$F5 zO2bH=`%mrC<@57gDP(;&2DwrouLSVl2P334IWK|56WzOAq>PbRwk*giu zc?SB0NMqbNtWl9MAz)TKnSArncoex8^r(xvnp*dIyVVozp;Ncvx;$D&IXsQ0i4wtp zp!->8#?mvWN3PZD+CX<26oU2{Thc&1AU~Nhpdip`feVaBH0J#K4Q}7gHl!l3C@=tuh^HbAd#&XEJ65%6Fa)Q9N>I<%h*{I=(+fHxH~E znqA-fde9st-4jH!YMEfizV*no845k_T03UW{l4{ji-Q@6G2It(=&~gbEKJi&0x?_? zI@iD5@{#9IO}zV7K>KH-VkK50rxfgNG@7~xf4hAQiT$`6JwO<_AMx;SUHGE%kChf# zUA!17(a-6Xn;k5x>%|=RoF#@a@&{vl{l#3_TF{cdP`dfU7qkN6(PZ2dy91bTnUyqt z61X-ML}x{-@O)~oNdD)b?76noYP0;Ju(gP9bZS{xWCx;>7M~;bTCBY4$!tQdu0gT$ zp?sNR@I#q|ljVZq@LzO6>l@X~Zasfspbye;Zq20V&k*se`mk&uyI!HiWAzs|eS>?O z>{2U=!Skg1gIwr`G{u3gwU0a=&u)r(LHiNI!v1xdY)5~t0EY~L^cSOB z=lacLf2R-J+_RX`Bps}z9jS=}oGk59N?hDCL;cT3kG0E^h@!OJC-cL=_BF&|A`p>V zKFf=DTLFRw-|V(n$wQ{sv>_&Qd9tqkxIds(V)B)U5`tNaIw1lL}l zF`QSCG+Y}eNC)0x$CT&j!*n5=;%c32U4V+Y=`bH;4$9h883I9Bifs5Rm>ah&PnDFq z6jyH{4;~t@OR^gB4mcRYISjItK$K8k-#}hK-7JBzI?MFe?e^WSp{t{eX~kU$cl84y z-e6>o66*($OOn(Yhc?gf6j`9R{%PL8<(I5-ZEYy$qal@1yQbJIiP*EJzXrH2?Nr13 zSEM1{FEgR(Xb@THlf2Z8w?m)^8Uk?5aO3xLpM?HYayU}y_wFjCn=N%mhkhk&k9+Fg zG@+??c&K+#uirX8WBaaWn@$~g;$GH(f8s(*g8n`kI5_IZi5-*;d9ypmMw5=$#?~{l zH5IPEBx4Iy^r+;*tFrB>EAv{EFqFsO<#5o#dkEO=EA3!dnE#@mo66Wu640h1D0;p! z$4Sf8qUUniR**HS%l#am#P0An-(9KS;^TQF0t`&f1!K2}aU2WW;*@pb2vDoFUiC5F4b&$NaG~rz72X9n>Ei2K$}2f?>`Z%343; z8osZ_LHoaz8?_DyP0|83k*qedtM=>Lx@47K=t2h$cG|Yh2gh`4RI6rz!jaKOH6CR< zH%babU~<&nY5;SJQ$+D#u)tSi=xFU_3QshZ*;+kf*)+ZC_iAzbtxB1{aswU%#rXK;r-ahVaM{7gLdlo^lv_lM3>TrmB+ zdaYfv=LbttNm|yt+8@eXJ%2g& z2>CI?!k8%hkK#&xC0#-@MI=dXD$(vSrI!(5{u!`Ix40}Xe^2s|wk?M6Vs2iO?a`0F zbQwV@_wJg~EK4v4>T#yaKTc`6D(bmZev>9rQ*>bXO7aQ?HAnC9}{+_Qph ze_}q^ltqi*+TS^jO8%B$m1%z|-(ptnE7xU&RgS%L}h$N(OF7u)}*rN5~9V#bjjGh(sWj`{#e(`~Kp*i;a zbnSd60r&eLxyxQ$f&$AATls8Wx)>xWL#!}vL$`2E@uXyi;~K0UYuI{i60X{z4(S{1 zXmM=)2Wed@6W6M>)_x`Y_QCErpZ@`xF8nUzY`2n|Ri_@B3=0!Eq&lG{+zTt&h%;9R zaqScWV%Va7Yq_ck^JwPE&SB*T)pzY4ey4T%^eBM9(5)0M4BOwlmR6{^KlZ#eQ>d+E z(33m2jN4Mi)k;4p;}cG6_mZHdzN}TXprb;}DwD*$NhBjwz-@$rt}e;MO@Fh#4#*oz z<-|qF-~I^3Kx)#?c}wp;dve301aoNcCKgT2QVG-TbwNfhR4nmitz`@3Um3EaWxb#i znGp@VsxqpsJTf$f)#NV@qk*d)jZ; z7dYK#DYYM|mGtaD-5Ah}U+kW8s9sYdFcd}fS0HpU27$N$e2YG7ra{``qc@{nB0-nk zgkw?sz(CC(aGmo`K)G()eiiok$m_cvkgP1@{sg=2V?`U ze`{d1Q#-|DQ8y{Zp`JbP5UPE(@u41@)`9mM4bTq1@qS&#BH8$-#A%LW+Y6Mo{9?nA=7krm~nct(n_ z{LEdLA;PIbMP=_Tw>wJzFL6Y_;bxk-Oh){4y)?FQj}u+9?C4x-tf-4LEuHvX zla6a9L+af0ZJi1`74JFXxyvuo$QF@>eFFEkQxsI&X!8MRQhdA-A&zl7w}fmbcG=+i zpJ|pjIE)Q@J0$%+N=ciH=uh*bT{>;Wxp18}seW7YUDi){$-vtLOx}Bd`?r-MG1!7` z{ttBLEUGUx4%d1OH=;POJ07QoGmf83&hq7UbJZ7tW=jn$`Cw(n_i{tFMzAu4_u`CO zy<7EFkjo4a>B_ny^nFhT@v$^k@)oh}OuT=-bxaVHod4J5?XPDjbzii{$-yWdal4iK zQpnL)>yrOq^H|e>{`w5eYe+lMU#_xpEn_86wCiNHwFH1vqO8$WFy%AK%e%etLy!=3 zm~$tzOu6C_B8|6)y&%c4MF#!K$m8PsMQU5Z+NKN*lK@!J=3oLo3ukWf-ra<3DRFB7 z{}4hZ>)_a6tXBik6ls}R1Z5F;L}{{qj!9`T`1P)4bSsl*CBM|O6J;V0a{?S?$v=+E za83-dz700PYI@=XdTs%0h7P6W+a{gH?VXGt&)JcD;@kXW#Mx|{)AL5)yv>`x?XntP zP*OaQ4wW=#W_zlY-*7TV%e7~MRNKjrPB!O!Fv+?(H%m43T0?w~sh-cX5U}%IanXrE z8gYwC^%p$s`!M72-o-yK76ug418XH(8d zb9CcA(ev?!#U86En#^BcD$isPaIv9Td{d=4QbvsG*utUpCB0bm$T&d$ zN=_~NgnY=soWKgDcH`GQiqA)K#VX_ffeOS?UW&_rhj|3m3Txy7h=hMQ1`ab4GoCrk zmwM`_VKh9^6e2ZT5zL%j0dRk}opN@m)oF`1r0T#MU-za|1VfcF~{P+T+ITrLZpQ*p|S;h+$& z{VJK(Awtc??>{gqe6Mh+&`i7V-plM;(D#4S)AE!?lRe7m(S;g+yw$AXd@|wug6LpINnf$gc&SkZD}96z%c$RweQA zNUa4tyi@$@xjrmMFHo;P*nsD2NhW@b=2+}xZM>*o`=+mah?$c^fH#us;Gym5GGG3i zPCsB%R@6I;vb?tjGZbVsQol$#Dx5%`;6vDt5zXehta3CfgjT27j~T6FLFzqdR=;5; zlZ|wh7aFznGE{eyn=NQ)Q)6$R#=`0&%xv370C6MmgT|EtqLPxzVK@CR8zaphC5reM25;)i zkbt<}mwE|PqnoA*tOGY!vVM8~{2f6gm6?Bi8VVUqv6dYZ|FGq1E@Z8~V;e!hM=%+g zJ)#jpCbt)TfOF4v1&DFyM5&TU8fviQhoE-`H7-Q;oE$8;_aD~e$oXSh{o0zqdWsPl z-JJ%!7IVvxs$(hpe8!Hiv>)NjKj{F;JGiUQ-z5MWfIEHm*+g2XriW#W2O2gSmu>j# zJ8U*I=j`4bXoY$P!}i-Qzxd{c4^}fk8I@c$zo7;Mn%-ZXtT9#(?k0J}zZA^rb=lv5 zp`0?Wu=?oT@d~}B33q&6^b3@DkSLXccw{6evCLw=NDO5+2cNR!E>*GS-#S6cr%{Aq zLs-*y&2>8Fl1P4DtnT{!-ngwUas71avx68!16QZxzpq-KvbtDGVz>X-4L6t1n=BYt zq4iZXS31R@%3+)uC_M5mi>%%q6C9)Dkdpt#BQg{}5E+J9CF9b=lK~a+INJPh)BF1T ztz;kNB%S89;lst9qSCgIAPVB<560@0+pKr$)MQ||I-gz=g_uaN^+=S`vAp7H26?K` zYlj#mXaSPFaX|1}f+FEy8^7U)j_g1xYGP~2cqeg>`EbLNrj-|B)LoGM{c({yG0768 zvV;U#uVK8f42ITQW5ORNeOsX=Ionm-(517>r)Bqx-pPpK8jjuWX|fedSv+6R!AXHx z^PA2^92$3iphYeJa!x)|LY&%R_My!Bm)Ol`*$}5Nkg`JtyY{=EmU9ky!Q#U(h9Vbh zN15!A=p7(b&oG$Y&lXv^TIP>njY1MDS93Y_E2AKsJF+NymbLS2ghQmY z)=Z>lPHFjnlj~yW{Uw&@arv_~iM}VAb7oVm3({+3!BHY!R{vHIkrOB-x zMISE-fU=xNjP3!jBxA5Xd-14u(Yuu{03sAUOU!4ung_R=-8nM&5h1W_`4YrnU~TW% zHzXU4_Bb6Fj<_USLMUlb$*to|ZTmUEUh359uPQsC$NXCw0QMrLAY&OyA*kns#{Y}& zP0}AxT;#iw5!SKFOt&~p?za{Spu+RmQ6Y#p^wlLRYtj?PN^ghwZ^5`oNq3bD&tb-h z5P$jj=rz_AXtp4NlWAQ}J;-ZeGwn)Nr(0oy`-a=hx1|}qp&}IT;?Q!W&ls7YO>Z{3 z)x%*L4p8YLUr_))wqiAwh<8)Vff3r`vawq#E%!>dB8-*!Z&B{FXH1Cq<8_2rkECZ~ zXegVVA%Lj+&YY^7Ian>maw;x;%46$9(Ttl>!*84q^&iOc`rH^aK1G{v>iwk>mpcZa z>G8*lM)g<243grb-I~0=p{Lz2+lRn?vwtmx9brB^!fjC37U9P4{PZ{S6bt~FBG4fM zkEp~s^54t6%GMu3&|Pcb9LF#1V!Q!E2v?zcW)$-J3WP|vFFk)6w;V;oH@7=x9A`J> z;dJ6_=>_6=;eO8PLF7fA17NN6M+R1xjlwXoxJaWjs9P_lH3BiP80H^eA!<~xzv;s0 zjAWOg%)Z;7Ee`<^`O(1xYZ*uIGp95fW@R5*N4u={hT7%@en85-&&yJn^KO9CoJIS) zNE7^`Zx7kYUNo+8FeE-@h+2ck#}g;sgQvhdPChz0tXl-446=xf$0dew9(0KhKu zA1JBplAtuKjQE<=cP#wlyMPfv^ioM|Si|dZe>~jmHgx!>?bKi07cQ{J3J|i^e&7Jt za9PF3H9sHVyqD7dU|xXlk2G(Hb<`o80A0zu#$e2I!;O*-17=kk;#(&eJxiyqQLGwl z)x~`Qkvui-r#+KpO4uhAf6?nU;PO+-ly+P2*J8)Z*LQ#B0|A~!t&N0Bvn?)G-JuU( z;G<`Nt%)lu5W~pm9aiwlKb$2fb6}l#fjDMoy?Q3jpxmT-eNS%jpha8f-B=Z_)YnDd zt?bBMmiT*g+jNXc!?{r7h}w+KI%PesYowx)JV08&>=ivOb=HOpiYHT}{&E}jRQ#>N zKbl!*hoLqZ=xmHS*+_xRxH-pOv`ATkooz2YeAVs-_z)$`p}#q{`4l`N@ylJpP_j|} zr)rBqEHnPP_UL5`Ke@(9mEgl%a|&dELe}NoN7iaJcBp+h9rV=+*V_7bkwpPElTT`z z!}46{Dc3oAC+&?9=vg$xe{Rg#GBsVRA**x_eO=ee^f604VWk&<$P_A)fIRx@%WEnd z);5RG_s}Lhu%Hn&$RK?=Q0CvlYA^$HwzM&U^=b zGSjE)v6V#DQ)r4>3hq>02IycA5pwLw6nhkHcbbVnb0y8JDsBXJaR8YyT%&80rf{~LIxdEBN#!c-9mV0Qm9ToRj{J**)|rqcG47e$Ms4n>M>dl2KOf!e&~hejj$mTv zIUxd@j>BLAzgxY@M}8OXrg*Q0{qg%&hRdnBy6FPCq5}7(811MfYj**oBB?^?R+}9> zB%(1?o0=lOCMO1XS6p-Px)nta5Dj9oyxRph<*jTv2N7L%T-w+{@*Qt|e&B7ARmL(Z zFwA`+7MMN25=+A!*#96O6AbiKNC|OkAM#HPCJk!i#F2t`e43ku>@=KW5c@y2w#+<4 zr`B>17LU=s4tybk%b&$n9W!EDRt;mq6H5f#rbzvmTkl(`X*oq0iY@@70&}RQ&Pu_* zaYK@=`Y?smakcW;&&M*AoWdgx|EY(|V)ne4?5z?gL``y=A7_eprX(T=m}&-VsS zWmfOvWeB8jmQ=A%jgoSrO44E zKHhm&Grkn5+ZuG4MnQz^jv0lNaDu+RuBI%yrldmmAw8gmj0nVN)ECs0*;eD*8`lM_ zyZfLMNMX}PY|6Rj?f}G@Po$EE?Wjz2$r5xY9p70?Ye-(ZC7H8lE8VZO=(-WYHpxtm zb1ZtJKnw2YGV~Hp^d34lIUsHX5qbDf{jU2g9BeFq5pRwmg1QUY;#4}@i6)0 z&jrDotgY3Q$-JeELV#G!^mLJ}pIY&Bb;5O$2LKDG^nT-UnrSdj9?WQwyRHEyZ107T z>+42|;;r3?-1clY^K6nuV0ulKRz5K8Gy`+0tYTm8M6(CYMl?4rm;p&#TNs}UNc|qJ9 zFCVemT9IY#8Rw>J8hhl+Yk;U6;DeFMH`v&X=T8HfOm6NPj7cq63t#GrE;9jzO7}g7 z#(7~g0ZH}97Y8w+OO!%cP>YVIqW!h4!p^Ofzr02O z+Wp6$iRpPC*6tX9dJq)2{}D#!BxrY-B4QVQtcj6izcSO#P%1-nI9m zyr|4FFV<}Jj<461R5S(3B!iUH)#v#s_X-C0IF5-b1CI^GR2WsO`Tm})rNH=iqRx{# zhs05GF2)Od5s8^^gI|4nzP2>~vYVL%hSYBFAO{B4Obtd}5V=az-TrVok|Su%r+wPd zZjqj}fOXi$|ED&+v~N*e4!_h-;AiN~sNqPf(P3hlwG-Ex*;*$P_vV2lpF7SV(aB%y zSc9(v;hTOdppRSii5Lf%!&rlEn(%03 zeXrQBjY`EdG^~ffttBCE`tm=7+5{;o@-_1{Yp*8iKK9KztIf&J=lJc%wjtTOSbG~+ zh(2U-H7$F-5%WfaBOQ`prK?A035%Xv^7R}39dx=*-u?D8_6vhA%`r!+klWN*dD0Ur zzDZ6I^d8OH%b*oDht+%wf!w*zxXZV+BNfF6vGzpONY4^gf9soBW4#cNu*@f&78QLK zS)MMxV=sX=*Q(!^-}t`xC)~cr^;7>~GV3CBB`*dNo^v&K2u`iNwxk5zpn2O~7%Ww# zUFG=MG_mWXe^}!%?$Cm~-A)&^{nSqD(t~#)a9!f#31NUYgs1EPaq|&UoU_cTTiDc9 zC;`9Rw1DxJ`wvwAx|>dK&O7ffZcN>p0~h$d4B-UR8I}(kf#f@$u0Lt~UbB6N%_7Tm zSo=&{<{_N=E^%3kz2an*5{NEhwqTxTLByEPsKDtKl znDFsH2X*4UqP>pP|1ie{N{Guq1@)|sf!mS{C#mXT9enBOB#I_gc*KNLAdn~L$+xuD zAy-~?<#!KUY?+Fk#O{*)qFY51CHVi3qqFd9@_pOz$WhYBCL=c*Nu@i+=q?2$Mi?|w z(hZInB?ydeR6wMqWt1SLbU2WZ?hwB3e(#^K&u7nb-_LcO=W!S{#<+(Wq_B7uC`b

    yRw|A-vd0 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 z zA}t(bxI22nmLh*Q?u}K*QwUQMqx!DFZhQ8#{51z-^82TclT%$c^or6Y$50MH-X;S` zGQ$|kc{2kXK*rlug{c-g*&1utw@QR>O0g%Miksu4tQdNsSPwU2QQJ8dsNM)uMM`5@ zpV)sOvlhc&ia@ePh1v&(BDxfx-->%PiX&U@9@kA9!|ww4&`(GC?#;8hQ<8Y98J0l8 zOeUc;2Tr^xTca1=&pp`6Milux=H5Fch$fL~OI4skJrpEq7_rOPiNns@Sv~pjL8fN} z8jt2KL@j2=@LFj-Z02me3?`9~Fa3n!UpJCUoZI=0b!V$Y0p*Si!bF{(;~2juT$?QXI|*8J~3mjZxN3c?ZFUuX`d(qT4W%E8ui@@ z_#L$pj2-qkqdqmt2IHiW;lFLXAKb-GjVRmzW$KIJ>c{7|Hp1@<{K+>=#TGa<@;57s zb8&c#HeQBLFuc{-fC!@ChxAt+rY5$U3=BDZ6oga&##uY=ANzwmZB)(P+fx~y1*n== z`V9(K=9v~dJW^>NrF|zc&|Nh{aK9?I?~p_R{ z0p#Z#l#Xfo1?~86X4=1*bJ*0C&-b?XliFprl?3v69h4nfhbeL8R3MI zoi88B&f_5Ug%4aBkiR4MsS?&yfc_}0;+6(pYhvy@&ucLMElAQ8zop9}In?YNHt+py zV2IvQ)JmCNFk}b4j_cZRYf1Y42RlSuoRK5{>C0m#Ys?0%fzyEV)jGT6 z@AxYAU)3<)SsNQpYL2BV%Fr_LJ(iI5()zgWEx(|wLvYmm;=Cza~i;brCGhZAs`OU7% z0=ZJE*{6OX8Up_7@}wD(V{HNj?}l6)m7d}5@fxj|7)h>q?U2xdpqt&sZCEhr^sv0C z6I9l~#U=UiI%!*&GU0k4nmP=Z`#4%*0FEx74_mYF4b;?>a~<*7pGvr2IeDiXy1?RG zODR+s+gmNV5h4-BLQn{B-_ost4Bp?&@)B9ax2SZwiiwNwrQ9Yb@fc;N_gAtZ4R{HU zWziULzDVw6#?X1#Ew2M*?jmd$QFeuaAoC@*KDgVMi={!{Lp3kPG$JA(1HQl$K@dY|NQpSZ zZbd(u>>!$rf|Va)oGG5jfGK=*fHn^b-`!w4FoJ}S^NEG`b=sQG(}ywp8eW9Uoezw5 zu}kPv-ZtV=Ei+}c(=BTaC(22*TewV#oM?X>ZdpQipWkmNr;degFU`GE(fz56^!{W- zT1$x~Gnd|fARTUvdsCn+j$h{8|A7j+3()AB?=Qj%(?g6ZRcKNPiwv0(OWu!c9)b*s@WFw>KgJ*j z2bz548|>-kMrv`3mRed%1;44$_qL8E9rMuNK`BR@XOunh&%4`8*XnC8_~Z$!Qm!X1 zX3}u-qoWZd-=4vm3Y7+n%f8@kx}+|po3<;_y+<~?(cLYGq8ThUj~UT7Jq?1f?WmAx z$T<;83}??zVjTp(Ac;&28-Wuqt<6b#PcO)OnWH?Oy4P{GTE39}Q@*B36A$IN0=d3s z_)37qmof*{hCbrPO~pyp@KFxbIbM%kGT|E{3E_-b&J^xXY<+=%4RZmyLm10Or$OqS z>Sa=YUxy2&1^lmE)Qyj4?<6P<0h|A?7;_@37Q_&py*5DcK5wEe`)4%GJ zpTj`Bk_QQ5gx>@Aol!R*tY3uOkn49Vm0-cvgM>+I6#u=W=*c{6^eAtHSIWN$-tkAL zLR&->@0t2l_)!_!*5dvk*p~c5UUtZc4?0GrE^nyzFvV30bVH6O33Yup^N1>j0^)Ni z(a66!3Nif3s$kBz&U@XWi7#e@Ak8Lwr2TRuic~Mq(|s_EZz>Z33s9+Er&qpx&eE$P zRMk(R0ZFxg+<0h5)C95{@yN$W=9hy?D~b)doxHIFysdN$1-8s`>x!Iy`;!aqS+9{7 zD7$2Dni8+QCI=JyQ-+QWj{~tuiw!Js)@MQ4FT~Mh=m$tj7KJrX#UKp3O80M)*4U|n zQ{&#=__z9Pkw?v>mYl3?DdFp!ejA^DJoHSoM)==WG-A8Vpo%B)B>I;W@^_VP_mTTc zDmGQYyXm&`E-3QLOe%!Rmz zSDn!|BG|YHa$|wuPc8cG{+nqNmy=vZ&xW5!OWgL7 zCLP9>yIBjg1HNSs{d%MQm&T$r31;qkUahxAMyZ{mdX)n)IO!PB#V}l6;Phz%*prBK9I{u{Xp89iTI=ycMOgkq6c<+3{*H3%g1!t zYqqh)k4ZlwSQCoNuol5wxn(TJY%mr$IXk%2oyxKImuIYr+k2m0RC&Q`RKojNq;r&! zKPZ>jYvhsR;O?d(dtNl+!=k+xtC(GDhEi2UZS@$n6m{!ysLkn?zUV~C0BAztk-15x z1d}++*f*BNiF=FMVxgSth~PGF+4)?tMl}&cNhuL@jGV%1jF%(VqVF4c;J~Y(5rz7@ z!k9fW9)D58@uqW5+Mg~wE+!?9DlUc>*D77ES>lb z;6qnBdDJ~mbnlXyGEQu*$y%FOW!J&`lum#7a6dU$OUs5H97UweXpOVn`^0F*%pyl2XEEa0jSpJcjz*x z20i_+wMU_fijBJK(%$_3H230^B;UGAAq@MT7$imy@y$wcC@9(;PB6AH;crXK(Ep4U zBcCOCjR=!o`EzDV-~g&f*Tml_K3dk70$Nliv+ZyDvX2eEm{%qf^X??;D>;Q$h$XTx zqxxS^q-!=%Rm8C{5j~d}Ot-p-9D_cam~4a={mgtXAl{#J*MqnF*7V$37J(gU4{ym< zne3vN-oa7~rk9dtSE;4ECS}bzKUa`u^HvD_$nwp>`}uz$;c$m|9j&KArUstw{ZAoL}xdvkymh64&vt&HQ(xzP30PY}z5|?^y`$SpFfT4t)2E zy#^2ihK@W;eq==toZBRGwc{}6I+mU+b#?5J)-V%8g{U#Hw4&X5kwj}Pa$XwmuwcCb#-D^scmQYj1$)(;}dX+_cWG&hD| zwtUf`ypZ_LISHQbRrVLQfD>;2+E}wtakGA3`FaIm|Q41M#6l1v{g9Os*%IKTXJg zfC8Q##4cgXMilfFCfH zs3tr*FKH7dnV1&GE6S+8^DnB{WOxlp!^(nVQO7!8(`94Tb(&4D4piK%rIkvt_>o7d z3y=15!d2^`YIcIGq>ik}HF#1lAe7mkP|>>Jhx|5JEKHBUW#daB)9u z&i-cze# z|7m`5HF0{)ju+fqwY2|iFt_?dI}nk(>nEGvCKyo-NRM=}IB1TFUF!D;z|<2Ofw%n`j6u&?j7gDJj@RsiCJ$zNXlf$wJTiy0q}eZADT zu&&?Ig75|AF{`sHeDi0frLZo-rWE}9L4(o}PZ9OhU#)ux{#sovEf_72|MBo-aqa$K zb^E#R$B$F9Hvs|Y+BPG@z8yX6U`ehleT9Asxbk8g#@-ye22LQ1zhSW{=&F6jS{3u| zqy)cJ@+*(GN>=`{vPEbyzyADJ5yL=6HxD7E274ARFOe1v*=9~+nVV~aZ1S$Jd9lVc zUT?^=IYOzUZ!D`*L+Pk|L-u`(*O^?Wyq`6U`&8Jw+p$(C$`vXi)_sD|p{{jY50lMr z%_luPht24J+DQ={bi2k~`Y@GS{a!d`{_uNDDrC@b^ko5eLd&6F6KN)uR@ps^-z8su zA*tS`!{?g-G>XSBukd8nWZ$>K?AMBezpWD-N5lgjHeOUaTq|07D|&kKR2P_T2I_i$ zkwHt%zAX#Qc=po8gdxDE@?&a?q$c~?Y7X-$4LF6}>)`zCd~V=eUhuSG?CXCZNP_Ow zAn&IKw<~sHr(l!SxTvl5o$tR)e;B>E*s;=2z*jg8SL!|%X?c+^lpz%9TiWC#|LPTE zBd;#E@UM%B*d8~%VC8=Vu{x&0gW&$0U3?)fW8GCI9e^0@N{6{K*TP<6H!p^xptBi3bk&$%3uA!^7e} zp;P$jgVv%e;mZ{>&z<(SJEpi?p8OJhgJ<5x-9_)2jv?K(qc1A+2J8?;YNZ%3u^6G+ z)j7z=9?Bv^Vs&*{*_`&TkA}BQFnP%=$$bLWTiT{su@aDQZ%UH&JF}&Eg45>^=&O|g znV4XyC_&}4^?5q{GuO6hr><`YbUf&eF`-X1>O$sqz`=eB+cJr-dQjZ86|D1f=5<+p zW@(eEQ3qFhJ&2bbiQSzH4kYuyd2%o^CMt{V@V)uf?kbkMeTbVeaJD2B|$Cc&njx z^YZ@?SpF`!lU=~~ugdD9q0Fkjir1mYo~I!qZo zy+?9mkSv8G;%#IHwR*6NS2ILPR=!DPrzH3n+g;*oQ_c&Ws$HPB-v29r8tI$Q99frl zUefT<rOejdVH5rjbX5{Lsz+?Q%7XR1Gv75R<~U+!N#|RBi6yW;XwHD0N z*%xxUjR1D|*{cX*1YdSo)ly4z0j8D8#Y>TOUGPEX?MfT5KF zP+61t>2J?hI6mtPS4a_yZE008ky%Oicflt6H~4tztwZ!Ztnt#Ow;~Ds z@avXW`fX7wq{>9vm?|^dfxNzl>+@lL_gBTX?x;IOJEV=R@iU8CE0$UA0XFE(M#ZyG zsN5S^#&_<+6cd6D9m}&dstj>Ea;T95n|;t;z*D|b@mV&BdyG>CmnL;4+L$1ECik9G z!oNv+mwO#Q$USk&aOAsrZBnF>{>X>|IbNRG%K_qRjh5l(10p<>c_&Hpm<}OswU;|= z-V0~CzCXbChdP;DRdee~cEL++kjP8M!wEu>3SIHtm~{8=LfYrCLezZlD59Gix}C`* zwOi49oD#KjTL1w}(i9xNV?Z|@l>aC|cQ+MMYx@WjWRVmkq9C@@nKrBpQ$ z8kDz?76QesyklFL4j%Xq<Za^7*FoyI;;GmkBA)PN{;8CIN#9n*oq-uwezG`tu|+(dMa}7-zf_~JcvUw^q<7? zI0#TUp^~X(8 z^YW@cONv|rfH&F0OAtc}t9DoCy#+E4`ErCA#z?wOg6ucJXFcBZ2&UgEo2#Sb%=N5Vno#`p{#dV_ObI$4(Rt@Fbg(YG6Ms#)$$dMz)y5P_ zS{$fWAwF)nDt%RjU-KGn3O(bm|#|26ye-e{M!;hqM5sce3cDT(jILbUEd0(&+Y zky1{$tnsQlQmmlSa1U4SbDcnRdhyR$NI{ZVp#1x*n5d~ zP6@lxZ2QR>v;$Sge3_a0x*3dK&YsYBw%sVwQ=-$GeB3Seu`Gr}A53xenhz>nn;#Kb z0EgdPOA`ZcGlp##$vT;z@iniw`>i36fV#Sn}h9iPYWxs}ddtu?>SWlr$+(DFL;X8i*jR_k(D1 zrP4{xW%ef{UtVxhbdq2ebJPY~>1Xa2_?^kK;{v$iMTZmGv8FSuOa^O`>!35|vyGPz zi#utf1i0f_1qIO;Hld~-%joDhY*yh-&#tfw-d&Nq6F~1RY}oWpM@{0&5$)rl=GJ79=MAvNK14z%-qLFTGQr z3wJ}!A%AT=29wGMTMCj>ZR4$pdDlcrIqX7xg;!VE3P_GtD3wiRev6hmLU1b)DYC4) z5(R*Y>qQ*`O!lmt=^a+1!Eqr54498aUW?FV-)`C5tMGKS1ja2G6lww4lee%psull!D7!r4%g3tUm_JRPMO* z_;7zB;krDa!>fVx+7D`p^+taYiFDVT3MHmcpLT9CEf_Wn{&R?aCnIYNLEC{9PYECX zcIx>l301`{<`$(Nc_fJn@ z++#xv^XRxh;B~t?|2|558Z1qgFE~U*%_{y%Bkj8HhKZdMCvxM0Cdq{iozKF z=(8QZAmv8WTSx0W2X4yojiQJGQ7fGPdr+yL(<3?Nqu}xLLh~MR>licxpezw*!z_h1 z>i&v~5YTt;QM)U{Xstu=nQS&E>W7a6a3(QrOut#qw6efi17SV*$diqaR6_77_dlY~ z8X*cmWQ54(d~8H$BmUpy62H;e&a6a3=iqKeoMMX$TfyA>m*dz;nu{V|HRU;4pIvyw zw{~DLKDr}!gpz1^XnnAe#?lC?h>{BeaFe6C9NONpUmrXF>85J^ZBO*};Z@&?XIF4* zBZwU4mY;i3`U&X8?AjLbZ&vU*VJ=+SK)9O^J~vC?or(I&Ix;BELAScD{P6&l)8iPo zb`Tq6a`vuNH=QhVcDdbNi2$>{I2#Z=A9DRLQC(BT8adp%_L~6bs+p0wl-dpe|B4E7 zQE!dz-cge_5v#EC{O_Zr=slW~g0 z_En%ytl5(Jfj62m()>=mZ=3&B0?x3ORAg{WPc%D-N;!f*Y0X z5_tohS-j-`I6BX8w%fmr$Bb2bL~V(!O0;(D5u^6JjhaPkQ&jCuBgEFKJ!(`@t-V`` zaoc*UQ8d)3y-Dfw`#*2J%OS^=>-)XV^Yc;povX$h;&i~_$CrkU?w07P2-PC@v#?$2 zq+OM?x9K6F+vcLzSPsRKt2$d2WNQ=Ma2B>Ck6!SoaLG|l)pM(}FtC?DHb@X~aXZ!p z14U_sY==|?v7E5zh{gIVG9%!DQXL3$v;vShN59zG&e3L;WcpXs#N_yXxXWLV5jwx@ z&abID4k?Ns`83#>zaY`(OAy*mC-G$FWrdE2bUa*{QQLShEdC}y+dt#qYb#~s*4OFy zGo1>bqkZQQ4S1dOMnUxQkc#QagzBTahGZrAL)ejl^!yph>j0f>?7?*#Zu=j8xyKLO zUy5jZSF%fwYVq+XM_K7zYS@*txG?M^N8j$cEExW@KGsW*_Mc?*&3>s41aH?=&zU{h zd)4rP&F-7kkAES}+V9DkiX2NCUte}WuFJZpy*)PmGd1iw|RdFseAdy0PXS&8Aiw|5Bo&=!Q}FB@lypk8;iu5 z&yU_0o9CXN>^L5S2&Z4lo_UxO5{-4u_@3A?jShjkn@);>uJ(s)HIWn$Uj(8S8-S1Q zk2-wYdvMbMW`TMNn_Q(*4cW+9(DWOz^Z5@$j*7|=%%x(n=JPDZash^WS7XTm{kDJF z*J;b|S-SYu8U`JGc$Y~JwZbqwmM7QVXzqzfy6$@JpkdFlRZhEJ{jgFIHhyY6W{?^H zbA^Im5DNWNBJ1S8SzsW(d|~$R+d1X30%Z#mjNf27J7D@$@MG*X$F%>@qpzlk=wBq= zqbdyretmaT>x$}dLtic2+^IOP$htP?byQXmQX69W48ZOT=3Q?Q;}Af13g9Ap)mp#n zc3|N8+}{SHQY6Na5R&z%s9w!)Z`AD=1-<(+D%k>Az`H$ubR;T-oAl@s|DKcwPtE0E z>5t-ockchT8^`B(R3Zz{R4MiF#4s{h?+e-9JW&9~h}-f+Qc`1uDIl1kZxMULa2HXw zb71pHTDW5nsGrpyB1{|c&{=nBNuM3M8gbqHZPI4Ct8IZq3Nr8FoNDX)&YYLi2TZuS znb78V%JqBYOJYQfi`8?9SF5_*%b1rF2bh@YI_kp?0nBmif)}Nb3rrt`niWnYzi!ttq5p~Ic z_xuFoeyenRqbSWpXk$1VC5S)I@?I{K_uqV+AqY|4(ahL4rA|1#s1Xt?{!Mut)x`N+ z8iF()IsCyK8CFw?;TCa4^V$I3E|}||k4z`$>^pe=XFAZF0@w$k*eu1)mdFaDiFSLd znNgCo?>Dz~|AXGd@dJzKH1c z%|fTt%93Kf7-JKRztY}Rb7Nq8XW(H_QI#j`T{@A#LZ{`U@y?VHsU=3UxATudoN+}J zY*U(^LawxgZa86x?InHvj-*{=-yJL$Qi1oOhqx6lvUL7|>YX23Gcy;`Jc~U03Vgfq z)1u~gJ~}!s7F;yY)d5khYLp}%xXdcfktCHFu78Xk1JSH&vpv(rq|Y5;q2<82Y2qfe z!%Xx;G9l03hhunRd<8@cczQwX&JCT7EGrZhc+wu_zaTE&H#E_2ws0MTaGnP@G5WfZ)w^TuZ}53(Y}>6O#!h9BNyyG|5_>`!HY)ftY9@2B5rPO zqjesnIqi|~ox=-Uhv>-0Ahbj;|$p)==IbIn?~oGOR!1sAL-P&s;fgS0XcZVkcAE z)u{+p&Z75!>$tS!-HZmtU=8#H(PrxpwWauF+!DEJH8S2q$p*bS>6u+HbGm%XBlEF- zQ<|rSRmaXTYAO2HUK;mDTox7=H}{I_Xlw)8Zq({MO{i+Og%k(f3dOvmo{EaBr}ac$ z{?-!@ZZX}g9C`V}KEmvo`2mgVz42hSC*1W<;oM4*z(2@ngJ?=)v+YdJwB|dMyCk_q zEgDZlwC=J=pp72*(Ng832A#Ukf<8L1vB@soNTkGs643)WyD{jLA^eX02d56swBgS> zs0OtWhLaq;@4ob;BF7YyG)SphPk%&C3qxc4p{0|U7N9NoMJm(?LX+-Ut<748h7dil z-1`oAZqLb%zS2;MxykC&FaLwpi zE`e^uv3hbm+at<_wxx96pinLbD#Wab;n#ERddvv~y)r1|#pGl1JqHWCP+^H-EKN8{S z*nt!bm(1+Te~ld;EYlfYwOs9y;=d zjq;y!4OkZi4oal024|GZ^2Y*_Leejpub=X%4Gmj~J9%UO=s>@e%BwW}1x4Yq2}S~B+(xka1-daUwA1FbR8a8>heFa|0S?0AumC7X}0QK6z9*yG#9TdEuy2! zfH2!Ty=Yh}QYxOm+D;Lw6>UiImRC2`6uf^G@%5(G)yoIliS5IeJg;H5^04iGjt;u_ zAc=_iPU&~s32usGH9WXvOSp#Em}!Y)#!l}|s-w4d+RYL-SlLi|v!sXlU+x+WQ86)h zT9Y9wah}CapTUiobAXO?s#IeK(j9Y(*XECh>mi_@jOx(ZCvko2Lf8qz`yEtV45nYn zi8Bn@medr>!~Jv33h6S!B+Sghpz$wAz7M$2qJBD;xFX-li7K(ePM2pUf%?{M%3)2~ zAmo0YxSk682=7T}|IvhYbV*p;jP?(H`;~f-IVgZcNUrbp`^~laTY49o@p|Vc`ETFz ziBfR~REF|29V_VmH};BSExxJCiK^+(plLO3@mMD#5Sujp7;>}++3}3~ zo5k~|U&@K@K&_0C-@N8mR-248uq3xNUG&Aj;GMb4)cWD7C{=D?k_SK~}K6v1lq z!}v?1=&=;kQ<<0u5K3(mdx7$}rlB-36;?|F?9QsIv;lM%T=d8?L916M>}sPrS$E%-&N}J(k59@SZC3sl{U+Om(Aubd z_8ID;XzQu+lUT`rTtQ9Z_rc+?w6I5|LB=>G$*L&uee$W9nLfkWoD-G5F7-yrZ4d7}Y&^pjSqiXZD+g(!Tl9|CU^^d+66w|55*2KUJuZ6kaE`CcDf2BY%^CuV7-p0)o;V zz1p6ixQ3&W$9hhCPqG$>e4~{W#56uJZ$bE#+(;8L)w(v^j5Q4tKl!P~cRYTb)-tjR0-ERivp(S+B(t1FJ{2|@A!ZSmY8V(6tMQS)}7Dquc_Z$zA>eb22KNd*R zNawV~ht33K&TB-8&q8n0$uL&G*}03T|8x#dExJZa&YqY1;|T5lzcSl^t0_T`l0&)Z z1_c_$yK{p3>UFrmu_Y(7?{~_C>y`EP`g6iHUu{){;zo3G!50BwtpU;^t;b^GNREZo zFYK2)o;??wV(x|7-8g!W$h2leBZl3+^Ce^PC_`fS_bXpK5%1Cr{VE? zFw*|S^@G)^P@5Ntq90<95^wmWeWlV4MMuBUCWB4$>wlWlMP)R( z;hX^k8Bd9 zrY#Rsl|_^@RnoE z!pV@PPnu^6Z&(J7g)T_vPXNaPV1GW&KYaBas>_(0`4AesL1y$0I)sb4WWQjVIm`fe zzy|X$ta2NEuSCZoAP}c^s-KLC$f z8#-0BFRZE~xr~}|*CkQF!Y==_HtjEENu{IN_k!=uvOylOTQu7S6Qs~T$6r{X;v5-(H|B( zY#QD(ey3uZ$a!!N=%f`Xwcgp*Cq99u-SH>ZaeYG4@ z13H^JwECr44zcT~Ol1Wp&oth~;8b?=+^ktw9kE29$)h5wvL6oH1FKS(+uj=9lO8Iyxn0o3ajokPcTOM00Ni?CE!;37z!TWM0hk2cQe(I9hu7afgf@%nI>gtr~E>g=>GDrM{ zna#ed+H}!Ydo%H0$@ITWWt#89nx4b3!tBa($NsCQU*&ePTC~bXuj{9qg3sP~p_0E- zjC6S&#Q?jVDTIJQ?H~2j4hK>cW=J>^+=RyX1MnR_+YY1tE29^sb_7wnVI7x+K31{vPr_@GDSN2YxGP1 zfcDtdj{+kjX_1jGjZL(?vX0R*{IIIOZLIQ}E{%p_!P_egL*H4ip>*PQkO4q-+3qhWHLBX58f)-YXaEB; zRS};hcpiyh1mU=;WhZn6PRJOU@87RlTt_1kDz$-*S~jt=e?NFalku^arMRpxjX9k$ ziy~+&vh0K6FupKyrHL_C`EF$g%a-6a5XzkHjpoCjlc zGE~R)1RncI&G_Y)V?MK}XUZ)!KY3`tB34*zObEoY1H3HKAYH$)uTbM=J(i~K3Nq>9 zz~OzNb1=`v)&Pg9&KNov^Gl>@k9#soI#$itztC~Bx?;7Q%J($mW4uYcBS%n`<_MaC zH!2T`3R-45({vQq|1H7#_K3MT!Tm{8;Kz~P51gP9zp$Xr`|6p-FjKf3rhm*tT5mLo zhc}a)xJc*G_d6e=Lo*-hSiK13j~ByM7xuIJfPwnL)wW;{qZ%|jelTZcEI`y1D<*IK z&C!nn@2}*pte__4fSbZ@XKJE8Ncw8h$ICAZwOoP@Ul3e2D~gv{X(v~S-_^r%CKIi! z?C6ItmcZ$8Gyesh_oP0&voln}|KZ)SJ5hFAw($!Pw=QHt7nYox3F$^Q$K)qWdCrq=|_l~Nrl_-(wODddG{$%1{ z#?*VMERIb?7{g`GlzjsyTZ=6&{DZGX23Ym`HGB~r0xZyHKBjVD65zDc^5k>rPNl&S z7w%dxKwrM9<5Br@Uz3>QS6)x8SCkQ-er>q|fjxQHk%RMO!Z4?_oobtj)K23n|6csP zYlN1vpMT7Zz`(ssYd4ZWMKAAvyLI3Ce|Xz4@c zFf|2{Vc$m#Lv!M=jJS-n{jq|-ASc49Dqo1j?_G%q5$cwG{zrX4hJZeFNY=un*LMwR ziCae*Q2toMH`TyxdY?T?s{B!W9Xx*^+QjunfB29iW*V9KY8Z!pqUFdl$4gG3Qd0r6 zWJ0%Q-AKbc0t}ZJ7>I&X@}uHSY&SV$L$?LVUP5&4uv6c4@ruq}=EKq~0$yWE=mg@S zUu6%yt4$1YjGk4%fw2KxRkM#<#Ke;8Ox&Uvf*-^9F3^0sT&Z;*#oqS)RDWOG+sdQF z!^NigAd|O(j@4XE+=fUVayt@ht6}I8Blvr0}Q7MqYS}VU3&FoMj1^P0d~9WLC|Dai%gm&$Yf{t=?|LQH}~gccD}B+~%P4*!&A3QqPwm{;;b$$la1$ z%)JiIHj`AHM-Q&);#rjs@qcSS_Pl2r}JvM+(h3| zrvFR;V~GjlQ0@3_MrbyaMuIx}$9j}fdJMpF64p00P6h5lIV=Su*euSMpi!SY!%nN9 zu!to=nhn<35sn}y0lHDJbBX)9_YH4UgOMT6cPNB2VGHyTi8`t-tC1U5ZhXIsdoLC3j_o4 zp-mXnk+R@fW49VNROs$lo&& z#!$x;sDTL4#uHN+ddcdA7x-dMJfLf!g=IU^;sguRI?q4UaPY2vUX9N@g4{+@_+FoW zh@V>)PL*tGpjOfW+8i(!$R@GWb<=tv<{Zez%*2P3@>IzLlZQ$8ZEw0K*nZi^cwJ#{47?eo{armHOC%YGQ|Q4hs%tJk0sjfY1c zxLhNo38!kC9mHg1MGvh|k_H=q=rribL;}g6%P<1sud1rXw;W5t{82>WE2TlqwFTYY zIe?z2Qw^|KBV`iKQgpc2-+#Oq>8GrtE8WddoRo7xPZ$iKw4mcP8=744J(#BT(0BWQ zke~e6o~HeiRbv-Jg=R574BSjt*_)Q&%Gg8vSN6czxH(}&AxWTHmjle3PI`$=zqxzW zGTW0YHj z8w;XWf%LV^Dm$YrVndV@z$$JU#3u-4ZtoSypfM+I0|AA59K>?qsRz|&vH>bp7d3og!Ixfn9EJscd zDs=qZTr0#cbwBQ@Jh%A#nwnqr=Be8%M)!2(Wb_83G1*V%ECB&Okv^C z%tAywDT@Pht}DisYEkxqBi+;v%etT(S+CP%W|FV)S8~9GzL}<386qF{K8{r0e>DqD z9=c^D+*f%5(F-d%Ud&?9*`c)8*}&mm*tw5`#55lr#Plz`8IvxF|VYOA%95F50O`yUO31w1RW_|CKSc~}j#s=ThtiTrXu zg&9SJ<+^j6`$d0-T+1q&36}cfbuP&?Nwn=>&uQD^Sf2hAp4iN{Gp;e zS*t;c?Hl~#a$2{nj;nPgiz30i`&zneK4X7DmVk~LuoUu2WlgajDw&M9q;+fZ&6PXr zN?a<*Do4!U-YBo?*?RCL`t6!C2qG#t$^8m@IEHjiix;awe8O#o$Pwp-Uq;6C0SHw; zn~#T~>n?b7aw#}F_)4G;?h4Oe7ugfrF5JZ~2VQr%pkGHD+IwV4vz%(L=-Lc1GYa6& z>q<8v+>tl*zR%fT)QUWmZusR)L@l_=@wDX`N_hF0ay4k(e<1NnXW-p5bK3Vt;(!DS zp#nZa(jijP^`$T`f0%|&pPJ*Vsm_r|MSVv}(t&eN|*wyYMlOydutWah~3smzgp z0u@mu*TSfs*K+E|3S~uVW2VfS;zSFGk>eh;N`Nyh=rl$S|6#SdMjw>>NK+)~q&J+G!!iPXh?`lNF<=Y-_luvh65n&2R- z0a%Iq04{~kks;XI)r~VDDmLohlcKkpCQtWv;7U)&7PGk){abUedlv-E%(P>odTc)z zM9gpHa%@Wt#&822C|;?^FVfe z&E7&GZBe?H+gFAnFX^+UC`$7?-42QCM0`i@p((Lg^{_H7`eFM;kSJ4Zh!5xOCm`&z zLHO*i%oXIiIvnKG84!5_6dD?;a4o~x}D9!dh1 z^1iM69p+g$ax3oi-^MJDxs#RW%p++dZK3F#YK?TbUTH|3#My$}S!sGe@d^QTQy}kaR!$mYsRDkX#wWepfT0Y=}i&&nQuc1bjiV zmqoCW;61FOA%zh$GXbfM9;}agj#N#*W8Jwj5?rHE|4;JgG-w1orhp}6n1i@&7^60t z0|iCP1NQ@mqAPV#1>N~5VLVtx-Z^ukw%fR~- zORJYIg|W)mYFNhWXie{nEDrH^39bzMUgDH1P@zRnLQ!~7r(lE0u1n5Hftf36udQJi z1Pz`kj4ItuqUa-|qnUzVGSs$`**=Yn)?ivc#RRLmiZiNWXI)R-2g*U=*p~2UdE7SX zed-M@?^9TgX4$WC#Ql4gHsc$M{8^+UWR?(%|LcN5Sh1>}6F zNUL~3-7-uMh3#uOMl`%CB#Dc`--NxStO?c2L{ z{27Z;_wZ3;6kVHh+@YJ`>YW5;N_I?zcP;(!fugHfu|XLYrz|(2;*$wf34>)TeiZ1E zFsB7rim(hBl!ArTjv+1wGaQC@;vb@*KEnGu<3DP@UOm;xkXa>zUPmL~L16B^AdI2RKCijHg#AP1-rbMcqRnN9flxsavKk)j6}8=yX9y9;Yx# zjx$HG8K=v;R|yNBI4GI(z8Z-;3uQhUcrwUO&;v=v`J%Em5t{Z-`?#-8%1`UY7T7kS zPdSF#_(PS*gt+XtL79Gh&x45KqOIki@M{= zaDWo)nAAZNE9gl}krz45oGaDDne%w*SO>|Ne}=Sx&}4RY<5*>cPNc8T|G0*qdN8c3 zYmd3HtcdV13mwkec%He;nX7mwnm8&i|DYbp6LD)g#Jcj%q^ zdBXoN;V-tCMj}W5Elt+(PF)nBYsCoqmHUpQx9a`Q#!rDEOFJ;ANeEim*~`b#!nYPG8*p8*czPyi^Up?p`9mq$3i%RPR$8 z?`0ugD964aPx!-K{z;P3Bu%F}x?yBdd)KeJkZ3g!tM*ir?=HCwJI8GJK4nbf{W~o; z*Braa4~2y#QBaOVD(!V12Xee(5Ap4f`gtYw#v{C-7Mo`RAPRO z9Q-Mx0ieA&;u`mLmb;_-BaKv?rdmo7Y;o79ddj3}GLV;-s7)c+G4r9)i>)jHMyJm) zdqKzu-R^ccQo7sRk2xH8$0B`h#ibuqPNqMJ0DnOvEpG9T!zXe!2L+PeDPcg=x$Ywsme`4%|TwiW@3L zUTtNBsEXRSK^Xomp1FP{^cQ4?C5f3S(TXi0ig(`h`Ki6`v<8W|j@*8KmvbYSg~pH6 z9Rs;h?Cw$979wMIMKzfLsWd5)(3QkN7G-~ed!_C_v_GFPmhpRA3eB1h)QOV?7x0$B}IGHCLqf`%flx z-wV~U$pvdgvnLK{|Ky64i_j9qH75Fo&m~iI*}B}*d(N+`kkr_i2B3{i zSbd@i#b>k1S=m~xMekVe-Qjs?TD8m7-3t``R5VQI%m!%`ejGf$^hEgmdY$r2CEu!k zCl1uc{cVT>UvIaxRds-)wq0AU@+`lrzXT>d`{&JNfd}R5?eA|Y+lF>>{5^L55r`VB zn10}Z3aFC+St#WYXg^7^vmIKE3c()l1GO}Pe?6|uiWz8}E?rrT{(=O1N2&-qXY4-L zZe1Z3zMr=b6#g^ye8$yjU@LMV&|y;&KVxpbBx;s#s&WMHbH6sSzWd-_k*{QNX1~2v zvU5;-&h!5W;v7F}?+@KbhV-^~d`oRLpQv^Jb0@dSbD<*%`NQWwIDf5PJLr3-pZM=< z^%%6_%Oym?cZoz<%gNBwjX>#jX&xVWHYfYHZ?8ROZc?sa?1Jameu|#`D%xjx_<4Bg zjlg>S=Nl=vhRSmXk7=p=A`z+2CY@Bu|NbZbJ+U%JSrIHH*RoQwuk!FEhbToeJNouM z!QysUWiCFf>|;l<{@vh@&m;4ipO)5~3V3T7cJK zR?TU3t0;J*buS#k=Tk3`RJC?viTdn!^MXH9-VJ&3TlYDCfT(v+mVE*5 zJLE8T7PJ;0Oa4pg?6J->f9u_v&?_X*+>@Q_@Pe@NjiunEW$}YThy+!mv%Gn)gZ%Kz=5Oo2{qx~-@c5ifFJ0*L!z>-gp2>fBj${_+rau>a$-bz2 zfClBJR#UgrHD(nCv42cL81&qnupzTE%z z6gMaIzNTsVdM?wv-m5QCpxM?PGQq7dHR~GF<~1+o!5P84;AQ%-N|xi}jn$S<|NNUL z?YBJUxsL}lZ0-%cc3AT~P501qO>3RjCN#>_Iw6nHVe2hQ3*Xwe_In*h_CKT_KJxms z0B{&yp;rc>R*M9yvznS2vuQI^H4l3;{ZOfI_d1rfEQ}alR9B_RLfc8hDC9QKs>8qC zze1YbkT$9EuqczK`+3Enf$(V?nEzv=9ySfa9h%4XEC2ix*Ks#%E^_JIr}k+bqLS;G zh+v0?$<~5X@K|&CgeSK`0=Bz zcExP@)%1#~eeLW5*ko$ZJIaZC@&rU5-iw68~G5pV0NS%hmwZf_AXmydQ|tF(EapmL<}_k1;yT$ zzKAR$#4P^Ks6*q+9^Q-)3;GRT`u<`v<3-LW25uh{ZE`*z->K~V(%Sf^YGB$6J^ba_ ztEaKQe|tRe!Wl z(N-zqjt^1i@-A07u_haNydaKc?{?041907HLQ;s#u(MO>qc;qJFvLo;pkfqSp!AAP- zlzVUlH{x_qIJL4C;hjlH2&a3(Tx4TyKo zc@6W77if;C+a~KDT3y-~B3y21fLM!PY-MY~I=|Z#OEyZyTnD@G9%TeXS!GSOmm>em zc%e>f8_NCqtH=_MXzAi08SHXm2QO5*I1un#8>z0nxQwW#rbVR3jZZ5BxlqWK>Snx^ z8stNFKocR_5-x#&Cp7j|llUFN!-LL7WIC`E4z)G8GJ-lT?FR8IqkhC6tin`PJ%X?^p_AeEfpF(PO zRSlE)PDAa^_wl~P<^<%3j$k-X6L-|^BQ~5#_h6a#!W9hL9p$RG0d5u=m48zWoA)2Vr_0^x)Pc`g9{Vxn`>6qjoc&4&6g1VwjLAcR4fEq!ePu;57{6loS0oJz+T|(q6PXz$I}vxA#O^J(l53jCe^wtnd)|V zWm;IJD;9(fj^JrXBJygUHOFoB*id_8o2*6V&0EsiUdE{S_U=tr0MbSK|+5mv{zFb2Dsv0~FZ&l%T-_xIC?2wI4&wrm~6;I)eb)88YFc7X9U*SLj7@dbN6grMg!2 zPQ1A8CjrYd*X90|PXc{|iNLg!DfaK=F?AT(Uy!t-5*>HGQ1yl^g;dknQ)hSu>TA-V zoSYrmA$S5=+VX(=bq73YaYxEA0#mwi&XZM0G$Sx+dU%~+6T*~?3AL|jA3qHjO+fcY=z!pE>m>o>>97Y&gTsZIo|O zjPAhYm-xeJvZzOZiv(vi9DXc+x!rFVyLLgpGk?F`ju*;Ameo_&O;K`xiu^4CIFo=eJ&#IY4q%nOW2WjD1I; zF$Z?Q-1u->f2@OrY*3-$W*0=V`hmy4C^AepNVxBJ^o}_n&is3O>gEtQR+$bNo6Im5 zI8c`Qy`NIxdb6Mtw8R$~VhFIK7Ri9_X=JLx~09Fi!X ztR|>jY!mnpY{?FYt-em;TCPM^Wdw?DJ{^GwQICF8>D1y$Ufh?qDLu!mDk>(R*E=A$2nOMw6ZtT|X9u6tGFu zsrr6F{O?U8u=Sc{S~%T%{zS{PvYS6&l&bhP}AfIXz`e; z4KIJJpgp1y&)XT})Q&>iG$ZO-ya)bluDe$m_AK4f632C?tmR*lK?&iqdKuZI&ZsvQ zHoQ-QuR-zW>Q{_zx9EpCx2j0V1cZlqKE!B*c zTZW3TtN)Z_M6Pq>KKl0r=;Wi^*{V`d@C44UdxMn34-n={`vC#A!;AvbqaX zTJWjwVe;Zy=y;$)WfTTQhaaD^qU8tdRvo$E-xM>-+Gb148%?**2Q`w(12RlLC zl)dd^Iu|O_1=Xx&lS$ZU#1ffm&!o4hKr06rQ4|O$RcD=6(-Y@%4(knbru9ET2mpQZ z%DMjQY-xxWIVjpDlHw8qtl+~tP$ltd1rYI`^0abAnP@*88*tJ%Wcnn3qHfpYGhbRo zwnfwi<^VM(uhWQ(55&9~T*qRfsIcNv>ER&AIybq3E^Up0t8S98i?%-mFK@t9@f*v9ZFA%)bs0yMYj~NdwH4ic$y@F{BN$dBN(~g zc?h5dJ@Df1KS}Oz8@RJm--w6yVGT^Lp<2S)XUy02e?hsGrm7F zcJ~t}S@^oO_@q8kw=_YMv(w`?nkM)4eS-{|-r4uXtGpkL%wg}R{0qwe1DttVF(Ova zPu94s*(l7t`jUiW&R=Qm|+qR*=kp{d%Lm}fV%3K^-fb_{6EsaiYSLCo~Y)P=4aXbC*AcTJ|KiTKp?O-T|S; ztg;-f{8Pcy9dwY=6Hk0*+6(D59aIux*&jAM77nTa+DL%38w z!M(a+P0Qn+XoElZvDDqw-7^lkVQwk3)bza#F^8(lqg*Q2!s~+d+L!@iWjeh~^1KyR!>K^iuT|h z>(+7}G2D%}G@#4X^-TEGxY!jbm#gIMN<$gUONd>CL~ru&EET0U({8=2aB9g}Kxmy+ zD36s#7NP@GeosznwUvUc1ck(#neScYuNe}P;P(F}UAmHt zzAfDr?}#g7-xYdVrzvSDOxI=)9mC<&@fj$1sjuS43HhBu)DMfxisOIdH}AZRG#%!2 zdz{sna4&tf=z!!LUppQ*W&gye_PnYYQR1d*Y8&p=`Tt`lER>`g&1Ro%SZMK32bO8` z1iB2>nYa@>vQj}WKcs|u9{TV-r>J3I;R}6D{kyrY!uz#9=IqncA&)`ng(tJN?G;~p z-sNVAWwko_-kv>C9g+L3<-G5^CNFyKSEFV9Tn*WLk2fn0+z=a7@4)XDpj=!E9_FZFII7p35VNgW-k)OxXs@fUs}RPI{i)kT4_r8O z(E)}w!92aEMag{7Y#CFz1p;)WT$-2#xmv?*7)}#)RDj?Q&H%T%D{o?&t@nnX5ZrN) z31n4S5*z5_7b<%8;8?r1_3HPHVt1Tqm4x{h;q->4CyR15&^5{ z+qFoaJ5SE`;aGh6s5g#JDIAYM1!XOW=RJRJtcEd{*sZrs`t(`uxbLM}KMWY73+RM7 zD#jlt`S-{zktz`@U4l6QZ_qpLlvd`P9oYtIc@gf}j9AxUFI+%)RQ6%$)*wAQ*G`wT z-c;;3$;Ysl*3sxxL;^hYe}nh;b5cQ_qDlcz_E*}{^nKtT6*y&80t220fdmmx{&N_x zC@{Dha~IPHDnEtZ+-`1GP6{l8$<*~|G_}{gtmcv#*hpG7aZ@Z7-ExXkoNm+`AH*;di5Hrf9#F^zLEtKy%K}M$9W|p}Y*4HR%<| zatY{(S9V+a$XO=;{IO9l)XADc3}w~&nMo`UA-xG)Gw)fZ#_CaqnumiF4auB*8HpI8*l4(_-%{O+? zwi31|YuPVd(&&ChN`{IB1$(FJM{3ISXcH;qT5=HJ8!Ycl@SMJk zHNj^VO53fYK7&x1w}a&o0ZM?pxfh8g8urhowu+<3G`=$cUfA}yn>);5EKDpf-s&ZT zYt+aO*>;R}f0|*M;!?=z1tNoSoMQ6MMcD8;ZBCJDGkIK z{xN^M07ek%EP)6j&$stv*bZZvD>7_G#gHAu4q#8u@F587?obxt@=sj4C^m^>%s}ZO-p<2bMul-Y;-Tc{2aOGL_qoNYsmiL5DAuui+F@i#3pV6O#aZ} zTS|kB>75!f{MW%$Dd~exBLeOl=GKsfhJ<_g@($m)g6OLF74jY5>((}CL{4IKp!s-S z2;l3+uHuyQVDxlfRZO# zKl6=cTI@kRzaWZ=0D)8D;{!H+-7>1ftPevQst7Y*h#T}&bA#@b*hRaCQ4i#GW-LJ- zPH&-#EoUQWMez_0EU0pLH$h{8)qk&UgqvToWksw}OH=6dqEy{SJ zodsGDl9C%`8Use6_t1K%=1$_dS>+HK8P3zTtr!mDFQA0ADQj}cpD#T87US0s6?z~& zT73M;JIQpxg9Hq{&Sp!J!r6)-V3d$Z{@BmEji-b=zmlKJvFx^APM zS`V3-&J29eDD|i%G_Ps}I0UOFfr$oxxxOc3Us8!%Oy_G`p-27&6@j;JVBLy)wY9Jm z_oX5S+>{_v4SCGEmnywIsp@GVNfWPF%(3lAE@~jw#3qRc5L+r0~D&~;;N7Q%t#)rhrOkNF~yj+Sx%-agwj4DG$^2v#)~(QTn( zx61Do(<=reX%zqT+4dOF6x95NNwwjMxHRsvIHn0!P%D0`c>JFNN9t%V6n{{-^YnUX zk!&dU-i>Q$kugNonzyn@7Ku0*sdbggXuvKhH47tT!yQSn1}e(bpV&*CVV~9Vcjr^3 z9RW-JDZ1=b8Sa!dC5#ME#A8KZ63A&BgWvJQqf!#342)e8?hlQvPsj;aUg8b=EdQPd zPLvJNqSo*>CEns)IzIPp7*=HJj)yXj911R}Q3s_(*G#W%b!|^_* zkL{RSP)ln#4JrW|%MGFA8oEAxVw&-fn?$VEsEqSD!5#*;z`^Z3-p2>=NO+dKXxXo1 zZE&0Vqx>m3p-Wf&oG1Z35LeWWI%NTKhU<^qzab%HPEvY31gSux4rMJ8xSt6Zzgnuc z&M9_Uy5tkw0G^w6VT(fA^ujEDX*uCkwcs4lT5(bGwfu?|L_vaFBmK`us`MgVlD|MS zH2Ty?4@J@&j+hD#+}-zwFuS@F7LhvT7a@45e0dy^u!MnTw|Tk!3-Q!%WZdjGG=Y5t zCEfHtc95oN$iDQcIV))rJ5>7_=n&9S`O4;F{`?Z|%yClJ%R`9NNd?2HsKVC6E3|ko zH272fH$xM7*V(*w2Ylh?fwo8=S-)j7T2V~lbovjYkr>$;yUO$Ai9^ln(>r=w{_;n( z)&z_LlKu3)nMc>&gJIO#LRd^GVT>T*0M9z=9AmLAC?6ssbEj62@KAZ*I2hh9AvAdV z#L*)$BdmmZF#LoH$))~8*^@>Z8EoCif+G#B4pY9VVrRTA#y&zz=ytzF-!>~YS}gcsDU`fVvDbF|Kw4C-gh za;o`P?)|oe=!#pVG_6fV#XsS8xt`UM!h2?xk23u==3eZhbZVWZ@fi?&O6+2iNGe)Y z34YWaI9kH~=h#f&OP&7GO-1lKzLI7T=QN%^mw5hCv9mb=5k=iYnT9(nV0HQ_&pF8a zZ#qk%X`Y@vr4;`~1HLh`>54HBm)Mi(>)j5eH!-MiQ*Yo4rV}lq3D;Q-69ZN#ZmY9g zBh#k4WY<%xk?;b}AiC*OpbcW=+n4oI+}8Yzu+K1H^ug-3Fs;-RtWc3$Y|%!<%@n$r zyr4lf@r!jlxLpg#1J<*vNaa(~&P?TR=GsO(0m1KB+g9kbfss5lu;)GZq2)+e-X7vi zX5ut;?T>ipOc~<4R*-V3gLYkEq|+g_RH18ZSSjYC^j#Z=v+FPqwavjMq5_)plB*XU zG~t%MxJTcXUZ)!NOps)f2yK<5Fk20XT3i2X9hxkh@NQ1)hC|{UAVOrQbO!3brAcJh zdnHQ7pxN~LleEFJ{D_UF^?I;^!H`$gFbi+LrZ8w@*1y=TZszVA!i{u9jC21^rKiV) z#FAWsb|?81zs?9-8^voi5e{rx_eQHy*AAWmMd%@$&Tfo!3VD zLJsdBQz^(#_2L%bz&*&j!A67v$leKT2 zpamXez0J-a6*-`YjJ|obS@YoSsS%Tjh}D8{FbeFB=ZHKJG0HM$qYBqX-1w>dYm}zS z&3P<@L~S!TxiV&ZDo(M+9+H44{eGvLW52>|CfQ29!s;KFGnT!VK0`}h*)Eqfm_?*) zRhTE+B;3xDXYeWmlun(s!LT5&QpNYbjo9&VHFQE+#*MqNaXQtv_+de6)pT@ElD!%d zL9PTh<_+6bGSZi0(pw*hxO?ZvUTyRxi1j&{MijM5kMoteRx$FQVl7>M!td_u4*WEJ z*(Xp7Qx^cmMn;8ZFT7C)oVYex0maGgWnau)JdmAMKi493MIlfK)-NVRJjN}jiQ$DBzts3Sp6JBn0@@T8ozVCHfXn^NRlD7J22|pj=I7lh&HsPXw zC^l5W?C3}jd&S})EwUNicB}<#aFTk-B2Ja7%K1BA(2zR(DV$CTurIgGUk3VT1F;{N2zi2kd zO}c(vMpAK|a}mOJ7`{EpZ=@z9987>?%QWUXUAK6U<;A+$3-O%_(4RvYkf~PIe%}!v z8R^O4pYIAC(wX8yJ^UaiZ1SMt+JwkC{MlOv zN3s2NA-jUWb?THH>AFh6P{}zuLrpniV;gM*+LROFGU)RTibX#bKIrq)wtYj6>Kg5w zO&B>ky7nP~)2V2vK)-J5b4POp5p9SKhG+*AKRf0`{XvGqhzH%nSJOV8! zsmG-5tPm4kZNCL*$A=$VdGOmXgS+UmmSa2*>n0>#;e07s8#Y5rr{wy_(35VPHQ%GVp=!P_>uWVshNZ!c77dvFH4%;o;^KPBhF~^ z{GzTSxvWLJmUpZfxi+L~%<0xgE5>7q*jIfBPoEZQd{m&jwxD$bQ4q&xE+|6o3p(*? z(n0ypnDT)UbUYir0hOZGHm@zC3pSC8G?tdzq?Q@x%!i^r;~xtXr#2u*44Gw14vQwm z#yKWJ`P_ z>)1ZPoCG3wJ&s=JY}UJpQuLrGvDi>r_{EK^oQAO5NDRMIMm<~F&B#%Q#7g)_4cE?( z6vSykm%_CTY0+W?G+d$|fFY#5i{*&*g{&e>^#h=Ru0?F_Q}=Qx?S2rMPHX7D;-W+% zq!0IfxeMVN-bzIuJ@q@Ku1v+@JVRiUG3^!S(Sd^tdC{>=a0Pp^e zTz8n2nk^f-$+>T$r+p{%Ipk!}yCApGk9&0;EolOQPQ*(2M&|HXToT;&C_F9Rf6tL# zE!&S3+M`Q9NJqvFk=y|3w!sffCA?`K{638(WC~wo!*%h_k5ZDRyj@xzePRF#aiWb4 zYR#?z$WB7V1yJjNMIRP^^QDzg|5jA_9+91N-_)~C=@kNiUMa?Po|*}(*z_GHe_q9F ziA|G=P{CboTMIuc@Kj~Mb{&cHRKR^JyizX&rc z56=}|Dhq^jP5!i#ug-Xc*XVoKgBU{LUK%y`VP#+3{l{xRl1eyp%|k*u&336Lx!=;S z1-}i!WGjaS?qCQd1sQdPv|o&PrRIV+%4Z|u+zp4TDg+1DDP)_){~z?7l&T<|(&us? z|8!0ylxRFVLZxo6B{L38m6$LbTMxQ+DVU&Xbr*^M@;Q@mGn$jITzM*x>5o`7HVTKR z?u)N5^M5tObH2h|`flz`hcG&2Y0V($YH<4zK{y3rCc%NU4|(`K%SGOG_?YDG$}6-0 zsaWP*N-`H(`~$1N@Tnqkc&nNdt;=pY&gVY!q`9*0xTspVuDb&E@Gj8q*k>MU_jtPC@>_OoeOrs51Y=c7kwl9Lpno?*5=z)Do12N(b1=Tpk8FBuyNVkZ&Dqi{c2TsKg5n^@edcX}41m zte%0GUZ)C@Ujv*7@x3;c6dz;e0~z0){G>^cc(9i~i# z+OPKYI$doMB(78?)Zy!_5v|L;l%cf}0G~0~v(JW!`zY0q!^!LRYyM*b`W?KyQ}6xh zPY2`I@}j~PX;4yM#mWMw@Y7gKuO!kp4Y5>Y8nX(hoP!riT8er5DUp0Mv66m7y%#5 z?qm%pX5WwjVbMa^iN;DaQ<`v6G59g$V=A5jwTV;mIK+2_Uegf5Ty0@bY;u@~&o zVBB3hK#*iOCBK*gX?G}>D-`6+$g}r zRC+tUn%)L=pUcK9$AC#IJW`Xd=`W=Q-wmm`R5A4>`pc>47c27s0A7Pq@OWO}_AYO! zi!0tzBRn8T@GB2&PjG;5{t$2bpfR+olrzE2P3&womy>-2Nb*gj_pgVX@+?%~u{MP` z@}GMZs}KfNhULI5D4<>A{bMYjp@!z zh%GDWm#K7}^4JTMyV_F=UF7i%Wp={k z_)|N;ZjjgZKZZJlYuwi4euiAGr2{_3f&@@q0!>^7Ziu#KgEFGYon_&h%KG{(P%9eA z$p^~7mg{OwL_K_BvTNqyboWTqF!kVm@j)qmyC&|L%BPnSEKb5-@{Zg2y+@+L?WYL0 z>~4lO;$GpAw7CtR@3|E!$pcXs93pZ%@bnnVLCbapx=m4(_4G@+nVN;!^QhCopRcdz zbcU{95?ljt{#nipp*rh~I8(aX+L4d6cFGHiL%s5T{6D4}s8;O-zY7eY86AZ_MLyW@ z%>5e8!npV(iP2(LPdJWAc| zO1|nq~>?>9MT!|=-e^Yb|n}GnWEUw zxMRjwR{Zjb_OdW>FaxO7AeZlN#Z5R#Hb&B<`*G*O~|0mdr^qnl8l@c&f z++|+G_}~SsrMDZm0Bq@b06t@+&Kz?SMH6`;io*EU8Fq3O&I6bzfNwwE9K#0-)MyE1Fo8n|l^nu+T`>D7}_FxGzhlmG9!8NaQLP` zaVdz?g|7@qp~$r@qFUbxTT!Z3FKl2HvALlXlC&VO(&u29D_adPJH>qhs9OQy3+2Da#(Kfr3_%lwS zeedS*Z0~Ucv?3-Hp8VUGRs0BVA!$Y~0x$d*Aw)6gRYwQZrMb% zL(=pRdI7cvgOVj#=!~)kX#xVjaRgvEa-|C=_btJn^Y#7(`A+RKy0#P~ypAp9lgoWw z!uwNWK$>+1a2cn7-27U(AFK*%6>{^ws1MJF_>XYkRuR^jr;X2W>|pR61i)aJ2hiu9}`bV2NxwdAJUj5`{OdK zZXyEKs}dTlR&5cIe_nl(FXObFuQ302HY`0-|VqO9R z(yKy*+@8W#QI>A#mR`-Bz(Hb_8xC2jt!<`^)xw$4edv^ZTmo83)a@uDEGSru(5L^Q z*0d*K+tQ6_&KMYONKx1=>#)y&bY9c;duN^=Xs4DLb7PI=`us)wCJ+)<6rjL}>vNxb zs-6;BZNuV2yD>Mzmxe5?ykBM)D@x5^aaadA6N+9ifQ^yj4R)k}P990BWiTy_W5pvw z#?1=54ZR7)vTYtrKNfVkE_)g$z`(_m`|bsl$eQLaNJYsl1W^#1Z-P!G%R{jkbL=%_ z2?-%csS}nVtps>DtX&<+2&pJ*ohzX*Tm`Tk>C*5t{Fxavx-o zq!*9^H(t%r>`UjpuHqONk+Wy>J3*)%{I@VQlEX)-Rqbn4SY>?TVF0tHptUwE(=Oa% z?NDXKd*T^g%!rhjf$Cm=!{W+X#uXqL-}p}IFH+X0u}ES=_L2?s+C5!asR^l3gR`#4Aij@s} zcFC<_Lw2>fEmbm>sh&G)1&QQ`at$d@6UEK$-5!lT28uLx2+}tzF7!TAik2`sAkno+ zRA7Tz$;M4o-zK{_XI$CI6W^b%)^K<$@`>0a}VfqrY6&c`;6UudBfZa7KVir zXt9|P1EFc zIR|bF^WKdspb0;5BU*YRkwbBIi+u;{Y1ScL{rnBxNI`CO@j2!S625TuFqT6Vt^KEh+gSao*C0>v9;&Bjz1=5^vG(U-=-0T3cvNsfa*FlHm zQiD4Aq#!ONpj1*RnvmAL$vU8SXh8;}WLUB1?7r&XAVaWAvRtkiQu=%<054CQuRZf6 z(-Yr|%b|VQ7bUjb4icZntOp$pZ{dqkDmS-|RR2uwe&%I*bT4vw0UF+oru5&?0pJeQ z3NWf_jRuZ?*n(7^69v%V7+Y$~;)QENQd4p??ZI^g$2=@cYORVBn|3NIw|-Ad;|W>( zyML@}p&J_ni@+lS<~&`6t=F#7Zd=^wb@l#vm?NlqbdV(N#~CYIGkgPzFa(v6D>` zg;snfI{q2^%4>%pZ3y4|63pgT(_yD`6#rXyM?A=-nniN`%VFUg!Q0K@t*DoO1~@Y~ z3H(TJoV~EINaV`iphO|0#~}MSF=yQ!C^eq-c@JjsOORB0lD9UGL_os#-HRfBy%}^8 zYc?)4aX>=?DL$L67LzC{pF~M-Q#22iaS|gNv@W2GBG#m;BY&FX(^tL7uWk?(7b^B( z;w@IWEUNv^7i4Sk!zuFV*X?|K3L>%6TTyJV540~xk{!w0XYA)O>&WH;O~SRZX&yw$ z8JO|>`U5n~^gyVIZ`hSNe`d{90l2BiUw6NcU$(hk`s%)qao?-{v;Ba`KkrAA?wg8& z;=iEuUu|zrYE-VBK#j@mGDqW)`5Q+K$?}orXEt%fN~kgx|J$#<_vZH&|Ln#8Dx55c zn6yYHvQy~Sk$c2omTGBPQm1olRz>WT=kraMu3wq-e+e2leO7^$??N|+{HJ$JynZq! zbX#AS+W=`wBuVKbb$L)CXGQum8yCSBETt){6*Vqiptaz7dC0aK;$r8v18(Lpzr3SV zY2AR>Xv-X#vzpqG=wwgbZ|RxLDwunpzjHicu2QvAwc9krHpl~sqkq!NY*&O{;Sj}B zBzFEt1y_8aFyPJpnfdu@Wj@o(UoHOx3v%6TRLDWj*k>1Yt5!NDU3G-~Yjoyg6&`4q zogO?9VuU&T!}*+#iWxf07P(2HIaM(d?K{rbv2>*C5NO8+xiW=R7FN~$yi@x_HS)vd z&%dRai{)oFPD{;;k9cicuDI|YasAKk1IWbNn(gKGR&V0crmgKq z^v_@O&wb+kP#F`(QOy!=SiwpeOX9^bHEw>oE0J6YB;4iEnhpAxROs?;@dE3q*(+y} zECt&K(dw^nLOIGmop=26$F$7ztuJ(e!os}1)%eGgg027Jc+LCsj_ytpYk%u9DJPfo z33VO*hCN=o>X=Z<=eL~9njU|3L$I{y8FqkPex3Yi2%{{QF5Ga7k3>*n%K6jy6}3hJHI=*)UxkN zMW2@6HJ4}n%*_ zloC>~*FnFYWGn&)cjnM1>{7vU-nu+CX8twEJ)5dWe$`IFmKB031lN`1T_)^fq6~2a zb?N%4G7azEDbqtZmpu(?$c?tjr7j^CudQ#H&XV=dQ$GtlYfiIxJ(9%kkY+lx{k8i; z%-Mv=SKb%G9$)Gm{L?qJQC=zj~pAis};-e_=u=Dmi~k z4sJb{#;C3qtO~({h^CdzG?l? z5SZtG)R>!^-AWJ2=I@-EB$;sLqulxnnpW&BOif8@Q*n{YW1$H)kff`o0wlyAR^Ej@ zGk!HOy}3FC>PW%ZQJqT3%sFmUXf^bHQ-PEz@1G|b%^$OywwV^=QC4EWp)aAX8xO)) zgeRnmY(T?f+=UKoou~0gSPO?C;VG!?5fv~ac_|&2iG_wkC+g&0kYMH28edAxGY$3_ zb-RGBNBK#;Y|+;*#C?&6Vkx;DUM4xeLs9ChaC6;8(f%}1`u#6@HC-dS%0|Y1YI~q=wa|wQ#GzLTH|3V;sq^CU7&A9<> zOJ@9Y`0r>d#t(q&VGxt5u6$kkQh7^E_+|ClRATxYP`D|Zmw}@4(aE$umLWKj)VRw% zRoUsihvNd7(_x=!ibUbh@%f4pq_iLDsxeot2bAjhWC~pE4pR9fhRQItbuh?bi8kIR z!&5KJn${70L;MA9df-qq4E_sxd~?R)x?fIB_F8{uwT$9ZJuR~c40=j8+e?5OSI}%} zBUirJNksc%XzMO4T*g6r7OdvkRHP8LQ+I|E-`Yt{&XDT(cR2i!dRhB|K!pGIJkOWn@ck{WphV-k^yq=Fct()1|=Xs;Te?>_;SA7iGpI%qs zz2h7M+2nXPrwWL8E&W`fQ}jhb&h2vW2;Vv0PJJ2{#G;R*(W-%CVz_ObHXASL(t)wE zrLA!TUpaMqbZCw9`v-oh%;O z`l0DX3@ki@BPnf8Y|i;iw_W6!_~6sIo~xgR0G7N$O_{qfN}F!iYm)LeXImd)ovsI1 zL_m<@{PV(I52aOf6xN3tNqY|2p2Q|L8+oXRjCDq>=2-d!y6vyvO@K=I3XDGIe%`{? ztlDUarC(=6DdMdGwVY%+o{m23qNKwwogFkkD_sITZN}|7(}7AwltrPrEYSjXOAFNn z1e8aG(&NUZItprFE~_Wipd}yTL;rTiD^SR7f$Zz%JDPx%8|LLsD3_{MjL#Piyv6Zl zAjYay=3b%LgpY+EMGpPuFkA?2{H!z4pFD(FO;^OjhuHz%eFVue6mk;oslYT1!}^G~ z{7#~QTWF|avwwE&5)_0K1WBfv(|-EUCIKio5CWhQbtLs|3~?Gfhq`r2Z9BhD%b$=4bZod>f#q57>Ut$A>{yL? zYuujuTD!A9HF;p&uX^N7Q4&>&Bc;{B9H$@QO;*-U8ZwLHbmyIMtZ$sX7UQ*t*24$o)RY_k4_W2wJ`>);&6%WK@A_XK6v&n?_U_Tr<0LlT0h?6HXD9P>NQkkGcVATx4D$+X}_>wph(5lM#B5lL!cD=YVl zuyf=Cuv+p>Trcqt9eiT1Fl9yR8NbD;81I<8Diqn!ddq*EX_6E;rEt*czqBbPWg=ry z!Xn2Y*em;&PLw^Z(pxqYG^(mn;td4B9)@-nB>s~DfsoewBbKdX@OqB6nf<5pEC+>+ z5LwjbovinSLP>ucU)GYgld2E)YT(tl0m@cuWCvSLK$lXx5C`-(a-H|9+ zJb4A}aI+oBRqrAD8S?Br(80T zX=V0c0&k~Txb)pZy#L_haPQTPUqT6x1a}LjeCKy(_k?ax#+jhdh?->YN1@}&^+%Xu zDHk%Tw%zF7utP9?G(82Mu4n5(Vg&jK+n2|{`AQ%z#&+TDezf+D@YJD;m;Af(gfI0 zQ@ZzQISP$hxR?l>mwCg!N!h#J-tlX{RT4At8A@e2t5^i2fY`7Thg(711(}Dy$jMMT z^xJ!j+t?C>p?-fnGp9hlgmwebXNXvlU%zJL3I zUd{E1ckbnE@db3P`O+G-S0yIm>{=G2xu`xoOw&HB>S%wxutk=xutMm-jM>S}T}}$0 zBDg8yIRVKzfOf_di6)QWZvN}*vzz7m3o6SYQ39PRoACVc(TM~1l746r{|jOrrH0)N z0W}&hol7=)Dkr0Lagl{MJMpm>fq;p?(r-2JODWyKAeku>Wm%p(^wAyQt9opxoyu-R zoo)GU>vM7>IEs$eefy5?B`Brv@nFy-V+^zTlhSOu% zLq@3wE$jDh)W>!_{|kIA<#%>ev{E6dJ=fu-DfG{TlX2!CqGJdrhVn!D+N!3;teDVh zCVa_&#;(mbxzQKZ3QQ6TTlI1nxe~B_l#vLlDFlaA6=C;*ToSOcN#Il*oh6-T-tatQ z_}V2poPH~+IWKQ_x+4j<#Afid zcnIIc_5>%5nVpzGbMP-Z7KTgkB@~(G*ICa0lb>N@BtK_Z*-R@O8@*PpU>v(Y%#Md@ zX{vX&Bj7#dnCk3X>)q}w!T(hT8lVvs>mq0`Lmbl_MGne3n#FGmShE||Ny^0=2D2R& zcYB}wnB#n0!Zg96Sge{ewo>a8!gx9am8U%IPBeLB@`Q^eR8-5wCaJTDAcvU*S)ja` zT97D6@q0lOW~-kiI27o#WN9=-1=HP2}ZZZ(-*?O zp|#N7w|Kr|JONJ{!}pCic3(1UC=!<`Yi_Im1;ru=Ddaoet;)s!_ z%tR>zok0!Gkemo{sql|_*&lh9ug|MLQf1@A#l?KCnHurhw7 z#wgRcd;v8(9fc~Wg$>OrSZ3hAc}+mPj#rq1GN6l*9=&(vWMGXDE@Bg+?$(sv(m_?^ zstQhu{P#?orKO}1L$Gq4dXy4hlIGVOR1bwk7)y!anFmU{iEc)Z1-(`$eYrnO6-nN1 z5s;XaKRS5M*Q>MvxsAiN25}Lu>$7E>e5GlyvnIPB^IrK2^1Rr#WXSb?nL{A?t=MFQ zk+x@GDE_Vou~P6)x=n^@9c9w0T2Kzof9$x8vZ$wg^k4i zuF;U4?A(Of&l6jD5Md1dPrlH3vWrc`%Xf;AvqqD@j~|?AK{~eL!2^gam_w2w{YA(` zFeRFOV%5k;8_Jn+-qCP5|D&_S|2UIdLd?CWQbWvMVIwzgXg;-|lrNT_RM7mDSkoSB zs5q65_!Vh*18|stELt-Ca|MUf3m?atq6w3H0`U3-yAT`zvA4)X65Tt|fJaLp0_K#l z>GW==P6-Q&Ijm@Y6IDZ*Jy$^rRd+hezHgQ}Bv~#dO%lcC_V3#2!uCk`=~-Cg$CO%? zweY8tncnGSW`L))nHE138p(ynzX9G(7MBiJX(9fpLx?;tvkXjsLx%`t~JGaI9| zk2W{QbvwKwxnpexCEAjc7@VweztwJzK|3lxDLQy3qsd7L_*}?F)(d^u7YH`JhlWgv z0P9S0ey9i2WgdB7sCY4N-)N{~j$ivNe0;ase(gKD?u{ zUn+m9GM}mkx^$Tx3*meGhN!N>N=r71t!7`lZS%Q&H%=2?MMX-2gNC`-y3&5b;Pg8LUJ#tl`TOQCNM9ZNB z=8Q-P9Sf(ah-Fg)J51wfWR#z|zVE3dRQt&qslnQCjLaieG*ov4S*ibE7Q$Bw~t{(+dVL{FXrc5b`45N_p zFOETPIzd??+H<;&!QoR?_^~Uz|D>V1Zz~Dm&!-j(0#ygDa}|O0_p;)Zyx>O$G;Sk( zfpOOMB(K=j7&Ouky1FTlKjUXGgUx9D-gqG#EbiS9v52l7DqDjWlX2fdr!T zBI@=U+u?+ibrTQMPf`r$OF5Fbjh~N{idVjMP%52cxAp%)LX?ddAJ-N-)ui1Xf;yS! zUwN6yqoUiIXRcTV!~aa3xTKQFggFYXhK_O*X`tp*75W-_H(>yw(^-I6yu08l6qfQL zubuGr9pL_}Aj0z`VKv69JeuBZZr`qQ++>9LCR3-ERa-$(VQ@Kmx-Fg#^? zytbwm_EfBIIsj$*O2gPMqUq=gT^NZZ5!+Y#=li}$)v@Nm(OLyZB{?bXbTrPchIi1Y za|+6{zMyOrKDv1@X+VB5Ui+i|V(*OIY?o5YT-kdp1kw_?WqJyau5Y;QNAXjBM^=#s z2=}!?hfPxp6~t8nt1ze8d#4OKkVM-VaR-Y#9;I*HB=Sd-iap`s;hHaurPHMy5#xXd0ZLp6xHfF1p@adaZX%^!D1A8&?0(<= ze0q#L&ymWja#|Q~PbziqBT4Z+-v;H=*q90$=blg&p&6+rVg-QMbjthx$v(tCZ1N-1 z`N;)ypwc|8VOdAXe?csl+e4&A4koIE{TV*Qrh-QoOZ9}{k zS{Sd9@6q(dgHvN_Df!};_^|o*G~hS<`80bp2z$Tsc;V1@QaglTox#p0hq5@_DjoW$ zZN5s)%rTtB}xb<(@{!Ay#0sVt3Hvrwmt13)936=>o>`rrL>!Q7${{QZRY!__mub zS^_QahyMKw4W9Kyi*Nokk%%?)*)vX^@jC??N<~X~8NI4QEw$2OP`!6LA?yG17jFqe z#e{=laOoK?w>@$RNM)GJpkaa1?B~g~l82--p9Y6ddjSEhTXw*XRK)p zM4fWIh4%3*o{~i1jSofM0bJ$IvNv1j5Rb{ED*_~=SYC{9$mTF0*-w=V%#WCP4PUEi zV{l5DGaM@8JK#RfvxixYH(qJ=XXg?v2q)DMsBwYiT7gn4@QoC=&9iq$i585J-rT8p zpp)_RDXg*6nkLVk{<;thE93#b&-x4c@6;^nj`o#rl#N3In&L0W7%Xk1dW%>qo1i1y zg3n}w+rH`27wVYi5qrYY&w*)OnpV*|PHLauYMpU#>u31D5_1$8yDaUSZ7F!};X+3Z zGpJO8Lz&`G*74<^iBDh$VZm;-eQ5w?o<9&)dmA{U7fJ_bBc?>8VXeK|?;GFAO|8=c z0~ozzW+7-#W%s$iwT+gb&K0NVT0t7n)3IbBP0n(sxuoW`stJk5{RI_YZ4HDPF*A7f zOp4TfTW#q=9FOj^4dSuwvC#w5#G9&=gjK&a+x!ly3NfrW8 z&aPLlF}9JY2oeJm6|DkZC$9mn9?@f32!@JeNS^ktgF)FR0%n1+yj35MYQOF4o1;FB zW!b*r-j9tD*TRyhT%~FE3R=c37{-G8fdpwM?|v6blsmMKp!~Nm`L%vjneUqPCOc%j8C2`RH#GE|wWV6?mkP)n#g}YZ2dfv&O5`4%=HUYGo0H_%5;giHx zYVeopcf*RZepy&gqV=3;BEchMUGLC**X{kC^tqbWha!T9dTeecUk4Yo^9nTcyi@Xc zxo97=@JOJGUpTH>ducn}!3qgV|Mx}KN!2mwb3?9HxPd$Y!O&9Z%^6Se2Hm%>ti*7e zlk)!tczIqh6Aa}=$olaFvcCROT?E-Cl47>sU!uNh8dJQ35%DeVY52Q3p>6}gh)?gs zc4Q!7iFhiNwAGjm`vDo>>-vwl$QJZfx3 zH4nhL+|S_vLmvs>)g zdQ3kB&DQ{@{As6ByFlBXf-Jw9Mgh!A4gLNnTpV6WMO?-aGWUhZ!0~aNZ87!H4oSL} ze+hzy>hqdk8hs%_hV_OY(HM9Bd`HK`t^Rgce^4QEI3W)h$%d_O-YM!fst|o~hir%q zRhPa|99&}d7HW;?Cf;4S+@=OP)6DAU6v8dEFHxzVfWjMuKgWvnFc4ftzYMZYYwA8> z-pHS&XioK^36x$zzAC_AjYx;#C@7-+Uznv`t=OK=hs_&~ykh>#1!5DDHr`)@lVyFQ z_!T(C5Tu_1ifE1L_6yzP+Py!b38I5kR7wuA+I=c#>`BFV4#?I9)5SvmZ{ami;BdSB z>?+r<$Pi4&ojEgZE1L~gMwgY^%gK_iEBoH-!3T9K zcXvy052uUc*lp)$-=j+gY@aAa&Vrmv9;nmNW-6UYNt10WXrFOFU{KJ;2tG_)G}xXU zEs4~1H%~>H&%|bR5jvrNGIFx(Oa;`jJ%W|gbFHzejYqk(aaIu{}oF!;{ z7aWNrC(ui&JzAp}S44Qd+LhOOHYg?`q|1gx2EU7JLIyR;C-FEMhH-BsTyLpf$T!!# zg+@tzG9K2rc699ni?6Ks>1g5ZoEGinIHw3yeBL)N6yvzd*G!fHK;-!n*(QOYDSf@) z$i0|6EZuI_w>z1kUTn;0=1GbH7xq3Ql$No+uA0vkJNGkubcZ55vjpf(MzU_}ywiT^ z{61=jLxv$Z_kuFE1P#>^A*3i3{}B*#4>DHOJ&P(WioAYck>i)1UJQ%7kIvc8VAl_q zF`OITp#FmnxeDaH*{%+{cK@f)(Pwn_>;>PowdO(W8YxptL6;sny~7=vnkz+qnLqHk zozzR>OQjSVpv(l5p`?imEAF5&K-l7CK{d%Ye7(W1CsFP~sF7V!fI_`qF4F22N>aDu zgRd(2>TD!wHBW(;)u&SYQ@_Q$UWE`I?=Iv#4nF}n-75@*71}qR4mQQz@8_T4AbVK5 zof>rkt@}&ND1O6NUY4av1ye#OMy}HEKZf5du)IT5AO;gMRrG8<)Y#sq3^$lyc5UD6 zUj^UDlCWYwUmW4u`qRx&beG?nDeg)|H<$yfkjC=6!zqG?T%L6$YpTVx0ay?J1NBRk z+uQ@Ln#v=DBJ#xh=lUS>UwmqlEij-)THsRk6(yJFd^nU|h9X{amzv0K~ zsuhyv>QO1t$CdpsQEB3Q5L!i%m09HfEq`&eZq>$Aqt%eIine8k)rtOI11n^Dt>`al zKdhwRWS5_1blt>?e6m%Yt&H8d=rZF``Yg#-<&sZDQMUz6Sveg?*!b zg-J|+<*6Luc6$=iCT4g=JX?5#5W|QM(@L00NMWpI75U65E*^Wqcb$E(=X^A6U!nF` z@Tck=T!YhJ9M6?2QJbR%;32c7_tYN0%puRO37|rRri}F)s*js9a`DiYmK1Rt{ll@H zP|4ee5rbom-s1=7w`w!Jfs4eAJ9P!lRv0l^16Ij%@T`u2H(xwqPfdK1;_1t$w}OQx zhen&TxOdSZXL8H4r6*gvQnX66V`FK}0({=O#=A)RE*g6x*SOJqZ3`=tuDwjkqJEm* zFgy6Gx5iFS8YNGTDur`x4{bx2?pkmVbCJMk1A2&q7JjE)XgX`p4#X?)9H%aX;>?O*aI99p8qDLX;V3$o~_3Uyw%2$f|z z&z?I~DC|VfhkJE03$gGw0N2a;nn_<{i(3W>_0dPpt6Qz-Q?%m@6|Mr}T&(W1z#ZO; zv0LYA3!3%rl;z7Gkq@AvAQ|jFri27A_v@ekN2rnbuTt!dB2vt9ORN74x-i)OV7%4QC)$dLv9w~bX5JP zOI?O*GyPgqA1a87k_5jBNzo`M1Bs-92l5h;u)B4o4H~MGXC-VVb9j3yLF51 zYcy!{w2rok-(%=`mp|f$;opG!G}M+9`BYxsWf=OLLlM&FSu>nt)crI*#6daan#82b zF3t~H7ZOWM)bje;hBt&OpD!S4v6Jyn`;cWX=^3oY!TM=_ES|MBL_tK z{$8{6ttj}n%|cBn+ez%oU~C-ipmvP@+7K#%)(->Z4xrUT*N<9 z`tL<_YPpm2k}TZ%8Co4&(B~sSK^uf+J4LKjWAsKgytBq^8)Y*h#1uy%Chb=@Y4qc_{75RPpA|Q}C^<5~BxUJ4d*NYUofSKJqdndrc&8>=;zzdmNd@Rh%P*0E60v9U>}!pJgu%1CHnSx8mov zHrvG^?IHz@ic5cgJ=Hhq^1}{C-aGDd>hp{7voNzSMUw%&PEM?k4_+ZP4!%I^H2wgw zadv)Z96LARjF%iGQ}i&~Vs`t@n?5N%dMOb_=+<<(ipf(R32Y=_eJ> z;VWpD01Mnn70a%og)8__-I`)o5mT@x>{kf1=}BsZtbZi}Dj? z0k2KFORniRikKcV9!CQ3H9yAjhYbfc)O=@!oA67pzr*`~n2iuUjGiax!g==07kcDJ zD~fnz240Wf1;Lwf;JflbozO!-@>pvJ~GJ5#(&>o`3l zGChWYg>p>&e4Bjx-s^wfKZeOFxTotnvHJ~4Wbin0G0^-6(ukhtmFDM|p1T`}RkxmJ zNXgjZW8{%Ue*M~TL;&_-yCf1@Y)zMzE>sMRU66S@BgvLh{8uuu$Qnyp2xo01ohR) zvFQQD_6MoqogU-jD)LDt3!68jm{Ph305zHy(4c~QFar5SBd^xHYsP$VF?aP>ULCc? z$zM<@xtX@tQvidUnP(l21g;!pp+kU0n}MlNhj+X00l%6`U5^z=`N7@>cq8`uql30~ z1nfi>mT3Z#<_MgJ_+M62mmm&-AEj>~4B1>u7wE%2)>W7n7!776`VG$#AnKbhm}q{v zWi4}=4%{J(%OPj|1xje4El1N8H}QcMqb*L=R$SjwjETA4U8>ac*J}@e#NuLNK_y+H zE%jQ%pHhVp4|KSX+6E=-QAq(gQ()G!CJ)NlgaX?S5@p12vK~Z4$ph!@R4!d@YliQN z$NBU!cAV#CEBWIN#MPkp zaD4bm%VZ=WgYSJ$*9G+nW4fTFSwv**CehN>=Y@= zWfCvCsrh8yY`85@*G+{Z_mvqhfl>wSrOBq$txk{87tVX8w(8?@7(~^@gyDmV`>6UM zyOJZG*vPV62j&zm={L)z!YZs@GlpdH?+w8*?gK4_fHs#xX4{)Wn6FniAFg;GOlF=& z>87nn_{CZTf)Wvm7n^Y`Df!?9tx=S5&!Nv&X>e)j!U+tuT`7;c^HAu#+Ego948-%` zZrmcr?^PY0Znp6a4_D@Lz6wWk{lO#{4{^sxiTLn-DU9pPSph^!20He_ z_VXE-59%RR=xq}=&Si+Hj+a>ub^Pg7fFx4Iv|@)`V)S*lniE!LvO#K1;T(E0p{dzs zIme^rO=#p~=vmLCZLi1A&hJDUqK>{EYsEPw78kQW9o=I=eo64L1Pvo}6<3Hw#|DBF zF`~TEplnQ?vGuporN*TBZUmZnc-yFgdDHk^m$$K@tp!ra)_2e3!mfWJlQMK`M^L9h z(J@f+`s=!`$AY(C&^nxOT>58XdBUJeY@JRfd6KU|Jb9U)WH%vcv``8HQ0d|VuO+#B5DikgAVQK1FIjSsmppqe-IjUbGT*}CA0rR(V+0^D9cin2WHhbhzFW97Q_Zd?KJ>5ihgDUE z95M?1&>5EVu5=X!zq`g9X{0-9O7_ue*QMZzOcg``oZIdpBh7a0+y!3Cdu;d=3w8?O z^Q%1NRWdW8eP@oA<>1a4mTpHIH^a!aAW}YLcv;eA+u%UM>Zq=u;!<#^7Kb`v2d9kgS%E3yyMz4sYe+OcrFVCv#t^~?79tF?uW zMT!F7b?h!;Z>U6injy8GttWC~>z61OZnHMPO>QteLq`32QJ_G~jYWnQoHV&>!FMkW zsm>Q|d2LtNrcE&$`T3f&Qx;X2GCL0lWHIApTX2?lH2p(SC6uwJ2_o})Uiz`?G2_uu z$&0t82WZq?f|b6ek14_y)L<*c4bk6A9&oQq#*$gd*YFT>12BmWDmwmq=JxNT6t{%i zeU1HvTPeia16d%N;zZ}>7&S^p<&pwKH;1|qZ-a8X%Nm&L-NrD_dNL@p~T*6_5-ja~6kOGsw*D6v;gqSFSTvUEXv=dQC>1 zzF4DNlX8BiZFP`HPkj>M%*(Y|>8tL^V*TW~Zr7CNI)r_Y0!%toIGWB#yMK@lKdut{ z3=>Juen6zo5t3bD-N-1dcsR|I3KnVQOV{Pj&|fP8GiQK)$N={($7uoNyI(hKy3$Ra z1gW&iGH@}UBK}MZ*p6YiOVEOU%l-F zNf|DIc$q|QqL5s8$_(|4dpb*Vl(MbnXt8qz=$?*IXTV;e?e-|2kuw8<$wm7tKm33PBMKU>q-6|Sc$yvkv*lc3DM(NOw?dP z#XJ7}G?Hp0E>O3xJ07}8zX~0^t^Vo!EDv7 z;h74_ms^8LmP?M}Ia$$^m8Bg;$M|P^>G{GI`I z8Vf3}HrSwrd6k^`+M9{NlU7awOwmw3ehSENIvL?Vg z>#jE0wkIg4xtG4~2)M%N56-q|KUJO^DxzLZzmp3xQ?lm5mnErIIzNjYWKedWK+2Gr z^w8XUjC%1W$*P}nbY~^}$umjwJ|pTqKxVj(R&MYDq$>?|bHftMQnirzg5f8dTqRQr z$NuXLAQAU1WvL>9s@pFgUW1(xn&bzdDLsc=C9+5HXUc&tsL9b9rx4}DgIej`9}sJZ z{LQyH>B-wimz@_AM(^2{p2XeL=~giJ?-352=uGVA=JDYKH1|&{Y>o*Dy*DFpBK})l zeyg`d<+^^zd}Tfi0f3w1|L#|D?FI953sU5OX@&lb+NNo?NiSZMdPYDn#dS%t-I%x+ zICd@L-gSO;+D?a+s;(mfE=qb*p6{{Yr$B+n|4v@MAx=p!tKZs|n>lURs5r+M7wJ$^ zm4^%rL;aCdCm`N2l`Vl%7!<}uFchYoN}t^$gFiC{&pFfareH97V4f%kGuUSzp9dHe zo2qqhibkAqC-=`=?b#tyiooTk`G-nvX6M1w(JNMTa7n6F$Bw7$JtraPD>5*hJm{l> zClPc4E`p@F{lxZbro|R4WT%^FK<+uQK7}l9&kn1G@Y3c7AjjMv`>;L1q#xvRSss7W zf6B$<5S>p-0Ro~?zW>M%{KNF3)jpoVIk>Cu;frl>v8%u+{o`so*4F`>R(p;6vu4Jv!+l^rr zTGiBs2@&;b32XXh$>kt+bC~)6k#!5l_!NDK0Nq-*95ZAZK`F+jc$B)cDLzBl8PTCN zN+%qrL)+Q+OFoxx6Jl=v{cVVP;)`bdWQI}JO#i@^#hv>e`fa?)9^9m+FL4#f|3LKQ z3jKq920D1ZN2-At_u4vIyU2=a;tCb zbFEpOj%Pzxk)G$SD&l+Cvfii8V;N)?o)xWvSUcIynA(2$#g<>eur&TjKvdbu9M@ZR z$=A1wrz)KLfiV&KQ9I%>NKre-(}CV0H@5i0PQ*tjCB5_B1GVahlNU{>lVD11x_MtX zT4hLnHX<{AiVA@D0k`x;a;+eHLmA_q8}Qv93syrO46nP|mL&$! zRRQjT6GhISN%H%dPmCLE$oRl<@^d`t%7TfCpf9EV%K9^Yvp;cgDIQvIf~Zt+`VmaH!6a|el_ zzlX{Z0V51`IyWqYF)v2fr+sZ$2NhIlK#cR%d#Sf_1D4)UOYcz0$O_j*J=xPyxf?Jr zxn9LD=gF;>VeX|jB-QnlwP>UCY+IoEnR0u$O2csDuG4$>5;znNN$N7SQezn1OU{{Z z*)!Hp2+zZwUL7|~FS~AGPuaw()dsazgq&4>t|pJDsLrf^g1CsV-@FVpXpP-d(&1AC z3O+XF1Q_3N*0`7-58=c;7q_|ybq()#y^jLoZ#}m2py{YX)10@nd)ZxpeuSk~s#5$H#KtAtU`kEuxptvM@NL0LIs{&^&O1Vzo^us)nRfhouj zEiVhBQr+Jxonjnc-zY7;lz!$A$$|zjr0ik~UX%jL`9ldI{lh>*7B|YYy%K`TtmYU4 z;n>A|VTvHVHg{s5{e0~$k(bF@Ph8Ch6GgaWM4Y<{vZz_0H#0wKNq)^jl}m2%et%9w zG}!TR)|K1M(3%kD=|DtfV7w?RcydqJl5&D}7kem6XTZ{HnI!-=OmBbqT!y^2Pz>4U zfQi|d;a27WlJMfv4=BRX!J;8RNob-BJ^(_MH{+e+Fw+cExC{3Q^yKff8Q0*khYo6Z_uqQy>#Ho z+`I*;1>6Kb%L-3nRS)PAeHg^ zdmbRzAD}_!ZVSrINspcUe#)+-?n0Y_0(4pBLEt`FrPDgjjq(wS!I~MlWEOdZEzRWG z3f9-T`6=@o$~n6LLQe1pqQK72MO;W$;0c5ZVp5vN?>%!E_T34&NNhUvKM>Q751Up# zUK;%dh3SiszMv_08}EJF^A7>n2dL+5La9EED>Qk~^O zEY}#O)O!$XaWy*31iFGHOKw_^83049oHMSA@KzB@AFtXe+yD7dzIf-G+|o+0zvI<<@V#KD(zI{1O#rAC9^jEC2THjmq-dU(OF%UlQ1Q^z~PKBCx~9 zq^E()h9sb8Wbt^f^y5|`vaaLD-oK;I)7iCE>tD|+v$xV(8~&VZ{L2!ZSlk3Ty`r<-vG zU=|U)d(r<0dxytY-S4gcp1U2Xmt`JwW%fNS*2t^j6P*EbE!pA+cWaP?vY(Mo$=3Zl z3V-0xa}$q(=}+~4e4bbGc3oXcP%ODusVj`SNer<1K4#!RrmzuKB5D!5?uNh9rdF8xvzZos@&wsM^#7#RN+N!2ziMumLFA_SG1-uvE zwmr`{+-9y1G_WYG>iSK$eLL^n*FkFu?>o+tmw9<9E8^GUB~+7VzaMc*0uykq^vsRa zdTH#&=*W#pu{W2WcZ5=RiVO7??lJnGFf`P6*=^PRewwE9_f^U5VLK$-cRFpe7oX(X zpLB@y^HK2zC=~b^P*kftrhT)hVnM%0-sDLcOX#w7o3!sIwlR|wt-`-Ft5*I~{ifmf z{0{?b)7%UFP5)mPbV8K5;@uZJ;dtavhus53aSo&$#UeJ3Vf4i}1=JbQ+-TGU%UbN^tR&;CX z2<=t`4uBiiHJz)hd|K}GW(>nB?LK8yUA6-Hf^4&P~CQeT-->98E zd}mQwYk0l=`qqn&w*PRTQ~nXk?6#?>;iLmHR|9jV?J*8bu}K=4FvX+qn%P3Hm}N;E z7I`o=N%C0R>PwAFzDu*qkGtCCLVJ*oY2JZ%zhmxe=|UUlma}_k0Kx?6FC(zTLU#cXMZJ? z$K+59@C91=^0Vc=ZYQ z4pV-R&n$lvMJwSKs7c(oIqJY#6QEZIePq+Ex~k4!%z5Y<|#5 zjZL?I4x<$B39hU1Vr)N1RP_njVhXFGgZ%Bj*Vq*^QOE0-{~`v5r1Fnr)X4d9TxO~I zZz9;t6J9C(s1tyw&;vB22>TSTeoMnsO=O7oT^HT9p3j2wYQkAL|YuSEr6 zZWeSAQP|l1sF00nixj{TS`M8#9S))Rfn;n)zQ!A6#!g$hJjrySEzZzZW%Ihu{rk-! z#A&$}ya6UwQ8#Fn42wS!U+Wt9bIj#?Eh#lNMFxEPmuqKL|39hM&DlR(@m6^0V|7qO z%jQQHd9J)s)2tPHq9JI$eokBcD0aVK09i|<)2Z`G()iN zg~?hVcx6iJg}AP4$Fr6nNd^UE{r`bRKYF^v&bWxG+YQKJUUzB*->cCUtXdr1A#9zm z91AMw&~gIlv%|<40n+r$CP}dpsbY5e0L2JMhC=EjHvbNs;F^ae#XgN zTCKz%E<5R9r$plp^3z|(beWr$zaJWW>d?y#B})O=W-&PxYtaTokv=uE5_^U&X z>(Qdhng*IKriFhv`*uCaakEn-0d{=;b0d!d;~a{A-5i3cxJ~ei>8c^;L{b>4xee~X zyB@6>m9((S!Kf%cE_-ynQSA{qnI13YX1r9PB%aBa=~qqxL-dAO4tQ1HeBQwBL|$Cl zRPXZybAAOqn;;lC?XvS-s-@&Nit7!*8reY2cVYqKaJ%^;y@L`M=2VFrYIE5rFpsu` zNE55_T6M+9#pAw8aTm~KM(qyzfX+97B&mslUm`R5o->&-Ufq}`!aWxRxO%jus{BM4 zb1}G=LU@})#G?=h@QI+9L@hn2_Wkm~=-0h1(OWdI{CAmmOZ-Bi9VWT;WXQKvgGB|r z8j1X|w&^=}I<8CqmgGQEcLGtra4fEVg2x1IP4Ypf@>$zEwHrv}j*o0fUR!{3 zi*1^nBHVpo;BzW1?I4wn0|OE$;_}PWx>Zi^#s2q&#BkNEC4><+6Fb$89bGlFqX|!2g{4b;_-cljIf$r)Q8E|D|P3dJD7q3;_RY^i`#){# zVTBn+!OsO=dkctXnv+7?2`XicZJ&=a}l_}IQHKY)0} z{!@RRM!N2dreA>xR4EqW=TH1URUk+3`H)W{dp^qP^UyjKyJ4ihJf2$dVr%PGGvr0= zJ2o>H7D6YBzSp^JPej%@QZ-CXFd*?m5H2+Vvu#`Z4yfQu}4i(}#r(@$Xqw)e}z}ka+y+XgThY#7rQBQ_c2D~0Y z>q5>vqk_hql@KV43%-C%t;8P+?P)dlM68o8cw*o_I@^5Fc|=~awI6(Ln+WqQ40Z$lYEv7tlJJ^=HP$LMjV zA+7kFpe;I52ECSKM=m9dTV5U}peXTq>D+pm5Gjq=c8C;r9Q8cZ3wtlWM3l~LmYhxN zM@rg%pz{n)oOzVozW-G~OuO8Bvwpt}6_v7NH$1IA0t&?T44EqZ`7`}+dnyF+MAY{f zU%bmXG4o1Z>-WHX5i7Ts@o4Ob$<3S}8SD{gm(pd@0~f4c{y6@Gk*@RRMXZI;XIlBl zdG0Vi1r5_AC1)yK`Jw(&=Aw1omC}=yjdG(o5T}4uYGUhce(gLDS8AmXhKLJ58|e~h z7r3*r;KIkI(I*+f6$|5Aafu>vn!Ul$o=J?Rw{)j`-gN_A2(R!QOn-N2s)XarF~x_% z9loyGOLHrU_R}4Ei&9l46XV^J6>5pOP6?_^~(fH#AnF-lNx|^J=yWE5yb69`2aVca)n;*cvLp;vyUvifPpr zUg8M1FxR-%VkUYiLQ(4);9G7R-zV8sGU3R0OhwJkXhw|3*7K&DW4^ zAqWSP-%m__r+Jmt2VJhYLB}U#ttZJLQ*NDhPG>ya7g53nNtdDEP|~Qa8|2P0lkweE zgkeG`838(GK-bQD!Ts$5;~w|pb5q+sE?EC(2j^O?u>JQxf_WRX!jq2g?4_pk4*;EL z)pKwUSA#b#E9oNzR*4p{AET9fetr?h>`%W2Ke!=D?k#A8m(M`dH4i{91A6vznypXU zD2bk)Fx!$5n{yIg^h<>i~NyBLEbgsX=LTl|AH1=`(;zLwWU!(p%+*D~T z)3kAkV~eX9XsP{Ke7GnkAP=Nb#xC5>PCJdXbj<2MG$kpV5i`oiTWJSRa{L7Nxt~>B z*?ukIV&nl@10HV4XuRFa?%ih|vDxw7c04_w&=rUYor6cj^jPpQP+eQgmu^%4IhfAW z5@a*>rjm`{xZ0K6!BgF9LWOw;K&H)c9|&HB@4O7c=1Qf_XNPH0Oe+E2shH41Y857m?o3~i18|1?qfDo)mX3iC zH}eU_ak5R?btdtz&Iwwm6Nbh23XrM3x-4%PBzn3=d7m{N_3w%1TUjMM!;Gs7jqI3b z)dgkf#imG*jw_d3cM&QR#`Joa|J2V%6?A}?olpxg?ZD*JIRK+UX7$z%b(`^3Z5+?ng~{hLmm*&#n4qH5o+IL;saKTj=?bNzC@wTQE>NY*1Z|W{@KrLdl2s|e z#mYO+^vK)lh3P{3Hi+N}Lu%!6NfoSsr3HF~K4q*kb+AZ}FwVzAb|%crOEF3H$BcUJ z8WP-c8hlf%s1;zl6MGIv1L${gni9{* z&>E|0dqG^MMH}BRcYyUb;m`ju)vNJ(!RWLP& z`XtxT$kB!&rYN)cUGT+17)udsE}JUL>6d!T4MmTE@Zj|*g!42g1;S+I_~AcLrI)pJ z(A$H{JT9O=4j^P`zJ@>YzpE^(_pwd@R6vc>L-P)9P-ayBW4n+Y=NkBf%`w%T?vom( zW#G+#sxnb=g7660h*GL?Tl$-ttE~H3ulkjgA&Sz0VFK#k8GoPEv z?ShgdYWSI&I?_3sj0)d%5PS$I=}a*z%mUU#4|n`DI! zrT#l~Y;T4D!b1Bn$S(z7nCu(-adRCdwiO69^y;%M<)U#(iOLcVX)Lp+;CY>UTA&l7 z1Gw>a?hxvY+S#lVZA<-_=n|0n%HcB`xjd|=TW3PjaVhn&)Ei9WSAN?=KAh+ssPOJ& z>(DC`l^DM)me>Et#}t~AM#1q68ufOFj_YE*O1qu>#=XSHU~5~;s3$&LuuQP3G_j@y z^VF`fOpu2?ax{@8>!lJZV5 zWY*Q$;smKn*Yn{ZJ{HZ2S%&B=mm`^Q_wz!It%s^Q)>Uak#{H&8iejj!$l%AKF`D|_ z8Fo^-TBaO|(w8M_yEwM<;j5zKG;C$!aqpLM8eRG)QYKa0I_Fh6AVzf5qHI{LPZ?(T zy~v9Zux5_FLe2!_XVf47uqdhFW%uLEOu?FIwMp(IE%y9S8*Oqw+W;LWn-LOB>jwX1 zg=!25H)!h75NFT(p&IyJ}A zw;w`&PJ~1~U@73R#{_d8DqkI}l|)CANVvd1uW#ot!dTJo*cceOwVoeF0|hI+b&95~ zve^s$RaeM+)_PPX`aO{_BRej!`SuXDvFtDJ!tvreZ0hB!FX}Ylt1;Sz&sB!pKnU7>qH=kv@0$ z!jx_@!ZVAAfNON}#s!rYJnWfEy_%o%e1AIJ#y>Ly=N83lCe&XaiA^rSBo(_mVQH7RFL4yU? zm;e16_d>2xD-9Q4=_N4q!hNc5Kn~i%9I3`caWL>oy*-$x^kkDvE2cA~!zayt>Ubub zq4s2B<7~nx;3@3fL=u)s)7){`nw3f(GdDt*4Tz}o3{p#`W8p+$;R^l=gSHnAYxR~Cf+**H^`j0j z!RYCWDpr;o_NbY#PxzfT92)OC+7DtB`?i|18xx-4%ZuLbLEg~XF#0okQ7Mo*7+y_n z#;Hp;*S_`R{gb|2C=|J^$~X@Krs}+JOm>Pkd<%m!NVLeKu8uq2gn6qD5yh z-&){pP4jHWH2c>LFnEegE@ z996$+@}(a3(1n$`&yQX#8DYYn)5NTXaf-F9Q6|VV71AAs-ca8+ictqLWRZ=ZY`=h| z!(+tbjOusygArWUe~;(u#pE*J(Mc*MN{5lQZyKsLJRGDmF^mQt0~eK&7fv{QC8%z8 zGDc+{vyV90R5$3zMp;pvsTt?a$`+6j?(o|yB7lZa2uqbP_ky%UYCGSVqbqpdXyKZK zP|HuyTtVOSY#g>aKok4jj7p05L*;S7P^#c4uOKPz)S=%>_Fri~OM-XafKU`94yieQWV0MQm^Zsn+hHhY1-54Katj zil-g(2;tr7L@+Ud8vHUKBQx)AuXNscWRDtN)lx-4P4AArN1dR4`gLWvOwijMhu7Dh zEAq1esBi(eL6iTE$Ktnjiu6s{+;gQQ8J+nG8amMh@wP9CCrmjsU63++5C3bEJ_<$Q z+N!u?+M9y{7&{g8r+n8{bNm+8_h`*|LRVV-MDA^(GUJUr5!uTQ9g>0`sS)C)z{3(;Bo)V$nJ$?V1T;ckMy+%%)336})u>Ynl+L>((Z|9OSR zWpf&<1e*P?s3}hJS9GEy@#-ie&n1nqc6-?J)`ynyHyXp^l|jZjiGcZ_xf@-EY>lbT z7i)E=@Bg5!p0xquDWwYwh*@P}c-US798{Sl22|cm?79&^ceCQJixu@%CTsYM#P%F^ z^wo&pO!k%zi9Dfws;Xh?2pW@CKgJI+l2;Lm#+@>9J0RbK)BP|P5doFtFy09v3dLbi z?)WB=C#qCf_*6xFRa&!1g1P=CcV6F**6=?3Lw3r;sI}w7?EgU8L=pP9`_emb7L|1( zOeqy&G#h}Wd?L2Sd&mZF!_zGEGyW5L1%(l>M+CPp-T=LEK2lSL(Bq+eL-B%Ffhy~< z2+dFaf02@g))|xit67MP-bEF*Ph>^x4lg0!+>A3ef_swaI`@I6AwSzr9vx@4yWgbc z!sxx;b#S^h?f-Cqyz+(2@OD?AMkO-?IrfZnFue7(;(%llV>{^WO5I12ZtDPbT(nLY zo#;|=9QSK$fV&h&u!2w!1As~YwZ)c~;N@*X(#Ga_oKgD(d;NeN#gB}Z{+Zg$2ldkI zUB&pa!sx?#x6C6bh}6nF%+tcv2Z_bH3??c?P48)ao*Z!Pu@U0PC@`<;=(ad6|iWm&%&{oV_H2W@3?C0 zf>GE|qz*Rn@F)|98t|V2gaw8N z49s^w$Q0UgD7cX2BAwsATP5sf5vxkDh630b4)IXFuzrs zK&Jy8W?tEE3FUlsY*XED$J69yTF%=hH`4VM5)B_A#;*jZ)9U7TS&@+TA%QPxkcUS6 zP-w?QNiou>fwAt>8kgUET+(8Pgz9K7s()e!F_-3KB7;J^VCu2|DpP{(C&pbp89}jY zp$Ai-@^+KJm(jniW+YnQEl$37KSpjwe_4T~%1DSMX;c_9{PC9@u`P(~=Q>EF04y7| zy{y4Ho}p@}%9K51C<{`gu5sL|w6qiATY?d3_&)XL_*=1NcUyQaQ(GOPPK4OU1IS;3 zvdOgI^tW)9v578{PS(>~x7`o@mba;)K%oRh1^HBn)@OYIi7#7v<`kmyxbg#VN-RnI zDquH^@$NUlFsp%k>$Yi99`V%Ndd0QVzA@3~MkQ4&kW?-mGi_U*XOs7QSl>~(Chpse z8UE~qQ13;YNci=Xn>@U!!+*btk3C;t=!&Zq?Grj776CZTN~788clLmy-38a|_@dgk z($dbkFRpbr0an=DgviKK8+_b-Q^?(6G4}qf;2ZvH*CbH12wKOR7E#f9?Hrb}L;r~L zMIT1N9EOf3loWN3Cg9cDv0H0_V~u-sqa4W7{G*iVMLg}=v17lK<96(WdxchFN%JjS z6P>8uel+p8LuhyzKk=ltKx30+r2s@ohemLRMULgqJ<9+?sZFs)v2JtNYUg*Ok-6 z47T~i#VagEb$08FPQAU^LcvFtqTz+L6xXm*$TVML1bXHF1GWiOSc2xzli7)^b*|`S z{`s62gc2jDSIN0a?wmUFmu`)QU@_Ns9aYX4pUpPlwEhLV79hvkZpyf-kmUzLMmBWu zg>OlY`laZXfp)f5iEaeG3-D$K-@I$sOxatwYy9qFThNBT z-);LiM*M>pq)}&P73S!~IuBG`j^p?#Mr_w~@;WI=j;PQFz9uP#^fJo{TZ(^=^C#c+ z0AtO$#<jYbqGRA@pLvRnFrl?8_(I%G+)5WEkpA;0)6~1OND~&nmYH#Iu@WarLW}=B_ZnQR`0{L!-xQ&6^+?9?4>9kCLna{qv{&Pw1n~=#nsxyW|~9D zx)5Cu$b=wKqd6>r7^GWL14?%Eao`NwG-sz(=6EeSs`<oxfw;9`2PNb_|gu;N_M*~rNpKAnXbc!yMl8qe_bM=V4nZCp~Ft`a@|6H*M*{> zWJ{xf235M1U9NNJCMxDwYmcs}aZm7n9GzuY(~sN5M~;$4K*k1aG$Nrey2nO$CHVc=W}qWS$~Bj1=7_O zP6o98OlFpp@3a=Ufy<^vQ!0>0jm@8qLK{xhw`q%`$Ya%~6^wJVjWv$?W{rG(ot%_a zYq}c7!ormviuB<9=)7Ve!%^mz@=jnvyX$wI%bYiWMEOxBv*}y-rM2v(WXkO=#EHps zS6;rML~AeOIV&x}S@fCo+D6TNMzv4@Uea~q>Qdx?09MtV`~!W#p62O6I~Nm4bJG@5 zkUAQ-y0SGc#ys(d+tVaG&qnml_vvkn@(QkLmqN3cWKYSNZVa_zyDhlWynwa?FLz)C z=ZYgk13rh(;&50u(;HB=SorM7FZi6MDki_YNWBPi-=xj55IRm2_nQ{&MfMp;8Oo!{}|O|_;j8d`2ZnYRA}(3vm*q|b1c zGjgRj#MORBfi)M;6HV;jgNS!g0J=W0@iu!2h0%X!G{ps~N|d^9deh!OMK$_G&MUKP z4|clX>t6CG9K-q7M!{#z>O4{k5qn&#l-78jYKD*fa}-hx`1^H%zmyvd>-g$9h59k_ zIdN1u z9C2K@))T)koisOP@7bOzT$w)5OX^Z=CuSLNH> zB=kE_^Uccl@c#iYKLG(66OwB2(qei8jl|B{Pp|Tau3Db$F9l=^i%dq1sjJAJx!|(u7L^^P64uf>n&7Kd-2IT{bU~HsvYf>;8@MFWc)-H5)x)I_AHc z(>*8r;LTt`jhFLR6Zy@i96#za3;QwAI*iQM#mz2Z7R*h&_|{Zlo|{-p{$i`)4ez;E z8p9kJr!h`wbxL`pu2D`5_n@MgEg*s8qq>^H0EkP>=xvMd2x`>amG;bZr;FO*g_+yH z+Ts2G03_e-;YMW9)}DWQ=>1>>6(f2Q@e9T3Ch*O;F{_ztdyyYf{cq`z|0$h>`(Dm- zs|iWxp%~@U&%45W1K&*mZ6{jlPay?;Swq@LB12=m?fqkHHHj-j#k_m*@`6gJ(CSuF zxl^nsCxacwnvoa?yTtBBgS$xjx1pdT6&Q#75ufe9!P04|l557VbiR34K$Af{LqkrO zLTS%xN;Pq}D+6s?E6@h-LRvFl$>|(xZH))&0_ehTUtJiMmY?Z*yLR(&>M-7HK_T1~ zM5**dim6(Z{PaN|dWszVw0`g#u&T^UMGiXV>a5WVLTzjVCta>_+fHh% zQX2tDnr5pe^t0-W_EJjZyp$guFB^*cbL;m$^gl^w7_I&fkWIh3iZ1K2q@Ql$>wS0+ z+xf+BIh)QxK0!#bD4f&@8gi!F* z_+R)$_@nuc%e-(tJ+78Rf=E?4!#=V#xSuleWC_3Z^2WYl_ zr;j@}-4H820N)T<8Fye|ysy1b{?1*fq6UyZ9Ib&6)&!`#?H5rFJ+;>)MBMQ3Y~A%C zJaroRM$Hg&qyx?nKbNscs=X$2oAY$}>d#n5i@LgPM4zl2$tRE;VHzrtS9?4By;EF)!$4iR~fe$%h8oCSmz4jMg(IU>dFj%`T} zC+SP_WwU?Mwm{fK6I}*{!l_8ma+++>dAvoRx#RMK3^mL$1@;tCS+vKirGc{jru&P{ zV9%V}J;L2rK0GYXFGtOA{o>Yn zFFmp*euICs_jvueOpTKVG!R_<=9OQWL!$6AI;|?nk35ZCa_E`_%yp?-}{M63M5mS$Qhi2uSVbgl4^B=%^EUOQrVkXrA4G~%9)-Tuf z?G}Ggxt|d;WhT|Hy_qv`RYBM%bc+*oX5wYJgwzZIP+goRpVrBdamfMIy5tS|{^>zp9BzGcNz8myf2r839Lg=+NTQ;!5tui#xJD=KlY&8x>z zeN5pGGw%?P;;;klJb$)x_=>p4%xoO0A@WL z4(+EAie$BpldWhT)!Mo_kH5gy)MZHmE?wZBdu+W+2VN_6DP+j+DzcbVDL2cAm2RCM z>ss%OIW6Susp6Byx-lB6N#6o}Odbk5R0#g$ zcLdA#&R>3HG@+K)e{X|&S8ilOB{rA*(-5xUTjVB-;Ff2>8w&rZ`ikVM z@kPQf6H-tg#jTU7)pTpJ`Z+btGsJ70p}p^35h$I6qFRZuH-gIF*WBxdT|Q}HAUXs? z__QcUbyEAgdsx$)u0E>(gph-X8Z20=0KRdv$fw zK8cc-KEP4yCLV{}0|xB`dUdV>WreF&HjVD9TI&k-1hefBUAPg~WM(YP;n$;lYQmG7 z@nN>z=+#5UcU2y=e$h3JuAFRDCAkRtzlj;ZC5my-xZJd&&yhO5SG_S&{>DLrxbX1~ zV1z^s2Pa5K`}bTfhO zM}W5yy@5p|-w5R11rVYZ87lk@CShwLTxqV)2wmKo6Se&hz(%tI(NN5goS}nq-eO@v zQ)aHGS5DlvSx|fZ*vJ*ZTRUk@*#?|ReGMahhS_v2-fr&4e5-7K$MSd-bv4ka_*5mH zf%9W?d#&dVV3g-sFd@A{mcmN931)&@>b5%U#EKsZ8aG87wn|4wMmoGrPx|T?CE1mH zSY=zR!=HjuGj3@&Nb5GQ5twlZk0g}cxS1>$XxJoIDavCJ#_Z#?HL&@W{7DW4{Wrj7 z+Bu&i^hA643Lr*)d*;qm0AlWK$IOrjR4tK8t7Z0O;ESfQXL}39-!P4mGu+E5YA-ML zGkl6w!;s}J6a9pCa}!Xsqy3(Z_pHGA(n^MUz*3Gta%G9<^%wZ#IV?IOwAD8U7Vq^fF55R*81MV4*VNZTT zOrxfiv!-4@?|Ul-7mv@|q3R3-o$yHmx!>)hhpYK@kHAa}%a z>&ku}Lq*UCkg`*bwHpSaS~mqP(`YT#Q6_Z^Gqn;f8)in73^4dtXl-Y6dUCLBCa<>8 zaP6aSIfC>w!6Z`8Zo2A|o7kJTnLi7>GfY6)>vnCjw64LTN-{LqVX)tEpM|9WJ#-Az z>4G$w@p~w+4QuYNq(=vLZ%Jis_>(VRbbUJvEZGYItyJ%`>5GYFxwCuFyuTU`d(vaV zj-DTt&rshjfnE;$WV>H3_bzameaa)l!iQFp<<;^_Xf})aFgQH?sn}ky-Wt`=4gxpO z$Pbl|Oyu8AKViWmf;0J zAd91BP8MT#lV@oG+kQ#Y$$r`+WQQfXV`$dcV!#0w&puvP=1@7;@egrU1esz4Z5>sV#hRBB=UcFBIwk%?PS(WgnE1dduIV7O71Zc`D*A5F6c9AImbb!Od%T z^rBk@Y;MNw?V`>29O2lPd0PQPOSl*FA(@>pOh%kNvU>KWcxq*3x6>^LbE}lo!DOS1ZF@IoVKi2)uKTWf!$ec=Dv)xdd zNujg2cc9KNHfbs4qRZp;884bbloZ29(}p++`8;fn%vVXR?}RmVKh>XwWv0kcxJc2S-QrcQ77^D!m4SpoVvOpsv{ zWxl4+9JqUa8isc8$5=BFl@v%bl&d5s0+<=)PdPBn$Zf2JHd3ckjm&o}s)xERNv#wI zlfCr8lJt%ryZX?g7(AU?eq4s}8KfKanv^{fvKhC5T7+GHXK5O-WC@BxjAa-G$; zSM>OrV|%vyc$_xTy=EblTGl(-k}X+%9AXMJYlxm|+P@=g2a~2Fqvy63@IjFYQ7^AS~ZaL90%hd39~)O&U9ja0^(i_6@(7i zJ4aEbEVgmtjq-e%Hk?8HR}m{r3`eTUB~$X3)s?!KOSpkdIcIV&|FA;&`-h7yStXf3 zeu((X=E)CJ9~~ov5~$EJp2o2XN`spLG_k-V@-yY9`Ywj?5NDpXpAr@vHt**6ls4O& z9`f~qAlv?vp6~Js5wAfLoV1?9vitb4xXoFjVHA0eVoIns{h+yLf!*x2Gf!e9qxXD; zj@lsZAg*14UK7kslv%-xbH7>4HeJq_D{a=u|1zmKC(zh;BR0ZO;aLnBKW*LeaBwEl zzlhR%-O3Qe8T|&AYtfwxcmDc8KU#38`fN8n=eAu|=T@{+eVJ&%eLDA^BW&Cf&E-dS zsw-vNQoxr@^86xpgO8>!@tX4gMvbyu%Bg1f0G~qLycq86wM4eAju!m~`1|js;Ez{B z%l`qCeVxxRtv>H8cYcz^ZsI@lr9}<(&p6-lr@vl=zKjnhPu&AP$@^5+(5e{f1lQ*m z(^ZG0m#pKtQ%7D>UB5b>KYTV#lCbRpA~9Z!YjiDDOx(x{nWGe(-5+$>Jy;D9QbXBJp?eo z3+DiJSG`g%IU-f&A1niU;&7CnDbvbKMGXWLtSsMT&09`RO!mk?F zP**U;)1X$-$Flczn)l*+>nZg%WWQ^6AuP3m&cE`yfof)mu+adiVP&bL5<>08?g@2#!xY}|VAGId|+ z-ISa$%=QD%&Fs&$zeVn!AZJX!ph(!P-K-p$0(?Pnq~+N43*o(@NiN{fHn3VG6^+T&dkDA=NbqcPk_S{+ZMS|lqzSX&4fhg~nfpX6QN9j|Q zc^G0I&Bd1>&2#bXKi1A&b+@#F4&S|cQ`HzaZ2ofS%NSkmqP>M1*DU#oRMC}A>TNC< zM+PW!(Em=_&h8=2pIMf>@H>(3BV3tmSaW9BZ^ zQrA7sM@q(fIh*B0#9MMUs?>WR5|_d{cHgT@*sN1xx@B`(nT4TBJvU z2@caLG82w!bM&O3zlM`@uji&AT6xmiCyt*(&t5$|Oqu<|)BUG$@u#z*fq|aK)=|;e zb5^CY#G4_cS6KnyzP;B4c)XkCmK&g68T?}ov*Ql&CQEQ@cGVY+@BNeRrb_p((7OQZKX9Pik&MLuC+8YeS;ZhyJur-d7As=({8np7e?ehre{k% zU9k(y@9vqgKG6*N@ip~#OYC3UkGS)w3Uj2SE93s?Z5pB9A-j4LoK#11TFbN!xRqP^tJckNC$jM#XQq>6Y3(E9KaeK7 zj*tCDiyo35VQ-D~-`=!9!TR_gKfa&6l_m&Bb7p&^m=K}8{ZIT?vji!A$ECBgjIYiS zzj9-PgP`X(#$4Rh`YYA8W`~tA0Z-kmKV!;Ls~Tffakri}zVQp3{9b;p#Nf2FXF&x8dE>7y>!mhcQ-?91Tb|K)PA+p9 zxinccPFIvLQsJ>V9c}IapZg{$G5GWF!#m<%MkekLXWH#Vp+~oju5(KAzsTXPnsHLv zUtfp{bN*Ui=x%D(`^oB5ifS$y$ya+E0pKI+~3a2=hTS& zc^7G8dD+omL0e|Fs z-YAwJI)~m~_D&YPWBI$E!j-(u1HFmM6W333``HD(mi zvD?Tlx-F!SQDFBKk{*3=( z-WryNz37a3tNSQN)SjUy@un;C0daA`mmaU?uvAKid#C;(nQJ&WlX zBu~CA_fMEf*G;@4e0tH1&7hu5Yd{Ld&wh6lA= zMoRW7=nt0pl6g=3udz|vp8(H4GBAu8v!RT(qG!QZfl2c2eC@dZEumvSRBhR>A7QWco2HpR0-AtlA_Rk&fnn znCi|PmLw1)NcUym6`JgUJIjo^?v{Ljvedz%5$?0XIFcqX9q-j&F8{?%^4>=tlV{zB zEXDMTv>7dWCk((MZ7GjJN-D5VajH5K{HycD^I*7$u#~`^W@fKAJIopj3QT#`#Am<&JNp(-%^b`YGiKkR5p$c>!N99+H=-*zZG)E>j%~8$#CF*CNKjG{`XZ{s zmRqMUGiiAM6=G%hfG(OC6?y-Dr2L*{Fu9h(VY=&mR9Bzl{s3zKRdXS2~uxTTBtQ-vP7rsZx043fh58y2f@;T5>g$2G5&!RhhFW;Q^>)np>DRp{KSI-w`m$_ zIoka%rMM<{HppD?$$GS9-fhLeF$EJpPi>A07DwKc%z6wxrIE2#$S}YdE}Bg{JwbJC z+jRvisZF_z3oQj`3rk3J^)WjC-I^P2s>SZTyz}oYfK+FCw@ha9Hqz`rfCo!_UG{4G z+e5iy$|jgHVHR4!cKxG3fWRGmnQnuCcEH`hbIKy~XW|I?w&HO#D7M;9MCRVJd^58( zEh+B3AoM6QI{&tfGIf8jWK6pOy#l6{X$YgTOS!97AUMhb^AP&3eo7F}&dV&Wb8z@- zFhSQc!qSoyoG`w6VEHZBeJCqo@GheT1``#DThI6JQ*TrnZ>V(0-x*J9*o~LYxQOaL za?=U5voy1*Ian-UDw4}F3#`3d2=%_s>%RS)iBDK4lds;JGqV$Z=G#jSgK_LOqwkx2 zp@F$Oghof=i}n!V|Lcl$ju(|l&&rm0Lr)*%4aAm*NBK{N!Qd{2QoP=Z*wwf#Pl)%g zIc%^{2-!*~Uhd0y6INZRCl#PGqI@IT95;DjqQRa|{W9@OtO_pOiPEE<=%NCqBHuaBMGo1jYJYE zB{e3l6$us>4~+hn?58$V3u-xwnRr9))#(SK+bUFOYg~J|+2A{hl+)6gc>6N#wynH! zE0NKV&&Px*}Ku%yy)-8hr8ibz$Mko#@AXn_Am`$Dm%M!0^Ir@R3nP;G&YZG#5Qe7*i#A;; zsJTk~!gpGN2qZMR!!jSzauMo=R13sjrBh0fVNcsctO~ISf!NIl{{y%sP@xnyrRDl+ zXuak(OMV%E;V>*$$pLxPSnrXa&vhAh3r?CQ5AgH~gW~BqXYh#mVi}{O{)-OZK_Tz^ zrEQviLt0T(Z!!iEEE z&ok!0&uhxrn!MNK8)>a*3vHR*h!u0cKr4L5X9peCvcQC;@Jbv%?-S0{{9%bb!9oz4 z!r7b`3KMGnmG2=c$}qxrC7t+AG)?wIPrdfTrWPensvc~rhKWf zL(DnG`M(>g(}ke4%zVZ94Ou*c$2^r2tEmdP(-_}2X)sHzmpnEv=LP+aq(p;*AnXs%Fmk)bQ;AGm|xxLLF= z1bK~iEcs4sMuRPrSEhtrXxq10jf;fl+>eeeWBvn}7gLJc=gMcIY}%L0o&^|+iAe-@ z(KLq8WT=ox<MLjp6{<{V#!zJK|vP7ujQTY5&RyS36T zRp>0vQhC5ohlcL`%!f=E63zmgYj2&FuZj{EimQ$ex#e6kM4w?8$b`lxdj8;pL(99o z0C|2`%?f5fy;*S*kdyvr&1yqg{GJusO?Oe*0JQz1&-J$wZDjL5gpA}#6tSkb-6#1Ij zKa9B^gwS)PXC-CY)DVFrK?<$xDbGK(a=R9sK+q_-~) zw@?n#CX}2Vh<@l3+OaUM+X`f=BQYp@54t=_^ubYbU`8D zyvsQ6PzAU)o7-dL=Il;QK_B)npY6ZufpLl@RFxWzU~FnNSvqx9tfhNV^0>S6j6y~6 zbOjwU`aFd?h2GG+>9>~ss%yY<5XNc|w*my=CN17@IICr!n5Ml=q_(m$twH zs>9zNkFTb?BIItvu&FTIvhUc?!D4uE`u5NspaZD$lE?3H&qi}g>fjS7+3Di}RoPl+ zT7EI+s|cq|no_S>Cy>;VU+4KjoN47<4%z-I9p2yF@%rd?he7byq)~AQc`DipTe$Ho z=c6(mhd)!!z|!Yp7g6&bNHwLQN;|Ynb5KjV`|Uf z^&}@!E&>I!6FO_1JvGE0+?$Gz&-sPR6cKW@%?fmgHsA0qHrxzVDz#gN=ANR$I%De@FFU|wUU ze|H-ubaH)172C>L`2@+Zmf`Cz`?~F_!A$f6(=%PT)^}h=w_Y1~>UkCKOr6UlwSk9C zm6n2H_kE82jKx|g=EH4=QMd2+h8y2K{8BINDi=Zn@gQCn?SwXhByDCanggDa55ml0XH7Z;Sh_#O;#*Y{*R*A0i34l;4R9g!Us5?htf?SdyvCOEhP8_87X{!SO!P9_Md&RKP}OPE;yamE zyJwnJa_35H?~cVsHo49YZ${WUTAQyu{BDIm)ycI9fAcGtl^3i7)~5W;U(Y`k*i-NnEtIai$!7xO-PcPdur8LAi#rYtf(;O$Kr+>Kdn(Pn%-2vTT&1 zbg^DkGn+~B4P4GZ50k_~Pr1DFket#d`0naKMjgJ@#h6=%XU82|SBuf@e!aRsU^o}B zB{rrJ`}&rgot<;TXRw13)fHi2j^zdPAE{obu9EgO`k9-Ku)B1$((1XNQ%0t0eAa`h z-txQ=v|5g0q8SR3|CN8)UQ?bVsD?7R%_#=Ec}F?Zfj$!rzSK}Kr^^@##eWtOIx^_g zZ=<`duk~6%p_i>YYrt?inB03{c@?7X^e94mc$=wfO$D#4)3>5k%?}9YWJBVR+Dh48 z0VcpBLe3!vuO?1CrEnDDgAZP}JkU)!LRiVC^;)>=vU$vNxUU8ieM-7@LnHwo@1w8@ z)Ryci8aKYAE8LMa``cYI9nb;QQ7Cg&&U606@0eN}4i*SvWmw4~j2hL#ifz-Bn%vTr z6lG!>Nh6L38VSwFc_ia@Ob^UY8!F08Z*xyc8$G`9{1L1%3^o?U%A z7vP*(21sIi;hRxU%N^->-;tfBecQm7z0m#k zJCx8e5Gu#1;{oWU)g;UmZ>ClEIE9xq>`q#RxiCyOy6YBHTHsb|sZ{)-;9v-3_JR|c z32PqGtUg5h6MR|t%IeQ6I4%=YXK7BnbBG1x=_(j(*<&CXMNLc9d@M>|Den<2%>bSuBQSd z1=AYpuVUHPgKGZ`^!Q$j**!~7Fj+`mzIw5gbuBG*jqSrT$b>l&G8Gw$&5_o$pggLoL(l@Nbw&MC2?=#6R!36qwXl0Qj zeBry;^c*3&&^OQChZqEkPoC)ZA8Ar)MdpaJuF=R|cE;tUYTMC#33Kpr)jZMKBA9E7 zG=}KGu>+;s;&Xv#wnbqWtRZ;w;ijsaPWYRj0j7hO?1u<}DZUwWGDI_kOy)U-eh*UP zuz?LBpFNT#@8%uPXZUI$ey1WPhkS7(cM<#uCMx)qKQ#hBqoTTPb4ueoZoBm7&e`y* zVsH<3oK#!o%N^?m-e9Sj$i3e$ZJ#YFtGNjT8P)ble z>OI$x4mUHu6R{NNq{JtOQg^#S39z)7|C9rj5|M5;85nKb-vD}RQZ|TMGc>RYI?hh} zNI92n#BuGnf|<4eZ_eeC|G4u`QmKAjq#bjPM++r-nyj0Z;OS53St+NZx*DCVM378~ zvD%39mpx~Z3-C6CRIUabJA&V9C$5INC;<k2 zhlNT^gkHBO#EQb`oO()FTwL5RUiHGuv5^muUh9H+Y#$BhPQ zlt|m*_w^dh(uz36>V8X5t2fbmS_IU^?XdW0Qu;lX?}ZUV zAE4t0^lZNaPTmwN@032Za*smFejS$+kIC$avW66q1T`vkO`x)+zigfUjzYiL91Rrb zBK~$4SJG$VhIZPlK0Bw2BoBQlnRC|NDHvT`$h%6%4anaL#xMh9hwV5DlV}QFnCh7!3zj;sI zG5PUp=~td4E5pVAj_O*`g|9(5nk-M_UFk1av$R@Y$wXN|RCdReMr~4o)d`ZVbey5d z6H-a2@b`Fid^oz=^uVB%7V0K>y-9AhKrxp>LR*%1kw4_r3=;o+r7SRa_S86rP(o9Q zTaRW(<7zgYyT8kbq0LX@ou*py*MQ~6*voY@Rt+( zfTfe(9zKGWpt2;FPN-4NvtTU=XMm1 zf{;-eHFuXKqTVxq9Ok@=K=XmW^Q%B676Fji%FrrMf)+S5 zKze$*ehq7OS9f!8dsbGC2Y3ij5jqbhkLu5#7!U)m`kz)|%&V0C4rupk0#WQPbo3%y znJN8^nPbGIO9#7w5IB*HuLqSv9B}z~-HFv2S49PEQ3hD+&v<$YEvU_&3gWsPA1xF8 zR)P`40#4C#V-f5w1g|&C=o+9m)LKN1l#9Yyi-aYrT*r&vb8tsT+tVx1-dL(n&NY0*MTZ2eTySUv^y>T|1d3A%u8TOlI4Ha%!?0ys5c|Sf8NnkvF4+5#~NOw?fyD17j*=Zw>2cH6d=MbQ|P^oCQxI=04vV)tLnF%r)R` z_9rG6*bM>1HRNqM#)q0m2ycvG+<<1N!S}>kUnNS?M{{jAV{079 z9<2SFrq{I5>NB&Ku)B590LtQ1SPtVJaE?@~K2fVFG|}}u>pRC_{toWl&#Tm1G-6tF zlsGnlp#KxejeCY^qI;(BiITl%f8|@_RntYovr7;MhZ>w?G9Ri}KIM?X7ttra_^0&} zdp32}QahslP|LgWNsV8^?zTFNi$3eI$SF2aF3Dpi=FVZQrryJ7%5cp9%At84N^3NZ zq}&IXM1z8+5%XQyZd+bomoxAf|Csb5bz$~aJQG#rfvCebhN=+iwZfU+yzAuJoir$MH_tJGduEzs(xz0g~9ppZ%@nz$>%HM!2a}?!Cotq?(y+9g+Uu| z(L^(ym7b-j&9|!U)q7MR*q#-_jT&xy=bP1N8vxnU_huA}38#453GFFkG-EJ7i}pk- ziYg+q&C*ruf3m5#4INOAihMT0q?qm%E+Ht2u(hp{2*e2~sKGBp%>h(9=H?_OWY3?Y zyU%H^)xDW7%hks_sY++?&uA?|G;YA3N}i`mSocyVvb}#%9r-=Va+TjUvlb|Hd=?Nl zxSl)!q@(?Ol}h+u2Yc~*shp=SQNNWGFH#TA(#ozg(vH!a)^fN4=(ywU8Ro7e0V3CY z$3F}K8;==k@6pV*Oqy&TqDdhHs-g}j$wdaFi_uj>gvCZJ`$37% zpNN+ZC_aLUdemYilkF4YxUbOB{-VVJ>Yjw>75SUg{ zvP;vBcX_npO<`n#H6!_o2fenfl%3xf$dxNgW*f?Id-Y$Xtl-=s>xJV8Lv>+=FP7!G zw<3P_)5O8Fekij*gF&k!7!)v&6vRE-QHBY6AQVDf8^VKGa#Y%90l1= z%r}E|#GGHOlJ?o+;wXH)^;l{S##S7+Cx5?GU6hI6jXb@jD9?j6>V5Q!jkRtCZAKcY zH{nE^V=X~h4nWtHk1J_LgJhFNpERT&`Y5{y(t(kmFf(-DkZSt!DtMTlxNT<4i@aU_Evd(%x$4DFK>E0hR_1i~c6Vo09L zdv8`9UBL*52G}MWrQ#DDQH0-Wk+F9`021CTRKL1XiG6SY>5%GelMtLDzv6Y)0s zCxyn^s$(nNmJ7>JV7LfWD`2|PRfv$&SOj2z$f`;i-P;D{7W{Vdsyqiohy9bXm`h5? zW95tqR(wnLm!f%-+)>W3-aC?LfAB0p=zwg`aJ`cNVrsMG`{zv)j1cCxk7ZC9)S?7? zY%4=W2CYFaVOcYmKlRf(8)bbzB#~EZDd~sgGOF;z@|%vZbZ*%-cej~JO@?%fZvUl{ zZqq)4@cRsbU-b2JuH%~2V*+cQoll==2}(D?sJ@A**`n=naY#270hv^)8R$HA8yqUU z5r3e^!4y0s%(Pfrx%|`VKL83cTb%RKCTnF<+#iVy{^|C}FP|9~4`wsVM2T`L@?a%W z^66D(CEZm5ZH^(d4@uPw(YnFkS`>%4eK=9%T3m#X!gvlC)kC@F#iw%LQ_4A*qTV)s zD6`p_leEIT@^9TpC!F`k;82bXn}p8O`RGd4V4=9N1Jk?7)j?nIIW#P2R|h<+5@~WJ zR-H9X^g!hq!z)QhN&_NlZywBo)4oN~6{CxlsW?%~A8sDeDmjB5##w{R5LysM zQx&$Tf5S+dHo@_WcL&t3%1OM5(r5&64Yhm0V!-VqyD4WdoVY-n8JF{@cYq&$rKEdQ z&tr(nDtyS*%BBu9RNp<9=oD3|H61|Cyssw@Wx1SE)L)g9d3|EFbgpFHbSx;n4A(o* zLoDOP@vgdl)@ZJV{Bz$7X3|TKjfpsr-@`{m3>QMt(HcvenYqW_aNyrDZz}*N5e=m_ zfH88op+E!UrGqR^e*PqA9L1Ai^Tmi$HF#O5c~$%OeRcgWmxRF)hjjSvlzyQdfIGG{ zj9b_?1H%;a(McHUnF+jYj|F-3kVWhVi%gn|gv*S3 zvX){hPBK}_@~gt}F!7Lo2q#vGD*x8Jt6g{|_0er8NB)u;{Ve-=-sp8`i#iDl(GrA5 zRPrOY5~xSl-PCT$=tVN>|JK+Ich6AY^CjrCADcNYWYUT$@FghnQ`yi=anLRIYK6zL zA&a@ZUjFxO8%k$$oki-)vg1llb7I6o0aJ+hBPT%UDeK8y1*`mv_tJF92~yvvwBd_{ zT0Zp>8m)Viw=o}YyZP`hC-&S9!7uE}0A#r14Ljrs)=usB zby|U|oJIEkX18pWSVlSw`ZqXc%M8uBWirYc{!~!)`(>THKH(tjH=rBg zVv;t2lot`X(%>4NX$b69SvSt!#6C4^D%a2E8LgR=QF+MxThq9G2g$#Jg)G*9-x&7! z!K!#f4*8Ly(~=yzJvhY%f~GNB$=@lV+u6?zA|-hqIJ!T`aqN~DKs|){G9Lre4K@Cc zqqA^mvi-aG$k7cB8Mz@T5=wV$Bcu^{LAG*8S5u-$%o zj1J%X_wo-6w%uQ@>wM4o9HHU$q!EyBGG>Tzx#_7JXdc{#li1qta(9XA4+dA|OC+$r zU0@YDm_V6Sb&;`4>g;9RQ1yvxzf#)Nnr-)YQq8t|edIy-Gg4`gD^fh(~LF zPG`>yx5rG|vZ{Zj8V+oUdB2KkLNY?eKG(gcrBmvWQUd4&Q2-9-BZka=&EFlb5`%O_ zX1MNWPvGQZO{3p!Hstxj?u>+p%5G`VWyzV|ChPCM;jDS%mdC0@sdpu&gHQy&IPqr$JE)FGtAaMpt3I^a0lvX7YsrZ z%2g@hr6?=bFXg}VZHAo8a-W$fK8ZV=q&)5^Yg}CQ~@(<}U#Hr`U z0C_B&51T_u3wV7`c)ZNY6i#I(+`WQ=5u-d4@lIOrX-;8s9WUDKJf^MZJMrA+7P~}p zX3Ui5vX~9+-M3XjnT@i^R|8)aE)HrAdWr94L7O*jKCqc8mSu3aX0kZ6^tjwm@O)I- z6Hh2m4d6C!0pgdJVzzJ#c2SxwC^_DjjmfgkYYX^yks2dzADGUD9u#_i?Aw6agN$n} zj7A_G_te!F1VDy9qIEX*EZBzpRaI%&Olus$ZB!1sKRNNRQV8?rM{cR`tA~qbQ`}s} z;A)(sNGy#;WNM}8iEpQGLO$BVthIbHq1REk;}UydqWjI#ON<>w7JwWw7^s0fe(16( zQ%@uiv#-uy#aR2GUXAYFR}&!(NI)^X@B1>hvJ@bAN@9RColuyNBWt2~vYM>1xq`z+ zy~e5U2e3eRK?>5fQBnNi;qgG9!pFdB!LFxiJN)+6N*Dep4@ziB&afw2Sp16yOa2Lt z17`f@C{hhRust5Hxmd)&U{svA8VD5dv0j*WtKkH~c491eh03AI;t^mum3xOPxkwx2Ivf#Ws!RY?wH>(S8?`n$bG$$b?qWG1YzX21sa#n^&8?Z{jR z0IL)7Xl!F-N}Cu2G~s^$Ji-cmMX1wgu_ zIfcx&YeExp2!KMF$fwNqjp#6Ep7R<>>P0{#b{+)Izu-?m&D$3$S&W90sG`N*2<~84 zYK){7whRe=_VHxRkv0@DK;1y?`uF@*iulfdI=EpxFQjQVI={Qj`o6oF!N8obPN{oP z9;u^Q^t$>vMac~*TNEM|DY$6vw|Rq)S|%&XVQMQiwM_B{Yh3hZ}O z|9awwuS#5VJ&ZY=a<0f#46dOy`9;w9#W?={;17hsDcr>kFA#YJ&NI$XL6$*FF>W~3eBkQ9#U)>i}^r`I7RpW}<2tjFqSpcM78#`|^QI}iwX%m@h;gM=8f4t@bF zhE6eg&RxBdTCI#1`z;yhBUaw;c{#ps388gvHY_IP)W2^hfK{Ec$Sxc!$3A5W)6H`n z3A(Ukb$9@^B8MD>Sv2D6m;RjLB_gkp9Pk}GY5N9FBhM&P=I4N@!3|ir2>yfP$(0E~ zDxxZxusalBQGPy|!)&6zXwoMN6(t0795j_4K`!d-QPg&zKN{77U}qnrUmkIK8DgpO zx$~g-Gc0C+j~0yeuZjQgoxRb|KL13e&Po*@t>BQc14QW9&>zrCE5C%bIcks@_oKlt z=asq?!EhkC)x)UvZ5HLzBki#nf$XL-$W9v;a`b{>2G_fG3IGS+Z*BN|+e{Nkr+jip z8;K2}^qce$*atvATg$O8j)WdC|zYGyVDOY?ZWBff@ZgES*1KG0` z-So8tYd&9T*-)tgm7;6IM4NQF<#@hT>rq*oOP9gJ^fx)$scgxq%IDE}Ph8X5*!U=< z6a`L|0L5P%<3nz9{>J(+aSPLwmJfD0=Zm}&O8UfK&OPOj_|^Ksib;DGnTbTp^8cKh zO;gc9)QGeP59UYzxxeVw=Mu{&xT@cl0w_s==%v7~x@Ljz6hZ&8@a{UNQ?ksnApdCZMB|#PNaPA&XMp(dd;w2j0 z=0}K_mS~xF7#0Yx@yh!2$OLlrBHB~m#>?C??OoViw!c2bFBOY^g&8o`d%DeaxSR~r(0`heoT%z*2MHm=gFI82wpJN5e?iUqSLeQ_-vR%{b(iRPdzI!0=YjF~4$O}VHZU5g>QBgg zU3t*SifOiuP)xp0a8vKcA5|pq!-F>_Ik0KhxTlZGEug7$H0W*qm70(fpg_hLEpYr; zKEixDnWmdP)K$TAF6JXLGcx3G@>pjf+)RFDQoKvK{KqT=TBR8bR=39MgqIZM)S~ub z9_FklXKxNLw|z`_tOgLigD9{NA8O0klL^Wacg=B`bkeFHM9@2g9hvL@!Ygj?WZuWz z`hj_-V%OY%QkjuQ)u}OwWh(PBH2p02Xzu5sj`#>6JbcFk+t$@Zr^=)>xK`CJYMT70 zA}dSw{qmL#g;>8P|93)R+ZZ61Lk7&!YOh!0TTkwwOAZIl;G|S1*&S^`SG2uyj{9=! zSQG2<0ZM5j+F;|xnfSQ80jKQ?>A`@b8}7b&L@1ELkh}2T@G)G*;ei&Icttn2pR$sV zgEHqcHO_dYHeM#2D1oRENM z-ToFKdgG8r5IH@~O%kas1AKU4@2-5s<`jT9*238DfE zM5Jp(zSa0dO2oXv`R208L=1q-xn#P!_fTgSq)-0$zXv~x))i~5KZ1NvvCOa^yslj) zeL8skGd+Kpyj!{^wzX%6=cmRI7+27yC9H$Gu(G-lx*8JE!D+{U&I*e7dAp(Ij?ldx&XrM_hN+^ zt{o;weVA)3TaH zJI@qOfD*bluB$Le_h?vguf(k%_VZC@QmT%8$^vZkyF+ZvTiwv-iPCmf#ic6L)^aZ-OSGA=M$R0V7|tj&9X-X=h|1NL($yM#!ft_2`e`?AJuYoLcjKGD z*q85_2&X0tUeBi&)Ks$>$W6$+;>aH&gv1yd8AnX41pfR~+hA1Ob1ZTtnb-rM*5r}~ZKxOP@1 zS!gs2l&4Bgs}cErWBiqqw`;@AsFFf1K`C8#pE*zd@Ao@jZ%;kgt?2yra9!{c%I4bc zw0l3R=;q#Yi9$zT`T^T7KlztK8`K#<#L*?&+<+&B*$*Z5aQ^I3dIeky}qq$@5J)gAeroD2P~ix*P~DE5xDXG-JwY z>D8}-Ex$ikU$ya1)BC!y&i9}D$8Xnkcg$`6J>p&0lI97gxLKuiP{Ge@k~uwBakp{b z?>Rmx(%qJrc{$>Jo6vG809b+E3Krc(n*8Ec+pNYz5?gq2KfnoQ zHYNO{VZ*LL>~)!^IbDso6MLdTpq2mNTI~vD`Y@BmHuV+fTWwR>QrEvAAO7#!ooOm@ zxVy?HS3Am{59b!dNFJRM=KZ^zJ7VsCOsqJKvch2IHjSPzkWpuO#2zqPT@>;~v zC=&$+5(gBAAOBmb92)YR2%@k&F0syS;%dv;yv^@klHyt8R@E^u_Nbz!#-~Y;h;wcc zC%~WuaZ0uSlDY6QMpIRi0ClqoBjp85Z0c%ZoJNT*TnUsbYibV zC~K0FE=v4f&c{7%R&ug7b0LZ~Qmo0+`%1?UbyhZZuX(+~B0H~ygEtyzcsyT1-jZSC z#X&RjS?8;}$SIM@CxQNn6-|0PQzs9O0w%wUaaV*n|HIq6ch7)~H0Q%@LBt0C$(m?< zOFsw2#s#Wfz0~@ZH?ZO294_CrZa%cIoE=i)c# z!V$EyZW*%LvK&f#t!wXBGFa1)VZc9yeb!rJrx^D~)5}f;s=tFnH5aU9X%*Q( zk!7WSLE@ty^N%|jJBtf*Z$1n=_5SHLdUVD5wK%|%eX*+O$h{?1X`>`PmH#&@cWL@h zykNuxTR8jv4<+~Mo81Kp-X?CS`u*>H|Fra?R#jP|(AXy#9^FMENS;Q( z{?E;tGC%)g=G;;smp?`#^XN@Kl{slIUayJzr7TK%Ib}VL^owv{^x*dvzx&;?ppE6L zo|WmXv`reK-+AOIzh{fjU(l5eLfb(eRz#%%^2{Ds{XSz`OdQN zMY5BX7Ne!nXf>R@(nnNlTjgvngMt_^_KPQ;S=a9dcrJl0S)ci{si<$4s5RxFP}t{t z4p*Aq;YUshOuM?2uMvteFs}>tVH|16_NKKLA%+>E^Tzxd%AxLFWh<&yb&$`B8sLv*Re(9yOp(R?fdl7Y5Z9B zVF5;THV^RtVm&-y&D`Y86utvM8qSYciB(`|g=k&X$HA8qlC0!n=8uB7E23t6Hf;U1|=T@ZO7%@x|eiZ+u zV27j5mLr}S>PX<{9y3z2C{^-(&VXr%iZDuqKs=Nv> z+cx-;lY~XZDV-W#35Upz+Em~83z9&n`>YjF>5p@5I_h-5Jz|84%~Qu^dWIV>hqSr@ zw`p7iOAfWHG!=!%{ZcZukv^C2x~dsV%cO9Dk9%UDgQ(#WgUYqf*E_B=Yp!(92xCS` z@lUY=n3h-2qWhOQ2=`bHzeFh1AN)>;5~ilPOu2mi#wuGW0PW%eAt=%@g|dkrya*s6 z3CCQ}u^u8q64yCheBh|+7l!#QebFX!-b zHAjYf{**{@rKEA`A}Bx<79AP?b(aj>E}R@5W>Wcu-+O`C*zE2s%aN01n!}2wQ-=4q%XwZ=vso!xpKchDidL?+2dX1TYV0M>d~Z zF+^kgg2nKYJnXJ}`|s2TeW~p~rxnI7?Z(@W1#s=f&U(n=xpFOO6?OEbc2!A2+4(p)$3|^Vp^k;uIz^&M+N+ABi2FlCP9dYyM>XBuP`twx|iTIeDFkk0s z7)ych8+clOU=t1inJ&Je1Un+Jl|2HOSVR4;Az6YCI6>(uX|A|QHxw3eFFARMZi5?> zxb@O*#TI9(#jj{_{r29hmEm_gxc#j@+4I`X8RkM)IrafKX7D21|2UsK*MWLo)VJ@; zpWE#2%SjK;Mgxy{OP@dpl<)r$UC^$Lu3XjG&E z`FH`q;X77WMtS9ch$!#+B0e4Rd1j_~Z`7IyFpy)D{#Deb4VRVe{03!{CR@|^z5aO; z#{MtNW7c=hc|g3YZm3dSHF4mAP_E$iaL9S1;)#(-$>E`+b@p>q5P6UX1LSQfledz(w<6x8d*xn1&BO&d z!8SLWEcv9O0=*I$etJeI#vRAy+}@PVmXw8*ddHnNr^|-#45%qT`q@X2LQw>ZZB|i5 zU)QM;FDWJrzR@s#?0Rb0SQ}X`0xw&m>*s^UD$o`c&KDP2lh+Ns>I{_` zzxSq$Am(B^EvNwbtPTesd3iy=SD*ax)d%v!@@DaADeMAwy_yKqJ{jshcvLwRBtFBk z?oLMyCB}@wC90FHmCZ1YKTf+Se7eJ& zg``%kCnWv_P3=#t04og>y2{$9URF_2PPyz|B1J(spdRQm=KRz6OqUH;%Mx4vLENlG zJjFz5*##VjH_?A0`o+|Xr`vV#g|F7u4QSWRRDQ2O%N&Ock*vlU6E<<4vu! z=6Q()T%C8#AIop$UWL7Cm>C*|z31Y55i5^%ZX^_>C`%(hsg_bS<*#~O2gdkL-oa7nA4MSpO3e1zpd6n3q_Bjlf-wxF+eK5)F8Y2 z3SwH@s$z#;zSAEHlv7$499uvnH3t+|uWGI|Jc9umN!fz3SfW7zkJH0_%%;qB(K|x$ zDNq7ht_cxqcSQ!0MVPpn5t-CY#^x%F(1REX^(SP_yA)5O1G$)wuX}MOB|Zas?mVfD zk}8_XYdp5$FUQ8F`GHC==RXb%BO@z$dcFlFIEZ+T74dL?e^OA#UIB~F@Sg7oO^_a@ zcPya2lB5pR$6NiT%Y8&}6X$5GCqTJn2vG7i{Ma!n26sDaFiyf#NPG3W@x+jPiEan8 zA}C`g>e;dou}Err0>u-)^@6;n$XRo&wGq>T4ZrRkGtNDTNl3^wiq#|*Q#$o)?7yMN z0`Hz|1ZYOEEQvw|kJ%d7lGK}myTJUo$UY`)fKf1N;SD*0S`_O$yrZe#B@9;i;xo?F z6rFp>%1m-Jok1!!!&u>$V?g<5sk#5(9aF`A&IKjZx5LE4Ed27>Dc;ykz&gRQ z-=^AA(qa~_o~Ps-5XG$opbMO{s6q`Z&C{&~lxE42UC{sA%W9m&D_1nR`zpNRg4Wc( z@Ufqh+Yz|B4t=V|#ze@W)n{u_Nfttig62zyq!eMh#~YNw^CeaX&jbb<bIZLje7I$vp-jV#vYi_aRn2O6Fl z4eRm6#iFpeGoL&^mfs4(S9AHN+-Fe#!5 N|$VCybMfZB?}A@mql(xEtQMmY23~S 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%0DWz~2xQCRsuK`Jju)ynpeu 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

    pj9YyKIGH-f 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­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

    j%*TWLU) z$dsbaX(e>AlJfuW35KOKo$6|qMnku}XEJuu80UoxaF<6>%+Z@!G?LWxtE%G&Nl|U; zew|ba?HvO-VnykfyP=j=4yjtC%=OhZws)?ltyoeG3=yNF53B{aOxm~Y@gg;YU6YF1 zssh=WJf4Uip6$u!npwZ=j7z1ysIww3^VJuoXys0>{E=T2o z1X;d9nn^^GppMTi1eyPXvL_ll^oFfy9ETF}@?~KiQyR#UdB?>hTzkjnF@iI^SxIRR z|D2yl#Zy`I`o5w+B3uyTrVq7Ei_8&BYId#Df!dM||2UkeX*(mUyRs|+=n0ZmUPG*z7EyJ9W zk7jdg2Xp>SOG|J{=19GV*LS4i6ukuRg(+3^E5J==nO0S4>nl?dY4{lJ&56@rJE<=H zYNv#`@DG}U?@90Xpz(_Kl2Jo z)dwg_XzM*3{3)RQUcnw4ESYUZA|1$8V}$u=JFNA(Q%Wa4h3to>44bSd6w_es4!Xc{ z`qS@5ry6R?t4EXte9->!=)N4qgqJCUFb*iJc#oNIt_F|WzMXdBSP}o3F#6?r@+ks# zRK>TFH&jly`7N{t>ZN2eZkxz37X{i_pXFQ*VL#UF%5lQerqW+0M1%QM{?0R~cqrJk z>W+IFC?qT%QVzExKd670$T?t0qi8wOs7~H&w|zu;+d}c-Enc@=l9H{2+TFavn_j&-RXLM;sEIKWzj_cNc9$-S^8M7$cS~)1LT43Q@N@eI$ z;e7~#d7o}$qqc*!>nqQ{*yd{mA5(X&fdFlTLu$p+u^Nrpb2;UL5!Dsow!9gK53(6| z4_G)`TK?8WjcX&Ea4U!pFqr@4Ab;$qTF30JHQg%LTff57sbJ}9{6R@3MV$nisqMnQ z;w6=r>J3N(OOwczH53bZtqWInk#T0D^ZNy<>1c5-dkx`)#lWFXnoI%iy)KG1zz_OF z#`n%tB8k(JhX-?gd)3u}D?z}m4)%)bRU3)4P){nmBvpj7eR}QcQl9M^ z%qBVahFO%%J9l#x=cjcWUT-P9k0tZc$bZg!!rT;NR(uZtN$>{R=qYcnZf$x5W4kUp z3N$=2e*<)iXcu0a(XxYt-MD`qs7R@!=z~-Q$~Bo9?iHJ#ls<^{{3ho`vg9#(Ejhkb z0O(O}^i~up68N(0J{d}RoQhxh$gjz7`0FPtXa3l->5ghZpNZVgk~`|X{;UxdT}|tO zyG263S|C~$@tZwPHM}c7QI?-9GKi+mZ1ys@XO`_glo~ME10R@;&&3+Cw1B;1KDJKR zcfj}d^?#s^i6Vj6e`!VC9GQAA9R_T+M~}Rh!ft}mx_jtWhsIkU$Cw7@3LIpn+_xiS z{RZJVInMGB(IDgajD&$TAzaqkf%3HqRb}z26kIf&E`o|hXm&x@gm=PwIDyI zJ$){!`>=Ak1in8w%q$%_QOcfVa$i$Y<)i;kjaFI{8RL^%EzF@6d11fB2k(}?5FXH} z9IG5SRiI3^-O;*6hU_36N=bs%md(fd5R!8SMN^qVPhE*a1jdavT;hd)vQ;G3t{`RVjPyR~L{hPuk8Gsjt5 zZmIuYKrVk*Rb7q7`R@@I$KSM9+Oui>l>7A|4%|KfzGInO{>l9>g`G=%Ka&p}Id#_Y zoFf!b9ruIz=+y}CI8nS2&sZ92JB;HwBT;APz~IQ(>I2jMz}O&6Z;MyysXfUDVuaNw z3fH_?4i~!phYr#7u8T|qEvo=-LT8{}67sIEh~+z_o$euLqL3E(X;=hgdvNZ;3j35VrYSK>6<8Mp-?Y3nuhl6DzJ)gbd#^~UPp=M5| zMtiCTU6GEW*GvEb`ZOOE$m2VK(_#|heSr?ONG>q@O3f69JZz1C@YEUU>`o>r%|AL; z&vK$q2NgXbVMa-wg0p&%+(8@sAzq2VA^nU7AzGs$#Y$}xqU{@Za<#p5ePJ`{A6(p_ zZs8Q*YHY(UTrp;f^CpwOz6lSX`FD)2Hp_@2d@8S>DkG5uH`%fm9+s}gR{l1vcGH;z z<<)t$&+=xE@-huj8(x+FsS0e3m1)2R*OW`NI?Jv7J^%p^ii(}D@Tg0eXt7kTvpHFU zB8$TzhzMGPYy%=YXBqpYrSQ1-SdWFgSPNyj>kEm327asJ07upL^{M82n@?vS)2-lc zbPQtYiZw^eB|boc_1hezaJ~&614pBzQ{VjmYiz|AyY$T z_rpwI+$I1P06$@iGj~*ZT?nutFt_hh%b$Go3Gq!0wl3|2$C;FIPSUmrJ2=|5B;5^w zAbNq|I5MeQ3&EZLW8ri4r5X)(fC4`VQMvHzk$Y0;Xv*wOO}c_J&QcS7gUbWs^Uerb z$A&ZPg1y>c%5n19qyUa5G7A__4me06ELf&o5GqAk&U8~B`|HHO0*1)kG3{wCppip)$=0bx!0!5S6F|yEWgjC^`)Khe+3nC*6We2~5`y;Zk4u z5yoiTsy6Z!*(y^iFz)DkfqVAmPO zEgZv8|Nd242!4MI8F3joXlBeu+W&pYHq1&jWP2q)51Aw)m$sed=w1`x!Gsk)u=<5^ z!KcPlY$iSY5;ywS)ze=$mKAH{n)n7*|yHy3Q!rBP_! z;!Ch1&DGZtawST+TRBjwSVsi*j4XEP6`Qe-!Jl2(=tn*D*QRxZUduI;s0vD^PhZmJ=b!1TgBXW6rX1pwzM7lz0#FTR9RTKP9W(sB zCbjP$Y3){C|LPjUKk5a|=OI99oR?auO3vB;XbBfwtPS}FbH6Hsr8D5WA!ReNVMcPP zI_|?CClHQFvik4SX+E!bU!JcUdrvW!zVgJxg-Wmpw^)d+nzblXoa>-twhMzO)jkR` z?NGxoO!@yncOg7o+v8N}_9fIHhfXcD zvuS#y61MD3FRtK5#c+mN>Ou9x(y;neSt}CZi^Pq~NUbo`N3EA4Tlti-kv# zsbGDvOCBaSrs6+)QT(b zXLGB9U&(Qs?dP2lODT$d+*+^t~#P}FgI4n98u+6%Ya|G}K}s`%|Z;9FxBUvo(#H&PnD z2!gB}&AqFBOtl`Dx#gI6syOt%PSTdXANB#o)eba-^g;!gxGR5^rb(vgV&XY?oAT=W zsjuoTkN&8dNTwyHzkRFr?fLngdzrUBQanQs{Re7=ZcrraKg8bqRw2Yw&Ms#3t<^I) zRyjSio_Kk5IX;~{UBBwZ`p_#WTtaiPLSU(&S?5_(Etb28so_GEgjMYtbyLGIw^kN9 zVd=D_>EwvFDM5;0IQ~8f_XXAie~uz`(-NSMd_EM@qDKe&cMvNf*B4JV5OcqyNZJ~f zdBx47Q_WWhmyth;1OX+A7BcK(o8usmZG`316JU`C(!`t5BfS}@L=D2(WL`UVI(C4g zPvSq2Eda}QbQDRcFBWuve=n(XoVvvn*Zk=tFkQArt};#iZswtO^!{vOC~p5tK$={rqTh91OPR8t_jkR#2MTVD#2?%9FVSa$m}^V%vUC-Fi^sS z*t;R=MxSxtQj&dzAW;-^q%N0!gWM)DxY_+^M#n+AUXm|Pi7H|zJgB3QMj7^M!?p=! zRgQ!uas!O~O6auTy*zHFg_VU|4);h?&LVN0Hii|*0HO@@BPpynG6wtDbzX+AdfWUd ze(8J^jqC)~&pM>t8EX+Pj^ja0aZ3b2xD_xz;_iqR%cE@xOtEG@?Iags@B$>>I09(82AP)GkkUpr7&A}2n=UTWCt zY>0Sg^#74R(9v)yHt!{OR4-!X{Fy}>B0bDx94W%K*@Q+U{`F(u!BHl*6{x5nLvoRRMaPgPq+H(>{oKz&+Xs57|_nrM}3hIy4W zDTJ3hiE!wK?4ELoZmmkV>&GEK4`wgMuN*{yQ(OO6{JYDM#~mmsI+)LCsW+|>U^Nha5oR^NT&kW zszHaAOJC><3Ok~8TS#%@@*^sqH!AwGrTxE#BYcQ(d<@E6h1vbE0L6_r>;(hD+7{cL z+Ktb7mzZIx>-r^^3aSJhz5>(dAUn~To`wL{m3JaOm<<6Kye9pfN-Zz%yc9Et5+m2I zOo66ZPw?)Q2hl2N>hyBOC^NRfqT~Tp@i_dL$}0{AjFbF~(8x;*4FW}!DlzirE%lRu z5+<_@SJ9C|#_yjT@B^ZoEP*#`saa(^nYOW(PG$m*J`&zYXMI~XyVS>P8RLSzC--@A zcQ{DiNx(_WQz2v?VV64jF?(s+tA#?}IHkhFvpBt!Ug z>Jk_g7?yXn5?-NuzRbt;jJcZfSFY4It9;G10s8M5glX?_ez|oVRiiF-11)IBj8!sg z&=D~l+PN4ODW|3BFC`_6vXf{~eET7085aKcI^MvviJ(cm-$88C7CsI3DHgLn|f}$!1mV;n+dXRb?wGCAoma8X;D6kbQqNeu~n{9Jb z;xt?cozJs7b=h5E06?;EULkA2@aHR~s<)OLcir+FxFj1}N}tzzQ-LvLdBRMsMqDKh zp`FCSoq`6r$ix6%`)-djY9iD)@&pC!j>c`@^~>k*==sQx{PAItykr169sFbsu@-z| z_(W*N+o3>3+~xil=~^*+Rbz1*Njg(U(`A!GtZm;KvFul7q=s{hXwFs3usewP+huzl zBF%8F^82hJ2th;G$eb?HCTWcEAPr%I0nxYb#ekrCT8&rZ!d3|2Hr<57)=pRamH>e| z(e5Pb&BO47hf%e+f_O8a0x*DxbAOi2tnsBaGx?%E$uh;!@|zXRT(@iMqBdv}+cq)UD+;%c3Muf9E*@ zt{+`9EX1kXIZl}+681wd-Oy5@Vcc{9MUghO9P{HTX2_->IKCrE@RU)-GarAy7vEmn z)no3=91`>5lm)w2JwpVD=eioHm2Nb(a)R1Fx=PdX?5ur92iJ}F+H-ASinN6(5$1}S z+ANG%iem`wXyfZ06uf^~HRD-88tBrj#1Z#A4iHica4{t%sJn|NH@@AHpx==c50j#& zz$i#u*fQ%jNi;-t@$ggZPOwBNYhff?a^mZ<9}t{X^k_qGyeCP2X(_7er4@s4i0~*R zy;8Ya0buvBo75iFk|@mhWi41` zi>@7^P||1hX@^Vr#0+v0J|#Fm?5n-YOEGXDJ#nP=tN8Au=>EX86oK0eq#|be_6q~n z*5#C-sQ?!MvKcE;j|4P6$&xV*%n&Y?@?27bZ6=HbV?;j1{b5QSICzt}?fz{#AK3M3f;NJ|22Ot-NsBV77ay#9_Klf{gyRz z5ck(5{$^96oDjP!wQWDwWwE%JiYLYZ^{5aVjiK%+^Ln_zQJj|y)|NJWIyL7`r)3}a z2N{r&EHg;*#+q2btq`^dgm;SX=^j&GRQFn%OU6vIL(}rT)__K;9QuXoiNfc*jmSRl z5D)9SVl6@P8(&jRS^vZ(kaWL$S@%WcR^*ljAnO*VzWt%nF4tQ~RgzKc?OX!NO9zsl z?ugOnxHVz%LbBO?u9jv^@aI*f*yRm98;Z(qLFahY%MLWl>F z^2}X^ZB{8w7e@Ei+jTfgx|u5mklqwh5_vrH6D8GnEuSU(vLR>(41Ovv{^JmxudIMc z%cB45!e>gUNF?)#MGp{eayR@9e`PHpGpEzt($&?NSm)Z}1=b=Df#I~psea7++lUe& zJPRWiJ&W7QOP$f})YtD-oDOnk(zS;gcqx736#oNhMrx~}4gmolB4(cV3!{nvf4F{R zLJ-9!@YC9WikKR6$;X0A88cB|N79!T(R56R;m|Hi1$ln_P?4n>XI_73|L-}o)%|8y zd@Jb<9)}+{oMC$tky7quSaox|k{OoQCY?tz4RZh*#_z@?>f&r(OQBQdFIz_|t@aZ} z#Oqtd zO$h{NaPA_j5Ep~iJ}8iaS=6?m5Zqc+tyxgycC0ylNbY~2;Zwq>Mz2)6_*$?>!dK|R z8$dy?(a$N5$~*i&eeg`fQ}}}evcpeJtfL@u z553UA0WRUjU+bNgE}UkJLt9I1{4`nD)O~UApb`0X(??*{Tt6|REvlmx0sdcC20W3t zNI;~nCj0p?Y>IlT$VNLroak33bGE6u6R&C0hjR?A{-Qiy8NvZh;~wgv#@!5)LJ zs@fgd(0wn@jLPB`jKjzcdxZ{O5RGjEl ziy`^{1kkIQ(k#_kQFL3N9M>r12!?1z8~h{(W2%|7sFSfdhL@`y7Dxba-z^3moESw@ zrcCO6iUpF2Y*PZ{WW{?_H{+oi*|p3x9~0V$BsQ+MeYa;Nk3 z)55(>%|vZAb8vr6S$<=p^8C&j zL3ym}qUBnLXJedi!lO8~vN}mPxcYN>l3W$Dm6Pqlt3v#pQ@mz8ECh%D5%e<}ZlkXe(zx1JJU9z4$V?@lZk!D#$nYC@B>*r~A1YmaPdSM{0A<)V~; z=tiNnEy>e$4#tD_Y)&p9aP{3;Q)1+&_MFl)2CGwq!M}5wuUn{u$@A;S*58rA%O%9D z8b`QI4fXE+#byaBKcuHHpAKnBg?Ds?l%H89{#MlTlnED4`n)UP-qv+&=ux=CU0r(n zabvK_sG-xN_Xj1$bArV@3CRwHFS7DzOL!>Wr5Um?(LPjoae8|C$--JiQEa09Y7}Ve z@~RnSz9tbP=^`!yEE?+jZ3OLWtEKGKaSU~-k)8To)mjw1UnCZcD6=P zdLf6Gxux^&6@TXMZwot%VlTZ!=+Z9iDsW?L&VFS zEgjptz>K(c%(W@I65`cIo*^c#^V)ts{9YVKlQO<)8dUS?JzXccq-vUh{rxIw+v--E zr9dNljk*6hT z@ye3pu>-eZ@WYV1dq8oIzsFys6f{^(hUv zE5i!QuSYLQ_YAqJ51)uN?W%s8_-af8*79`(vFaGD)IkTiURY_i1VxC8Ja7zi>C19> zaxc`=v-$-cRm#o-8ymXbnWwBOm8n^f@$@7s{u2TpZF|w1eo8JKdZ1+8X^!ns8Gdo^ zp>Rrz27ThY*y=l}Ebp^lrVQ1z=sqt(>>Sx4B8a_J0s_Q$p7g%1*X9;=#CC6s&#Xr& zN7v7PT~9VXe^$LIe6PQ7{Qi`guMtlF@$;ety^Tq3=xz^Z6gIrp`f0+8lBoWsL=-jm z-&Zar>pN0cdUFS9?oQ!VoUE)LKU+RV7>)ANWfLtidXL*t)s)G&%RO50T|m$RqB2te^;QBo)U3#W>*%1n%*Ph~RaUQJ=nnE;BXavfs8M~N!LZL>}ZqaWkC>P5vXy!x^6Gyv}t?Z ze&mneA$BQH?pxs;#*$dB z6}qBGSW^%&>AS;IaLP5htVqTx$!qz?i$@m>Rb4mKzR&XK19A=p{L{iF_O5M(R^KjGn`&7 zow}~5jBajZ6%rm_yzh97V|+Pf-bl|U7Mr3xvnR)7*P{6={>{AW(|=fd>ojtuxj-xn z)}f&+(wj6LO2moKn8^an+uaGK4!SJS7Z*AvmTK$6I$n)Z=How%?kvzofc!HK2};kO zoiWfp9z**mQC|vHz=At|YCC?ox?6+74v2t_-z!XOr#wgDemBFD0~ua(8}OrfY|BtyyiI#Xz5$TS_1F8%>6y}3 z{mQ0+bbveUL2E#+TE80Lcv3NI?PMe_EV-NeJDS3tn|*QcjW7$cwq=+;`ii`7Ztq_r z>UhsHZV=1kb!>RLkBk0M8si_FmR2a$ivKl=m@V@?0j89GgJ+FZR#`Uyan0TY=BFDIk#T#=1+Rv3J5ALCstteqz8X;9oy6+JQ?n*Ad|X&1 zP|SysD=RpR-9LPW4rx)xotL_&aZ}O65tS)8AVr$g2e+EVF8EV5=OYufc$;FV!-%9u zRT7gM7*|M|_D4Sjota!C%9pqYMoq zj&&j)4!nuuk_C+@&rJocag3;V}^|bL#7kE`W{sF zO_{|0a#pG~?Aga(9;H9Qw$f@8&Qmw!Yr3zH9THM=p{uvK@?wTr?Vrd_S4__JQ(m_N z%A1>k2O=p&s$w#hc1S=jt3eMU2wZo41Syue>NRd%5w{%9T@AJuk%b4!3;-XqOY^Q6 zZM>_wsEmLhAcemR01PUCZ0sZM{cHqT^isIq9Xb0xz^Wz=;5%>iaAro8_%_6XiRv>( z?^hyp2wFpqL8M!mw$gTb@95s&u5I_d2wPk%-{|#wv@5>iiCZg@?s5Zl*j9 z1B)UD&7DD286F_9%bS|>b+bseL{zT&J5_m9LXP5vlFpkYQW6(73roVXOhR$ZTfPy1le8}VY?rC=jah+F z`RO&Uk!^aI@Axj})wdqgS>w7^YG@(~2ubl=wE}N6`h|Wla!cmpyQo4z_f0wfo0_mi z53Jz8-&epcyU~%1JAY01+%_7Y7P4~X=Mn)VNd=rhX{j zA5ANM`Ew`5pG`4}aUK*>uoaBW?*fJ+nb>FK6P4bXId$TR+2~16T7yY@3V?z63iiS% zHZ=b8eN)9Z>8rBuDmYh^5j~d-i1N;%r!V$=Bh0mDR4`|>p)JBFhy3(l?Rss^o&h6v zM+2SGK3w4S&05jlb3<#dWa05Nxu5{Y=xy|GdE7rC9zb&?k44e_Wed75DAkIk>CDTB zLzxFMa7nBXs(N`llUaL5R#IE+qA4PfGlU3~XZ4x#O5MzWCAX0m7R>nzREJnAfE_7K zjPDcv_Jil&_{+)J;aB$wqZdcl={t$GEY%T~QU^=vW$J5)g09^$QZjG}N1FQ!7he1j zww};Bae9q2ptfgk&}3QFt!QLk2oNMLPz;*eLtuOR5 z#(z1Osj0R^NWk{txW3CXSkwXo>~LbSI=uL@+ZG8IBr8=`+cWO$Rr7%ATDPZd<-j-gv_bAIZIbIAq7vPBZUlFg z$(Ny$g{}0cO3H6ZGTUNpS3?*c-~6b_<;+ew)7!K%ls4bOr9rlpkW&KBV%bhkZF%4r zHxp=h$I02YiqV{Kbbg61xRG*I(q%VVBGv9UmqJID9qHX6^x7HFfDaGXN>0?8TeZ^v zKKNi_X!K6nahECfV04M6SzCxgki^ifC5i9-g-n$BL+?+K*EfVw3}1&6nfCOF?5DAh zjRQKH11dZm8>FOsrL+j)R#1}_dY^M|*>FT5>?F1?hH@_yJ>VuKEHpO^mp7u9PzlQ` z0_II(P~%O$*rRSwFJYyxpKUW*1RG|SnjUlJCuLz>OX!!UfIw;T~^hcs{fB zKQ+pWwfjWA#qPA6acVjQKu;14_5Lhi(>uS%Pb_H`R(r9qDpNXi1N*ipYQ8EbBUVRq z+%fZQ6WO21F&pSHMGJEo0)5Cf}<=*q!Oq$n%N|CexH} zB`eo}_iiHcnYvRBYl2&Xq-gx)g9R#;`9OmD10m3-E$^?fcGSflzPm^P<%c*WnIpC6 zYW@-qH!}W&;Vp;8e4vlTgD7TD{mUB+Ruk1`S@YtxI_z`f4!O!N2*wgZ;P(`7-v_mU zKcmuEGY>4(Q4ULfYS$B=-UMp5dz3~*MwiBBg_(s#L2n9Bkw0FM-I>L_mMC(N=S-Is zfAet@7Oy>uUjyzSlaYF%9Kw6T=Ii;rX)0CWfgVq7!Ua4 z&30zwuH_M_@@}Df3NHDg0EsoDqgI|EBZV1Mel&An-|CGsn_Y>)}4 z+%-lOo91il%n^4dJWJK3Rve5y;c?WFYIon(G^ASDKFyCGDRqHnN@}sVeKi}XnCDid zX7d!zApkQ(a!X)MNdNP)cqNKIa9$#T5b>=a1PE}LWZbSI;(+Rvlo<?4l!i%;mLa6dzv@R#k9};@7Bk-=?-jPtcK2TV)jZZ zkjSx3tdWeQTKi>P%d%k*FV17~7{F?Hkfg~r-H$0JS#)l=_lin~Ar}FPOGj}5NN7EK}-s8B*lbdpM zpQJ+?3NmPVvSE{18L7ss_W?r6+ao$-QYq^MQ|T7y-Z*Q#w>(8voI9hBZDUZ3Z@G1& zTG9gycU!<}^3V7oF6G$O!7s@P3F2c68+|;SpCw-MihW3)m%i~J*tAMj$0~9j_5TO* z1;~Ui?$8NjEn`J;zPaIR4Cb^M{^I_n?eslaZ}xiQB4{h=g#QK9E2sqQd7*>Gho|c_ zl}6f}uH=x8ET8d+S<1DP->R7nQkkx$$C|ENsLIhfVE!Fm zEX|>0*`UF}S@3+|Kt#I_CLF$RSdgECIx%nn2k*=Kb>sZn8*}EB%nvA)Rl3kBG5w17 zVubLoy?U56xP31mg(pjrH?{MA+8#o@l$}N@)FuAC7HFa|H$#2PQdCIvsFLiP&Ah%) z_O3WhM{Kz@XxsteD>+Dp+s;?<{gF%eh>2AJU;J9dLW7&>fSPW(7|Sr3b4e^ZeBe`d z5Ie1%lZ1x2@Y8>PkB^d49p#xTqUSPu!~T_vOHB(O$}03Jnr-evgQ4Yoqc2kL8BO<> zD2LGPbH}%Ryz!qj?)DM~Hy#@5H0WP=c>$=YK^Er<98xO`@9x7%FXC);o7)mLNm@*7mXv22) z4Hg24xoOpu9~SgD*flM^cl{b8wZ+89B%&Y6vsat)zfpIN*4p7Uf;7)I0>>xs#&^KY zyM9}Ww|zj@!P}bMVb%r0lfk?5JZ(!~Tlmt-ycMx0R{-#!@2sWR zlDeM8NaO0=52AhtkUqw^X!q#(m_F zHHi1OW&??*Y_~1I5n0kBMR@WR}9BCd=seTRs*&!t959RXm1&)QYyoW2QC>-_wD4r620i z-)ZvY3FSSnB8Tuvt!gY!atiuyQhxaMHN(nvY}?(x8%S8_mQpHfd*M_QS>?-EgKt+d z8)zVa=iqj$+gDn-U}wDwU1|y~Bt^Gr295IgohEOt3Nt#+S292Eu?6g8igBZhzLQBk zRmH5jo{Pi=1IGDWo>F$Ux1+!IA+RcxY}z&wWT$oa<1MeQO9N%vFRmD|@&f9O&$`Fb z9~fl7r5NuO(;OUlXR6ui*$*eriZaP-6pKOe?)SEX9$xBEBBq6FwMFuf@V0KOrxSUd%fr=^j_@w=~9 zdp)Q#XBK&4b?O)7E-!dV8MOOYM()zt{79=-;YQwf0xfFH+2>;C<)^gajfPp#v=01! z31oqmFzeUYH>Rru5YnFH<>cSAF?YyGfE8vR7PggJoTGkAt9e%6|IfnCq3AnI;GDTA zEBS%SP?PUhMZDSe!xnwzjmH8}f*TcWBF$4&*xH@PcvXb+;Y6Sj#tnZ-vrI1@EzdjB~YYM}?y*Pd9(x-E^~uCJ>}yu0Q&gH+ySv z`{13IZZFfd*y?^#nQVIT|J?w?o|&S=4b!wbki+$!XhwI;KM+k20cd1jPG7Pm5FVn_ zZ)gpAa;RQ$TmzaDf*IoCHcaj1YB7l*7-GD$RT&2)7=PLH-B_n(F@0`=bD0n2E%GIR z)}jKYgUbzXr5K0Klh37k|0&?eX}&7ytgPuTgxKOGtwohq^9~40ekU3#)`e{kyzH1) zxPyhO6KpeifB>+CX4OX8YqALHh1ni|&wXjuPQ$Jc7iJ~p4RxlhmUw&b<3!hPXe%8@ z>Ni1+iT9UwyjXJJ$>!_y-qbhK5a}|{cXD$c*$o4VEX}eBu#7N=s@+)or!VDjM@HC& zx@d}>IfHR@fj`7h*zA=ID9Y0vVyZ?)PNT#Oyz?M#@5 zKNA^N4mnV47YFvmF zscD%KiPC@+=F9J^v%<>UNDv?P6W;<+|Vi zDd)rQN)Nz14f1sK`lD>MO`~THA54!A3X=~el?<|ty%vdT?Mrkg-n_LL8o>Y4a*vaE z9~gP4=p=N^wBezqsQzw6ak+?3isJgbfme$3u81ukHa{Q5^M?Hq0ZT|r95U4s?!iKN zS&SqUtFshTCB&ZL2tYdZYBPEb#p7wAcSktKDxK0kKiR>VnTDq@rOiBZSfWc#89s1l zHS3{KHi7>GQlV(M5b=LI*7-ZJG?Oq&HnfrD*XWUx!6k)3jYah-&i&uo8A(t7=%voy zu1JSJXX(W;HTwrlrzM+-ijU@JG89w?n%VpIvuHhvg)k};_*nFwZzc(9WWXDf-m-El z;)mcKx;u`9<3Sr74kfnAanR^*-q)PRV@P*agPDnU-stH8z-fYJZNe#DcC5JeAQ+OW zZj-WL=+ni1c>Se{)GCvpaBBHr-MxTYPdjtOayQU1KuLI@vRvRokzG#O7GAir8I~oHx79sLZr04*EZd^qEnT-ZeIjHP4+sMUryQDZ_?l8?n!2Dppal z(OrLWe04hLxAt-F|2deVt`I`y=7^FdhHT8UTAA%!vGfsgz&J|GNPvFJs92i2G`(rH zl_jXJvml@lVhCMjNB@ey)7&y{dDbWWXx6LRw^jg zB|on{GtiyJ^yb@Q!+jG?bG2{`pOUe6Mrb(=6c3(n2kpC>-EMl(#4@ftv^l42)^;$A zy8196k&!1oi5SYdy|wUd#ouqx)FQ>K(2Oxd{+7K}@_=Ya_ke%Nl_BpnbRa1{i}N9y zmVe1Bd|UroHXW;n01*!iar}VY=_SMCH4kgZRLC*s@keS{Mh3-x2z;gJ(oV(x@0a4K zZ!qclyq+EsM(HNM97^DeI?_N528pLm=0w00|2dq;1c-aAWeW&~KN`PN(mdds$vc=Z zihgkOYnL7+@_!&nPTmaxa4EftHctu~IeJJFQS6DpT;Tw9%|@wFo9^tJNw*;JHQt6H z7=&KyfQ+5CD<^w_1{LESgxLjrR4r*P-3p_A0`nf18Hm0NEn^zZNz{R>bJ1$kF8P9V zSNx7Sm1Y+{U1Lr4Rir)R#uL+`y~*NrdK7)aKRRVUSS4lN|3DQ%5xqppFV${f8b6+)n8o!CkienIKzCjhot53dkq(gaytAfJZNtt9NY5T)D?Jipd4PhA@ z`fr7X*E7bf^-eK@I{kpG4$wPKR3wt-vFSriZ-2?VbVH@fQ zUa?OH)(>SiK&&DeLeVQ#n^yYdG#)-y?M06Hk>nGUYf(-phwDG+f=RAY8ePV`< z){@2z`S3=3X}$C7_UF^ViiqU*?fJ!C^HB;z=Eo-iF&kBzdGSRP&TjHGW^efH_L~f0 zETi-q%Ta~N?K(PQ9@+*X6Yb&xJe=LZ*U%X3SlEkIx(A6xGmeu3+%CVawF(UpLV`9R zdslB|B;;??@dsD4XS1zS7>xLBNqAFk?1pYyXo2(wK{`v0#xQK4IJO>OQzA*J>S2BtP7>(}WE@H^?Yt#tC@JjrT1xTCdFu4fUEPGJWj~w<*Ew&xi%dh^|eOi~Rj7}d2$_|9`VSWI2w~};v z!9GBJsblyCglfOVs#_Xo9r+>r`TFt_HfaZTJ^&zlULd3gp{{!)V7$%bHp4M zBIe&I5l7dvdVOB*PV8`F%;I5hWMN#hWZN8NIavBDO z8P_H`#|~Yi`UTDIA{lbUvK{&Thu+m&jijjYOZJ7eah$j??92=7)_?zP? zSL!l^aRTCaM_?w0S`;819UV<+4ADDLzR`7EN)t}KlW|-2Gc}#^Pi0j*@IHv8| zs>fJ^($O_<|Kh-Z!&1$lfiOPN8*gT}r*GE?7y`UUzAs?IA7AQ7WX}i&TY&Y2 zuA(8Cm!GLcis?9YrGy75-4tm4F%EbM^3xcc5ZS^joa=M$_IZqLVzsP)5u?kZk-Pq; zR2wCmSgAcvPuSczTzr%)z_#mi^YWkvP+r058Jh-HbMC%Mjh0u)Oj>_cJxF`CKq3`A zuWuD+qpz`SSt2fKS!|R zI(T}{gzvr~K!FN-s^rtoy@}K37B4=vU3*1$gG*+(w%iq;8$!?oJ~oq-46!s;S{631 zT8DI^j~YWXj<_q$5tu9X)1*X9mWk zxapL68VFF2(W!Zl8{Q5C`STqsA_@6fa62bPjb&mQ)@bs$$f*Xe(0f5^k`sTF8 zT&pS}k0IpTw~lE4ZpgT4pYtn6d`d@-r8B;txB1Z+FivENJDTSBDi)G`ZxTGZMeWpB!Ew4n9^gSGFnq@SNa#R$?MK{rRBGRNmnsUIfZsb zc^{}$;)e?c(fvofkH#S+APal9k9@dj4$G8B2EQ{9oQ3Y&vYhk~$3LSir0dv%cO6%J zlyKEZ3p>*VfmWUT2nF6YLkn)V4DrR`j|0Js83ySrL?DcrZt_x)b~s)bnd?hy$Jw9- z6fgf^dO@MMy~(&=uu1m12zf;o3)VW$?2k~{x4oL98~kb%(`hwHMmi^9#Zpv4xqg8c z@$`t)Zd1XdqP^+;mo-KTDC`REvxFPK+%>4|_kWpJ5Xy}wlemVngw^Hmt3jR!rPinNe3;v8X7@0huSS%nx3K5a)c{m9mnjzk^Kb`=YqRl6h5?UgU(F6 z{%j3Uc6OsCIK&i5Oe` zU;6##3Oo5TJ1ysEM*p_Ut4mh#ClS&x&xL_0SAQ7dZr#!kWdY^=uotEuKO5EO2} z*p6l$Q&^z$o}}3w2+uAoEfg5LDF%b5k(Rm`j=) zuIg+sP~va(9e;)cqaT&0q#OWj`kQS_MLBhMRF(OEJMnr8Ocxdi)#~%b2`1Y7w)R+k ztGI4d;2d`pw^9B!L>=jvzCP_7#B4c|t#N#}Gddjb&=ru3!|J&m4d^Z3g~e)r%JN=K z>R3BnA&F)P7JC_ZDo%{>D}KG!jCbnEVuoHeqM3`D=pUs2zJ*|lmW$P)qwf(2e09`w zNMni;g~b;o+R-`dNn49jRj!z5y0DxOC+Z!vd3*UNudxpB%$CTW<6ZlCFMJ4tbZ3$_@?*UB>kO$Nk06K;8m{&0Q@WdX6u=9yO(ZPJYm)hWpQ z_?SHTxW>}wS9R<5K^5}u}dvm^R5XpgnV`6NexS_4B z+GN?6)5y}sCwCBRXx|X%Af#x%Jgkb3tK*lsAO$~_eulict7qohZyg#3`v?G%+UQy7f+WMOwbD!t9E%F*mGV6Eg8;1Wa4jebAM5-?F@;We&XDqKld8tpuws`hHhHe7mRW zh*Os`LbzQ}{DCgTN>N%|;qX1ngw`-+i4nssy&hjVrH!l33(|W^hG>sRmXcArEfk~^ znP5ROrXY0l&2G&1UtHVCJ0cZ~6>NuJhc*97k<&1rSzKNY^p4O!4@6Q*Ksx-HIb4Te zCtGGZH?*zcFB#;cf#%znhvPymXShL#X&>jd9~XZm<%h#-0$_nPvcP%ZhjeniPPqYV z0V8X04*$WJTvRo1)JJ7lJUD+)Y`fs?5;xDPnX_#&#N8cos4y{iqxo?n^5O^k$lFG8 zMB~TW)s*Ue+EolrU5Yl&)YASsz&y^Wj+euD{InA>4H*&OUI8IZkqNwP1s}I9pdQ!n z_F2kD=3f3(P1IN>d8>#Z-&4v@s>GC9yl;d>Z3xh%@igS2q3 zIaD)msYD0}-*;~ls`gNyskc7wDlZiN(Y}$OWYGqCbZ(C>+B+r^1w#$s-aYP=NlaM~ zO7WjJM_4ju)mR`UyKgC2g{-ibx@@{QurE(;0E?R2qbhNWwl2i=;2i_$ik6*F-Hc$6 zL52y-f@?LoloQpKPqXfVa@cV_e4Nlabo*v({$wXfJ(6eCh&4D}lfV*UcsvStBj2 zL|TU0Lwt8N2XMIaz!j198{OmHItB=O^{@FY1( z8n#FG>D9Ke#|H?F6I0}r#JI_r~yt2qu(b?~M39kRl)psyk%-?ziqWs1UHHGLhxE<+} zazo*I?WwM$io-j@Q8uENa$aFX*H>~| za%fiSlP@pQ(k1ZQao12cbl!7yAa+O;C|&>I(Nh3YMX0(JPZ_;wdEL@658mvQGfp1t zRyqR^GeW(_`m&`4fsbqn*n3NfcgeFGpd1_km#|J}SV4EdpD1>;Oif9y_8sDDzf=`M zOkSsFAs2G9gZYLE;)f2k1Oj@9a0$BJ$NNwj1TD4lb20y2>w}~5ag^`duy-77m&U^- zQ8(p^{VAI+ihyk|T;A~)g|=KWsCr{EqQ_aY6%AynRM_V5lf6YA0~v@GL4^^;sOq9Z z&C_iqi5Jv|gC^hbQ^{Ee=Uig{_&OO0Bw&2HiLqRTwne?@_;@GlpP?0P{w1^1x?gm7 zQCePkJZp0t?1!;{AG$z7iGEud9!;w$;GNVI`FG7h^;)hC1u8jXo^Gx@E)EC0kj+`F zw!gj&YBqTj@d_p+nZk0#uVFeCO8hKV9`^3TR5X6Oo#rl1Fb#}}yToWeo|`g%XLL|r zOn4^4uL$NZ>Ij*YCwQ%axesbqsY zmYd=URDl|+bK%O543|+NlQi|LwvvX=F>SmOQVAk{Z)>Rv+*lHTv7a#3VCIok5OY%t zAD<3;+c8sFufTi_FnKXt3^HEfG+wpgeOnu9d(5waC`_5KK*T?NrGmQ3$R4|W3+=EY z(G>~VJJ={!zq-1*#Pa>@xzjJN7opz!@9ym}{?t&bCWAR@wci^ld zE5{?~Vdw$oO6%nAozWa7L1mGw9qT!Nr2hyxFjLl!d3DP`xQc4D-+Lb-<_qA1O=6qa zd$VmD0o%6;Bw;QRFySJ^Cy=XBi3>bWmUNj?l&#$lH6wGId=t69+#FjN;~DC)J?eeV z>pG|c{;pmh(b)d7)KEwa!4_-VaDrJrhT-m1H?K^c|2H@KHQ8W+Nn?tfsX2v9?_Ucc z!c~g9ry{td+f}n$uv;|;Jdr@v1q(oeUOS0<{Y^gX&Zja`#;>&d%!Uv}cjI;9y`qJ= zX00exV^c>%*TCa~X&G*Uiq$?S3V3Sc&$&0W#~(}+{|EYZFdYm?%|rnK#XoHJciRpc zQNA{RMb{wHxG4$hzqCe!5rU5P&j#wg1|x=tM+!E$hYluw(E?vpf8tylLsxbMi1Nco zn>d&N<@KA$sC4GTKCK-}3bI@PqM&X~p3r>_gZYheBVT&8oVmIIpL&*^RW~yrx6}k{wPy=0A;zD!DrF7W_JUg=?8lZ1yK&uja)72 z*&A7Zo+va%XF#RoEI3$``+-Bo7h_7{T{ii~=h{$+%iGcMe%F3ZpxB9{27mU=D4>35 zT7X{jh5C)HEbv|gy4J>%^ag*WTCoyT?Ptb*pnafzl5IeoS_AtYaXNBaLFk^p-c(DN4hO&_`e3dKjRPXY%{pwuOk}t3{z7nfzQGrl7Czr)^5UbOmQ81y|TL zzqFT{ZcsxZ0twym#&7KdbRVh=#m&RYBQo#HzQ{w{=MRtBJWc1Bx%WrWsr7##SjE>l zo^nkK=s?}C;79x=h_}%(J2D2!VjJp`BI;96mx0}XR`DS;qDu^NV+?5^GR0J_(FA8u zqw1y3mf|3%xqP?P!r3Jdb`$KPszI%Q5>>O|=FQ%!d5U{J*k~G-yZ=l{NN$!kFPZlR ztCkYjq!z`+eGQ1A)Pt9F0Dvu6+A9`8Oi=Sxb3O%#k-mHSf6m+>DrMjx`jr%U8vk!Zf|Z95W!}d4{p2lqk2IWzw(IL*4|85C4zL&cKzhD%s*>*W{jbL3gX5AnS;@ATC^v z68Q35awCEJdA)88%`GupZAS?Ej%q{C0rqIxLc1^BWZT})>{ z+M@Y`BOkzt}F)Oqo56F$p$;E2J28hAu4r@nByQLb!AVQ%+IlJ$+eU78}U zXsW_=3zB9k;Qdyfl(_}_K;`aetyMLosp@MIehuim{eO)0svw@&UZH^GjFXN=xG<}y zR74t%fy62dU;de}a-hyYX5V23{-KfTw-}<4%J8GYT)s^I#E$G~QUkzLWab^|@c={o zP6ha6YId#%#|NstyB?7c+cpOvsnQK$P)#V2qrF)kx%^kUwm1tkG)_dq_ImKjM26j$ z6uqxp*_snX|Kk=^x}=~#+xYjWly34F>=C@qXn?MD_2uHZZ&^$x;P4UMibu&KBsq2^ zIX>KBd~tAzgH@WuwYw(G*7kA*&Gbq_lsq)Fd#Tc1*B!p@;b42xDgJonuTw+PnU2?Sl8J^U(ojG3Cx z3LTHT{PN4frVlptOE}9UXf=%jv((|H_xvD@rNBQds`lECNwkYLt<#WWRam~&Wa$v# z1v69TpYYf8&buG^YV;lTKi1gUn_{Qy(P~`UXz-vCpKR$11Dbx?HUEPeH_S9Vx@T7+ z;eecpCuUxoEwd0|=Ss*C@14`>J`83o2xkwAoOyj_iHrQ_rSW>_`y!n5x^(T!hy?Zz z+xQvbT05g}hmES?+CR3?geBkYmO!)qlVn%d?1@5F4;_N)y z)mmTEeUkq7+=TynN}4q(j#9C9S301eKCS6W(Js>b>%p_yBGl;g0Y3NE z`+?(!$LXe;?oaA?@16nz|a@&Fwv^GD}y_0;8_!<Aa{HRAdpHbm? z)V7$<3+1_+p(UT(YroZ!JKlM5*+-Pwes`#r@|yEpkZ`!4`u|d^NBlRDk3C;dD?Q@!KIbKHp{lVlU8s$Iw zY-zve_j-%$Xe)J(T3?grt?vG)oCzJ@gYg5U5j2kV<9uybS%~`U7cp4EpX-kkK5bvd zPyFb}w(=@GaV@QV8l!9b=|(ALU%|3hJmdcB5U#v80`=Ge02#8Vg!|{u@Z4wt@z~*)j3mlAcj{S@>Z+B%QYSLz$6pv@Dw1 zXD3=^+x9{j(WiTl@afB58X5o#wM?gJ4-R+yA^PKS{?DUnJf8 zM150ad3r#aNKa>$J%w<&vkXCFN*RBzWl>+yQY)saczpJY`Xf@ zBLy@N;IsJ+SPN|nErF{sx1*9nyU_dW}on?BGmxaMS)yvImz|B{>d zQ*CPYi@tge->Zhdd;(T=q`~H}VabY5*7w&R`nL=;zu%e&yZ0hn`y?HK;qyP=wZXaL z6izAn&p+gHvE|(lOtKr4lH9C}|-{Nr=Z9rX3j{e0&e#=nocI1j9&Sj_)QSTDs# zW{^$7pKqx|Df#UX@8JGp*AN-^+pYF`UiIil?wf>d>-%E|p2_#_ZKsxUtRVkDIdxJA z=h?Jp>dzDn{(E;#`1=Hq0xNwQdD`u!7*{} z&?qAH*<*2J+0J&Zxb*&4|Bn_9g8$ar9da5S7KG%z6ILtG5@t#ByYn&F!V1rd7;QDC zjQXa|y6gGUH-eNToJ&8C7&m-1(HpsW>qy1J>3)!qS+wcUpkE=xl3}Ru^2e*!%t}7R z6|XBM=H@aTX10<)@OZo?a^AUT{u4*7ZzU`zt1n_KZA1Yj73x_-sIWhJbAFe6cWq@G z%?x(=WQ41fv1}&w6^jgi7;!YeYY1PPnET-Wmh|I!(fpPVSTorQ6w{0))KcSuR+O#7 zo0x*EydEUxyk7oqPy}t=``2cK>JZsH^Apt)9TTu?1-~QofDTHG-;HQ^r=iPpl<@0+ zpt7P`feJ^SUpwX==dYWc605syZH%Vvo7eMxCbi^Q&N$Za&vxg9im-FD>lRS=VaKhm zxa9395_+>jJJxKT(huITyLEjM&l})ye%Q9Y)Fn{*RQ1z?#kXneHgivFaZwg4P4~Y4 z$ba;obi-GGmWEf1XQaSj(po$oyMiei9qN)@)0HcFz)QJ?K#_SoK-K(L;r~ES-alG= zN&Ureq*A8k>AUx4@~?vH%*DUg%&;%8ukSPa2H+h2l<-?NZV!rlfW@69d|^P$Il{j& zH#!`j@DrM{0H0rkCMkR2uDxtfcOkjzS%f{K=(@;f=v*OB*YobOnX3nG7>Ylxv2;f( z8+=cHyRIqFGG;LRZR`NrkYfgd+#aHowk%XB^*(+lq#6xO$4Eu--jCQBK2lxrrzfW} z2uJVRL#;YbcCWVun@x{3>{yuMHGTNpx1j#0#k>oplM_cpev@0$QH6AkJq&e44wp;k zG<)MdAMU3<_elGp(!JT{2o?R`iEt|Z1=xMUaHeoPa5y(->IvtZ*UafO5=rplqWofvOYYHpgmsgAq@7#Vc;bt9xFgO#U+Vku|nnP(+eZ?}}(?H{%%*Nf3-5pn#$@j>|9SwS7VzMJPmk^>ach%M|6+`8276|BaHn8tad%5 z!xxd0>Y>!vprgwkCcj!#{qyIt=1CU2g!-wCYr3|YlWm9l;1tj|y%`|wMd(bZb)S4{Q;i1L2qBIkZKjIo2pTG61#ao)cZ zfHh%u7o4va<>-DkCfWXcy4OoppZ-g=JdJaFh#Lr~7q8!VQ#O>Ylp4?oW~$j@^`$tv zY@EpI8osvU52NG2mM}W*%MI}QEB9(>dZ!zPaVk>cK|1B0@Gmu~0M)ut!vGkEhR5C< zZt_;{`y##BgcwH51N+IafJwnL>feNEm@nyvzO$C`dd$^E%*1np$q=Jz`eI6o)rir? zG+)G6KrgNU*r8TDTQ;9fv_g3C;v}T2G}kpk$;_`ax;H~<^i_N94Dk#fnb06p>@n`H zgUI7{#RS3VFA7O+7m5&K+VW+Hd)Cx1BFR19!zBHAEe?D%C^ z%&|@*6kKY~!DE}_GJ=-Eei67l;*W9(i|7hy^pNLzOhf5F zD%i<1{S~){RcGeP8tI{)xqGm(C0xzj{wIVKkXon4hKa%H|3d1}I#w(+`>iWxKNkzA z)DFoGXEx9jt7`5MZc(V#PKP#H(%z=goT+HU=|2h5x!F7LkkWwowtNQ+#rpv|(W1<0 zc&F_G*=F%m-bjaL9^lk4UiQG998J%K>5$4jb1XO{<~o8E|3Lj3BCY^%O?(^GYI#Wo z0-G(2e8`@`6}dUKmj%I(Z;|<<@jOF%voCM4XO)WH?dV5Pxav9ZUET541mn!lu2RfX zq88HZ!=-8a&r5&>X?)YZc?|C(VC*+_O=U7%mC}Tih4;H5nB~2on9=TSSqA(v%~qsH zs9K4fTp(?kk!C-e_)D!tA=S5zU4#GOG{Oba&?p0O#+zyu$4V(o6}G9%Id%REx7%~C zR!Coe4&U{dL@nQSTr<;lxx-Xk)=_)Vm6V}^&K9Q#K`S=cRx)*p_G#-&Dzx1;gz~~l z>Bo7_z0uG;sAT&Cy}a?5>HEGnxo<%8xgPg(F*Sp?O4R(r&(;Frv6v^cQx1()&dDyG zt(C?3um|Qbryy5#+H$e?!r8i93kO&twkz4<+Yrc=uu;QW{L;`}5<3tCw}k~Aenao7 zg{<*si*6-Jpi`${J~}RQXj}cU2rpoduM^dJcT%`h8>+F`R1b;{0v8zdrn){W`nB(~E zJm2r=m`}yk5u4DGF5;5ftjNLJs!WZ)>{fY7(zz?#b+1FHeM!VM_G`}y_0*d@BB!6I=%RK2w=5h%Zq)9R#>Cylb4E6UBu= z(D?W3rbLM5?}AXcFEES_Y^&H8MVi^6jx)JEWiD3ToQg=qDQc#a-E3NEqwRkRNz%~k z`lpb=kb{Y!=1U@v$?*H`M=qmpnrxnqa32dTEW>uv5`Kh9*lH@WJ^OBnA(VM-0nU%ifaMhMZRH$Nt* zCsNtxJS~}uCp`}#*qLCbM8P}*=4L>LDvz52qb6;Umd{+w#Zp5zUN|7uZNTGtuYXSF z(&84Z09#WZ=B~}iwX|TCohkKul->V$=FpUR7${Hfl;7KROu^-6OYFPS&Vhkjw(#0L zv*oMa4RE1>x{OMR;IV#GVh@*9xbJOH3T|;1jGHffYY-SaniPO=n+s0ulmof+{ zq#nF$P?wW>pqR?6*lS!+!H?|5oUgPQYt?i}g{x#YmU88J!?>{<*-s|DS3*{c>m)jj z3Z;0jd8^)$c%XO%!0b@ra&E>gmonWD&~Cydxk<_2#qin~HSua1xI&2%>5r=%q<@bbOFj!BOI; zO)5x32HaSA$NCY4@^F_TKN8!}+&)$jEzOzIKl{Mu?t(lXGXM-a^OzyQUCqc6?1IE^ z-inMeWGxb&Fbz6ybN038c8Wy+6W>yrnO!Q`C;tN}%&nGLKSVoMrOs+d|kEF^97T`e4{HD)}NlpwPg zp_+}G{a>qjmo|$t9(iWy;VEY6cl3LP+#cd!V_{N!>8u8pt{Nw{(=L=T=>?QqG^Vh@ zaKPpBK;pPIL2Ap(1LP{z!F1II6b6kg_+JqxsBOm<_8vXZWxwsLzeSO*tPCZ-4%O45 z5X+Ts#t>iH+0XrLliD4`_X|Mz?MrFW`HlWz3w2^_OF`_?)y`}toCf6ds8-aCb@lsa zE(5OI*ok;l&q%gkm!a4SBWd6;`F8xnm%^5TZtPwzBA5QxT~kvFe8U5U2KHaMYISe& zXJKw2x8jAOY~#=eZSr!5RXB{gssrWIZ6J-cYo(

    0;sL>GmfdqK*KA+U{jqgCD!wo?t!uf7DJimxJc8!(NJ-b#_Qe`Z z_D-!q2R3%bJYzlv6n}huWpL|BB6XT~*z=Be)mc*6EgHwmn312ln-;uNC)|cD$vP%K z{~%rOCkf8MB&Tpy^Nm(cn3H|AW0)_cA5+BWvL3bMXOoWLxaco25zBWlOEodf2}O)5 z%dcuFylCj*zUDjlr50s6!0yq^i8VttkMK68KQ#C1@j~kXEh-@M_pL-QEVGGhMKe(; zPq{$NxMO*JEF5{8w=-9k1N3an;w4VwgyyO{`YLfzAk=X3?6Cw+EKYEyKL|RUc)I>~ z`mKpl?LPyRF9J!y&!;Q{({TYnT<*ZRs{FfBsq~JE(Cw7&s$lg+eBgT4a#3Nz_gGOz z2_nlmS)vB&j_kV*HXLGbD}xSN09IZH`8qS^I(M5j;1Zeg=< z0cA-x2{q^CNWdaWVMO`p(=WA=#g7(({Bxn{ANM5cR{u#)kuUM9{)0cF=+C8Yh2Mtt zYGi(NsFjQY1RWb61s54iC3(YjKRmjZQ5vzYdxZU;6%|ddGM(8RJNmF&9p}CaBZ`%8PJ)&J*YMfa|+AVIk5kR1dHC-Y>QLmA#X(CrR($&OKOF}_K->n66w?Jp_IYINFHh}) zoKi7I`>KGGsRn$?*SOMGoEPM>cBC<3j$?MZSPZlpxn}tBD_4v>YY0hdY7=QP`xAY-4V^H6bqWPxhQfhTgV?AGe+HAFDlJaWQqe zERiPZ9Jc@F$z6AjRL55xB*%HzP4EjQbV_)&vBj^CY&OjJtv3?{G}F}0wi>N}Mq!)u z_es+inNvpfaltGG)!rkSYO+MAf*L4@SyP-$pfz!hn+L&|2o#^$^ZDhLYBf#jDk?$? zaZ`y7qw018jbb5X_^zM2yT-h2o8+(Wl$#BXQYSC=L^RGh8|*Cj10s>Vb1{k#PAwt+ zv)68_Q}H~J(yepcc>r3uCs^C=OBrK{as)0Q7TiKb7^k%&s&U_LHcg(TV`7IQ7Go0oZS|rQpqBi8mAL+w?g>MUQ86?gM$jMN+ zof60On@Dv^Qkm%Muf}mQIL7_%BSzzNk{G(892iBp`4}i0>Vvxz#T8YU-XL>li?AKK zH(|!6lwkXm_5fk0ofzz8)t8j>0~g`fg%qy3{ko6-qE36rWKX#xT51;*?y@aGPT>|2 z`!9qi^$nSjj1?s_nqlVVuA|aw>X5q(Q}C~Tyhbl!XF4X>qhvwUx@p3 zlr7^0i&U32HWnSa5wFQ9%9r^jPRA|{ma3UUvgTrz&Jl%LJv-y(`I_`6+kA9&7c&Wq zBe;WqxF{7SC_j@1fEO?5aa}f#P+`JRUv~BQbj&`9@1Ch5R29RuB1-4XzU-I{6J2gM z(8OLt+1R1N*TvidqJS23MoY=T$HG!1MA?;=f>u@a3esemHb_z-BU1*dB~89z%KF4eo6fLMpGz-JlYFL-7~UMpF3ihyFpi>l)Ic5MNi9C8QPrb+C2g#v1wsWuGlSp2YezB5-hluCdZs((`knHpRJHmyFYc>O zaVU(?rJrv4y`r+4cTE8vmRrn%1^I<|B!<8fMlk%w*0eW^%nD#E(f#o9=w|mj@zwRh z$d5rCC9DI!IIL1hRtOp4LuY!)KN&a_;9Oo*p=L&ZzBbk|nCXjM%ga&1h-oZixK+r6 z&J)4}Z6@uS-o5vu>dK68oi%r91jk-|ytSUN{KH(cwYm;kppjFdK1iB~mNGrAgu_7x z%ZGMMb_q9^B?4ZP3Z({D1}l3;PUK~VT@l8S_S%BsruhxCZ4H(|!7i{Hpk2P}S>mp- z-lVofrB+7iJ-?aT>2S;pTOi%Pvn$=g!z-pcHYvywb%D8AzoE`G;gyG%RapS3CiVvW z5zU&NHAQdl!t-L^g!{mDD)FKSr@?$y@JRj5V{`t<-e4g=y!t2J%TKXWWsi00;)r4oU!Fy>;Bft#GXOWvzkR-09ZxPZ;B3*npn#z%Xptd zn|?-H1hrk$ohKviOaUX29F)2SrG%b3!Zt4Xh}Fahd4(Yu7>h#Hslc^463p8fexEO; zL+8oBt6bPAW(|?Vn0$n*dlSq2v{nmBeO%T796t^LIq)PmMHLE^n&`WNmZ0k8gH^DW z6T4(8Y6qSOFgkyZK6~Z6I@v?yT!(avOu8E4_r4Yl@FOw}B7W99`IKg7H0T^;4PftN z^vu1pSGtXR#*1XXioTlwCH@B@`}}^czPIq>IbZ1Q{fE4eil39z_#=)o*8xv?dcDkd z7)NqhydQaVH;PS!B>rwXwv{hj*nh#%qBr4j|6>IJ*kI6U$?oD*M~_vHz7;;XubYmw8aS2ZhTPGBw zGxdhygB7mKqra@2ITG+oxCLp8Oy~G@HQ3>|t#n>(Hphm#H%Ks(GM}>lUEdv)DbpH? z_eez^DAz9qLd&J0;o8lOL(Mx%)`|(#Sn8@wzFdv96 zC!GlPgJi{D9M;?`;S+}kGCL^D>0viZX*J`C=?*SjXB!x8`GW@(F0Q!>_k({!yj+u$ zmQ!MulMXP-mqCNQ%n6^%oh3h~*D1cQ|4#Fe97P{p%oEPk=d-aYCSREBYdn>(dqUAO z7*Pb-4R_wg+UqJeHb2VZTV%&Ln)NA%a-1schij94f5y*ZepBeAzll6y$NF0@ez}{k zsDOTjY)6LVqwYXq>8pl1hMw^;)o{t7^Ac8UJc8^YRB2U)*N3=_U*Z7(pfS5eS8T~~ zE;6L^R#O>3Y^sZ%1mIQKWoFByq=ZysGJEKfpfu)mamL&?_HqBF4jQdfStv)7MOM1^ zFM*!U$yQSPBM}j7`Rjf;C=E*LBQ{rZsTH^kbN16V0^(jD(>;+eJ+FjeBL{m{-ebOH zEeBl+MvI+Hdc4mzxoDK+XrGf?(LKx>RNI_vpz_~J+{~R3;L8L_&?0(&Gje9?z9Ilt z4{hXDxvzE${E@l|p&42&33frOA0Y_mO;X15)wauYyg=_}T)XTGRIhp|_qBZ>C9Q6i z@C_;+jh-9Gy{}<0%=1*B#4dSX33fvv?G)gdplUoXT(#&y&M?8vsgyK=F>M+vA;poc zn3@wg_M=adR@hhAKE02t<%ld*&~2Rx+Aoj9EL9nG-I4hGDn^5?Gt%BivsH;6FlpKf z={e*)vhd*b2%cjvLH5Z2CyR@NqJ(%o1U=egT5MgCp|A_#JOe+DBAgp9y>?eIPwWjJ zqe`?fug#pm_iz_*(2l7^DV%Ovi84~?P(HsW(~)>n{5_o0yzp75sxIOGm4q+EH|(FfQ-(!wVGwn%f*bzrlH6U8nMBL)*hfqaP zt_D5#fImHY)WRUAJ?bixkYCFxmOguvUzz0Uqv!i!fnB(6Y6~mQiQR`pNN1_j!Y?Io zP!$E=WId*&6tS^~)rgR*L&$uVKDZdpEX?4er(WN#PnqX~X0xvi_J7$bQ_%GPP*`$Y zTFrY+ry@6vH~Dnr;y3y?(L(Zz*k2CQ92+MHpYvte3Bf>J<5Q6y6|y{zJ+Qg304%5b z!KN5S*k?myDSZ*L_+dStedHXOfAakgF{b-)U|I8?uq34PWSUdmOfNyijDOeIv@xzM zzBnF8z9VBFC7GM+$Z(g@sI2*|i|uqMf!37|hY?kt?$41aRYJlx^d)xlHo^6p|N7%X zR@bW^nQwm(ND-Gn?}vMKu-G*6!Oc*j`$m2c$PTd_;;K9v(n6kwj#qU| zL;P&TG8dABcP@g|{qlldSu1hLvLr|yaTG)fEsjm>M_dM7G117(B(4iatgj1KJ@JtHLrE>9r7M=8aDOu^$2mQ&iB~NGUGDpk zN*-pz4x{_ghm$Mu+OY^cZ@V}^SD5fH%1Z!51Dmy_oQ$)XDo}@fjv5qN1N!?v(?iDC zcIsoOxEQQbW`^o*T$+ptU14Z1aI!{UnHq}9+`R#%+LKL%Bi6Zm_hJXRB7!cSRi6YR zu}bF|Tkjp61@rhDZ%N91E{^Xt>+VJuyBlzsiVFpx$eQ(5U=r#XSD)>9{P9xZ0r2vb zh5hu)cGK9g?-_2Eg3jqFoz>=>gdh_?o*Ieh5$K8b#>kC zP{*tD+nrN!U9#dG;$93Om=Pr-is48Qq6R+Kov+X)uCezVYHm%$p}nMw5DzkW`Zr>xrHb zdERM++7A^Kz!|Hc(~gs=uyDC@ujB7k^3MzA1rtv|hlfc&;!I%CAyo_s&0ccFrnAQx z-EGUns`)--ZU_Z)CL#FvWSvTtf@}E{sMgAAbw~Xa2x^Vu`X9J3%gQTb?+kS$88N)gWuz|9=Uxyb6oH z$RERUqNrT;ae?hSAMLkZAUI&f9QGJ)X-~gjq3Sv1nXGp8!~KE7$&C0yKM1gW@>lIK zND%m+M9;#S3K1!+8nWW_?WQU7N6#8#|3ycivpZ=1($zUkw~2Rk$-p*}W)eKF-I-&I`FFM8+G5PSZz9C9wGFU*=rB1EMVkTXRFR?;BpZm zQ7MzpRQQ){)8dUu8z_a5_T|C|VCOFZ8`D%{UhRr)!3Pt)(z<>R`DQB9hcoGxikEwc z%xgzic}mgJ?uoFI7~`YD6gHk@TM;N2+Jjv~kCCrSXX2;5qROBV{uhB$42wc9b#E;3 zr9QYJUHiUNjt(8!C0i7+8uW7`+1!$YbDA{2`=fM=<|rgq;B*MGUY@@<%vRe$Qh;3| zXOyd)X}QL2eaejTqx<`H^4Za&B)iXc{S533wS3Y$%5i1Agg)%`D>0EivH)*vrra5* z-zQ__&X~4udepN2)TH`5t$(t+*nuiZ3mfwY9gZsnUUs!h9h5zDDt@0uYHOG#=Di$| zcQYgBll0jfLNP#uuNiF0+3cRKS-*aG5}xrP)Rc)AyRWD&v@{zj(Nqogw;r^y82(G$ z-Vi|~jvJBcd=B5ISL+XbFHpJt_h;~GOxfS{A{_UizFGQE*S&x;#!sFtY~i3({cTpP=Bpf3 zI|X^FqdjaOImpRV|Bb`#X_QvZ9;WayItO;MtO*7AHe8zX6S!9&0v0`d)?#*rzU1Jy zbi>WK$TZok90|he^&*KG87u+9a9%#B&mo5xu2;rAJl+FhqnxuMhZE}jxp(;|G_wlG z!^USW}N za`@2)BX{9>O|{DKf%~EGoQ$qoHErJiadh5+Y_9Jc4?(QjDybC`TUBuEJwi}>w$xU7 zj2N|QZyJ&qRjt~awy4&uS{19*Xlsw+5C^pt<^107@BjRj_kExHx$pbBu8;d*75y8J z6Zc?i^Y^hCo1w-&OTc0C1@$a%L$Mk|Mu8w z7X3S=ArT}n&4~zh1w5m{uYRIcO#b8;jL~p&PZz-pm8C`Rv1zT+gmWLT4ZL~UJ;aa= zL$BJa@&Rpu@;!+1D}x##(N#OS@NAX=4p&+HkIwK#;5rkvn3s8(-b$_Io3=S+jw95a zxdC;s|@Al;i%4Dw5gtfFZlK| zo#tKQEptBYH#Ay4YgZ9g`QSiQ8X}wzqmbnLl-ysu9@{sr#?p-B*3BAR?Qwm2ZhSyM zGd~Mf0#=F``|U0dC5kF%59kmM5grJd`Q9QJ@7R>MI{fa%9myH zkzF}S07&&IM>*v41hqTPsMz8Pf>Up%D(4MUDi#Hg4tkD_-_^=Af3;Me0y*JV1Wr2& zrHJz?Z|_;#2_~bTsP~KCV)`Tl4SM)YAeWg04-Tov=?3mKPDVZtCm1<#sXCp0eJ*(a zJ+0xQUxnqYN5gN<#hO{wOCw^QkJ;xMMRes=zz3n!AjiHz#j%(z>v4MN%bVuRs=gof z(_mJd_SU^d{-Yx;k z_MWy1rM3aL|8dyW0~2Q0Z!^?{1?Z>p9i2P^hXwt>q{+Kt$peZM5c6cv%BDyqIPr4a z;}iuZjP&=9tFVPnEU33qK!l?LN8Bgy#9dH=?i={E`n>b zvt8KU6i3`|sa#nq@vTVXgNFC`(ee8gd5h}AGZ_8KSSKJ5<>oR^Oe+^^Vp?r_U|R{6 zY`59wU4}`5qZncWMI#H>7}D(`&W)gqy)EcXi3!wUtdnefw)*s>`A}W? zzFFQJ^dTcyDN{O#OrRT53FQgnZngQ%D-IOF?8r%9R`lxpqj)MW7xU(ZbL4OT`70bf zy|h{K+VitAgF5bfP6JD6-|bm{BwmefrIcayBV)#^(a8qi1Y|ot5OANlTz^EaM#%4g ze(7gmtH)a;ne1SoP2fz(sG|MeGh%e}Cug7;0gM8H5RmF7$p`s%gdMw5 zl`IR=+?P*d0INzy9Nqbp@66RKO^w5>hqYi|Ui1K8n9rG6otN4fF9uc7jnYgf0on!P zrUr~m=qO}&80DUjkrx&!GgxPADjsjkUh`8un$7^6rsGx)g&Q*={f%|kZt*5uLm4R@ zyll6$ybjNkJ-RcrH>4+P9CB}GhO0>!-%_U1DVw@z%I>0FvuON4IXd|Y*8{9psMZRO z-E#UZgxswjqTH)lD;0K}xd!prF_?o^zPL1*b@1x98tU7X zO4uUH4XE2c&ts}KdSY#F@^z9KdUdUg6rwZYI!^4>;&2drGV@FQ=SKHhCLOTn5Z=j# z1+dj2#HBa>(fT#wyHK;Q9~*vooJ|?;m@r_YCsoE6D}Pms`XC@8Fn<2-{{@)p*MNjW zZsW1L$$jod8SDOfXe(o40~;d%h)w;f;paFe{~_Lsj4w0O8vLSj?CiSLl?_ z1P%Q!*&DTj)<+4Or{pQ78*l&nzIUC`B6sps?kgV6mR`J4Cs()YF|NMA^zoDBi0FQ;`WW=(mZQ6)8=|l$LEsL zT;SZ*ur<=X=cnAgqpv#BG1Sb}u9hGo)+z<-A<(H@dk$L(HjT13<#8(wjh{@I;(z9z z@(f72kql&EAJ89HvzE;bAS7Pi^{2&gQcyv%tet7IHKxw4013)a%ILzL;maWqmY~*V z9IwsAT}fk^6KtWOIUg$%jhg-vUTf_H_8b1Y@Eg@r{?e{8_Iw!yA9ai??P=Vp()E?e ztiw_*#7+8;^@jJ7cC9cur`luwRwM2pV}45JFwvRcld&~fQWVs&vZ$&<|b zA=eYyGY~kdw5G-$XvOqdV^{Yn7DvqhXY9%%(3dy)GqgdSMYVyhzee@Tpsrr^gz;o^ z##Y{O{!M$39s9G@2TXLx%ht=7s=KZCq^GtLiACFP?{(nE$x|I7N>n^}J{r_`Apmw3 zRI}|Oa_0)VAD?tV#Ktd;KMK0#Q6dSsNkAJdy_Cm|NT<_^INLjhKT z!UT$fN%W^H9k<~#*X_Fes8-2@P1qVPSU$EHIjNr`FsH+la$DFuw2X&3m?ukB0nLG= zB5wU$NZb|e>OU03qJPrz6wPNcqj|h3D5#4a1}eBGJtQlbI2ZUI#fOidl6%BbY5Vk8 zJa06__c$1wt2AbnbjE%Z{Q1&LC!MnK9fp;5*vc1P3|fDJS-+aE@K8gPVqgv{=+AlI zpo<^>$Os%{bRJA`BDk8q47e@S&T`-PTaj(vSEAxeCaO&{}Ubswl*( zbpuv`QYJNySc(ZTgQl;EcjCbvK6BPk_w}NA@EJMHf~vuC;L;@I&3~Y~^au$K5vgvm z^{}y+=+XtNc`b%tef3gqTHA83pE;v$?#|kX%S0vgTwUCMP3J|+pW@YDy%}jjM!I2{ zHjcL0mN#za^0FulXY{6@eCMQkrU!)&>^}b*&)nEqW6VPtPX1g{oI2myXlDQXS0-v# z3+9ve5U4N!WmgNMWFBujg=VyU#D<_E*k~0Mi9^QGiLu$8G@3^G4QaPLG;RooG=`@T zB0*sT5%6_x+YCBQ^RQ5fo4@=fNlT86B=9i+UM2s^N!4`M8uenc^|02SO{9kVhW(K! zLhwfyuq9C=>`|K3Bdm|6=mnH6*UN&H&@N+9Ff)8&bKD zs?dH)OBDzQ0tfArH;2$3gV_j;ZBuPS;g+0cy<3Ev!XB>mvr6{a{}?0#3-gw{(_&sB zhHR8OA&?}yi1cE}ZI-LM*+?Y0%}Ro^DhO2G7k zZReMpRyYELY`K!%%)aw#9L@$v*e{H3fqM-`Ig@8Ggxr&}>X325=g!zjmjHa>YYG>N z$8f)eNnxY*tVv2H7B{gLbUER`J(A%^7R$`Ur{4(fGFBnWVVZ3m4;G-v+C9V z108Q`mI(-FL1#Nrbk8Jiz3o6Kj?dTJGo+;an}~4=4s)Eh&WtJ>v~l`m*<8)Xb{jWY z<_xD!bv_>fCF(es<`fF%V5EmTgmtt13P5wc41NpBxtV%y~!4bBEH#W#iqIdQ9}ovBx4TahT6y z)&(f1VXX@zmmliZvU%9gPK&zs2 zam#_N>nRYwABZ{b+k+;tWfWrf9&55b_ZJCB<7j@Ouc|;WU9QfF#padP4JNB99gppj z+sbqtQ@}de-h!$yqX&l5f#n9elga^JLSgsSDpEX@@(QBv!~EITju+2 zH)iKC_i$^s9){qvPq!&2l`O!s+~7R!VQPVSQE7Y1OWVt$!sqF_Q{$pnxT=Tm+$cLi zCjWuHB^2R{)FWIBb=hFw5P_cuA%C+8iD=ZX@i00k08t;ITEWEn3Dr0y8+&>TeS9Mg zVgVh7_yu^C@Gd;X3t7|3)uN*oVlZn94rms9)>vF=JTkGpE4u zAEASSI4L1uPi=@69(>T^Bjq66$TOSgi^!pvb8t1gEp3GI0g7@Yl)Pky-kk5g?zFiOnA zxP@c~WTM?ItfW99E10u!Fn^0hTyI)`ATjO3=eFGZ7s455QD^RL{F12u8Py!BL$QPl zVyUzTtFZhN%mQ!*vhZtY@JE+#HYK)k9PvMrh0d%99P;}sUUvi6T`jsOWRR8kMa8Uj zg1>87z=C2_(FSC#<`##iCM#P1l*5x%IRj_OaONR0W@@TMvtFtYa{wJkZIVp2Z_WB^ z6&C~OUitF-n&e*^PI)J7cmjW>XoqcK)JVYz>%WFB-OcW~taa!SOA!Q{Wz%(~D%6gHX@s@OYzjM4gZPu2gPb$= zi_|ew{3kTTJ#Cev-cb0Pxm<~`o51m+HTR>qOq!nEgZ0gFP3^oI63qQ{XSvOe;574^ ze@Hb@-BgWI>fa%#s;RiB9^TI_AQ|~#@*V4@AA|eDO1h5|F7cOYC}9(^SrbD)72KC1 zMG<%=Amz}dzt6b0H7ky|-Rv$Q+vZrJt$+)d_Twn0=H;okpDxW#%yc%HMm~9Et`8$2 zf!>6Y4br5j&sJ?sxb}nfiQXnBbg8x;U8NWorLRJzx9MoO5JB}Rk~1qbmv_2(kw!Di z;ZYrF0v2~$?S`{saZGBJ{9pthBE{-`+PopcZNeH>Fc#f>t~B~)U!3Zp4>)fT&i zfsD_Sw6z_%8YSdv8p{6`%+7Z@1Q@p;ei07<`))5h=a(}DB@JJVWV|%D>%R5ECDs%H zy}n`&wu#mCRQtENj7C^(EtWg();=x&G#zj!i8iY1irOnG+J^0d|aGe*}syO~^ z6TCLA+oK2mQn?-9i%Pf^9lMtV|i9~sN9#DK4n?8 zg7HOh`^rSLxgAdUlr_G)abfi(gj6L`sD4fs`AL*%-hGdCf&AUD(7~&J@?r1327q=@ z%?Yi2-I`*fZez_I7%9X1=Y#qhAbQgq;(2KwdKpNsND+cszerF`*sO4&qkh7T9-XBa z>}@5;|AR<&g@9LcqT2NoD~`=xO=5(}T>Z{0Ah7slnoi}x6OoVub3ots@(H*Ilohi%t5t%3lmauDh zo~uJ3r=Y^1C9xD;g`JCSdZU>@IQbm^lwIGQe~H|`BBb%jP{Dr2I6?)oaJ z?Vd%>+TTy?YEky-)q|Vs;6ZZ0bSWK>u$Omc_?ha{OS89o7-)?7oGQMhF!rg5q83w> zhUb*=E)g|@wObcY7#D%@O4B(Oj|gZlm3u5Ef0s&OOX6EBny;ax4BueqzAokw9h~3B zJC890oslw$7`lr7moJNqyM8!%<$t(zL+k-2TW}`JvM5s$(M@m86}RUJk8b>!%`bwC zo+Xp4I^cdMXh#mY;@-(F@T;N7P;>cdJdp8>SG z_D5RcNmd_z)`loX*4(*uiGW9StyOs6;hxA8b}n1spc>&MG;S6hF*mO9!tYk9BA`14 zIYxYaEGOEO>6S{gkgT8{65v^PV)zW3YhwQU$%N97<)EI#Ajl1?Mz@twP|=44N%+p^ zc+R$Q{|9O$0AcVs{Ay_HxL!+MnT-C@euen!7w)SAG>6wrk#TF)BUy8u)jAw1F_JYx z0k;bEvkdVX%cb7UQXH&?b+FVXseLHw~yP6HY3IF>$!|x7nU%P*uI(GyGdUyp68Wr*Kj{848FE2eBb0u zowYR{=n;hGac#W#b=hLa8x#M5Flw3Y+Yzttyq-6+{I1HfGIbd3s1sM22VKNqticzzR12q=58{#H<`fC*Sp0VjV6!F*^IWQJRf+!SX1)w zdhcKEjr6IiEQ9x` zpigc;JdUaTYvX2D<2M^ewpH6|0IO;-wYcr^>SxPGZX>g4+&W>8tLHbEH>mwz=X8`1 zmiD@?>TA=(oVy%rp@$36xr?5D2M_ArDCe1z=#Fc){+9TRAc@8Ol(FjUdUcQaJ2}hj z50g6T$K4c>>)DU34iD~+92)6^M12#^C7%s@zd5U|d6;E&uhvplK>wM>P?iFJotv*v zs)m1NrHo>8W~cb|eQ=y3$6o!!wrPdbck<_ZbwVDc{eC?X;$q)#7|~Bh1pl}@7-dlS zN)T1s05jw6f%Z)1Bklc>`!;V}Vpn5(j?N@dUQynERldmj*S}<0#r*rEit6ipDe+3t zsw%rwmE0h>l}|3c>HU&=S%_lHh92YI;R|So-XAq}T!;6G{@j(@+e>`yUw8S6KRB*b z7(Ue-c%;ngU&uBju5)K&FiZHR4MF2mL`FwMMa}O%31(Dl*o1%RThl5JkKg91eyVJ@ zAKdHv9TKJC;M(;RYJU`({pxogetVPBg>ifRvgKC7y+^yS^2dzp ziiNkTWJvr!75FXgHda61H*#Nj$ZK{Wb|lEge>!`mWVymGekW%v48XQ-vwv)OV14hPuZA?s3l|xn>X<)`4MtcUtfwz>5;DDbhI`WaP)%A9ajY*K4nyAz7`Tc59|O3Z8g&=BZ&T18~h z(cHqIn1_-<|EGGC^d<~;l)bs94Cn96nh;00EZ^C$E_3H zip7)-;z(~uL9uGmjg=xLG8?-&08gZHNwpoR<)p}-9K*URo;~DY%F?=1Rvr?yGdgc3 z?KmGwz;2gn5xVHW)rI?tmO$)LV1{g_1MeC=?cMzS@D*nKRm7XM-X_WbdT5gRcU2gI zAz5+g^n7i7lUM&?ZQ$3Z;#E^Ztlw`BlUo+d_{m`WGNhEMvbf9Baqod@rA#%uB>4)) zaG?o+6YrGMcNI=zM>aA6VTp4m?Bc|e?fv(Sy!7F@ZHe4ovJ}viAGQ;ZEBvU=Xtg!DLtd(nHy~S*K3>bai2@SV! z(-QzzbBIFYq`nN3iR*r3De-Fmgn?=4iKWX2=8osFK7m zcX#cQa2dt%HwIUlg)|gEBDIZyw(mxiVtfM?3-3X`zErnc78kz6tgMG^jrf<|=ngcySHmG^+%4teTnui`qR_5-1_A+lHm-_>6QeI& zM$7%s{N6#>^LMaYdNZz9_Tr}8CbZ)K!)jw@LqGtMhU5FXps2?-_NdSmhd=`Suo#S|R!xj}9iD z6hkH$+vNqVXuCI>I+Gx{qO6E$OZHh2Hc=b1plyTx51J@x9^IMCW9vnijTzk+%7m&FjNxVHN7qJ;u#Xb$_KU3`)8@ z)@3nE{6?-Oavt_TX`cFNS-}{c#`FsSn8Cw$HirTS7%N)Ix~-EE0TMiaykj0(G?EIq#(pn)g~I$aY?E+I6+qUd7)+BAc)dqjW(;DQN0h&KSdYYVglCj zFd&uMSP#kbq;%=8q1#*U;?fr8DyE-?1x( z{WJ+_$;!AS4yfy^(Q!_T&`jbWo;ZEMauLR1Eygc{X3Pk$^R4jhr!|HUHcDEF7O1r) zyw?}G)-8fN7M&0eDZx80=-fz45RYwJ?FvL?MnwB6xIbT!^rCu6x5S$%PwmiYdR-WB zG@WYEOKi~QpoUDF)uU1S`dJa_6SlR-yS_a+RCn5?y9*?kvEUu%mW^Knc+>CY| zfTuKX>Gi4y+G}U@xiAoi=Fbj@Q;+E!5g*M(05L=|<1F{nz{ua^+U>?*#Ww*LPh= z9Y8L%$j~^TQUzHwBy8Ulzb+X{vwxSh$*12!TEGE5Smm!qT$0z>{=K_!xZ9_Vcc)kF z)&_*q|3ECf8``)U9A%Y%{Os=`(sFs2&WZK{*P~x%7;YHTV&~;y6~T1A^3B$pthZ)j zu1@f0+Evs*HZz!Xra}J7QuMe&QS$p!hef@U%j4O&_c`al zq~}2d`&KHlytH<(sK&|97ODDhLGyY!I-}Z@m(6VH2a=FK7Fp2YVIMP<`E;x7lT~qT z#v~=(V~SJf3wI#Vxo=FF!vOzHq(?F^$yPwSU>ANaGH%rJzg;eIeGQ3wmo?wrGh;ho zdLA$(q8SouMa+*+oHIbcW1g>NnF3nvxGuAr*?47FA>Vq+xMx-(18W8NPueRuj&hC4 zu74=Cx0owu9n<9xig1S!?zZnC-!k%NJuw3C`j=)nd6`!5nCaEUEipexso_aljy=1Z z^Dp!j0y5V#K0g4lpy4Y)dw}DgW|gDzt#e70RRJo}OV);eqF2tzeG;{9w~vh<2N{eA z?xF)Z$IIm4BD#eccb;-9gxVKmd4d< zVmLTpjQbVoHxT_fl@GAzT@h}n7Q0wc!hVEqGls3j6yY9Ab(~%l ztf)vt#(hm@pHSati-^tAsC+)Bopwta>>Nmyu+9(cq1U;!c&+>thBbdNMwgamVW@8U zWI?u(g&NMPC$d^#lG<;D z?(;k>*&RkU%cLf-!H6OKZ+9r!It)C{)x)=#twrUOFtiXOU&8PoF@LJBD)A;@s(R_sohNIOrE$`j&jjuIR`|L-MMD@KXWfMoC? zdryenTtcP}I(fG-^{V6J-Sk)MHw!5Lnm_Ot{ z5KbE4e~7_p3og%b`Lt1e@aC}F!ZH3Zz6c2|$BFRFhqyLjSy`%#!IeQpMF-2)foRwfO<<8Od3az%lhW=7jf&nTK z@>k`FW`^P%y*SZ*of}PvaC!|b_-{U@=qt3muEec^@Q0usV(F&ZN@w#QY`Kere#G!@ybkc=c^8aioyi@V`cz-yO}`Mw&ets}`6VD(KL?SCN2 zS2MPjJ>pImpXSy0#uT-Ao)l-<4fM3sfsiq5Q#C1+CJQ$$mM|KhOt=kvatsvb$|C~ZYeJC% z!&x#Kz@3ZyHJAJ%sLjQPtvb7mmsnfew|521iMx5HW}VQRAWnzuWZbJXxMepJz?ruq zh*`=?=%pHc2*@K<3G&f7tFo>H%T>HT2u5Le9@Gb{zshLl6c5UA8Izqd?=bv~&5jsl zbQiO6$g*!6f(?nRTraC}ijMr&G^~LZ@N3!aJ=Vl$K_s#>%KrpSeS#o-gk(LOF~E17g9mkR=2jHj z4*3PD<24Fhla$SMej@JJie*+$o&F-}RsPf3Tn{#nml2m*U@UYjW@Lg{cWEoG3+=x2 z+gm;d#}O%dCX1$k|BhT?o-a&~z5At@b(_aZJO>1AGB_UQk3Kcsc7hZ}x>fD=>Jx_< zgnxwIzO`#LFMe~$!UU^>RRl6N0a^ZC$B8HREFk6X0SeU^EE4NKAzO8A5Q{K%nP~MZx~(kAw5aDmzH$>bfiT*C{q{1rpQ>#q(T+N>cFhGm z6{(NU7Hm35<_A}rBqe#fdEmomw|y;RK`Us|+U1{PEw#5C&IUSfo7pyF-7w57$vkY) zS8RS;$?&G8q4xzWHL^EqV2X;Dn`^vmuALq;W243TPzp`+Uol-%W1#&=els72N@$01^!z6Co(STu_lna^8eHruq8&gP8OJ?Dv&^L~C34=XI9ZwHc zz@Eddk6@9~;LvRxUp``jh0)KnMlwzOoknx@L#j(7vCBZ&LGX3bFw4isvHlN}H5}J~ zl#V;8-B%B)#<=5FRyKK&#~N~?)@t%jkJ_{TO&p@C?xo8#F@?YZ)l!=Yr1qT2V`+nV zLq=&ZTSe(MY4G=A!X!ZUWUF1dwy&aJ%|9C|a@p@t{dJk7rr|C+ByBmhWS$1V&d{7% z*YSY{zt3V0x!V8Mef23{oLaN~Ca12O0Eua1X03=&R%LJ}zwv$OZm173_02(Sc#PFs zGANjMN0VBYh{y88Ms>v0+Kear$C_qlIqrt%=!oazIdiQQF6!5| zLT9s2D$Q<2b2WFs(E#{3#fpfCozoB#<$%clM>btrCn@qyrH!MvF#CFt=!ME zMHon*z&zmts{et$`dyUOZpCXV5i7iG9-pZCER6Ij=>hQG2+jSJ_A}S!q?u}4m`wY% z-RX{N@sl`z=t^PkftJSOQ$A@DrQ)C!Ek_CX!cfIc^&$S^IBq8w{v?-}XdnZ!>+^Bk z!{R*LfIKii_Sj4b#T?00PK3($;J~FK_3s)&28XCAE4BhcZUEQ%4ZK z5AR+^t-8FML5ZP(ts7czRgPwQB3s zaniRfpa`s(&7xy+J%WNB=^@q;;B`iWhnKj@2um#~gagO=iwPzOW{NE1i}_Kph)f;cOmOWn|A$a)!6`1I*r zJ!TinkNG__wYVA2o-1>F%b7@px5Xhk!=2lxlHJR(R>xqu*4hOZ(6d>tEU<^8NLOSV zZ0ucO6a7jI3$yFmM50Qa_V$YW!4`h&p{oXGNWo>`K2; z@OF2T>iA0AFZIsHrmjYD$}(j!Yu_c4e;~K7eFCQFjT4YhsXRQOK5u^J=bDzbT1zR8 zF>jN*o6^ZQ?oaCtv*)Ov%VAcrT6U#B{j=j_?tT=uAb=@tMz=_%kLP|3zC5 zX?dKNGUENg4W7WfP;Dp-5%AIIVK$#^tV|bVcPe4nRrHR0gP`z38Qw{K0iUwrvf$KD zQ}6XvV&+TFbcPjD_dkCUnl*2c`l)6;w%@lH8&0}v2M?OWBGN@W1KIh@ZbOppxQ)zByha1^c9R6Y5l3L?KFp@#eYRfPiNusvKb~&lnpwEjIGd}+xNFFfv zHL%U4@UTgH2xSM1zwINDnWChb$ts_g%N-rcZv4z^nAE8K_tRlR{UnMzr{#Sbcx+F; zaow#l=(oxDz-O-|Bu5X1D~Oa|*h+U*{TTbt2M3rnJsR~4U>M8Zfxi-^^X+wrSxv%d zEBHQE_PVM%?VpL=pLuVby<8XBFa2~ z2@co&uyIVxhYh;0!x7HoFrBf0&6VI)l&H46zRih4doqR#5mBRJ3BF!GZckjKS8ey< z`!EP>Yozo{bXYH#TXGk|5S8FUj-=i;J!HMEWLGMBf!J5D=XJCfxz>FcG+8dN*h?GJ z|He|%{dq4eCv^}UJ`>ZW8hqktA+?~WbrPj_w=c;-R%45*Xg`NZi(d_{WX$VjVHi7L zx{=!B0ooN2Sr{}Wps~skrooAawY%c-B(cv5bwiBdaMm^TaI(dd^1z|SG5hj)7=}NA zp;3J%hkq(z$nSaLMmN0j)I=wue)%QRnR!Gf1GoICM@=x>kmU}yTPMCCS7ln%}Y5z@g3h`@Y6T|Yp-7gVqCdX5AqQJLqj#yDg|ZB(GCV@Jsj1r%p% zz^5)O6h@n|exogI!8)*Y{8)XQCrnZ8FQL{F8sEl^rnp!%+*u{?pvJ^5VO(Q(%FML& zOa}uZdPJl;3_z6|?E2G53;jHA)FD9k&pMaY<;#Q+k0x-dWPVGH2=@zpD-wbREt1BK zHFfE&Ib|>$G8aB{_@j`KqDSgbwgMXUz_Pe$_annTy~GN0EwL1opa0#P4h<5U6pcAZ z;*iFCiMUp80DcNiJ6^uSfxkNgCI0q0MCC$M`J}Om+X_tEQwCzI_h`T2{%+JksLNOT zg~*l#B^;b?zl#$A7!t=#bLDF{&v81eP2lD~yd9zVAKl=wo%OhBCXRa9oMVdPY!^MH z9($MB^VQpb&oiC37$zTdR(Y zrRql23TAJ&53}loJ$9BYV1{koUYwARH~+V8_}qYKCA!>^H#E2aXy78F7iC{W)ZE%L z`|dm%$Wzv(xj?4@Vc3UsZ+WwbT6A#&OgicfLljQ%Pny=1LsYva@~7Be)1!y(17i~d zpFbp0$C8ps$f)*4c5ltI%JPCXr(k@mN=Z=8Q=SiNBzys&RJ3esmJ~JW;i)hmg;_~f z-;;jeSg#O`lz+wzS|z-aRoe)ZoDemT#6wN zno}JU3_Xb8R`H5*v+%|3usQu6FqjvvmetH`wqb>`$5IFiY0@ma-=A4I+N27u5nRvG z9=`vCHL*{(v)blA5Nmu9zUA`RrMNmxOIGYS{j*@5vUtHSsh0tHm#iz-i#Mk~uRHVja6?es7ymTX3scgm_9BEN;j3igAZ2&DfqDU4K-=mPyISPqkkZbZzDu`*pM4 z;{5YHU^6QWX!7Z}3acsgb+$?QydMvKcQc0U%|sgvZ|-K|{oQXMUt+9Nt&Yn>;whz!3!L=$Po-h*IR~13x7Rk?LOS>;oDZiqOXk<*0*qK(I6Uud zR&AouR+-$HfPkEHKU=QrG>@5YV~*8i+UK{KDFRG&{J2-Q1aqe~=XM@9nrk7QYk@N* z7jUT2o3mw?QBp?pG+KF_q^g9x?d4p>Umr|X@a>sTC^5kpb>V$}^DO~aP~7=7AkcfB zxbhaZV8Hnj#vSVcmb#CS=oV2&O@b583~1h%4UbDU4X?SxifY{gavjHUe~3lPr8nq0 z`xaS|iMllQPK$kThXF;OXKVc5t}eteV?PPTX&u}nv8}yf4=5I*G*r5ldH(|5MdI4k z{d{W~#^`CEqDkxMrRZ=qwWup#c;Jk@CseL2%}w9+9Z(#MpS10F7izAR>bOMh$iDe? z_q1kIvfLvly5X85a{Zhvw1^xH2Y<7Xv`exUG%IwU(Z?MC3MHfvPgJ8S;4HY&F-!Upb}nPKVXqYR0;cJ^o9_;O{jxjV8F4J*EPy$qgoS z?=IE%yNTDdEXHjrjRTorq6I7QY8rOWhgci_^uSM`yj^5F{z-KP)=33}ux68;CW3K8 zd$U2Jm~(ARpCz9RbI+JEmi{|hA-y~$zNZA=m&FD5O_!)5n4FwFkEhX8_^ewt=KTo+pmXphFPvqL(IO(S^yX;O z6UO2l6~{mz&N#M@S5VPp%AoSJw!F4_^z(hM2bzk3SyEWY{AR_2v|l;y_c89a3~V)? zkRtE((whfG_^Z|7+&9Ns;Y#z(NlIa_G-)+1e@1m(!P!LqH%gwCZj^zJvBu}!JwFCc zDJz%%Kw49UX>z9zd_B$PKhznF3pV!Rn79G`iIBiI@znf~)D}#30}#z)%l)+49~92- z7hBW&;GL-CLat*Y-s~p9Fvi>hC z&c8oW-sILa_DEfj5kPEi7QTpoQgP~L{6I5F|D_PVHq1Z0oeFTtv~ zgmu33*7AA0m05@s?2}A@fa&*|9D*Oc=4Eh=en$>k#5Yl+4(gp08Oq5B_cvch>4wjxTX37dHUSkIe0Wqr z2Ju9PEr2Xua*)J_jyXFOu0)oCBg8u0Io-HCR<(-WteMCB$B zBK4WrM(GIb*AEo8{{AL`EI(}d*ITBk$TST1%MKIGbro&eL+;*TcdC`gT>XWsgtl{{ z2W_6JI>+sY0|wa^Bj22jZxe!?61Uz+!x*R&MH(^+3_1SrMa^#Y-6%d16)d#!U{jWK zNlWuU|5+KM*#M6%DTx5e;He3U7&;YqCSEtmFTXP7!i8r^|9oD%G6i7W7I6c;hI^d$ zn349i!|v0Ez3&)T+xE49f*kw)Mrj#bDXqc)&2V8!BcA$cf}1UBG<*ng%FoLis;lTN)4JZDDVIe@grN*h-#9x0F?uf*A zCrZfrTa0qCH1fFuvY88g;w1PR!>d`gRV-p`aIem?24Ct`LMG_O zHxVtB^d%mN1Q$^z-u0dDSpW@P0NH8BIw3mLdKIHF1uV z0NS2ksmz9Q`8ZcAaeAIcBGxw7C!Tg+^>~pUH4)Y@lvOT^G;gj)s={R4t*Ijq2K2Sf zKTP~9xD!Ym9uUe1Vg8Y?B!Z6{Fg0q2+YZ<73SPK;6v)#yE!_&oC=@X%Edn7oO(sgB zTF(@de=n#|hNe){iFi({%RmZn2VZL_|I*}p$~z!BBbGZx^-z`Pj)*!1S#YN_n>I?O zBj&HCgY_^Xkd*^y)L-sSQS~R{Mgk2)UX~;P`oLWMABX2FxiL{#?gw<#}40;F=yZ;QK_3Ko{wJylV4MH_|evK zBLbHG1C{en33Lzq0!q{*N0zX`x`)kUn5(Piq4-5o)aXt20^iGgUN#UX(AFCgL~dCtkf+R;Tof>A2WesC$H32KMR$tCuu z1ejIDTOA}^UZt3%AZRfVbXgUNg49JGv#UMJppd=+5CD27;#xNbL z!6zP|Ln+J+Oeq>cT|$RwWhB^OP{szcD$@0X+`u#rY~c$*gwOG2A9V;EcN6`apOG2J zRtSbM)Q@o3pLJnyRE||A6u6^EyBVs~yzeUC{2baeuTd^v+|NXdPoqf$Z zf9B^rDa&zVcvU|SOqv1zs2@Q+pZkegJ=EhklYF`P5WQse{GYq?^1{+UbufuYl>=1< z)mP4bhwpC7FOD>hx~+DiL~5S@T^iR1wkTeVWm7sU_2$I*HCv-!SXJoa8GZPb?7suHceN5tN% z)!I63Rn*=iB8lCq8C%sVTCH7Tlv=G>G&K02sIBz(e1HFd7xCnN&UM}AyiZ4AMXUQ0 zo&vT@SCG1Kho#?NgACNM{Ol80|K^7*w)1>7GzydOUCr+YoFF;VxW;cffz zTq9iuFv)fAuFPp`3G$ah zxV2Z@k7G(ipBD(h&=N9RWcRfPq_0@@u@tNndu|0k zlVT5>KnPPIXY64J#YgWp8J<-!dUz*K^=E6k0+9+e%R|} z#HBvmjT})HyqSp`nizSTC;X#oqw9V5jr13|e<0V0|4$5j2Fu>-d!HtMp0fah7U&=R zJ>(W&ho;~S`*qa6{84mflKD+v(G3|e8E2q>Z)x^5SG;4@hMFNO=SKE95X|OJV$Y5F zNQnRCYbWh+&(7PSA>T{nBWb{tY-Q1ad9F!F1w-&)E<1m3=iG;6OZm^~8j#KC=kj&$ zK3bR^Obv^2=QuBPxz{nJQzR~&Iv(Deux#fHy3#Yg70YrR>tBuI8$p}hxaCIPQcfIc z^)26TTa%xDs#)uXL1?Dja!ID&eG|WT`N_EV@wJru!s?%y^0*)pS+Yzje|}Tp()qad z6Ywpz4D~I(Ousc9hJ!txsZt!NA=%{fsWmK3W*p(V%zITrMzY7Rf3WI<*Z^9bgk}Z{ zH}iV<)gGkUNVVo#7+7&s`L1;t@dn&-9J^)gBV1iLE}ZXa5TSV<#-IH)@!4)vLyjk_ zf(iSf4#zu(2=a3QXN^bO8f$i@zKy5uE7t@_t3h#k*v zU-WNy#wu2kU&A}OOfCkNaYk~fmuyVvX~*bBM=#6nD-MWNS?kY=au8EEn^azO-t|f@ zRfP}zWrGTcRcOb+6KG-xPm5Dmf@mEj(lkckWI{X*Q@o?3cL+Tl|LVZHhf^mo2sUM^ zmVKS58_7cWc)GU72cH~+xHYwPj#rVqx|H+5|e3e z;btu?0&2K0)>MC4;LoF0+G)Tzh`WihDm)(vdKvaph;H&>(ePM6^2qTan2tetfh z5&wW5$pcrv>vnZM7c(~F5C1dXim5b{NSk)U%L+fbi%)F}t+vB|{+^#PrW=yStn zvHSkns6n?-o>F*XyxS!Y$1pfzsnbk5!~4FJ3QAsdahP}kLwiZu|NXnKd}W+nB1~6E zrfdPy1E#DWRD?h-Px&a29AN0q3}^3k@N&llFF&F?L>28;@%S245NDJl)nKO)Lam!V z_22O+AKaKtd^Q&%AEy=h?F_T2D^sop zeoEkuMGZV;)ihR|qlc^t003FIkRpSTu6(5+ajPB4BNgR8e=Yi)H3k6rG7={$ttAwU!~pDazk}1< z`|fW2|4ol4C;*dGf3Ga4AHi&O4TFTahcd@fhexYveDJmSf{{_wI&QqkO{vpvW8s#mUU>fxBOaxPn~2H4a<>8NP*e2K%*@G!sXrI0i#okCdf*=j z!aHZ#Vq^-pMpXSB&#kBZ$yC0!s4_A_2@ZWs|Y>g&($W!d?(u+_+U z-GV_SuKGGQH#3hq#jr$%lFlt=sl|*Bd9*|ySLAQGRx=CTcAc;1kya$GLepCRg*_9K>;4^^N|Lvko`AUL3V zH$Qy9ioPd_hz(sC%I;x#%fSfAzj^9}4>;x?u(ab9PsN9bpe7_Ze?Qbw^#}n)Ps6Rga2p?HArhG80sdFOo0z@&l^`*M1samrp~K-Lrd|!ZST^@P|}b$Oq@0 zMGnMp9I_#_qcqB2O%aP?{DD-O@z)!u`cs0Oah2o&A?n*b&X##O^1XD4Q)Zu{FP7UYHi8aKC zBv0SvMj+pVD8ozG2Ud6eBjl#G*GtvBL}d0>A*Cuz6kx??LTxGryVm%=5Dh*)N&u|w zdF%HdjvOmfS`|uXAS2 zS?$o*CHk>!s!u72jQ&JN5`qQhi&w6FI8pXVof60qM%2lD?A#Q8<*O|)zdi9*cSQig z1h*bej56Q_d8KjZ*2re=R_rjGkcuRBQf}YTbhi!i`jUuV(bZE0^~T}`1rKg9Y98H} zUT<$b2U1`O*4`XZzEQ!8h4tjJmdPCk-Dk!MS0u-%0Q>q`sRm)knK3HjLby+B{fW8e zy;t1HJ>?1vn#=9=r~Cl}#`dYchF6`TfqK+(+%Q*)NOQlW^!cJXt0fPTkw7^d8Uv!{ z5`??0}zBW)CqtDpfwZteoZF4 z70Z{7CP-GZt;M`5{h<_`kG?73jrF15zTSAVDrTN*iiqYms`N?b4cOV0MJihtRv-NC z*|w(Pis@^FJH5Zrj$c|*+^~EiajS7~OZ!Xf69oFjZUiJfDqw)FgoRN|u|(n8OeJS* z)EBU;EM10JzCfoMpZJjRgq&(Ow|ierg6+ejEP)9pDBaN*Fy0C2V#jmT2eBU-RP!C?W*;gQvNtJ+7v3rBOhBpH$PzXLDSxlQjpQ%C&TM#i;MZ7*X6eA zeyb14n-2|?gr?;^oTw%HYui^X`sr7z=%53pVC1>E+)%7bHq7sOf@D5tzxogQKN+NA zwO}*H{cQS0_YA+_6}Q$W>;~dNrEOGm{=OP6U%_a~WOrJn?mj8h|O?L2SPwN@uTUfeh^*bMGjAtA*PG z4Btw@y_HsRZu+4m!M}%sI*z+hLn9+R6D}}a{rr_Fc|*1)Ho?CK1}O}B#@S14MfXM& zd?U*>J2l!iChjZ8gHdff^mdP~`Bb(YdE{iIr_Yxgr$U}HZq}L#e6!?QO$#GDWkqy8 zJ;->Q(AA~SJdx!YkmvtOoi}!DOFMdU!ZwD7M%xQ3m3@Hq;)qcaaBPY z?WM%MM(!c^cTAah_dhNJHBSdRVKY8u2+(iC7x6!!lkNSLm?}$juOG!EN4Aet>vDm1p&HkIUU2e8X`J}T2uEwg zr?PsjvHW~eg_@NmT`@-pGa=%>2j-R_C26i>g}lnKH-3#>(J=?|rb? ziJ}fxB&kX9eccwJ1A`U3w1?Y3AerTrzkt(VsiOX6$`!DibWjb5Kuhew@H}5SQoFrh z_=rINlOK(Z>h7{7DhKFUf)i2aHC1MRY&8H!JzprQKJ_SQ*M}JUN7jUBe)fbhZ zjqGaL?0;LWuFEknN#k)*+^iSH`hz4fQn47uLN=hsw$guCa40)KEZx6xzpsFSu3tG0 zTR}fDL0s0q`L{iZWbN~`jKjBMd=E$7{<=4<#-B80;HVpKDC=6*X;pL|C3Y4qu#GA7 zwtzq{|C+rtMEnW6r zqf|77s!dtlKdXOudYQVe6xJ?50n-2 zVri!4_*n-!P)!fOY1JK=pdY``(Z7DZL7T}yjaOR9XQ*pFKi_Y1Wu&{(U3aNx|H-E9 zSl2^N0x}7^Nt-n*F#@L#Lypz|K9%WgwV|#6-%DFJY>@W)0&1`1Z1PT-%xq=a ze6`J`*Mk49YMmqE5sYTrOm|F5zp*tq7e=bd1Lw4qZrVn`Xc{xbi>{WP`F1>-ADf!S zPZPcb%y{iC{cIh(Bl~WQrBVBxbL7g-sxYZbAVT(8o6}VY0z-(jX(e<>Aj;u^%t9WQ z>-RUR+6$|$u3X7|?0q;5k2h)F<6iSIRZ3cJdG7vaS9wEr=3dI=R$E><)s2=9r5)T4KZlyMu|JXbz$ZT@hQh4#^R|naN zg-Z>uR4sG+_6dhjg?;$iUThp)oT{6e15enu9TO^dj+U5uKUTlr_oCWJHMd+) z@vD}$Bpe!NeAaPt;BxeG`ukD;SK0B|0`C?zyZ;PCc~k+1^`B7?_+C9LXn6g(%?-K3 z$pz)=@<{>1PdPQ%$Mc`}C$%bzi&G!l3^*vGzTCJc0cMc++PsgC^A?P_c=8DH55$sk zVI;Mu7}mPpNI;mpT5FEH@v+eVO~F>sufduBZjOs)P99`7Cz>61n%$L|-i7&nxg9=1 zd8}MAjux;PrYfA*=&+SyEgG3!g|)g7k4_EWL);D(OMHf%mo_y@Hs1JfO>=zcGb2eV zP&8*PN%YdF>qi%M+P67fFpd@3?MHbV&8dLVsHLoQU-s?iUgt2k3nS(S{Tg9=(^+&8 z9RIyDy!DuGx7*d^M|Fc@&^br?A+XVlMsdXJqCc-%yn~cf>CP7l->0<)ENlhqzIa(@ zubFD(GDWKRG7jCJNZmTK92t>VjrGlDW+%^o$}G;IIU)_WDfY7Aj>$#-dCl3$b6nBk z^RbfZ9OfttLF)Z^SpMGBZ4YBb`onNyz_wZi)ulNLgwDZ_+o3S)x3;TZKrI71J6=8O5!UktK}?6r4;s;tQw zXdwMC+cNiJg;A-II!Z)VK;n<&ZVUL+TBO} z{#xt2ld~v+&o`fcs6zJ$cp4YOs9%h(nGEEos|L0d$>?0kZI$WE;0MrW2@c7ZwF2`M z%*{X{E2{DkW?qdew1^cJvb7n&9rInC(-iPvn$~l$Mff(sf3Yn&% z#`m?Ek~167%T!qr{+PktP_=3>$@bHo9F-<%mvJ3MwD&L#aq$v}GXXQSk)Lidb)2yx zLZ}GOWf$jdjXz&x%xO5)&HRvgbt$$XB{$HT{{)NYjBCfu;e_JagDwf0*xMFU{|@tI+IQ9>7|JCS2~$AIc8b)w{}O#k95halAg+JN!f1w#sL6DY~? z(u@FQ-Lmi@vf}7B`=QI?La{EO5IUYAJkH+tcSFF{uF=_EJ*+<;n<6=ViB#5-@l1SO zQdqJdsDlfTY?PpZUVQHjbLNk0KC--Zc5!iW&a)}^G}&S3?Fp(|fnpc5`(@vcRHnsM zs#C)OaZQ@woZ&3A=~^vqp$Gb6$|VMM>|7&_BMfC!(Y`Z_M*?CO%KS+&CK7lk%s~W& zsNhySy&v+2v^|vuO4VFl+-%lz>~N=>3X`$4CC@E~cP>?lbFprUuZupwl{h=N>xfQ9 zS=f_og@ER|Rh{R!1YsFStU z^)Dav!uMqqYF0t?yX|xZba>767tjv7kv(t_t*$kUn4(E4G)X$qperX}9Y37sJjoNb zwf3ZLiRk5)qzyO+Y~JyLs=}qgIa4Mh6uQEkJPdT8;hPlx6Owc7xYQ zQRTc;!$P=RE31Yd`amS9_w@eRKTtN4kR5FG?Yq&t6hJ%R2DyCZhCr@e_die%MtEc- zaUpodkxY|bh*e*d+`;)@Uki%jV+en<$v$+AC`LZ#$NOg0AeeWMz3dPP5u>zXq(-Yn zrc0>1=8Ak1ojEsGQ!`bf)*rz9OvhmV!BF^M|2$J0_b2|BUe{$|N5mpSvsUOA9*S+} zF8uh(-cZOs+swgYM(NjI>}~U-20ZpcV;g*QfjM6?2fODu(^fL!Dvfs9%r(t#@j6*9jAPNWVvbF1K-xfEXSiXU5KkYs)0Cf z2Dzp_9Ez?SCq*}#c%wabdp~lr6vWATduX?Q4&=KxRO%}g-IiZ10GO|o0hDZ*Xi7@ePIt`+H}vW-#u?P_Fy-Ub_)~69ml?_eZ6IP2xdatotqo-uBeI zZpRy-m){31m?_*?@?*EL@;_L^Fu<3yRoC9ocUe*ENa3W{Y=(oUsAeEc*U1PRTFW(yC&kz&5q4scAm&R8uH?;5PbSOX=sRh;S z7~C(4sxA(Pw$eINJaC%Q+C{3H>0W;|Qf)E~zEw~nKXtE*l6K-6hDpZP5A6(W_a2r} zV`Ow?A9i67hFh)-&RhFe2A}=|ZR+b!>zcsK1b=iTQ}I=M;)1ZVM4p@&)G}+9_%;le z^9`>+1G7P-5u$=2$LV7HARtX?`fay#@e8b@5d;!=6XzvrFvF8@2q%u|y`$ajkn2sr zaKU8kQIt_vAl^K$J39*sA8qE1d6}c^)xXj%=SlwqP0UX{pwpO$BpeFb)PASGDg88B zwErSX$eWW^eSx&yA1XV+5_kNW)5y>!E;@%HH@_|j+<6Mb)~Jrxd$m^J&u+>xJh~4Z zrnB*9WQ}w<|1(j|nQ)%<--<}kz4q5s2&r>+GXK`!Fic|OJ;u9C-eFS7+HP}ETtVIt z;7x}DfP|Eambd249)&BWwgo-narULqd$z)PGXo%uy{z5M{}6Ln7*JiK&-o_%JZ?sf zD11sD+z3P!Tww`q>U-sYw@Zovi9o!EvRsJ#T4NgCwYvXp)@Wd{)m|d*)IJt%xqXj0 zd9U^CK3A|R^k5NMYh7WdlsM7j$*lBBVhzK8%rD4;8@#+1Rih3Y#IAzOFY_r#)Dijq z%95IfBIx%?U`@t7Z%IP^A8vA%0O({ro|*>y3LTOa4x?ss{xSZZ#5lN`{{m>rT8I;Y zdClWxClq*En~-*k?Ldw|nPc2w7L>fmMRoRI5>9yW{Hpn^=7=mO?ihID$1|9WlKk}n zl!>-anhty~y2Wh%cs(M;T+PB&f|dM8O_wdIoePC7gkz{8$Yo(=&BuBMX0SL3_vDArn>E0QX3 zDU($};HwceR7`hAqP}`_C-LQz$ma#2niVyM;X)hdsa(f$P5$$IS~>zp%OoJ(k?HdB zjA@)zZ!A@ zgeI_Vvj}No$|#3*^=h-xK*g~K+vr3XFzRCpK3T=Y?8pi0%L)A$DWc(Nsnd0qr=q~X z3-YOxwFO>Q=FaePb6ZQ+$U>+S_Ktw^TJOZTMLpOST1}kD!fU)<9i2D5Mt*Sx$T>nt z>3rk)=y2vI;| z%514ZbV$=&k7Xo_hPg|bQlSnCQ9OF9I3~uYv;q?nd^Ptf6~%$qHyQo_kEvGg?HhK-;&GqVL z=NcvZk*D()L*XO9K~iCe^S&=@YzT6F&gQ*6&&kS2J`CTR(3uUtqN|{YGoox??C#~) zu5yaeaGB&Wj*fB%ojq=!@yJ;cv}l*E*ZONfFv_-s4xmhI(=`r$pzY!Zka{mIgEtiqH%a zfh8)BMmUwf0Sk+EpsSCOUBE9%n)=_xkZwo5zZa-EdclD>OH>GasHk4o8 z40T{^S4S*m?kEAPq1z-4dbnJ==J)BzmtUrZKjLA15fzn09T`C(!%nPYE1+mhb2)1= zugzVR9dZR1nn`3_M=(oJhhJ)~#~5{kp;c+fLnM;rOvK~Dq-jSLFkXJU_`hI*Jbe^AmB-x)jd=`8x<#rhUK}-1Bctm!Jo~zwclHj?i zY(sv;LgXaD3S*Jldke2V^;EgRcS3%zC+%b1|eaxib%a!`x^4|9i?(+n}Nd)|c6A|c)p&ouAv9&@!G;ji_GjK~CTwiHuIJ)~z3$7_57( zt8vGY6nZ}P{E?wf49hofe zw1V8Wv^y!_$GrKZvT^0Z{w`b`{%RhDb+Q)GC+Jjekb1R1aW(t{$7b%C@WrhjZuh%d zd1Oc93n?9V7)tMzlwQsl6!_{2SQnpX%eW+2cy7yU4-+UHv7#J-m$i z!Cb&4Fs*+$F|kHVYL9v9TL-41%g9pjq~m zjs%!psSMaZWf{tve9074kv+74jT#t7&KyLeV#j%SS$|7rFyqoi%wOcEyI9T+-<;=V z;}c%>daU$F)MS+60lKkc+A>9iM@RfZ^UvsS2$0?rL_*AT13A+hP_O$IfM|BD3xcL?<)P5jtiv5Q_7SK*GQN{+R*!FY`8r@ADk@ zy(G6&pHqz8T#-8^LKZn5eKDr(Xvxf1Qv!^xJ6gU*B?)WN^(_78j5A@ek zwErqAFy3nz<}@>!(zDp?BFbTT)PKrN(w&tsYjK{d#WkaoKrC(A^5=NruoiXN2<02! z3ca9|>~Ti%JfD!P8ojuLpk$3L^~Kx!`K(HM&V`Q{-!!ijD$cQ;Jnm2pBLlfb#}fJX zF3Oyq;3^NjUN5M(051h5)^X5a=?UmtCDq$PYy3F6KgW`l)KFSkP}9dQP}c1`HF>48=g>iIA)X>^sW?;GCx1&eikGES@c@roL1Olc(y zPvK|ItG7}_y3;5Y;*k_iGcj~@V;1-%Uyl1|H0y%#o&N?p|9qh zjsv2OP&{%RecIa{>c1y^CJU`cy&JWi`kR zd_l>JRAGKq3y!D(V7A+VEkl|vEyxunv%J<`4wOEw^mIYJ!i79b%LfWWy1wYe4f@%f zFpKhIi|8i5U7%)QZ^HCbpohtS*98%Bhyv?6q&snM4}Gv`B3!rL8=Dipib|!WqY>sk z`2&dJ$zqBBKFI35xBALFp5=R0elD(<($e7cr27vh;lFBSQk)2*O)L#4mPfMiOSWA& zv6KY;y&LM91TCw+!S5k7)zalg;fd=s{WU)ZqPUDLo*$!sL$i4gSnjSxttz}jDx&k< zL_P+do9BcIzC`n-jfm*fyTt6r<|NCX2mtYl*0{IRA)C#OoIl<)GYH`04fv;JRJR4_ z3JM=mu*|UrZFeQLf5^5r=@Yta8`T$(4i#iDHi6+~7yRUuhCS8h!p5c zVj)S^JVWhIMKU11Z*~~O`r#KJ1gE+E<(1@{8!H#OW1>d5kjuUvVtCN$`9aba_IV(O zxNi7}yb3z2E5ldOrTJo1c6P&S=aoOVUmry(uXC1J81+D<~HNi9^;eh0zV?oK5DC5{1CQ@DZJvm*O`YoLwdL zhu+HwH=nk#&Jyo2IrsmIH}wbpmbbva=TP^P3m9gK=@a7l>DWR-H|aOUyJ3Kxe1%a# zvM<^;K}%36OUr?N2I!e$s4w8*hqMBMibmN2TuqC3(KQR9G<%r1hLw?(+c^iRD^qQy zbyPX3*Ld0q;T7j@*_Y07X$|oQlcCJ-mqW%ht-kXosh+T`x8=i-J^GYn8!zkZBdrn4LWjqtv?K)z450&p&tD(9sw^I z@_P9xT$UZ#$T9-;JfgoF6RrVUeE`~_N$X^3M$BC>nek{=$e?XdbNovxr?gYCHN};-Xijlw;2D?w5lp8QhJK)pUwJKkypxT@@#cxbSFuanbu1 zltb-CE%FE%yjbh-%SB^{0ZBIb9(eVF{5RhjUO90(H-AoGISAYq%}_veJ^}7@C>0E?|@>LVfb<%~f|*k^?H z+m9{#zdV%~In1I|^ZC&VajfFSP%uSb@M&_Z5^P6~_k<1vViPzHU7`1vor3aPOG?K| z&KxE)y~E|KUcp4D?oCkK=%zGCDIEY&5YS%9ofeFzo_MnbcaAZX!nFFOIBXv>vu!d0 zI^Gc}p`hhX(9ZzeK)RIR|D243h#({nDBadk9})SdWFh|q(5`{YLJJutFlR(Y)00Hq z%whakcJozeu`trW-d$OKklZKKOPQ3ns#MJdMIKD}`Bh3t{cTo$Q z@@VEAbqZ|Q6>-LESg;smmu1%nLY%LKHBqD2mM){2jStR12hD`5BC>^k*q8=jhHd0MwS7vs)8M=Zn!dLS1T>5akW zq}1FGP1~O9iqq~(FfXD#>X$!-UY3?uZ?z~>bYI{=MEt==09AsNEbH$B#A=656s_X;ONd0JksBEqB&zhI^%&h* zJ=1;|{qov4Ump(wmT@3m`LQkp0s>k{ZpfukTc@>21nLewT@)*vyXA6eg%2iGRIkUq zy00QPnVVVbg*{m&uChBVD8i!2WP+kunC~ZWx(#-Pi>@-)PoNrgT*`LAcE+D2(q3S} z<9oTiMUYFYR_pug4QS~|@4`m@b#2F3$(pF}R}dP6ykBP_O&I^n_iKvJug1vM*&3K* z8IlT^_I}%*UM^l67kt6VT>oQht>^W7%~}UK4nRc3pF+!TkKcaP{0OHhNl2FMsBI^@ zrSrBz1m?>OwuHEaf28roCuR;nUUgqMy8TW+SVtY2Jp8#28LEvAYBxx*hy^6CTNj{7 zwKI8`#)YuiUbxaY1Zos{WRcboy?oKRJyC7+tVAem7?46+pY5iFSi6En016nLz*$A0 z>7<^3kQ6)wW*YIFolXn*4TrC0(M6gpkxp^5hoNAnCiYXGY9jpWMp z1_=kYN}H(XX^s;5SYHmdO&EGL@Qu(oTPTez(a-9{15B)mY9Ku?yTV4z8-V^B*bTKY zkgzB~&T3cw?U!I{bJ0@wj|l!VF8&=anHlNJ1W;pftr#9@co%Swf`YL#7iWf|3#q0U z4Oh$>G%x=0YkV&=5agm3u%UMm@|c^kq-$$p)2QcD7W^cK2z93{v2=g%)J1!@SRWm+ zha9 z1RF6abYz3ZIh)-y3vQg*n6#knDcdA*Uv3nkf3%UR9lrWZOIl$-N>0THhJN!C)xS_v zbuQ34UpzmQ;V=C^u8hbqM%XKGtx;v0NBK#I z306;=nB~OEgZj1jWk(cGMnl6}Vm2rU=>f^((XJdL{)z5ZL}^vG^4awymCS6*cT$4U zb1pms2}(Q;rW9R&2KW@YfQVuEwKxx`ZTGV*g8e;TPBuv=@(!B;o9^{Egl=O$0ny@N z6KQ)}JNzxA-#GWGOMW%3HGM_d{*m2O=&&X9# z%^CfT{58hCiHzqKkF^jr$a3{1d+uB{*KY*_ie(U}INqaY)8l?Fo{cTW5?=94TBl_^ zQE^^tQw7lt0C?XO{U^(&6FSm7uVFB>_tCC<JOUlA&LABv4CnOaO~SIv@QPP+aSwxXzOV|%2>8Wo=BW(6MV z)8q=Q+fbne8b;MGgs*r*v-a|Z37_xsS63xP7h1Cg{D~e!JN7v>e-#Y zpC)`@oRZNA(*h6@pQOo?8AC-5<~-ep^uz4orpoG|yChsGOfd%GB@5EwcJdbLMtH}aoEgOUQ zz&kge`Qr_KFrWEIGGiUE$qLh7OoTpy@H&Ukk;|>9uWU3mv%pFjMOd%xyFc}&d~%xxa;4IhC9*+LNlG?WXE{eCLa1QFLt4~NgxjPypZmdATIVIeX`W73HuT^+ z0|!{QA^w%W@yMH`UPPbLT&ITmPLg<9OowgyA)D>3z?r@3+TeqEidN?3zpS*#P}m~g zSM<;ZTr>#7%w`KWR5B`rnzE&DEvc!cpq>$~rZes+aQh`QS4?8%X?vNzuNxmOG_;fvn`l{4BQLj`eAHlFM4|+irAodQ`wG7}s zsh6SDmXgU-x!WS-(}xW7MqJQY>so@}>t+>lrzxC&4*&qY>C3z!YKSMAZmr`Fn7J@( zjPr!2b=IUYene!t@J%^SqC}&W(gZ-{sj~Awsv@}^;W@KUayDR zL+q25S06wNk`ZQY&|!tjp`pqzLP{Bo3rLHw*yS+bo~D3(QFx{~u9L7Ib=``GtABRs z(K9i+Q3Mbk`8wy0c{D#6&;C(JOy;VB7m5EG70KHl1z?HGKsJPENja5X;r_ZJ)u)N9 zpyeucNW3C9iCnRjTf$sD4ze*U!M$!rMVqbB{sX};7jKK!r-taptyvUhp^o|+;(H%F zfnVqg(p;Q9;~>0rviN52o^lJD)F;ERm@W;v|D0x-jLB#9LYUUxeaN&yzBLrZ_a@y> zByovULiNGdoWdt!8ZP8*{+29C%Tu^C8XCF+SBn7;h_kfm?xEHUCB*y07aDU;$ACV1 z%PZqoc&iP52Z;e(ZHb!gxFZ z=|Jt_c0hvDP|+l4SWqO!cb}50=x;@LtXt@PN^SJ?vFSd1&l=?3?99AR-*0zB9Y`}( z@kBv>GVOMqT9GlHf_TJ$VmTJP%)jXLF2?)ldJS+5`G@K{SMNzDda4-+4aMzqV}i&^ zq%jM5ZH`=s9_ME(%@mQjqO145KpCjhTIs~EdDHRo7A`#VdMjcV$im0z`R=;x1fm9L zQ$cl9(WHau>t*T23hMf7pMI&U!fW>_9)ort3Nh>p?A2i#%M-phE06cQ3Y1TrA)G0*?J?^w* zPy)ZH(t4UGy~)*Iwsz`ASP86)Ce$CdnlX@ly3vhF)z`YZ(MqpH!9`GnA@71-M6VVK zx?!UGKxsu8J=ln=F4roPe?K^m9g-DrR*x_nuxV}Cu-|`edo5^|#p$#V#|?tM*Z1z4B_tA)rHUV%bBt)`#`4y^fN(zWWfaggD|_ zpM=R$aYN4orogK)b5{CX{3$wIC7Cxrh3nHXcew?oAFGCiY$m^6bL7wuzmiuTLld5a zbFP#UP84)wwBnB-Rkpq#$da@Fsz}eAm*ZO8O=$sht{&v(33~9mKyIAsbGeXU0bbjv zp1$(GE%S=Ug}%(&Yf-10w(4z+AJIGbN(tDH#7$>kP4U>^g`waJx8GBrLaQ&X^~9w zjKJbX6~sZib-_cEUt=5Uw4OJ@`4X1yNhLoG=JG%J5g)?Ji3uJXKu6Xt&k^>Jc+dD( zek|Lb>e*|;nga2R44{C)iw{CQ7;F%fEyVcRud9|0-{3p0|3Lik0Rsf$7DZem&7x$2 zp1HYx0Xu0>@l*}Io+~ocP;ZWa@GZzs4RX5+EbIpiSnyafI#EJ{^IG=f>lw?xYXt2@ zAE~jgr*tvAd_%Ik7oC@{Vo1A;SD1M_W^2zPiEoSTVNuid$VINoe2JZgRg21P+mJPQ z4+K9RUS(&L6v zx-Gx2UJ64hx*tnvreE7h@`9qac40zcynoUg)YyIK8Jr?SejQ1vHuQ1%>!>oDiA;}4 zrRTFw7IAQ6ZnVg41*Hj4#%|f*L0P6(lh@+ zLq+*+7ooD0l!oBZ^B{)CF;SarVb-P1y|YXRDK7sR$cPc(-%qfBTC2S zF>xup!brm!F~S~O2>%~+&go)1X-j|1l*QLlmGFyO#2PD&3Ll~U9jqBba~ETV!T6yLin2zCF=KM^b6 z({<)?&t5-~O!r_5FcT%AvX(QizJx9Fp zM1DmlUXBS0MfnuBwm98PaWg;cw)hfb2a-*fQn!ek>!(UtKtq$zK)D?+WdtOQIq=-d zdxd(cw!O^iw|P>jw+Bb%F*|vCU->Tm%1v1g7v6U#H_pC4)g!t0WJj`yj=0#J7vy9{ z8H1yp3Q>~f#x4_D+uipajGv5}?Su-*WTs_`iT_u^;lZQ?B3cT?u5#oF^ErII1j2Pe5^W^hMj|PW1GuF&b`P zvqQ`ONR`;|+4B?pS}PK6bRIIuUlz3|o*&SvtU+=b1^)0}Wf1i6ke-ji+zLBKJDsL4 z9Nc%}yK>r*RC?#szO`0YadaGOe{vkQb8#jFK^cTWHLhEH4`Jf}_TzaBd%_WM@8(#S z;>O2L-Sds>PrxSQB?&4vHplGR8cII`(wCs+9JrxKS$;}U!}#7(=CjA;veyK?_PG-` zq00v?h>9d6wyMyB)ZU4`Ri{mRj2N|QZyI8cHZ`MG7geKFQ5CDyXpcP_N*vVQoL|1b zzrc0n`sCxy`#$&mScChxS=0`(!dG@yPif<;(pmn_&gh0HsF0;JR#x`Z>!D-hwXt$p z_CC%mC4Zu8?1=u=n5>8FIlbTB{bAQ_l_N5$_voI}WpL(947p3qFO7;_6Y44Zq@4NQ z2d_NE5yqebA}*Hz$u?GYSgd5RuD%7t>dJ|W`C;VeG7fe20IivF_O0@uWZFasE(qvk zD9OM5m*_8{-o4`Jg(_gKvUJ$Ll2w_?;g5#cwwHnUY}F$UZEDkV6C5cG$L`N>xwzFg ze0ghosA7@$7-8fRyPCoCz_!t}Em{*1Q+DJQ-;X|4e=Oz0Pp2-{69cIHp6|`uSdd`| z8!w^NMry$2@256>EbWp?{N5Cjg!dP&roCv5+p0Jb>YmAlawf)Y{-;cB5U1}L3H z1U-Fd{Ex4$pUF5!?{)7xSKTc_=ICAH!g@CX$3$$NVJ7;X|0w1e`o5W!2@+2A0EBjS zLC#|@t6%Qiez1ur&pS^O!wfIu#bNW z(H{>hmY!!M@{_hg4-~-Fwh01;4vmtIT7 zk77G-Dfu?j#9K7keQ6VlJbcpypwFUfXfRiVtMrfUog)vcXB8`bSCs_iuJBbcH~4UF z4v^!i$f&zCZ;gn)k&NXZ+d%U-G1WW>rT0or|M0-OH)$R`-%MytzX7B{G2d*sLfCdI zS88>SGwHaW8e$%ICzP8^U-(-aNtc!<6HJlZh;}@oI@AWCR9*^BJhn?=?t)Z-(qke! zm{(sSa^J*p*2x;J8zm!e7W6x@XfBvVEE3Qfa8M9!^yINswTush`@|^14MhXGh}$F> z(X~>-q$hCpxK0~656Q@BS@Q>f?qLf zbDjSE$ubmG-hq)^-Wh*M;^wRWnmb8)52VJ6VrJt1H5j3N5Y1*0yLnf2GKi#97}U5-FvMsk40r>w2S7q&eJ35ATW!9M9Ui(KlRE(&A)-f~dv7BQobUBLS6 zo~KipWBt4QnV9FvAjvK$XvCbSv|Zauz}l4u;jMcz3v;FoqfWf5BgG}3kN{(8W9CoF zj#hE?P75_Ds*1!DAbNx>Vz@NIoJ<#ibdclE%mc(Fb0=ly{Hqqm0Fxc1!@jzGh_2tr zmD8^i``8e}^1$Eu!dP4KNIj@0Ts*4!L(Sw>-sD6bhAn8tp9kS^C}q(E^- zw3OF7y*bu{d?O(TaY5G6%a^mDYq3PSMNd-p*?6jDwMQPwr?xFJE#k!*8g`Bnk+-?3 zU$3hSs8M%HWjeHxDG|Oyfgwb0-i4!VS;+wv^sk2K9&+YAwq2bLT_rJ=N`2m*a?R85 z2+}0ZZ@ydn6R^F!cZ8-?ol305bT&ouJQr&I)_i67y9TDKYj2fssrFKGG(s7vi!SzV zT+%Ng$$7q57wl6H`ZONI{KJvuAqy|UH=;k+=IRrj2Mc~#hyMZU#0(9U6Is||#a_I$ z+6*A}EONd(BQ#^h_sEbo{z19t`3A;;16Y{Uy=2H2Qf5&@i+_<~xmh$mk=k@qYNQ;)x;{MF0@nkn! zPc@GjX}KD4UQd}dRHuocK8_bATPBEE47ywQLF$3Xj>tFK$4=pqee4?DcKpgiOD}%9 zQjJ}NxcW;bY%jXHfSVKM(Lp{*iQ$!EPesd@&JD*}I@Ka)-cvGBm{$q31+ship|83#q$8 zeiO^KJ%*55PGv*sd&t}e`6pYBV}>iz7NjcG{o@vU{+*ElRc%K5 zQU7*krIKFPo0#|9Pz-OJa?3nV0zq%S6u&n3YN3g+#uqh(;ORd3!w{mip%5-_#ssFXlckO8LJJ zJkA))HZ(HF^EV}}7*x!3+?waBe%jOC7Ijsv7NF{1*pune&yD!)03+lckNNu)TX?v^%vluS`0+k0{Y(vytuER zsQ{AV-B!BgxI9b8H#cm>R>TdEsSMnV`2n>9KeY0A$H=F;0>X~(dyVX7?^2oBECzQg zX17wzFdqVp^~Mns;Dv}0VTLsRS*&i9x$$zuV)AFs>d%6g>+iocTWZtJmpU)M7zLsBs!`}O7}i+!w~NTtk=0)p{m~Zs$;`-MCWTcGpg^UKD&ebWnqp72Z~6BOU zup~;Y^_XlHzQ#M-mhMw>qw-D+YLB*sPGDUp8Fsq~TXE>P+)-5Ni?=sS5o^&ydm*4%eDr~5|?@IZ~g8j-8_b@WZeWDJ~=b0=P}!fwNgBG`i7xF zI$-}6@G1ruP&K#iO0$v1WTR!q!^N}mJ$0Z6c_Dj4ac$==SsK7aL*r{cifd*$@?&%S zK%ofl1Uw3kqdA;!2if$hC}rw0Ip6Re5MwLxKrEN+uf=X8oRT_u1fQTR&$RC{3Tfqw zYwBLk--MS-%l4fGpZY6R;LHn(LNRC~ zJls^Ul;^3ag{7}gOCKBff%oX@+=x2wV&K@Jg~?{Zrpwk!GSaDI*1aD@o(tUu(aP;I zfvR?Nu1va1LP-I&xDY5OFt#{6px`kD+lI^3cA>lTH_WndVt3dfJ8&s#P8FJ(s;di( z>p8W)ba8@2z4-D7iUIah&iuy^39lp9rET3cNrChW`Gz<}y|?k3dl^x4eR?OY*39Cni&0kqgb?YQqgO;viRD)LRZryp`l(I58VKft&A6RoIc zZHSE=4eLKx0R?B77D|i`d|N$|Y%bKD@;TRLq)$JGF7wnm=Su5|91UH=K#gce&d<4d zzZI1a| z=B$UQ2Qi2-%IuRK+RCz<@sy>rzVeZQVgeLZmuY#(i3n+W-pziV%%KW5w}B~a{F5)+ z%>Pq$n`&f<*Gt>pdMcMtBWDs7gFa;1IfEt~=&R~^3L|6-Di9%w@$p<5CQk`IN*3}+oDYn>}>DWreY8pC9`%fVNYgcM8URw*^~v3-r%`Uh;t z!tSJdlMKKOZQ5e&h`K%w@>zjAI=Wt~CuiD%@r`?yUIcb-56$qCe&PKQaG8*eeGz#|*)S#(DF10%-P4nid@a%w@7R zK$aq(M=JZ-@CY?@0{VxXS^+AWoJOPchss!`L@E4lZPJrw0wap7o)K;Umil4mhNF{Z zb5ZetLoSP$)U%d8@?Gfei?zG+JL<@cWwOZ4TiNl(FmYrHIrPK+^clJGC zt+WlJQ)*m=1i@@E{zb^#r1?>LSIoh-U z=6ZXCZ$U5uOjq~6k9m?)T zSq@H9*?oZ}j!`TS088ImH|uKN`V*GP-M%doR3^ZxU4RV0<1mzqaHBcZCHA7H%s)c< z@pb2hQ!7MvR|HrqV!wam?X$|+q(r^$GrV`3!#K{r|FV=LlxoLeeSP0JpVU|+Ba+;j zMjyH8Y!$doV}Z-2Nt_+rUneWkM_fZ=O48l$m7Gmn_hXONqy_%yyLpuqnil#-N*dC- zPyHZ-jD#w_e1j5;WX1Q2Fo5zOdPPq1(f>LD^%UtOe_!cuByTP@79B~C;6o`d5ebKQ zj#MF!X{ELZZQ?5@r`02J=iWpRmh@VDUO&LuBoV&2T_YTo$Ceq0_xv-_RgWI!{uAi7s`vXkn)m5}!@COD=6ur+lQ@HNE!0fJ0pYNDR|)jD(^%!K7uGp1VF z;pik8h!@AbH?hzZ`Naws?YsRvPAZZiTCjhKL3O#x%ny`zRpANtsvwsgG8-jBXJo`2 zfSJDPRL+p04zP0wb}ZIQ5O+9S&J11SwACxOY8!(m;0AY%j!n`lQ=nMdjz-U++X2&M z`O4MmQ|?k$f#&aRs|kv4R2a3%L8>_}Apw;2!ePvRYq}>vQ#lE$6?IeJzZ(~(GrxrQ zPqyNcDJ~K37m}+yrv)@sMaJZR$0;h?x?h)U&HJoG_l^{mJaeJF>`5|s`BA?pZEJSu zc_5fEkl7w0==bhy|IFq#XSG8_RFj*Vk#!ZfQcj~LsuRk5LTx%CIow62Bkyz%I36vl zl8=40YAjATHz#7-aTUnhr`V#H2;hf2BQU-fMD;#KuWFqkg{M%_L3xjq8!pq!Nb+b^ zmw+KqADL|MK0&zk{PfD$sXN1UrWYDzI-e}6F9KkfR_qNg!;tn2%?>&hTIV>ka zi?E}0%i(o|)Y{XU64rr^T3@yzR*F=6R?8j@=6>;7RG)f1=K0h!BT%4VK`PfGJk=a< z(FJq;573*-%E~)nfJ|?b>#A^Y)AzMBH2)#h9=ff0VGPj5Zl$u;3DXZ%x?Pq7vhD`F zF+u?QU>ZC;S^c6J*1TB~lcRHrBF1M#6&e9JeNC5QAf9h;G?y>^fns1F_nf&iOZ)Pb zf6nNK((1t)(TAq7_L#YZhlO^wr?D1lv5WLtGc}!W_>j3pB<)*FYGc=SpS%-McgO5H z98sx^3AaDW=`Y^kQ65L|J6irv|BA@4u&}qBV_dDZyXw>N&aAAVLISS9;Q7UWRfG#N zCcKsD$N1A3v1u=-C-Dn#S0>zZ@pxpRrgJ0itei)CtWUhhcv4J(g{4@VRn-LxDNad) zh<1b-_V$P|$t9W__n*XvYSNy6=`{=6qxGbW)xet)7d^60{AV&v^9eCT;T35kKB_R^ zt!3xb0kl&Un&1RlC2xMuijbVs9p&f0)?Q|J@cf~CG8;e>r|!AzS}dj zc)KjK57`r&{K0r@@9g6A`t=`l;oG)7OQcLe^t^z&v=L~U|9xE82rwhlW1ik;k@QG- z;SKG!x@5UvO#vabvVz ze^X}sQCgeE$6_yZhAsY(E#{a7a`K&+ChS3zB9#kLuBW|543y4eYBzlXo)7b{Sc5W` zNaAhrVQ^m+Op{XtF`y&m)ocQv?a2neWWQfD&E)L=#Vxu@FNixPeKJ;0@QbW8vtSW8 z69~&85Hpen6zKozlphqGHIi{T|5PP(0`jL-XRLtNW9+7Yr+-V(g_!m5N%qvVU6uyT zjlqAsHD^|Q&w=Uv4zPBZt_2Y}up=1%ZWmQ7rIRoo!tp&7eDe)Mx4E8SRh-fnPGFUk znzbUggzk&luF$EZyDAK44NRIw!_mH3q{O$%N^e5AOce77jM{!Xz$!vq;8^t!AcrmAOcVzW%))o(+ zC6x_>E1yVxtUWNb&%Q~U;H4)B(29N*gWC)hkcJV;K`h5FpBEFKRNYVX!>BPn#?r~G zYjj&Ewm_NpG73hKS5|`CowOMIx{SW4fZ@)uXRf5e1H-J142?89$7b|gW4;h;Wz?l& zIFz?^fLr&sGzO4h8{mjpi9yU(ob4~(Hq3MsNm{GK=W6p@7skNKo>`O}NS0HlRBXfH z?yQRlnNs#4aOUF$yi;*=+BiRZYt`prhKa>T3W2+`hodjlIZ+kOhhyUyPh4U zSgyE^493g(pFZjXsMm*@OZ>D@}oEn z4)_lMyYgDd&1LDIdBkk5WLBi&R}hk(1q|gdnyDP{E#sOYxt|Y(@?bfB&b#>3zLy#{ z51owCYFSIxXJ%)ZAx)M=T5W3OwMci#RH;g4`Y-NZsG8ZwUu6nTXQ3r~xC9RQuHFAa-*dX*oC9~6l%fi|W2t>Y zyCOfLNp5ug%h6GUkM{~XC3d)UHw5=2G83l*+vWb==|2K4vq!sZB+@1A+;}SH;xJ1I z)~(w%^-P?d1WU$Pm}~GDBq}Ck#kUwv&gYu`pc@}S#D%V;z|Wy2Q;Ns2?R}!w!hsYu zW~&P&m~el;bKmObxa5(+YjyA1cX`hwJswx{#<;?`GbxB-I%qh~Yd5K&Ft_EP`&$dW zPM7o5?L?BPEBJVE|6KAuh!E&2Wt@DsHwMH&lSEy1u3p^q?F)zBtkqX}yW-@-MohZQ zQlQx$s#nkUv+u(Uer0R(yTe5-VbJ0*7p5?BeC*ioahw(S3Os$P$sOG2#?`|v#;knWn`~iz*%k`rR!Ct&ALI%N{P-EB#WogZ~ zmvRvepIJZu_;88BN0(9Cwo5YB=-fKp-K>v~sy;;usH1@W3=mEYEf!AqHN1zCh$;_j z+)#+`gYlEmx8y_GfhETpAi*b|^4lnuwdv5nHNoRSu|?xWvdLQZ&T@J@$dUD{P&#YN zm4CZ~J61GJIMsJihf6``?P56R&~A5SewX!b#da3+2nddri7YN)$*Pe!+`mxVG2G&8 z;}LLjoSDNDnrR%jt|-%ln!b3X&rGECt-UW=j4{1f%1d!D+n-128KxOyfak&0GGW5q z+ge8>w7-2~mvn;Sa=ay->f-H$V;Odgeg_Zwl*4_u)Vn{R6q5iH^Rt^=Lk%cnVUs)K zr8trW)y-?7w#GH3zaQz8M~FSc1%yZSe-!2K-oP8Cx9$G0%y~!5q?zt_N){@;>Jq7J z53p>IY2#v257&Q(ebL-PwS@^q#L)TD(Lu{)K$g#<2@lkuciZ34P6X! zf|aGyHR@!RF03+9E5>+=I^<+$tj#pkz$daYxxI})%fvnDXSbTz9v;|rD3Mdnmo09;*DkRgvj`O(3_4FWI{hXN;*h59!4%mCTt zdN2MkH9(Gz)=*0-yGnU1;Z(N#yRT9o> z^OJLIaZ9(zhzk6kogT}oZ#Nr>$Q3Wh95BvFbl;`{w!m(E>mA#K^qx9y?>2tq*T!O_ zw&loE7n?EmS1aPoLtl;KPP&)cnPAPcL2rZ*>~nVLojz^LBdW?4+v3K-LV38H zb9kn_Zo~YiTxr{?-KXigMNlaL zoj`!fWM+8!NJDyk{#$^qt)R!lJLB1kW%tt3>r4hpcqOw(9nyjcW z`gD|^K0U>DO2PtYzpEfmJ>3)=c(lahYd7~t^IotQuh{yfQvli6W9UsM8=sC8U2zvA za)(+=?k)%teb=&0x44R?l`Wr%O{ZnQuw~So$~K}40cRm{W*xgP%Q-Jj;ZMo}A0k;g z%wnG>p7-E?@lxMS4}CjYganQ*Fv|?=*p_cT#}5H7D9IK6~E{ZYl% z^ib$&_Tbi%6L1=9Q9?_p4z`x&&-;K~@%)dcbq#gACSGntW%pCG7Ak`YUhCNn^x$d^ zQ|D%Wo7NGw3&Nk#X`b)aIxKMCqjzYITF#d`hrOtsBP|X7>ZZ4z>GAk#dN(jkya6cx zW2YEHjenc4<-_2TUf=54s?+@>pw=pKU^(b*E)tibuZkj{v~AlP`MLOSS%0R5O`0*q zYuf+68(~jvk`&f!xV&A;PMfT1mGVKVFz@}tl;#ANx7^;i%B0E8L%C~L&zj#3M;-5t zhnQ<*R@gnJi%*aY8p8|v5MQLJGpf?ShVUwroa`@X#Tryy(;S}3ZU%gqiC!0b2qxW$ zx#QN*Bs`m5zfEFi*0~>z3&({niJ@1n-3l>%$HxIB_Bmo)r9gYaTI26Kp%!`{-&Y&dzhCgF`5@5+vVly zLw<10tYBN7uShqbITuAY!YiKv=}Uw0U%XY^jt$#TivN+2M!Kl{aw2Rv`s_IyE-c^4p{7nkvErv$x>-_J=< z0jFW|24wxP7{*VP5rhTxptfnn(9$HgVUd5t?To5B-#{cLM58o8XZ!t+jR2zwYO$z1 zB*LlwLcHlMgXiTOtLDSVmh^h!S7{s3ZUQDQB<>Cc;8yb43{%jhp?FsT`C{PQUB51U zK$Akyyy=$tz4|d@wj)@PS4u6#zK@0AOW7uqiUhWH-s$jwlo;5}SN9j@FaHD3wNs$s z!3l30PVM!1X+yvYF(tRaxfzhZ&9bwaky?7B8;+#=?n5VZ`-YT;sr*%)^uE9?xIaMz zbG1S;!8(`DcClr4FwSPeLl`%vutdOf9<9|FTI+TzGL0GKa77^iiwSJQShPAVN`xz? zrOB~#;QM?jPqCR{bX}{5WW9}&kE(Iee~kjH2d~QCe_)FD1$9!09LZBiTYY_e?QoI` zJHFFBUoU;MYC{#ipN7%yX8rS62H!U*9G-U7oDWlVidrsC?m z3*iV+A#aY_l|w|shq&b2@=@-$lx-fB1dn7d042#5&ACqshKDR(y{aE9@wzv|SKXyb zTMq8g{Mjx~68Aul^Obr0GRduj5W}8h%MzTb-jnox_il*QzPQqU*0$fT`q{o zkk*z92Z)ZR* zz!fed$L^8qo@N^OAvk__c5jp;X`J!jxQt=vd6CIH-7@Z5OH4nv!=Ytd%oDT$(kc#E zX5enUbVqBPwgxy2`bpB6+}gdN!)`6JVmHP11~&=kZGkEPMob?nDut%=Mcr~C_3{Ub z@ytNLIy1eR7RAqU5}H)L^rTA9@d|j(_MkGuy=^7CjyX#Z(3|vXHFQSf6N>$tF(M)MzsJV#2)%W4?1yk!$@SZ;7_uk+f?+k?!nVI&Ik`|vzxW9Vt zo9vf2IH4S42rL#Ip>P>T28H!<&UCG#!Ps{%)3m=Ah~pFuoid9c;AZ6&{Gz+|Fx|{f z<8H*h@Rb0*c|Z6E*zwV%sZzdM_xswVr?T#yda?Ou*%3ivsE8W%)nM6wUK{b8X4Dq( z^pceN&|Lv_J0+WA+@otny9FFI3Wdw6!g^YoRUh&SpSbn!5<|}pCjUL`V@Q$4D4q4Y_ZeU{MzrA#dDZ{2hKHzB3_hh@{efRm#d z3Sn|zO?wIY>(j$8%8}M$w$oPQA(aUKV)cDBX@Rr*Fq^-fDkW`pn`e3aLr{BP*9<`12I_}IR+_=g-@T#UM{ z!q4f|{oy0BP(b%CGbE{BL}0)q;6Tz&E(D>F>hchnzJW?m)l@1$tX4K2n2K~^2cw{z zdVywC*}Q!{(2VFvd$SOzZ;wEDpEPA9_z!bsQQw8kXv`}Z;Wk&aZZ+)lLd7)KA6bfA zT5L}*Vx3V+OG$0yb5K0K1nK(nia!O^d=}w z4iWOeN;jGHOYl$Cm3G(StR-3O)Q=yo?()7Wj7d@O>du zuS$|>`z#P9B~l65HHtkuKxm8o2-)ex>bxnVE(hX-+Kh*SlZU!#m!Y6cQ1M;h|yV)b|5;*0V1eM2E6 zLqm8#PpiE?>{^_~DRBHpg7~5^W(;S+-u+l~OkC(d<10R+iZXJfp<$iSF<>X8lkXQn zYRoF=XWfXL09<1H@Ju}Q1}dKf&qd!gEUO$>I`q-r@c(}If!6@zPL^F37Ll3K zqDVRYILpvmlkDu2{Y~21TzF0_Oy?nMV=U4OAHxGGoN`FydCLGR5fS5c+=%nk?yIi< zGdY$I=^?QP#%}qk)6t%{wI}8MOk7ukbUUiA#q&Dt@;|>^I1{-UBvR=pfTAX7TYX6? z3LRwN31C^xhu%a|QHljfzVjOa-m`Dpl8>BoV{q!c#o-9Md*2;(4+KGzX>O9fRNyJY zv2G!NUJFAj%zBolU8{ptcQ7uI9;xYtFU#5@5~fEXk3_!6`_ZB3gAO?^5RrkZ{IByN|V2ZUPsM1IH` z2H}M7yH<(PC}UwIxd4(MpLTYA>D`R5LxOsVDm6yXU1X=5&p_kP^^e-M3a}W|=`+M? zanXFN>XC6s?UfX)cNoOjjXt00?I%``l;j#)JoBKCzM6?1XOlSBrBPJ zJGVaH>j&{8BNps!;QEE zuU1hmF8s#8urAsIc5IN+wHTO1roH#CKVv%Yx~jZGeK)`QFz0+d3~^zI8n3*Ii){l1 zwGbrd#Oj<)xEczZ!p`WU{~;AVDIFM~TiBeEfIlDKe`Xhe`V>KAcZ+^&oWrMgQ|6b? zxAbp9+WJ0?XH37Lprqb_@CW+6aU83Cxs1GuSNfiR8X)I&(hdYc6HgWCp<31&^^3g< zjz?N*cVH{DhpmXosLMcRemhYTdfpUye!jXnX3qT@>@ACOM?+I=Vz7OlBUCLXtrKZ3 zZ5jT;&A}U8hQQ zG!OF0h+)iu!Lt~F$14(tplKCO6F~Uimk(wM#l*jm+!FnKe;#tZamhN&-rP-wq9_|T zU3l-o8^;R=vY8;>Q5KtnU|QHiinI}BM|oIU&W z-q4m+m((Blv|fT`i*QRP3=+KyuH3&5ksg{6%*%`^%0a+Lo|zVq?VGj*Kfp{s*^vdf zImHa20P-9)2k#UHy@?^$nh)s--cHOd0!edYg@Lo?izr$la9%0Icj&AFd<=+u7Gy?8Cs_;ZgEVG#Oa<3^lUv{y z-u|btmzf}o`_(3G34%E|ym3l{7zL?>>Ayf9&yCYz2jA9;zM!zy^Udz$vv1MKS#+o$ z&k+#i^dnL_``ANS?J87{skxOoR7XBkYpOj1kF$a5ntb@uTUL&D()``86r-^N*NLy$D`5ot26nVtBm620~+u*`ov-)VUr{ND0(9UnSd*^7audLfX zW@!Ffnew91jRe&~0-%BD{+Sk8{3_t)HKcokGs&xOz{7T=^_do2x@*Lw)+Lhret8z{ z$k$UZx-x6~zq0fQ`cSZlhA1=LWSyT~l9JfQ)QLH3XsXE`F@m^SOysb6%#6xGDBnU| zdlvK@)oLr0Z)mrdLF>xRc$%;&`}2Tg$S#)iL`wSKRB^8+7ell5WgwBGKp0Wx?`6?mZw^K z=se=??)uDw}mpdBHdQ|E5ul@M$}L1tdBPt)#n+hT@H~vSF22Oyo&;J6x2^Ec81$fMJ0ACA|1neW$KwKzPt*gQbHfq{+3*jn3|FGwaMHR_ok( zoL`DXx6aSwF~UQrvv2nJ*!9KanaY0vxS9Cq6_q;DIEF^234OtCd6oN}tNs$|M`)e< z#+)KM<~j^)X9Nd}u=ZS9RD)jai<1#O%#+f-e>dHoY{sW!lIAmn*@q)GX?7#BK8R+A zIdZ%8oCQn>BKic+v`9&wHiwR65f0XBRHfD1D!L_lgy^11M|6aUl@r$CCnFahgH}Y@ zH#X9_?L5P{JG&8_0lS(Dfn5~n&FsY6d?tMjJY6L}2%J|DJXJ{FyUlrlTb;)u*E&*L z46su200%S~0-Emloo2JG^2BI^Q~dxAk)Wa1pEp{(Hr9-#c`=iWJIxE&9LF3sKwF@C@dzS;suw{7$0b z$nebrfuOrj`)1==<(a*9z~Fsz;|fpNtrIQedC;Sq+Rt8$)V0R>I$aj2#|a8|!v2iX zCnT=OJ!;5||2r8_ua?BT%X#Trw7Oy>9OVwTbQ#P)5Q_6PINDV0vQq~Hj@WhWI|z3h zSV5N0=t6LG&iQojH;~1uG&x3;yK9WHts*_8TYo>$rU^pd#xcuPJ)|-8_N*lS;$trQ z%~~m{^^>)g{SN;m%VV`>uHYW>zAJ=FJ&6uM#){sg8_Vu{g&DW4i9XncZ3PmwrP7FW+VDV9Sj-G=k35 zznUGjbVz`PLJoWyb%${)67qNCOj`6IfB>Bfb=Ur#q&0FmeX1A!O-AR^ux%TsFBA9` zwhI{nD^B4<-lp#}QPe!d*L&?2TBp_FvN5(pGUJ`CXJ+UiCTI@9*f`H4`eYH70r3^|~D9Wwi`F zr9jvzwWQWNbTzu|2yY+g($&*|^e$~p*WOU{1%YgmCxsKSJ`JR^v&)3CCfHBU@13%! zr&mad7;anLc_N8Fl`C1?6gOssq;z)2m#kl$)`sa{5r5Q{tFHskj%8ssU2>%Cy|cgcsx-$F&}&9^syZk-B_m;*1+s<|U zjP3`PTRh9eVq5mT#y~tY{k2A>reQ|SOGo_%Std2UEcvy=Hp3}9A+#ziB9v_ZOiD&k zmDica|0YA=A6B>A60hM6!!Gjh=*Zz(Vur0-Ik)g$g`+Nh)9jUE*S79EU;iVGn~YR> z<;7$V@j{9p39&;wzxa4B2Z;HYn!&UZU~M+@3lZ}L*`Z0RIc`u}K}GW2wZrVRz1Zmd zZ7@fqsAtbJsR!M6P#6FG@>%N++^Z`jbT@dJVDnL6yo`OQ zibt_+OD%KtQAOga>anJg^(JeJKg%@hKk#lVeA?1KE}8dGS=7yC?u?2+z={QAc#U^L zNzJeY3&YLbaFrQ?{Rb!pUg&Lwt=HB5IOMrAV0YDY2rSkMd=e}z=SFUjc87*UeR=5* zK+;JjTwG!I{~~;|^`X)_=5_9ztou_Z_E<`>(M7Eg_6C1uCu3#xy$XFipmqPGH#PXk{;_1S6v_dd zI=28;iFkbEsXdQ!ihGtWKYS~ogR7;lS0#ptLp^JhUabr zTNAT4>IX`=p{sbq$u9K}q9p%q<~uZ)23JG`^=zkJ^C}2x0E)6d&x}#1+s12tDf?)E z)hd4w@Se*d{R_fH<;CK1wDYJhspqzZ9Fw4RA_1TtvnW%{j6T*3ho9**wPMU}h$~T( zp%pQ;ub2Z=r$IA06J_UPv7>1pG0J_3yThaUl~{mNtB{*`>zS*FIVUU6v_7UNRqy3b zt7aK`BGfVE?3{xribyDV!i0M*rMHoO_)A@?d&{pl`sgsI^Q!Sf>Vn^@1bsr+)c!1k@b1CGjSovk8 zB;gWGy)9$F$NIcjh>ib>Fn6L)GQ%dAfpfE%$R}BTqHzP$^X3l629ru%!Nr}q2>!F; zEVFJiQJ?kT^qD+8Zo;5z?@y?rrg^ykC@6?T2f_2G%s|ra{1oog)K1TdEot2wgVg9+ zsJHN>e^oRsgufSvruIfwK{C=`TYcJR^*wkO6Mqu6${zVj>*N;%XK{L<>R0>H{eJjY zwg$y2#sN$$fiQ&1S)ysiu7GM`${*oE8m^-A%sAzGP2#AT*Y zpN8)7^H~HhPe%5;H)}`q-*_4f@k~IDkT%!3RV@vpm2jlz8y>%}wW+27)iyjE_@>34 zXe-bknnOZEF!xEqd?+wM>WyzF*X#IL;bk8+(ED+yh1QRq@e@Fh{%oDGz$a7pT7LFq z_>;pLr^qSi{{XIJQ|Hwc8+@#-b)h^XVz!bmgAUSd*WPe3xi0~==1E&Zs-O{`RYJB0 zENX0ifW0^xJ``~Pk0ssa{R{Ve{uLM0XTN2HvLCV*(3$j-P#Jo~pJ}pMk=(2^HLn(%s z@%^=}dHCfZ;LF_pAH~yCJwp`+o3?V*ob|6o|_5 z498%}Y(I)c*&nOD7)3tD)84tOnTuyLAcCrha(AdX5}2z~7iaUCjaENA=Hs#^GIPr1 zv~$?Mmf(gfc*ZG9eZ-vnPfntY9pWCXU-MitJ&O4ll7UxFmk4}y8@n#(+!ny#v>I%Z zm`PtfFxh!BQ&N1hz>k&3M=alNPynyrYiE|2(#^Z&WPv=Vbe`>Nhf6`i^!z_OlQ!P+ z-(a3egD$zkp zlk+r)0f*Q8KKlxfuASX9YFQ#XE{D-Wc`eZpRdXz4(VnSN$U0#3k}t7V91rXnr_^15B!TOl^=8Pz0_ zWVM!@Ev1aGy-_+0+iO9-q2GT&1LiC8*%I+l_P;yHooj1==l(`Y3Rybvfw0go-j-2d zTKgwXegCg+HBqocv^5Bi=jxZ`Za@hw=IPKrYcovOuhA;LKXI%glySvf&SpiBb1!O< zQ-krAF%=??S@5MDgWD5lX~T2kwF`I{Eu&-B{1Lv*om8ebUm`bi3mrsr!wBkYl_boC(rUeFnAA(Ck^F2ABcZ#T-?7x$}xTJ#|}MYhy?W|L?Hh}->K2%0mit1>)L3V| zVFd5V#@UQ}$eCu=39v`8QkGp;UzQU>HMs2kg1`1j`s?07@n3$JZ&6GBL-{i{ozTv~ zrB7m-#4j#K)|1skB_WWEa2(&AwF*SOz}=OCec-!A!@&!F;s52*rA7V{wrGbs^y0Er z-o0&qB_FTQs%fdRxi@kebU@2rT@<#4A+yT5!~-fZ9Qy7%o9v*RBSfVE3MXRqx2!y+ z0c**iTfLO(G1BTFL>nL9XoiQIgp>lUStF?afk*OJ?*gvn! z(U$R{803b!6aO4B@KA$eqFHRHHqy|~axo^v5Sf3Ek|T@<#`bEW$i_Lzfq(bwI8C7y zWxAJU+Y>mfFzU2?{Av|_4zE{J)U7-ZiRZgW@-ltZfxvwx6oG+4^FU@ZMz$LFY)uAP z+b;Kt=qy5x(V$uN{eyugI*M<)r?OP)Q+&~k!UtDo_jXx&L#aN}x22TC2C7|kTGxyFv3)-HPXmtgq3DZ}v-)Ts~Qo=GORbZzVm_VJO|` zJDtd)D!j8t2GjaJ%szgv(cMe6L1;sR~)$rjv#uhV$olKdKOz0rJ zKJ;2g>TO|VtEs*AKJH>=hCyCjHRWiBoIzxGI~qFtX5klezD6AqmziRT5=DREEt$Yl zk#XOs1(;6*c15HBwkr!O;x@P3fQqL^a#E!X7`#OWh7d+D=bH`@YW7E$+qyDeAoTm?=a6i<)@l?D>5Q|q6WzCe&dS+dPY1BDL%N6}fhHTkw-c;x6tKt^sfl1k@* zF}gt%1Q{qQ4boi_V{9V?K|n&%AS47yg%LlHQaT(+NT;OV`~3$T>^+|MeeV0Z&Qtr7 z`3HUl{mttuUDx)MLBaPGEVIANi*Nrnelhh%y=65?ErbXy_b3yAlbVV?nY7Rf#>)S? z<9U%2th47AvVMv$mTi#SIM(qCi+Xg&Pfx11>c(dXvP!r8Q`e2VL`@ju$sc`^nkK?> zz_`=BWpb}+CElXatG=DAlDdeLra!c8{Sx;Yo`3QMez) zX8k*Eb)h{j*~N%^n}#_?UZ2Dbe#>yAO~DS=YK-&!Q?Y$NEtSrz>$dZF>gvBl8VQ~7 z)qW{D$DB{>c;R;2b6(iapkKAWo!9qyxwrSphAj79d3dlWLUv90AE+#yb(1StO2pJ% zB!%)%Q?WeyXKmT_%L{glX40vrM#hD9mBhOa)AOL~8!a2OVdGBXo>sO$W_LbWEqu}uHOG{ve9d0;ge9F<@9@}M83UwK(P6vhh5VAB6b2nQyHmK z#Q*v$c;LSbi_wLjO;3`V@aksX3qKxZaqoYs^xZj?_gP!W!uekFXbuH00-X?4DkPRBZ))PW5eldjEZ)38RhKty{e>jB6Itir(i;P~a_M zGtO&dbdwvFc$<9od3BQ4Dn96q{IPe#xOy(#y{>)>I8hci!0W`#2Yt?EJLn+sE4PYm zBP)-0jq_{8m$znK6(Gy%9M+exuE+}UheQ}u`uO>f>(kIg2D5?Adk&KJkVqp(Op4mA z(P&4*^K0gFue?T0TTScv5A~hSA2;fsH<;h?wEE=tecZNff-O(zRB0x)e}zIs?NB=T z7siTgh7lIo)cvX4jjoU(e}G=H%27Jgq4UvzJf(d4R+F+l;S*TssbE(#Jp9{R1uM9y=P9 zNqwTw$PKHsqo+tIOTA`D+})_L+-3;W|CH=|*vju5GMLBn>aFHC64M|}y$}1tVH!Mh z+m2+{0(R~j7wm72BZ^R;P52XzD7CwM)|=LSF`U12 z04ft*Wyhkdia9`lw0sP}YK#~F!>m5%_XXpoEB^IDo7BKJvY`ORLljidhA+B`k&H+f4erM+h8py#f5Ss4E z$&4vI6rR-b0lu%8wdRFcxAFQ~T2!xIA{m8)4k~P(HrMlG|)uO5HX0 zXMzV}qfyV8W2gUui50wX+-s}y($Uzi6~_eYTCO?QmDWN)<`JD|3);y?Ey83IolTcW zw7Wf(88p78cUZjoBx-aI{@)gvALCP5uIbg>n7^!zSe!T`ORzc|Pc^oDj#G#crgq`;i&|Ro&-Yz9Oh>Pk2+*Gwi+CtGlifB> zDRI}u;u=)*5969++m(2@^{J?}zStkOON*wSWtKU7@eiHyzFk za|XULrFZYxuI62KR1chymEO#IUUXi?{SwCC`(qHYJ==H(*g5j43#zkFa0)-?Cu|i( zCqTr=Wv=Sc!7E3zRx_rPVhn<~QXAvKL5jNab6+6Qe5JzQ9YPgkDLKJ1tb|pdoaSH= zXRxk318JUtGMHA?fN0ncr8#reG6=6 za8Kxwd4z!AXHlP8{HEQ?5@ULcM(F(r`2D11cGw^uIibs-zwRc-dOJiM*5qIB?=8N@n zu9eW0lAKt=1ChmAI-ZYMVgr{HsVX}M4-5GsOSj@*iLT^k4v;CQ$?p1;#fYREM4{Gr zsHtma?74xrEh&%H(|YH0tB@EnGPD}0MofS&f<>TZ z-9BIJ*$qAM>P0yN03sC9bVQ5>z8E93!eEfLSGqQ|g1$R4RgWJnvPc+)7j6R|0{P+%xdeDrOURsLUJTptE&0NJbybtlad$hz;#m5f+=w?_@TYFBY&CihE}B-H#J zptgQXOFGBXbM9LJ*0O#hmM&Rk)-E_iIU#$UIKv~`-{0$7$U`bccrbwmEh+qRC5nuL z#kd|4gBF$hj55ExtV^7$s?D+`Z)A0*QzigLAkh~6#ABPfG4TtF-fyQGnqQB8M)&QG z2bfJVh9=zY!e-!Zrj;<1pWj`II@aAk*=RA%6gNz`t5WM(Lf44_t5TnVfh!J$`q;UF z)i^_}%knf=2~7zm@FVZyx&O%q$$uj4Oo|-oV@GjswIsyAhm4v<&Op-XJixl(Zz=uP z3o2~A1Q@%$YKKlxi`M82h&FSVv}fS4lx?D_nxY}|vYg&y9O3ovo3|_0Tc{qDk=s^9 zKG&DVS2A0jlPozG$mjDx0w$tcUp?>yG4G0mB`V2o6E4e>NbsGmM9!|mK2!Wf0IoRn zDNKv>rMG`uJV4sf)+_-n#i5U?#$fTt5NMasB;_8Q*VQFx>k*N65fssObQ~@)2WM#& z@bEk;rR84{WWTl3cl~fU@=EZQgu2D3TEgo@ki(5Eg^yDR8CD{64Y*Z6EQJd!Hmjh+ zFgNjg4zhHlkx3=crSKzgRVH-VRU-qTfb|pP-(EoYI4zsO^{WD&Wccl1Tjh9)zHOiK ziI!ZJEFE?F6%4R>ZGF=;++O{e%b7k_U8pX|`r_U`uX`6m;CXnuxhElGgpWVsv);Q+ z)}1>8x7_GcrS>#a?cqJFGh-Nb&U#5=R=5%$gs;MdQ?{%n zv#W$kUA>E@GAZL^G3a*F2mXJ|7#sR>Go%+aeEb#V-ew^|i^<(Xo*J)pP>{8&8d%zoC|s zS)E|=-RVLXt>8=0mvPru;s6xjn!qMU7+PVsWllIy=q(DNUBat8MI^ffBC7BtIA~ZK zZjB*)e;9nSF@EnrUr%eGXk|x9QZed8X@9wI>TLZLHGrCsm>l_=GAh1`mw)}Pfccwo4L(V990~v7J6)Hg);9WY$n_ zDMXj>wM4S&0_NtCeI>_X3$sm2Gmsz0{)eP zc=)$mDzZyUIk|zTuaC8tNQfmQ2m{etRpo+!`AW{IS?%c*2lz7x#0RG?EL zxu;BhWd&KPPbWvA$tI%t#kic)@ItANP${>CQc4R+()l_>F!>40YQ?LIt@&Fz4f2U3 zKhJY&&oueKcw{knJAJW)VU^^eK)3~yV5mh+RfvF5*j-PUbnouLT3PGo`x5c7PyKEf`sK{5 z&S%N;PF+oB>G!Jn_it+LY;rVUSOTpwsUSt5QAr4?=4c_Z^^~l zH}`cx3ktej81Nl!3C|Z7QMdz54 z!x7v>Oc%)$?W0_-S9haI-ORW2q;fMoG&NysYh}(yS~vBDxIO~Pb!}WSo{9TMtWxi) z=h}!8^lhtXMKm@k$#%-X@vVV;7MFjvEffpf<)bbPBCF(R4h)}b=v(j>1dt7= z;t@2DK^|pH8EJ2VvDK75b;1(^D~i~tvdsJd8rzGKFO_vB|FwaPJVeMK`ui~#e>ZSr zOvycS>Yzq53;v@ToWS}FgjbK&|(pL2AsFXFwfGSWxz%ZKuakVD1Y5Gv<_*-c) zv03z4r=Hljw5l~;|K5;|cM4;P6)9!*DXW=)Hi*y;h2bzt;9a1)#zX>vrllsve{{9y z-0N%&p6R*l>*NFYrJ46b;K?j{&)u-y?52TCxT-w`rM%8ycpiuO^++Le<_-%_3__v+bi< zQFjJiLcKL^6CFvMF)&$3t&~ll|0s{wY*g{F6d=h$Y;cEnaoJDD)-6X{#B^#lU8$)4 z!k4}&)dQ2Ob_vDMIrCM+ZjeiYpdq3_+Zc2F$ho4o3AAZWA0Qd-PgYQ1(+CMAzssUI|hV8H(7D zBQJb;4$F&NpLk;vKh&4l{b80*8A9A1qfW2eM?D@wAIKZj+Kth?E!LW2YUb<(&99Yz zUdMVKm@lv>R;j%Gf$fEG6~iD69^kmvE|FbaLH6?et%9VYiUeCXAH)N#%0bo@O3rRz zGOiayFxGnxzuU!?R7YPL@0>T}<$KNQgM=P4ViK>cJlZY7Y;S!lQKOvWcqU5XH!u*M zy)jZp)@^bY0~Me)V8Z7poBOAYMJ_%hmM`mihTYsAfCZbXXuaRxk%Xz4Z? zDWBnQ|3ET|?@5UMBz-49moaDY`G#yGyTkUeoITO$EC_Og&pFcUy4%>o6+YlN_(_!| zKBfhuc{WzK0Unuqe8nNwycvDw!<;Q=fM9G=MbW04XkE4RhWc(MKrg>d8IhRAOwbPr za(Vwp&9~XVv{v|WQ@7vloxsR1A4pu0t2fj&y-wt)Dr=ywh^5#ymLqOcO4(VCaeK^INvC3JV58ZHWXc}yT3x8yzio5l5+8k)H43yPG}Bn{|)DfP^iE4t#R zJKQ+RaBJ~Z?_x>9UGGeCxMKF|5<2D@6)Hxp;iWxmLADY7EMK7+TS|i638-l!L~$)LKlQG zs!p2n^Tb+b_a>QA^1zadsqwV==P8aFoOEaaC8QB7+V;8;*JjK*?!JN$m*akNcO)CT zz0{OIUZ{2qeelL#$$(r|2Ak;|4ua#Y3w;KI-9(Nb#~hC0qY*Qo_I!p3XBM@6Reo=B zNZF9PuZLiPLBI);cVZ@VHl&?8!T#dGl zei$FDzguz+(AsyW`i+N`<4tO#?Zz`a%o_50JC?nMfnRoXhYX)k0~>Q>=dom*5CI() z`YwDW#tmz3f9JYsM)Q#M9gQ9|7PBr3NuUhkBgxWN<7+Y|PWsB#m zJPs0{+K<@_%@_hlV^eT`x`0YVe=szeS$sF9%YiszN<)1UEWrLEvy#6rnyFdIBWHJ{EB0l`rrgok_x&>zZT+iQ@*`Y(+@EAiGGSAt0*# zLkvy<`}8p6vXS9^$}9t0wd8O!*HwE|3lD5Hn0X2`OZUbRF9?$JS~>(IPKFyYPw$}I zZ9R5atOegFlc1(r0yRZW#g1u`u6n~{GXz$osMoq%6o+B@RxL3t_s*)jw;DQoSSvz+Mij8xhcDgUbZ0neT;^NxL8VUAqh zjCK<^2*#x8+cy`GARhlaKR97P?JBM3uYAMZff7s;w2Xbmzw+hsj8f?zVDQ*^nc$8`NPLiJyNBVS0 zUGqZG61me6PA2LC=RrKfK0b1qKmUPJg#;ROTLQAC>oRw2vLy`-oOmnvnY0dk$K%zp z+V(SK`^cdJX40mL6sr=n_sP4l)^!gF{e zowD1IWO2vJ$P$1$^FL6(>!RM0TvZ>Zstb*JmC@>avY=Vkh)K5(dI2RI9+mh$WwYod zUMKd3LMN0D3cLF3dX!>A6T#7~C{AK5=-cv<2rCF@9WS&djs`wm^Ca^SqV-!(C zDTB%S)Q;wXwi%`-RigUFWgWAhIephOLI&X7@c6yzCNmTw3)>baH`z!;+`0n)f8?}@ zmud(X$Rg!Jx$4>A%&}ebbzCETvGU(lCpp*SumzPNB(oCiX2$Zq1ed|ikzq!oDkp0f zj#F0;KYHDSXpNto=FR)S>@4R9DUiYC{FM{F%xs25!XDT*&NH?5N0|RSx51TW>xuUreYI8;N{whoZlsBkTCqSXQ>knwY4p<;#?g$; zhj9R=B{H#->bjyc`X5Nw*E!3EWD4)}R27%sh#c0>KO!%OW5hH~=dw__rQ#260pmj% z*NYI)TE=*3o4rs5cZQk_9G=WsA)rW%Lqnqdr~#jqQPyTJV>z@Ym;7^O7X~q-WuCh0 z*~WDD?@Bseq)MA{QW6jxZ`(Ydms-6GKlhjP6QR+k3u5pks>^y8%jgIA@~frP=?aRX zttEhmfV`I5lnqw^$Ph_YbuM*!Hu@XlZZe;h1#o8~ z7#?0x7a;q{1ELMLgFhrqbND(Iu{ohc53&C(F*X@MN6F>IZ}?qAXbp;^8|Q!p!9S3T zieI#lQ8V^GVe)7|XKmhFek2bpK%3x6yq+v>J*!OL62)`4W4M6BCDIHTuiB#94`m{p zA?(Q{-rIu*<41r;_Ug0tm$5@J`rq;r{Y~lD>oi>)e*ZwRoqQc}W3$N1!4<(*2+0em zl5Fp0Syu9Vr^!E%KVV;%VeuaoEXxYS>olJ#Emgg^0`by5jvL?lJ@Lp?0vM;R%Z-5x zB?nxS6c9h`#1&p96$0S9N(o(9jJceT>5?K-kgQs^hB7g|iHDtEn!Q`t9@vVTd&~Bg z(ie#{S`091gfn827?^g8QbOEZ$|u|m6#1Tkc(eu@BNxN-kCxx)uCdr9{K7FPBF5Ms za0}#W_+Is0U$a|Ee0??sDWzYA zn+b{dO`C5w3nrZ^)|TKxc-7v^;(+%tiLRlzA6ub0R-8_Io(kOyK&evs@?Fzs%OOSU z(W}#sY^Lss-L#vL6@KVpXrLx@5qZTDCK8=NN*0-&rT7xmX!@(QxHoE`bgldY@FBU& zOMJEx71w>fk!(Dy8Z|0iX zXKmJ9G2{_-Ki1)Mlb}GlB;$x7cCnbRrdRR!YDq!bLIgbf}e|n|BJp>k+sVEqwt*ya%Av48|oRm zv248HL4@p{S?}^#QC!xMRmI)q)JUdm@fWBpieQEm8Q2Ve;d4(<@<0ln;Ol?j)*dI)v zOI8q}XclwgeIBr^=xUFxF=DGD&qUr60m)O%9&>n;d=C9R9`_BZo0cqdUzRzUlYXE^ zDFaN{s8lbRc_e#XG;L$vEr9P!+l%Wb9E8%hRgySS-kn33PJo1e{8nRrz1-2!xxoxD z2;nC0T5Pp>f6wl4M@iB(YeqHy0|Dp??2n3A(^Uz6_lcaQkH*d!O^`x#fKXD*aws0b zu9YvI))k-DKyk6H288$E652uh8JxDv1g$63ZjWd?XZL)8evo#XAO6H%@T3>DEZ-9K zUeRrU14_{`dll+gIdJAi0v~MAzLK2l9ZoH@nmi-UuZY7@RhsL#eeq!6X zyZ=k;esolm3DOHEEhokuXMJIu`Xv*j=Is&!-ag$QwIp4Bayw%euSTe^ibEef%FrPWpR8d5@SEtJL+O| zvZ#rtBgpa&T^S3^RauFPc|1AF_f!rzH={bVEU8rUTiLP(bam+HvT3(xTf3m;Tj((8 zWHE(BqPne1C!QvKGf$IjOCuBjxeL%ULt5ZB$t55;%Ly^&FoImPVm&JtlfUr1D3 z1ml}+5hub?ha@}THy`wbieE1T_Yblu*~>Lc!(63HKdkNI#)?>3pG~_3FFswlzL#iv z-`%2%@h}}wS_-Gr&hPV?{PvF~&1D^^3(Mts@w%rVDNL~SMzYgW*%?Q40?{1N4O22N zy`H``&J?>ro$G4xu|l;;x=EZNu(=B$wcac}?WQCO-qyC+Q*3?gJ4pZDDk#AQpzQH` z$D^uZW2U0u6fuEPUma(2($CR{--}_=H?zD3b3iAs$TkZ2nIZP2ln zZ(1!fGhY%N8k0n~8BqhEj`u1N?Ufwoumh7Vx5rZZjHd9u@!XDz^NKc*d^#SGlE#e1 zvOL0m9q83J4_u~}Gf3p@l0FaKL#T*b?7Xi?7D))I@s#vkTi{sO9pTMyHvq?Bl5S%v zz2Gb>o@tq}R8m8OZN!`bK2V4ni0wnpUlDzC=C|9;F*O1-D?2!ez6JqOVu!x2+1FDG|Cf0aAi0 zKkVuX5LlSs9*xWil1(d|=x)~$9Vu@{$NdB4@M5399oOUjFje5HA_JcOemp0@?BC)z za?P({#&ZY8n~Z~+57WkU8)OW$c(fi8(`)y~N6ntxZjI1x&c87wsIzl)iO>d+*d124 zeM)>+g|h8tA^3VDn5A6840Q^O=>PHX0;|HW&Xf_JY4#o`&exAuaJe{9(`_M6qnBcc zm{9&%Qx$3B6sYHDsB>-aaD zcIpw9Sh!rZ>b#DK%fGC8NtXOimDaH>6VW2`u#nf7Rp&p#zmH<`d#kKT{(&a_RGuPL zMk@vD5va!w5^R;OmiCL{))fDr8jqL^=wb+OM9R291CN444>Yr!jZ{^DdOWcV>0v1_ z^qf>o<{LGQ#h2@Py4A*fX0-pPVr)*qpH=>ZC*LcK;@D}5Q@ zvTg4Y-`bPZ1j*{Fpj<`tiGx8A=PU)^vt$%dQd{=u0-9iH3@!PAikGEcm~#b-$_@9s z-gqgCl8mE)LJwcu)p;l}Ui~Lt_E7<6tbAe;%aUh+MVm?X0Z_pQn}Vyn)+38-;|}jO z{(wP3$Z}$Xf!JXdt*IGRS+&bIqUCb$IIsLJ*%OM6a+kj&1^Epy2zoB=Xi(PaSxs%_ zT=lsriW6L@*`#e~4!>Ee26C;m@dkL}GighFwR{?(Of+)l$wukGROT%Cle*FD?Qm2V|BgJ{ZsH`es9E`krX~ z#iciZMTo%lNR^c%{>>|;?_SJn=UilB3yVLt{E17Ll2Ql3l9>qPAX4@W_rm$QT6FN? zEa5=k1o2%ET_CJcTm;9zUwnoLHZxI+DKOYHM8XbKMJgG8<=Wcl#YfX%+X!4*0HsWZ z)b2lNbZeHSf^40H(Ix@hXsY`(t`~^+Z`?S*iP84+0}qLuR?Q#IND|M~ZG)G+K&!69 z62x*|Jhg?*<-+QJWGvx4?~mwBQ~z<#7FaGE;|iDI6q(4AZm93;pPHjt5Adz!6Izrq)5rjKSgtPWU_DxJMZCERZMqSIQOU|L}rV{27#t3uI=#riw=PI|GQynH(*0;gX(`dhOT6O zPs7O1d~y-M_}Q|)D$w3#O(4kKN2 zz_;%r;&YHuA9Wr}cq~r0<5jO7gF2WD74JrzUvj>_vI~f>eD$4CEL=dYE|VWSP_t^B z3#R2RB66->eNOvYIc*T|NYm$$jf30(iRZ^yAM+*%Gm%GcAd`LndHVDwsf!YUyO?IN ztVx=mcySbM__s7RM9@~yLb5FLB?&bJXdnR_F_I7RolGQ~w#6!mK6mv)+L|g|c9(wC z)AJ}bI_=e1xt@2|)w3LWU3yS5={jV*(^}u4K}%n*3Xd0=GlQT}Yt=PNmLpNtx|KGY zH*96)=x%tMI2~P(q#h-Zt!0eHGGQ%DOoS&wTwUZla(Z-4ea7TJY-*BWR3auv6(&AC z5ohC1<3T|q*(AN@E>e&TGGP7yO6~AUGDg>0v9F#Ys|~RT&x5K4-;WkcYw1CA{so~d z7nYRK`IVc-aOv-H1JOP$4#{%=;Rpwd>RP{d!~@$vXm$#!O9IYqVPAKcCuL2b#3N>8 z_Kj@$p&0Fc*cV-~7B)r$o5ni)l+wttKQ?k+VZdm(;eGadp#aUFpf3N0_9Ypck7}2E zP4M3=VyZ$MPsUU+zXks4Quto`MVWSo#&_u?I2*aCSxv%IZ*&i@`gW?mgsv3kpYdI= z7czfxOD9p&H&0Y}>>=wk$_$oLa{GUe>x20Xtj${`W;eQt1Se!)o$!pJ?BI@C<8Qtw z&J9Zms@xa9$a?iDuoSigkI1(+eBM{rD@qocnaOV2GWMitrIPm9M z-n<~PC{OJt9AOCcIiqdNSNgyorb8K=4=LqThAa7aP3cSjsH_ zQPdHIFz=VO&5X6<)HD9e?^+P55PyNyWUb}7cW1W6?wQ8VV~+FFsGJYHi|QQNdH;dz zP5iAx%aUb3XM9BHe{t-1vr1I%;=g<@aTi_<%WKiS{S6VwVJ*s2;@EXx6kvWPDnS!QYk549L0qgJN8kl;hD$`Yrvl@T$D2-x4@j5yA%KMCP^1q z(8tp)4aV`>Kz-gdH&MDone+N$N-5;iU~-8xj+(aL4-lL?j{gl0g$JNU;eQNJx&~Z! zsG{eRxNn7)`dlapO*OJ;eKU74&6$dk()Ub~F@Ly~H&ldHC~tK{ty&{L*)l zr9tt?(4l4qh9ZWLG}h@{M3{d;{op`HQ=L7%Oj4#&%R{jcxNVvevvyMqAK05dU*5X!!m1oebiV&u?FF6 z8hU=o_jI2))FDd^5s=!y%W+Yb8HCduJ;#3$KSBIi*t=gX+81k5r8Fj$My3?hU$Evq5;3V zu_`*Oh>wBeSRN-c5QiCOOG*sx>Iel1Fudc8+VC6|k2&|>FH}-H>L2~aR#jojYrLaV zXt&J?T?&C=635`8e4s4Pno%rUf*VxQY>^NA_OqFRsy4O7&3dRrn8K300Cy5_@V{I+ z(q5}_8AaCW*6hXHG?Z_BqH5=UT^xDEk-ro-NFj)y2}0JCKU~=sH;kUm@{2T^t&Cr% zr=X?9pBU+$H8 zI6r?dXdG1dBn^(R0d@7CT(rv{_91$@O9e%THQIa|ZDQBV~K2)PJ9hoFlQw3tmi(Xv(ckqYCJ8CgaN! z&#se34gc#0Np~1lC~Iu=bdR->v+7U9KC;y&3Y?bNITi2f}C_MUX2C;w? zRomaczEUMc7nu9Q#CJHx(k2XbnDC)-$HHppJ%ok|K1Rni;6WI}=`k&m)Zk0KU_Uo~ zuhKrzn;)+hfFpB@U>z?es4FX|gqf?puIN*p?-MBm1xQi#L{mR7u#udi`O}SZsgrJ^ z0ZZx+t1u++Tl|q1wso%H^n4Nasu``{h*Eoy#C!=y zN7RoPgT<0Xs`QgaF%CDTY*Hw@$N~8quL@RlH`Bcz_nU5{@y^|DY()iQvp56j;;1vw zl5C#TFoWM7zEhxGcZWvd@p)ZI9Ilt~6p(|G2B{U8M=>2;%xJTMXm3B`A4s^e$kfo> z7!7$i&y?&iK`kX`T}7T;!Yb;lZtQjU?5InPE-Er#&!7Cra9kDPoCFGS1%xB1!J&T%}?S+W*-`;T6xG~B4C$pjuHp(jVv9Etb zDzmKW4}K>{D)WKQwff0M^y|jC^hR}Wr%BxQWPQZuWa1l3qD;rDlTldP351msM(UBW zgs*f+F2&mqK5)mz;YAG{qjkEM*k5-9W}hgZtP#L5 z1?W41=0dN@eF&V5Q%J4w#9Q?!RR0JjcQ?zd%d#+RpKiD&ciRIern9UnyB%g zVjnOTW};S^D45qxeZRDwK*xeyvQCTak?o5Bt$RG30@S+S94G~#kGOLLXwQQZd9}!b z3JW{T8gby6qZSIS)jc*k(W%8p8k{K3jY^FbKWp6>ZPj`S4*E7=JlQX`pzQ#Zx(nhP zGPRe3`8?eG+t{C=7<=H+*LS7VGH}3DXAUl#H^ES>cdRK&b{?U}>Bru=60$Y|Ioqhh zx55oj{T^Z%CwoKi(afFnOCa*szmaNS%7di&ep@w8ki&)*5u^&LK^!bTx?ohl!)@Xm z??QmX#0$zR;MEdRmUpfI4OXA>hF!o3=48ihdXqY6r@wbQH37}O7a8j6Zqb0@a-eW> zXKI}59bC!g0|k6jQj`ATK(KxjzRS1?DXuyT;cE9qGq0672sgMOY4+6L__k@R&$=ro z@$vbE018vPZmO4J&9#1RB*hQYO+X7Zx%)9|1aRtus)fXUf6WveFbqkWRnM|@qTp`SM zlq`U9c=e5x?Pgv-f}@{wc^#pAx>zGpg6 zNIv`8=|uoS7OC^!w0`cSKR!aR=cy^>bS{GZJ}>vGpGvxCxwO{3w?6Et;+0BCOWWRP z&y}d=^;9v&yl^%~dshk)fkD#InCu0$OieP)$UILrbj+MU&Bbe-w~j_qe|y4)WxFxK zXFv~(c&knD+1V=RC%H=U*EkvH64li7Lwx5_so0!!M^UrS_UJlW&4F=}yfRjecq%G5rl`eA6;ApTi$ZlS7Bg-&&t#B5Tg9%2e#L^fDE2h;n z&kaObURE&pM1?bw0jXqphcJP5wpC>~hWVjV5`Yf|O_$D9s8;Htx_Dtb+)+l6sh>CyB9Yrngnoc*MdO z5adzuu}FQ%qVoF1YcyASIW#Jniwxg^8Uq0QLU(5;tWn~k&jo5(aoetva)Cg)C?%}y zPh?W!O@7Czy?2~s8PwoTHQ(_7Qw%~0w}&Dj_j{OLep9pG=?ZKdDnfPDY*`X{Vv|YD z;{&BdYxr?!gsi;<*WIchudfNQyBvA8Tu0zICN1zy=j2r0Xf4xYU|QIYQTU{>u zbcd<6tJg^3Y{hN?^Oz%PVy0Yu=~MXo)ukF8Dea5Lko4{E>`=?hyf7V!7G~ss0%$rl zJ$X(@luih6)v~}DJ}R&*wHHXUvEvfH6TO_WHb~G|Tpj7tR7d=}WjMP2a$Eqd`kp!= z2F`#u=90mN5DTKlEAqV)Bt73-{=lIG-uhLnsPO%0FS$7R_*Y~n6!W3D_VedAlGjDh z8C?uVpt5^xwmUYMZ!RGEy`@ycq6L5OB-GZ{d`zNRY=(sB1&l32u|C$)YL@+lwi@wY z>dW5Zi@tZ+*BouxSmGT8VyY$x|8YV{&;<=Xb7T(~1GCt40=nL9dOrF*Xsv0h4yu@pbs15xlUwNM=+Ie==@=(NeDqniR0BcrOa6W5&xbq1n?l~6DoqRNsNVaf zwcZ?c>|gd`+$pN&YH-|olGbR>sCrIpK@gSl>iE2B-ToyM_RGA5y94>BN>FV`HtYJg z-R28pp)pmeBejJ1KdrOD+loQYhg-@oZFp>}njE%&Z2ob_IX?6DrKrf_*>Ccdn$@1q zi1`s#=aTi?KIwVnGbeHCH{ACLq#dy1#Sf)YD^CiGd7>62wg0kcQN00_%K?tS7zSj zQEuZmcgqOR?e_MzY}OhkGH+nk-P7o`t385JkiSxj_f3T^-8RSX7;9zU8*mGDPza(U zmB+Na2IiR6CJb(g|3LLqKTq%b5C26!(zs{BSAHq=e6e9(s&zs=WAdg3b=CTO3>CZ-M65Q_KG(M7#L0YKJJBK`#aQ+I7kS?JLby?!#}n= zysC|^?%X{FPZ+uncbYGhRgS7y*=_#kI9CZx`v;@L%CMvQNJ`IGN0QDVenO{X5*Xm_n+UrUBp|RW(|jz zo=Jp_2g!ey*9+`W*DYw+znA*5331T$f*CtRDQC9$-e1)^@XgEBrak$%o9Ke zhwp4VCPl`xlg~@HO^8}gLxU6gD}Pswy)2^<_f$-ZdG*R&q}RM5#&3|grBC^r(!0lG zl@OJ^)3N&4wC90qxKbo>)bBAe0%`XnLN4h3hSe9q*uCbu>3QSA`lnprVol(miAVFn z33Ds`H!J3*J69eC^E_4M*;8?7=IQcOX}B^kO# zAYi?PTt3ZqYGTDn<-OHE#yqH5m>#KQ(!m?>59k~;>T;@+a|C&Z_X5r$DhV~_NfnIe zWEN1u8c(mL^Um#Q{w$wK_1VgVg3RS%Iw8r57rEBaBis?aJJy&;m8WLz1Xthu*!`ie zc;!dt091EO9=+D3PTQ@(wqXDZ>GI(ihY|F}qpYZa_|$)BV%08%Y0qZ<#w6+PAf&|^ zH7qlj?f5ROPU-laHTU)!_?mPCmy=FnnX+ zi5TLDHQZmiJYxS=NwSr#YXN>+!zpUZ5_j#T<#x6ya!++xRLVX+PhH=JQ&P#IfZ7)r zM8#GJw*MLOW>F?+4^KekKQzb60$6^8lBu$;(K;z3XGBY&5MIH1OzW@a#r1EdR|aSH z)PUIYhpp)B4@(3Y71IpvCNO%t7^!#xTsegjg2C)G9JpSTYrj;Ne zL5oH=40|5##rJpUALw_lY1GG!E)xgXF#I9{PMv06O=?6apXluC>r%s%K27VV!H@2E z+XPm64^B7!kE8SOr@HJ7WtKvY&~1~IJu*7ZutoMxWfdYB z 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�s6v@n=$>~`>q%=S&;c|TbYfq$kt^6gLfi}lp8 z!q`=0Kwq{XXu zm>LY|H0v4gW9a&4=Q@2b{d-9<+xt`CoHTMWT&WTWt^q%0^Q@UnhS6SUj;_brege~dWT?v+G z%(;*x05(xU23azLb?FRPa&yS^&Gt+MM4y+=F4^z8{GceW;lkYWp`0QB9jM*3Ba{EwC%F1((w=6 z(lhkm2MZXt7YR_BRvMIE{DQU&iQ~S6rBXb?8W27^SV}4_k^M>XRjzeMUZ|5@myi zSaJPzx`vRx_|1hpJC4B`ydwL0eIm!}Rs~O)(WKv5lxr3rsJFS^?m)7_pfG$T1fX{& z7R@WBR1|IQ*TV#7SLYXUCsB%*2_>qcmHhK3*1yrMhVS9Y`o-dW;g{{&$p@r#nlR>K zw8o$867vOD*=7>d&lf;KI%^VF_nA?kl=1Yp9)H@7o@BR~;&0t5h zxW@Eg#kq*1-#Zk(MWOWUfitMJs9%z*)B6%0mXV1j1Z_0t?knne4W^E$m$`bi?+v6J zGoLD6e~JNw;)mbk1?;GpnV+8lM~?jBC9OqMS$-278`u5Jx+_Zikwiv8KWvt=!Ihs!t}w6yvyu!d*lOaMWw z)Y7To_sE@6MSh85{J6+2H5734Dim9YmYoSI`NUoGKFyrVySoC!=F)kB6&EEi=>r1o z%b?FWabcJ&F7Jp z5z$&o$j1#LLWke>{0I6wO|o7*NMqDPn!ZUb9*s{H?X^P#*I_I$#W zcrwDyG0V+wO014(*76(`Va!UemP6+YIEAbQF$B;<`_Ct|Aa%NbcO7g~UCp38ZvFjZ zwBir&Bs~d$wJM_e5VRWp5qzY?f|!fCck(*Rq4Vf#%xgs~7SS=Op08Y<1#n7}N!6eM zpLAV9TWNCeywjENV9C==>#x#-U#GzcBIO?mlTF;1_Gkc`JOdN1IxMl?$? zxZ~uoxFU3`%K3x&fkNoy?7fy0(Jay`bg?`+o;MSWipMxKW?3*#qsQxaoH%Jh?f<|F zS4zOU(-wlAbkx){Vhy5aeim}#wcTF}KddNP&|^;4Yq)Lq#)j^cY_iSq;m=E}*Z zP`Ntt!_z(ENoe*AkKSaf)Z#2y4CqvupxFkDiF7rjS`K9yE$^f^5gSPWw;~ZBQLnfX zi*qeNf8wVy%1PkEP4!A6dPZa?JCS?+#a7|L9iMcU(087&#`>>f9@8XhJboc777%x! zrsTgMGO!BXXY3NL3iiVQ__V;NlImUDKEA3YYq2NK(>^?7l(ufH%fyr;_LNRa{>60i zJBd|+r(N^Ig41o%Y8BGzKR9JT+zS=ADmgIGZRB<#ExFe2aVXYGEJkWS`@p7rKK9cD zWu{f7={K=+#N~AZ!lerWbiKI)70<9nUYyL1K_nv5diLAC{7eStPEAnWP?e}oPHE2R z1gx+yeuhI=!wI!-$>s`Xpj)xu+YAFQbXV$A0&gF*m_9$E+xEi-iT<+eo{r}VxX>-= z=U~*}nIk*p%VB5zf6KGBWiJwn79iY;2hmFY;=C`i?iF+%t0J_xpA!&NzUH50la~M< zDVLIJ-Q5|pJ7KJq$NbLXZ#CS_s>egRyu(!dWiO9b+ZBw$C<{23@`r0GyqM}mlWfD5 zS{#e8=rMKI;-dE?(jv0{eR)Z|_T*N<0w&wNr2)iC#+4u^vW!Od)w{xX+YxSz@hnn# zTHRKQg@83kVWVFpjf6KC1E34PywMnCYUf$FvmFeiK#+iHUC&z6xeK3ejZTUCN{sktYNNYr052F|GcGBUyMA`toQ^}BIP*0H(On+?k5F{v$S*H zMcxbp45?TVCIreKNo{N23)$XaG*efs#(U(5W|4Kgv zi4E7~iL&|jrNnv2j}|K9T#o5_u%-4ND1dM@x;x2|rGSZ&(MeV`MlRU;_bY%e;gT(Fiv5zyswfw_qBZ^_5(9p@X^TL=9Ot~q$=|2SKp>;do zpElb>3w@IO$%FoyI7led-rQDy-LXBvd7tddVk3K6o=h{W`8!lKfEys2Nm_lOK800M3fmN96_2IOTp@ z&{HYnqIkvMQzp5_8R@UJm<&#$fNtrsTAsw;HB;yz-rJ_jdSnUw!E%kB#A*PYp?rP*e0!ICNZuSVHtZP7M?<|auY8OeS{ zI1$1r4XcKHqE;ddn&H@9#Q(^Bun9w7X^of{jctYa6zl4L|Wb53Fw*CE{zAGXw1j3(#PZPYg5f1@Y(a!lf2lwB0E zVX0vPnE(OnQ7ZmW@3yVF_e~e>Qq;&jc&188q12|vYq!TTxg=EuzeCURm^ZrX3RB-m zNy$edN;3RT-XgBTyUn2R!fOa~31H7^ z{(nlWzsTre*0AbE*Zbp3g_vl3r!mjUH4b((lQf|dKA?A?ngPY+BxEr?Xef;gBikW}^*E4?Ey8E4kYZEUf6#UZo0CXmc2r#_@7tpjX>d+~$G3 zlnQY8=*9+3x{2mhYQN_|o^D2;crrX7%r015f^3O95E zTPL>lYDwsw(JBiO*zUcW=oD5b14uNz+=*l*!1ik0`rq8wKPPzOn{|1EY0Jsg=uzQT z+KIn5UmY`3Pqq{wl;3CswuE}{MB-1dhFMKXEh6THhE?Xj0&ex{gKm-_145kqow^rE zZvB2b-EAn=)T39lQsCW8;Og_}znN?1Q97&2V^`A$X?E0m1EIsOh>GXfC!N3Sss=kl z9vn6uhkWO&b)$8&1~q{(-6JY6dR3Djh*hmWB)Wr_g@}wzrQO-x_*L_$xy1c=l_;#q z<2g`>KN3~hQP#HB;S)yx(T*Nnal%~*IILKxdHy`S7B90x{qav=R~U@zva&n};sBfV zSkWs;;x%G}uOVL7u2Ls=DV2hs-OBXne6xFCy&>J?NnMRM1$xBw>Z6l9+x0EXp5};J zc#5+H+boHe^SwEhmJxhps-_L_(5tvkz?mBjd`@`IZO%Sm?Bh2(Uq4@!$o z3uB_+c~!B8(CiK~wf%kVlAdmZOjM(Y4m&JPNADVZ*IIY-hOtCr~ zgAnz9+v)c#Ha_@nmCzJC4FVa`h{Q>S?@1$+d2d*D5M z3*ZFkQVGcaG=4iWxjVc5m4}ac`;Y@AW4eHSI6S{uKej)q|9CMadVAB{A@j_nbic(k zwmKffe)zK~th9!uDA>@!#ZrrrfKHBiNPTIb7r6%@Co(3NUOuq*|4fxR<|;dkvsKi! zoo(#0miG&RWOR}h7v{_)C0n?0#36Fy7Dv_SCCXkWVe=qBLFJ_>ZawzE&^5z0mc4~Z z#~(FJJdVkaYyzLED!|Hw5>bY+jMoZ-7vA;{IJgn}u_nuRixnqe$HLS?EC?A{rR?q? zu}^&9a0}N^U@U!ocvGZGb~}ZUheCoiC)0{LLT^V8PawJ8pHdqg49dt!K?yObEtOV~ z-{Oj~Pds=mghf?|>Q#$|pIqede94?ukK$Pup*DPNgD+7ZR8a zh5%cLD^Z8_XN&O$_OikrT%^~r3jL0(^!xfx| z!!XGPk`zYo-JtGWvcSG6DSDamb3a`t!oFMgHmrTSfn(kVd`!C%J;ce& zPSrCo$96R+AjS>}Q_oMYZ1b();V+htM1}KG@l74Roebmjo!)iQv@p)v@eImeDFCfF z6^344_(@Jmp#@0#y%KzH#n(_77ppedMG7r*Z~xc^bZ>ludAh)44nutzCjiH zz3U2phW?a^(=kK7fF+Ft7hd7f;Wg_Liyr|;Q04V49j7!I5_d-v&K3Pu_SZm`ik$J8I#HdIV&~R>8BXFriTG3q-=qLi}S$2B8?t zJW>2%<&UvVL}OHwN7U`ZRypJ>Rbxj3ix z7G)))vVF76DVg$s_`;q4`5RuD1pf4N?CamPQ6|SLqA}t6?^F^9mc(tX`XLdJD`YF&nW^Z*pUK8Y z3SYB^1kCiT0+(mH^)ZLVN`4}69-a42PGeflsoP`Dq=dEngwu0i@{H8c7nK#(xH6Xb z5L@aqkgH8<2p-46=r4|XI_S&_>?R}NB2Wv5=1mcS@h$aQO~+LY||-|Ag7ptB6r$mi1h^$v6@k7H@X;u%Rmv$Vkj#Omx}YglKMpr-ds7nil8i;C$stGRHJKxU)T^+5a)WzK6JCNhV#3>9o2Hg7icJVQc zc@p$C)F6hbr9ckd{qR2!14Ef677jeTfd9sPx77$6JWK!4BqU3UG$PamQmjC%{vYdv zU&1wvHd&34bVrD)^D_HcBU&k6n2L(N2I@^9G;`JaIt&dgU0>u-n`Nb8(5#*~i*5%+ zfg*hnGx0=~!%|luH>ZY)H*FfjCoCYPJ~S~Nt+{EPzN$w^t$7Nqv9c1K9iZiRC&mDv zh-akY<-=-)S@&>uqy0hNTfv9$=2IycZPcfz#Qt|U1p!Z>WDa?ir;synj8NxEx_h26)KJv}zUB|=m~y5HXj^45wx@RiRbF_-UWlip zfiwAG0hydSr?wxRF?1V~clX-oSVnjMJlHZ1Va#Hs$Bs@|UHuBOR%0)+>5ETXX}R~b zle9j|#1uq~hn}hXD#a)+F;d=13uiT0iv(GbhKGswzG>H>S$Q!Ee8BK0CfDS$$3h<6 z-GJ2fqErj(O>?Xj6=%FY zpWH9&g$}>IP)J! z{-)$4f>*RnGba|_uaE2z-zfQtEb5_$oT^2~G+W%+N*7SI*XJSCz}bS*S@i`vB8fy| zW$dwTJ17cEozA`}_($;iZbt}mPhsWylXZT1-v_3xG2WLlie~Qw7PhqNq!w=gwEJM@ zCy570J8hXJr-Sa->VIHKlrkDTo&d+M>L+`zqV$FbzphVgQgFZGw`V=sB|L`{CizDO zA*6R88jcj2%vsbFD~xUarknGN2{UneuLO|PDZXZ0>{^|ptFMWdO>k9)zg`ZLkv2It zB>9Ey`fc&Wfr08VLgiFldK9kE(F~BORm;${f&x31eV;(TP^zA$x|b?m%iR2wGwq~k zeT-xu!=`L{adb7$JjvQij!etb+_6Z7B6Rxq9%9?Vls|>bJL}ne8P*uVZFBT$i!2&A zqXQR_Vf)iRbNYX*k$f{8|6Q>Qfw=lfXQenRhf%?~d8Unl(GGR+!I7vIrr0niqsvx0K=mn=qdpKj1-Z}r%`q@~nM7SyU62RDs7 zOdR3aZ2@ZcCIFWzr}k*ucp1R00iFT!AR}n(9TV1h0#MwSGv3fxo|{>$E%fzl!i}6ow%1 z@@E7rUQuxP8R(Vo*4B{JNfH>#6+i?^zN){@c0qW<J|=bU2#W+#k*A0X zcp$7r?wPZdW?%9`CydzNuU@aHrsTpLpZ+X4;XG;iP3cP5_V)+Kn?F~KlsX$PV34s&YaytKl57!cp|k3+nX7l9$$H$mfOpW zl)Vi+8^wynO{nUmmQ8n*F4$7BGxSvpwKb{K(DrbdDo%h=xwghrJ$4K-7HH^W*qS$CcFnay zL063dpOI4|sofoUb~v)F!HkN`rj_=f?uy4=n!0U!HIHLCR&B-=1O8*sYIF%W>(A+zt8AXsedMSu8u`@@S#E znsH7${q;=EXhw*01qr=q*Y7F!&z(YeRjSbWDsS@fD$&x9EXeQT(VdI5s9--)tgqDz zWQ-qIz)z~`Ued`F`sdzN?-pPWbKkJ?sfQN2nxD=(6`V}R;H`IT=DbMQHNBQK)$^yI>EE}u72IS2~ zH2P*#0H)nEotE2sJ8%m6!{QEOH$6?i#Ue5L@bXCTQfQSNCEX?!HG+86l0<2s;C*h* z4ZQIR`6%1t^}K$L4D;L?Mlx}v{o~M%NKa)1P;AehVtqPB zO-c!wme~;w0|SAqIw^@AI;8GeM&Bpw$gp%vOoW<^ z(^J0VNg7zGE*56*-FgyXHWam^S2h`r+Kp)sew1fuu9fw`TtY;`F-6|c_U*x#h86x6 za?fA-XULxc_*KGC>b;1)Pms+A2Nea?DN|iHZ4t-jOUo6H{@!|$)@pxesPv9eaV7KP z4GGKRckdLvf65FFa8`LZI%jmqO5u+^Lk8zxNdFr%Joaa5%BvUxGqV?ZrBf}$WpC{( z;ZO0I-f??&1m*#b1e$ARj ztb9`{!QHCuUQhA0l?n41)T?pkdy4$WrdH1j;#K#VTr^r8v5&QO9m%qnOTGh;FE>!%T1Llr z-!`^%#iZsHH2hpj{=s?nd2+U`>Qm#B9}7n}31#gX9d|-~a|j6E5K&(;q>F?rn6jJY zGUd^{xCPYxOUAMk~vm$%CM#-+; z3$1}K92}P&GE6*;vQ}^>_xm1SpWAzIn}i=4Mj4zwZ2ol5a@p^?J5J(uKI5Z2#(?%I z-N3psj2daZ+CSrzrpxb<-$LD9MPvdr1S<-7AqaiM_iMxGEGP=`ke4sJQ1Jx4#Qy8#=JI`?Hg|#ZizD?_B4Xi%)_RoT#-)SG zac=tqRU-oy=AZwJ`B)$3+P*O$WQ!3|>Egx(i*S@p7JjqUa||W?y^Z|*!^O{rPuKd7 zBdQidy+lOXI-ZNXt8a4HmOILvL{TRg`WzZCCFx)oT4@QcA3k@M++rJK+x7RGS&q*D8ktkPkK!LGz_*%`>`lO-giVq+9^Q#hWiuD-gdy@2o)H#%0Ej&<_ zVYW>!PiTHBF!fR{JB?JDmJ*Am2OSM_r46)22A0`bRXUoeJ$jh=5OfJQi%i0YXgt<6 z=>Ez6m)y}ReR%D&7MvT;YwvMi1y4wrHaDTC#L~faQ99NK0j!a0Y(mF!t2izh2&A}P)jmyi z3P+pbZ=LaWRyyvs#>odo!Xc`Dbn?+tsy`wwjF*ITAwXWOuZX_A+zDLQh3bZxs-IFl z?zJBy-O7%gBbU!5h&4_u)ckGM-(iYf5jSr?^2j8~Psr%C;XYBl^}?$$k#df(D8PH- zNgHG6=1;MF9Ucf;FRCnN+});barLECWEX!tN)oNaD(Ti>fZ5nJ^#aezZJk*zT^^Bz z=uzM4u3&(^R$D~ZX{c#)^M?|FGq#c{9g(mW;?!}}6_E8oZ8+)^3;K>1{%Dn7)+aYt z1L}~Gq}=;I?n>oBVkcSJzx-H!!w4Zz5NgkpNUs&^ z>F&RRt4j$g-f`7l5$)iQL6h8JDpK21{X@K)5rLiXKcLtg+l-8{XO0;^J zkNy3~;VZY2OAc#%z0fhhy%p}VVDhVq;+;b&--x9;guf+|`%Sdz?vHI9$5~0cIYW4U zs>fJ^=M4G6#oR(am%{(FU!*1>b?|@q^K?1DD<4)!WD3KRI8LEBz<#hftyb! z9&#C%d3Ry-ZzV&)v?RpBpq~?zAF#qtrE;~Tk2IJ@+%)XuFrCq7XINBz`zI0Gzrx1_ z*7CY&g16{cCv|hXn=t*?NctV6XFHi8Zt9kNT`M2j+LbxENYw-*zzjRj% zEur{8R^Zfkt;5F@kg>cSTT#j0k@K%csN;PNWVfMFFNwf`rCu+ToLI6LbV={l5%-g6 zT5P2mb>GaMFB#>z6koiC^NwnsOrB!;ODLtn*kvy^%8E+-sF&(rd<-d!Z0?7YmnTow zKHMlV)EJR1G0`Pw#}NbTobc*G@KW(!t*DtWZDv8agdW`3L$qCBK+3|&4Zielr8SD9 zgWE(CR<6}xd2bjblfHQaE+le$A1!6IJ*}~F75rrYG97p6jkAW0^pOngkA(Zw`f4t9 zL`Ii|Ne%Z6V|GZ4`(^>6Cout)%kO|Nk~jsOFKi;l*;&T}8yU~QM>p3%gPHLx4a(;3 zi(uOF&_8;dbRwZhEfakeWHrd}psM)8C{&DB{BNH?Q&e@}i2ejWI;I0_KGpOqSijgchR zYwb{ZughypY9*`ZKq=_dXwEakjf1m*q&=A=DVjO^;Rfd`9`51N1}=hA}$RExT|*D99llv4|KH+;Z_xGTPbtr*B5fFF|lF)9h>=67>)%>oQv@V zl;TJnV?p_BpkqcH+kDTS^tHI`^(P6C(OZ38o}<>!g#?)#4OIb)fUc5-(euL}IZk_@ z?d%N~%uPQQjQTW~ol*a$JRg{Npp`|DNi!);VkxViJ1Bz$sH0OTJ zQ@fBI4%2mzAYz43xWc_Vb+;7#@~t6LMev`N-s!yguLb1`YpjtBk#74xZdcH)-kEB? ziyrINWADEfSIH<*i#c5pQ7u~=YhDDjbZ`lIcUR@f%yC(?{zBP$mW(26vFd*9VwKqr zRLFP5)q0<>!o5&snW_+?Lm|cy@mV#a!*wk##AS%cPt1fKPKFqpx(Rn$$Ty&3nXI*_ z`7&p|o^sJ^MLi@%G4YLzekO~TE}#;Myo-N!wF1n+@q5D@ZPtt#_x$cKw3zh#G2ceh z2Ji}H^`K3SIrJw1Xgh7bnc(kB`z_l7e-{-=vdg!ZK@m~RkB*7Ff37~-Nd=eT78nlP zJYXepg>?D%`8KtHP*NU?3kU>f+(1V*b63_}cWr>)`foBA|82@U0+Ga#MO^E_lthSJ z3aUKQL2skTGWXMxkex0=fg&8KMJBQxIPhvqIHnoxLzzQIZMu1(WoEbk4fi0qVPj^ z)NF#~!?*F$I$?!dP{>!$-O~vj4qdrFT4zR|?oM17BQ@xIoRHyRc=b<5sl-fR`5Lf< z6&4d0*+}J{l8U!8zzy9rNS+=R=Y|Mtg3AR61DVs}Q;5wqR*jQdoQETno9Af7KezO& zbYan$T+vjgU3-mipiG}j0Q$GOZ$6nWZBtPNF}#HZ&Dg9nd+p`8f>Ok0o=T);3g^cj z#mAQ`%o1oNrh3_1FVbNCk#tHg*-tc?Bzs~XOLQCltB?;yvy`Z>4XA_>s|*?^Bi+GF ziRPb;s5nF!z-`XSAukR}Vf$0_uU<;Js=d>eZ9>Yjc*{!s2g0BpbN5EeUdrqAFAHlT zTSPkp_~IR@hY_H`W|~3F35;G5sM!Y@Kge0;bI$Bq_($30lmcBcvn`%*gkL!*RwhQ+yX=WOqw(2sgO;qAEJ|wL67C z&{LY2KT%6`8rJyF|CKGV)s;qez`Jqz2p;kuxl~BY%qmk|6|;#zs>8#Fs#CcosmA9aQOL3Y|}L-dh%k(?hWID*4JY`n6s zJk!e_^tsWv?aW+J^uEhlaE&fRkxq>x^8#PnE4J43b_E->YU-J+=fR(2!exe_J3sY> z;x64@vX8;bF`Ygle`wtN>nNP4QvxI=3#CtLu?m-5^#*8SeZU};32V8C+d_`BAn0_2 z*D4z zYYCFLBcoE!_Y;0;vNu1cHZxe0HB2{le~dPF1^HY*?NT7Nc+4LyyY{A21rVd?mGE`1Qr%TX&s_@V z{ikz25q3{>|Bs`y3~TCt*!bw~mS&@o^hbA$4J0KMl@w6vM!LZ<#t1=>9Blw1-5?vF zG>SA1B&552&i{G47rSE{^OYg315d04!OivcuE`V0sYUY9Y+v7;Ch zU&a%y{g*J##M(zZJAk}%d8_>Z*pYwYP$PO;kbLjQ20~M}`r|IUA;iGgZ%|2zw~4n) z_ZM=FX_B;?WTH-M@{ z0lIQ>j3T)5R*qT?70pZ17ZgJx9tiLy33xeb^@xT2hD~xty<>A8X5e_Nia{(|yci89 zlAj)CoP#{gcMfn?J+ZuR5g5N^UgurS9EH>*Lfug%eL9oorJ<%2>IGR4(4d3p%2kQ8 z{(yrCl1y75bywbWx?GfABC$AVD2b-CEgdFrG-`({t=SWNhA)>SZ|~grQIW;Gt65xT z?buIH_fssTY7jr7G^)+Rlzj(YQeiW|!Fn%*y~-sJn4)CQxw$ogwF^-jlE_w?j>9Df zPIAivKr-yJZ7>OqbEl~%j#3i-PdYkH;NNO@ptCqsr?1K8Tn~26ohMY=%%6eX=%J<) zw(c_|DoaLY)`@7eGWcLWa%U>~N2~*B`qWh2ANz5bZKEj95AB*|SnNO0(8Xr{A#-X{ zkl~N?Iu2&6+p~ElF_x~9dxOMG>!1^&d?|Fr3vy=m|MoX3(63oVh}p-{n#{cV=EyiqbIhaiD#gV&mLd_(Sc@zO#E8~ki|i!%!4Xli}p z!Bw}e5%E5mM68@HFDg?@vrhkuvk;%1U$#Oa5zJXeeMs1x`HbF%mt7Tqn^=5a5Ug{po|^ez zEe-l00V=kq;<rhRDAx15kn7Bx9GEUr_ZH|=S`XclM|`1tIe6FaRp-wLL0ul<`VnV z56UxIH)%(c#uI(fMmu{`dlw4ngZqLxeWnW89$Pxaevkh>JIiW^s*KS`iQ7*ZiX7X- zuOet8kFTVXNa(-L^*|#)y_jrrqBsjNikG0_tMwp_(+$-z1AcNZUBO~^0>?zEX1@7H zoJqs7A=vrCg8U&uZ2^OW4UAE2f6_-hVo#lSzLT7Xj+27lSZJuCVse+1wInQ z((SP*iyb;1Frc`u*~VnDxly6BEr_IAFTdYl=rYX$4be{rMkbk zqXyl@$pX5%N(8R65|CLcQxK~U8vc;7&gG1#xOq*4G^9LiB~OqQqI-&C!QWm&n$(#zj&xDl$9VX z%fv)TB`&W-O#RuDw@WoFz^y&rVu0ewe=TbFoEQ&e8|p&l-^=Y_3y%mULq4`@+mnyO z(pO7Z#ItT9Sn@&}`|$1;SI4ghxAJxGbchjUIodz|I$C&tmBil(Pp!n;rSpsNfS)XL zZp+J-CFaUeut^Ah&O>KR$z57+u&+63B0wmZZU;&XvT7b9Hw1u{TB+~h zx|y;WK!qrJ*Ak2(Cr(?sO>{1<-avoOX{yZ}a-Ov&CS_M2&^qIx4fPo!Wb*6blgd(= zql?jRs2Z)|QB6PWFrZ9oYBgToGk=U*#YJmK!U;y!Z*bU6o>2aAXlTg-5iU`@i9Z_K z%BR2Kx9qFxZ$H7vK;kG1E7zA=pjNff5Ns>!~lh*qDv4#y~*GC z2(q1t28d5D(Ew1B`?}cjt7-myiu7$ER)eU56qWw{6VtS?U#3mFL@C+v{=6&Fn>G}t zH+$vQO<;V%1o7lRNDUt???Xdh=pE|~?X+Y@*URgg!|w89 zt=e<3+}R zA37qGFT{*tD+zbsUViDhhvG0%9}W|IyTJH-B`oJDT$ZSf&3v1(zYrv{%yhbmLNb`E zu+G;}E;Dt?EZ6JV^Z|+D>Tx_EhqN%5dym!LS zJ5g`ImeI3Z2Uz=McO(+DXeXMJ!}r>EslRuD5%j7)ll*J!grOd>aZmX#=yA7eZaKdC zOJ0VpTBMre8XX}2rw>J0W{L&9wRkJJ{PLYDU_~A$Y{7Gqfr^2g(>65Uzl7D@T+_bM zop!mCuKFxUyLuesk$&modM0|`H9!3@)T#g_P2j5UWrMTCXlq#p-;7{U(!qRbY8v%= z%qtH~L1@uvqi8!3uLLpK77l#+w**1E+TPnQVb>RsuwF661}=;p%$o+xzo+R_0oD$3b3bQMSEhS z&H1T`Aw4_<=e*YuZzw+8`NpH*@P!9TpdD2r@FAo5V&PEPGhV#D{kr4Za5MJ@vB5$g z$~G!i4e;q^x|9}wF{ySLcmV9NGJZ`#zRG~e_eXEU(^G$Mxp|gGv&AN{g~U`56EqVb zDMr;~HgY@6i^W6ZpCW|DjLG7!i|oP}jaLe}2{sUSM9RF&IH@{J$w+7?+l2J?L&&-T za1imEuX^fJ$7KjySJs^+EXc zqLuvpBNXwLYK&@HEj^2%VFG>tyv2LG0bAiTkXgw2tovZnReJ=c!44uCN}EqR*#Mmw zn}|>R?bPNlWK6HW#QIhPi?tWR+sghQc$uIR$&ecfn`c_P-RI84qP#8ZMe?bbpeLWj zSOur*3x|kbSvsGEy!6=z4r87u<0x7doZ@^N+#b1_5i1Zm2Yk_)`N5vg9=Bz%3#)MW z#N?{R_~ZkNGni;C$~YOu>W0@_D7u8ekv@DO(d`1&2S!CBgmbAFKgp_jXSerPwgEC^ z$VMQBj%wPG=?4Sqxu7o<-OoE|p3LV9BcY+&uj>!)$fnfp=8mDhcH>;nIE;5`q58a@ zZ~XBkCi^Kmw+=!gKLf|i>f4^;9D0PeH4nx`(jMy3y*wN^l#*PnRf?6;KYEql+gY|9cP`(i*Aik%!`h_81{`AMP2_c&zGhN^$hfGOp#wd7?bD$4JcS3|y(}RF?NTF*2S<1dwn(|l|> z+VO>C$aiWby_3KB7N;aew$b-e$nADAxOPDZrye!QSAtl7x?gM3K)@<@ zhvAKgY#i=ZW*|8=8=uSrqMdBbsi1B$)ECBr%&`-A{F8B96I+>p4&i3J>_ss}9+ZaS>8Hn-4EbT)J|qAdnGy&zBG+lB-WyABsLFN!gzZBg*%=Dk#YCga}Ny-;rVD z3z13Y3=uIXr`rvbhR)%0;^yerBmj!F8<9uxqo-ZgPmv5cH6DD{>vcleFov!rD= zD&#b{GR!=br!^?#2~CPI5qsQCOlOOELMTQLCk8nMyhPOQtLv-Xt@`gr2f8AXp{XT{ zRkkHvr_|Hqy)kLXpfHAW>vfR$*W6^;cCodQiJ^Yy0(!Je16>Bff0fw&vXr=m|B)ZI z*~?$7E&=h%lHQjzBGjX@=Sed6RCSyysyTUv?&*mGMrWT4=b7gvx)%qQ4tAk^;%22P z6DPJ3X%c&Af>sT=*z`Cy80Q-ZCl%9fc4puopgh`gzIH|UM~QeaA1OVkg)wl>+r6@E z-(NJ=XW#78_m4T3b+P!|kh;gflunL!lT;0+29i8aP&~=Z4&s}2S$W{JA4JNGkEGIK zmw}iZzCx5!p}hL<=C-+-K6FHfcf#~04S@AfY5ykU7e1LvcKIdG##f(xcXRhNE^Ylr zIlR4S;cLkqIQTAK`7sp>^&N}(aSbK6M1s7%{M#FLw~eT_*7GUNufz@s-8MDl%MZHA zmy}c);hP>JL2)F$ha%6U>%Jw`2u)jD$zQLYFVp6vIWNy%vbjh`ii>@KWRMZ7kPa}) z3u>pY6Ej9AJ2JLDm1v`Hh%Sqlop0$=3Fg$KIs%-Exe&b;;Uxk7ei$ZO1_zg|DLkyl zhejXVt{xvJ`bv9xSMkA6+rIxmNlTE|`7p+J(iY(}PFx{?zHJnaejs$38T!&8>C$76<9_;j!sue#FM+Ax*Swg}7gy)JkxCcdh&CjnRanmS zDgw7n`y-8WRhSwN;<^q#8jt>3nXHxCnCZ}7E5$KrwMf<*K2h3}paZrfY`5@>o1g4Fs>DNZ<$s*RV^$>( zw&V=lKDqPEe*1`3fQ9M^;aU&}%+#kq4B})P#|0XF<9^F7VQAXzFODXs1)DAT1`r9R zTQQoSAQ_~l@dms67Pm8GXPcK88px)Y;bx7T`g#y$kY^GJPXFrY=(J}e3B&($nuDug z4QaGS>B*4&`1+vrKVA&e2*oBn=EW6boFIaZgiR2W%92*q75{i0tr5vh`KVVy{XFHR zE@&5qNu%uve)^4!oyRX7sG)l^(zZQe6AsPpqmS2wh}@!$7rpiOM(>BtT6F?&Rgm*c ziK31?Ie)!cU;aPPCa}%@mR!A7!bw(G(vHt83k$^I40!yGPB%fQfRgp#F;BGS1g=f? zfghtu%M?MkCoSlI#q&Qu2dbi7G;#0cSpi0E;dJyF5%1semwzT`|D>C(8N|wl>bz(r z*tJPstx|Q)Cn{Vj@kKE$@YJ=q4fifCOeC>%>i|*d)Cj*Gb!8;F)4E2Ia-jOE#7efx zzQsiaoCMs_^IeRp(JpSB1?m{Yr6?jKE$#DbuCr|u))zmZ`Wwjs;Lz8`5SS`$5>I`7 z>DtAI6A^-e%PF2nJq#FH#(eF@92!`eQs~L7mDr@U>QOZ+u-|}pZPK{u-7qRG zK$z`DT`rTUJ>$ySu_3*fw*M$unr;cl1N`fCRI#qIR%Od^0ikCik>LHI%G-%F_F;xY z__~H?zKlHHT~Wl)D?w={p%;>CPdD_5m%@+49*wEq3eNoeu7;5msYi84f0VIafJCu9r1!38XxOnMw`h%_U`Nq(QXK7# zggP?)Hx;5cXjZRB;72H`3&ThjeG9xq$0*QL#4x8900!o(3+TPhg45Ttb8n?Qp)f4f z!R`6Ri)q$fM%z^@DA8>4t}okj9PmTzb&gS**V^pnhn@*^n0Mwe?nu8B^}Bf>*&Uab z?@ML^Q;15*q(NS#u!IjbG<8hQgJ`b8fJ@xNgFlodCg1PgX-1k7=6s9w!vRGY$;c_6 zNsqO=3*&G#olvl^FH2fw%KN?4aU302^zIeWuRGb8b4k*|)Hvz^^6@W7F2FJYppJBqNj z%m?=mi@cFnypHuK`Ix{c@}oj@XsGsM$6i6(g$j-H+hTjJLL&zgN|TshN0Z(O+ojVv zaHf2myxhkrg7ZV^E>E<|ihS&5Zf4!d9rK>?ps3W{9y=$#eHq*at~Tlp)KJBd>oYOY zv=V3t$@#oS3gU+k4AnFb;??^%eM4t4e?QYU*D0YmUFKe}owNg@)Eh|SoNP1bU5~n~ zkLI(!s{EGGP_Ke>@&ZFVquGwp%--1#Kxq)0ID3v{unv zYWke<_$t$nFiL$i^EJ+UEyPa$O`ef3i!&S(7Uom}Dw5<*hb+H$ur#2@N_v|mip*U3 z#n2U`v=s|-5?4%{+ahPaxy6dz(NJBF@jIFT$Gyb|W0)G+jAiVGXmd8VcYK#$|W=J~BA*k@{jmaTndIH?7i> zZd}WGTbSVaJu%#P)!i*Zt^FquFH{I$$kwxHgZ#wI#X}jZ6ir6EehP0MSwk1-^axS( zF3@_T_0XB-r51VUJSSc?u+wwDZhL)FILdmEE3)GL@6;l5vX!C6C13rz6ll~pm})Xp z51A4f-_f||3hknq`noI_HnjD(2fJ~j0U2Zg++y39Y=5`H_)UHIx{uVD1d z+f)-M-r>Rko8?L2P^T%!>9KyW&h*70>!@^*KHehmZ^`QpxRJf92Y(2%LbVqw-V}4}Lwn1?sKl6-=WUCvVnT z4=uXujJ(1~pfHeoos{)gPxuN|9egG)H2rn{pi`dzF-Kq{`uGu|IGObsm?|}I!Rz7L zyzl%R=L34_`~CHC3{6U5YvpNsUyvXTqO*;#HpA~~rawxZ?zxN0>He)twr{^G)8<4f z;x=D4tgP~9n3c&&I7Fol5s?uUaH{aKoR6%Tn1EVlHO_-$i>97Yeg1 zyk>yzsz*bPM$2wH(`SRC&z^T%1(q{}n>hHxNN%r>8&mY!{*)b~$=@KE!EYdy-v2-W zdIyF11^M#hZ05)JKgP)aLWl-<_j#+|sw)Ag%|`|v-EmKj?PB&C;2i?4rdq+_sZwffH}Kx9spjL<{Ud5mI^r~B5k2a8=Az&89^I+OmT~?3 zuyJcQR7`49{Gy43-%);mIKQ?pr&V5Q%dVZLjtKQ6l+#b~i6&69co4!|s>FA!#YQ;% zrAfeZ5n&@nK}Xy)$Lp!J^;E2tPmYkmce-7(mHo8DX%g&@#_2bjhY{S`9cx9MXl|-8 z+HA3!_l08ChMSb@kBS`Zszhg!Q&`JkK)Gkcj-z4 zM`_aq8YeRB$EM1zp`RW$yf^FLiD`K=ZO$h4%Ypf$A`Rjtk20CQeq8SZyVBn+@?(k9 zJ$ivbea$^LoDYx@fB%878`J_joWA7H58rR}vh`>y@e>t+GfEuPZ7qs7M;T)|TFgn# zC=afmPz%93dKolei1Wwaw9~0%N^^x|+(O+_SyEq{eJPEZVP605wx`V@bQ(-lunV|wB) zdA&9^J4}o_##GaMXEgSZjLYAnZ3T)qg8dFFI{PiXt)s|!s4BaTj0nw%C)t1P9@EC^ zVm||m1!-oipy*Ix1^N69#uoz1?dJ5=U&+Y`kN{r#AILtGe~7TdB7~QGD}K_41p3GB zDoCN{U~=}k?hxh``I&02d5)^o7D?9}x1y%@e`GEA?m#iiAP{X2PU%7k4=e~J7mHf( zw>*t^)iv*<^tSla!|NUC8C9i;!MyynYju2R%l{y`40RASa|6yVoGX$qW6sao>>J=% zfX%jPspq`$WEbZZ9`Kb`j*9)?UX;P$W_y2&(PENOk8kNbj4uS60Kn~dqSaCwkR`zb zJi?THuEZ2z%comTH_h`Jb35V>L+MLjC7Pn(d`}3pnpMOHwB`T|Ow$rR_UK?Lx=hch z9(t_{3$(ERko|12UbJV1EH*8TH=>L{cimiYHLL752e+Dl+P9(|_3&z7m|Kie;O|EA zGs_1eM3dk#vo@dm7tiKmWbg$^B%B%kUrkz^h-*@NZ2y5YPybh;+7Er#!4edpnZ6o6 zo`h|Co*aD2&td;z70`N&70uAE-M+;WB^^es>~NHruBSYVAO*sMGwl!J9w{q;S(J6~OV7i+!G)V--&R_TJ+G zzC{Sa)sJX3`gSQ`LHsxBbn-o{v)ER_zP^{CR#m+AFhVA6R~`So;&&BOlKsY2o4B3lb!FM~>mOZm4X zY!D30sn(bN_hP`()FBYk{Wx7smUi0cW6?Ub<^{fNadL^d!(7{02~|_M#KGSvyM8z~ zpbttb$ZORpq4)P=Faj6NCQH?f0e^D4wgSU6#S_8@A$R9`HDdML7ybMzENmmjMo`VPi1KT_(li4>oE^Q+2D}n%f->-Rz){!cmzc$;-x1*z$@dN`) zmf_$n?sh%Miz5UItH$^^9g)IkF|rpz{h-GMP#S=P)TCcvk|qDwdSSs7ALu*Vvx#2Jupjkj=zS zR_xdKs;>=$l)I2 zJ_PfWNcUt3ozTLG#e0iV>-;YBmJhIMVkDAgb#=3c5^dwiX-O7Ml8y_S!KX9ftAyE zC44I=>_fItI95#tr~#PJ^6d^rIiNxQG9?T;1D-LhV&?@NP4a4^^m{iO7^J>fq94a+ z4z>-FKz&V!DwB*UnG|X239B~gdxY+8wm>9Oz7H-O4PtMT{9(*~$^0Q4;je2IjfNQI zUDiN6-XS2Kkj-=?LkI);X*GKkZU3hhNQQWa!d3k@W0Rdpj5SJ>;Xn6>=8UWmXxdDhvqWV7LYliUY6fsg zOQrN`7o=G4)_EcYGohpBC?;R@d+nDaie%kbqqfY(OF{pJ1E~sevAPWKK3Ybs=lqWr zo|kMC*jh=-;|$GgsbXb6gRHSH!hM@X^8V~>eI>7 z$`L}j{brM9-iV9>cNH4~6Vj#gv84BAKV%{EZOa*8u@TkXr%lMBqxLT^24#_qDX(N( zSL<`9Vvqui-lZf_qr70EVkI#v$FcQlOB1&RIXGVcHkptFER41dyPa9DTuMLOe=kcZ zubr;OpEj8y9Z#nc9_8Kn(?T8aAG|}${&>n;cDx=it^PQk9=*wykw~#xH30mHcInbN z_d^~@TYz#F`T+#q*@Dn6sk#ctWxV6*wt2B$k9QsB!YD9jH!7fZ z7e+a0Fd|Al#0Bb0$4>^wzsuq_FG6NppuCt&un5_fMl&F&a8$>F)LpdB>ZY(f z?=ROuYW3b0<3HHBy}glt{B!UY=Pe|&o*1iXePXiIA52%XmL$S&A;3;Q?!{&W6i>`;$3L51P znXBFk?-@P%2kNPNigH$t*U9HlMH`Y@yHF3jMzz3!9$?a7}02c{^)cUK;ZKo}5L@cvH-9TY=m% zZMExKlf}qO4;D@?sRfrUq_q2|m)Z*rQObeK5~bI2{=c_U;Y)2Nr}54Pt(@N*ci^_v ziVt6O{Ly{*FekyR>A_Br>T<@}RzX+p+SWGxnQDZgb8p{DzPp|1N)azk((T4G(Asd* z=*7I}1ZR!;Xk65_(EEXXgydcd}22OMgTNA1Ki2GC@*s zMY8XTi3nw}?+cZM&_DLsO8$YU`U^-oK(&l?Q9%d z0i51t&4bD33z`A6S=G-&LpIPqpBxYSmVGEZ9D+0Myp?PAQc2bf{fyblnfxyY$-J-e zq$YmKhxT5HXR5-fwYqxgePnc)kDO{ruB;#16~-0IL_(-40clXtCM@ z0i)(jNDRz{-&lFe+bNN~GdR_=?MBr1ml-wUhkEC;gR7XfmTRHg!X4$9pA{-MAH?_! zci+|ZIFE&fy97f@=m(~(ALTu$o4u_v+a$4*aOOG;UHS4|Z!gCY@6Dz6b0hL;muF={ zh-6rPXX}||V@~PE&;LMojC_o&?+lU_wP>mNWH8(fFKO(rHRO7_epd*0M!o8Kqo4{~ zm{k=bW8J3FD6+ltqN(lWJEhx-D^cF5pU?kBBt*P-x-1&M_hsyK3E*gNNjBDm$*GZa zhCF-t3X}1b{9xDq7mpH;iTR4MnjwrczL_90GOWt*?I1OqPW|*hkPTqsGY9SdayL?$ z4cFWW+x4JPGkRf5Y$=EJY@V#dVBTn~T-G|1BBjiOupT$;A+|j6zgP3=9Y{1 zv%h~d%q4yZg#InSng+U_`vz&~&pV`4ABFC8V9lRDM5jC}xUeOwHXFU0GfGCrF~}2I zR@yO}-FO{iMAJ8OCX_u;%!mE8=A+kDR?~DIyfkSV&U`8syqqnkSI)Qu5z@9@MgAwG zC5)E!`|;$y=WDARp1A$;!J+f)FN@JHV;D*~q&QMFB%DcQ>85~$i=vt_i#o%jS%Jr| zS-nZwh}=fT#hvy}H@D93cbpKxK1oiDCs@w$P*-k~30&IG^|I=j8rOx5UUZ2H*F zpK&r%%zwFSoD2C?Dkv!lFd|B!>K{m+9D83+;6<|NE=Q2M;39h?eXqQD^bH_}rXK*U zks8HN@$rJe-=xmz#@2qIGA1;(a4L8}oqW_(@nQW$KBK>gn0*b3UcRi3Q-M6|bM}iLEl6~4Bk%hvW#u*lLf+3k z{2RyHj3vJLJjt4=)mJb5y`iDrAy?}-^STNzVZFCXo9M2~(;@3znkyY8Cy-z33S?1u zy)JKK^0;u`}=KR3nf&}%HU??H8X4;f&j zH9?se_4$dWBxZar5CtV(gHq9`uO^_h^uk+}s8UHS^9+3=2sccxCvaV z0g+KRxWK^giw$fsUvSN3kjHqekSwDBx71ySscL|9A&ogVx{2xMb>9Nk0u!?9{tB~7gFy5(qa^Yo{vS0`Hn#z-X9*7V~} zjHa$Gl1Thh+U4;yeE3tG+DK}n5{ICjMh(C9b-mgUcMI=Q*^{dA1f!4Sq$b|OiA25( z@2=)>WP6C?seEWydEiC^d3jiGjC{Yj^USgH zZ9dx81PvFBU0359+G0}bF7qUI0my*Q`5Bwt@}0aYn{U712K<1R!6)3nBmvbUxbZ)p z&ne^QK!nvHjfq^d9~5?R-!1=tCZt~TLr&wdMtE?qhqHvjrJFH()<2M4fm|%s@cE;p zCzs2$FJ(->vz~XK;$CO@a4e^Rc#*-I9>38G3t@sz8?d&h^pVw5g4$OU*eGAQ+Z*{s zTx{E?yh(UjznM^vLnM~xaz zp>`^tbdqxYgdX@w|Jo4=s}WVL)lgF(=4N6tTun#Beco}WS9IW5<((`<#x;%8i$o^n zu$eqt?&P+db36|qTQ6ISd%YPdmY`FQLKCoyt?mlrXjbWifyXgC46kLgMMbk7xo3!B z9R>199sYp^fjo#&*IV&%Wl76lDSi$4QHH@Nk)zWQWyguaP^KY6Q3>{9XGjhEfOW8A zm#R+zic5ebES3L+@)hTES?*W~bsxksHGYH?klUj2Sq|&y+9r-q!KJOkU6cUjt&iB% z{r2LDCrg-wn=8Faj2vMUE8KQ%8s6>G+qC4Be=LY8X;47RCyMfx@{!pmeQutgSMBze zR;^qoD=(q+)^|CiCZQg`#H>$Yw`c}IBHdT3k)Q5oooXZWw@SGY(FU1(&SdH~QVmfN z7ivlk?;rl>!q>HBy0!8Mv}Qe9ti8V+v8Zg3#B6-(0^)A3bP=W!<*jk&ic!TQ^Z(bw z-2TzwuEQGetWWyaicRY|dFjs4=zTJZ*DcGR=kKW9#cwq9XOB*=pnHgC5 zDu}g3QOS{cO&3O4UjqA9}+j*wA&MzL+f_9Jc--VE`boK>bvYC&Z0 z#oKm_#%^<_;YKtj%kM%a9>pjeJXZkq4ANIYNHYS1UU4peI^iw6`Xmw8-s9F~C4xa+ zWp!xVz>3m**de@WoN0y*{CxXAA1bz}?%Cbz_Z)Z#JBS%t0y*928-0=AU7-pQR{ssa z!sjMw_O--&0Jeoi!4C6L)v2zHJi9nOTWH0FHScwpzmb>!+{FsLSeBteRhvkz^9X(L z2px!SYh8`Ok?>OFv(@8FGE1900$*L_63{Zc)Cg@sgvaWv&3BMNt`kf@-d$xha*my5C@{ z6b1#hM;QojkfO$^eK*bj!X`}gE?y>zsKG5~ZQaPV`L@K};Pumu(@MKlU2}=|zmkI_ z@eITXCv?I-5Sm0h+E?yqLICx+^o|vk*ys4P*(gRsutCV|2b>b|>a|}%o=17BZhPmZ zKmZ&>m0bFSk_e%2d>C1ij@9Lu7hZtf6|Tm7)U_p<85kC_MkuXknag@>ajaJmrh7K1 z#__=gc7nU@L4K&V(pmj2;*gs}gHI)Qrw}21yC}JPZp^Zs6YK=p{MZ@%I*>3sHGb;Y ztLws;X^Z;G6&(`^r9qrq_a}M7lYI7oL+1>jjCCD-1QeP90B%C9p#~&#HpaD zoeuzAd9GwmC-a@Al9qeyM4Y0*y3lv9zep2ZDP)u1JBe=7VU68)~56P%T zC)q$Ke{T{dHZ*l56N-Sr;r$_p4&Xrz@j|sbsUaLr8O@z%)E|=*hrB;t;5iO8)fnK6 z5J>Ai`l(jlp%I~>__*P3{iIkcT7q<2=tGT$=lFCiq!38%{*R8PFwJ(M z??!fl;#^AYKKDyQhavMa|E`NQTV3~|%TQOObfQrjKZCGH6r^k+?7n-gf$eEOi_JP^ z+vlhyL6aqX*^ngt&E}R8_1`-f0}ZHQQ{7Juua@&o;XgZ}F>u~#2gV)qf@qG6peTb+ zb6oxdQJCL@hT~N4i@K`#2^`bh?CjTosnJ3~zxARoitd=&uMG)arYM%DR54FR0t&8g@c5GH` zO?+m8=KS#-B^3V6KA1mxU!4Mc6~N(5XOTh-j@#^5wzPKyvhZ{?4-)q!#;qPE2+mRb_$^VTo+KNLEtM0fMv z9bKwyn#j>{AQ7>}r0U);<5nORUi=4IyL(u%j4#N?iH*xkYKNyVTX&o0cvSC=3}}=+ z<-#vBO$RAv1$-cCT3T8vMKEOQQ5Sin=jup1c6)n6wJsb+xq>-{A_-0}DZa1+V77(Z1A015k^$xpd;r$j zQtH?J%*f^_Lu{W9RRkd^JS*smYF^eCx_#J_HaY;q(h={9l+rFchNENgH*{*2+1`us zZaRo{kh_U}6M19ORDJ!|7HPu6c8NMbYzm{N_$vl~ohEKpi=s!TYB{p_aNwdo>vtR# z{@f=Uh*%6|5+?6|@gvzX?^*_&rOA%q6pwWa?4R&WsMpPm-(VT zc<+nRy`yojkM!9O56NTN(7M8Y+0uO|5I$SUVH6b1trSG@w!5>s)V9P_9<$pm!vlNJ zO?~T!-6_c6)h|d^R^gH=Dt9|eW`)ysR|HZgsXAnag|`=EEQK?^kVl%Y!g?gEr4ZCr zDomcVD|oUi>HzLT3O7#J;+( z*8;juW8c`Jf$S#dtHQAU?Wpe!-=rTQgZaE8LZ!o*rHGpE2OOwMZ}VnbWKyrdLpXfN z&DQx4C#uF5S+<-#l(KFn&7d(=16tg;Uq{*(vH|w|lUE~UhJ$SWaUwcZE<7l6HJhU^ zNN8Z%E>IpcTBm;y0AAI<0=>wO4QugrWZtC`W6vN8+z9?92K_w1I_R%AQ`B=@k8?Bwic+2 z&C2ArkjT*Ym=(AV4zeHVS?a&h$r!`Mims$(83>Xk8KPi!6{#ptH;$Yv4%Bzv>F2XG zh|J{Zx$e6oJ#=Z7wGfM_Pb*yFrt7zM5$=5`^g^~Mb#gK&TS*(R`T3ST9d0y$hJeSA z+E^Q78UbT=TykKx(;K5X)tK15)z$N>@K$h!dnapa1?6*rT)3mmTIS(}aN#gmm0^m} zuzAj+uKQ7sab%3u+?Lobip8fNF|!Pqe=X~kVZF-YgamNaV}r4QZ=KowsJ^(-%D<>p zA(^x8jbHo?l5ys)F>$bQ*myf!ogRf(uT;^AUN4}4gkRQg!ni~@Sq}5;E=3gie-!A=)c#RcLO$tk;T_b;VjD!bI2~X|fY+F-JmcAdMk#~4 zsN=Fk|3VD-9lyb#dfkDlJo&b3TLOm+J}^x~ICgI=F|Qs& z%}ppKW{HyHA`{F7#>`k0$sD?Qn_xKe!>Bb8ShRC*-E}Rwu<#Vw9OC@J@-b_^eEN42 zrXi|AvmZKHps18cb94w8U)CJm8`!}3rdo%U@M|VDfA{T>8b2CE68 zNG(Y)zwXoytZ5Cd2D9Uf*TlGgeiWGfOGwilXFeE3xNjWBwCX>9rv0Lx;5hMb_uyPN zCs&%dG!Nb0(Zr?D$}8~_iQ~;SKat~wgYAs#U*~wF`i&x4wXf!d8PoK4cAN3TIX2Er zCrbHDkkje<*+#5Xrr@f-(czmD{PEEpUJC`4Sq^gQm7{%M`Q@9-+y=tbfuYCDKK%my zwstDUW_h!7L4>)7ez7-LQ$@5{18ve!QmLiIY~CH&z8R&AJ}>ZPBG=96{hypr8@BYZ z+zusf(q2MoE?mLe72B>bpNS*#Wg+_5L0zm~y?*kbTMjBgPo};5Di?LzhgDO`Kr+%# z9M8>zWrnJ2MP*~#?0LHNhZSNcjx1utm&>LCXM#SiYQ9&qeiGR)Jikg;I1|9M7UXg- z_*KtjPV&X>u}Zy3v`F zw;o>~uT;e}HYArFW9EeZfrc#wZ{AA>HX&6DK47^?%&j?Bq<1}a28J14Rz_~AQvtaF z_0ZZH=22@X6{%RMR38siHR&uY`t1KGIt#xh+cpf393>q?VuOti38fh|#zv=ziZsY8 z4N}sLjEzx>AURr55D8HvlolMJq<{kn>2AM${0IB7d(Zt`*Lfbt`jG7J96P&j6+dI+ z*q`frnqE=vL>6zH0Eg8Y1^%n|4tkJTgStKR7M*>6F<9%pU2^XTIUOMZ-JG?69m>bK z70rB_OT`Ch#O|oc_A!{ro75ZRx;=xc$4kf;#28FQL`Tn5(lN-CPs=Ss<>eVV-zIVE ztZjk)6v@fp#Bcl|5FB;45{m%|ma*mK=c>?)?>v2^&eaU^b>|dP}5&(u2B7q?LzDaZyX zDFsXn8g5~>2HG9blr(d0(PzrD=K|P;7#E8>ZSG-SpYI{V?K7yp3I9N5-pR8P*Au9h zkeocK9&}tN(rPx%*~@CI<#Z1^m@8-~cD${0dk<>0^k!JYpGe`JDH|3 z!D5?ZmQNPL_k?5GpW{jCf#AOi&?ZV$_Y!{rP5{E%k`U)>9A%Bsl*2?mr!hO#I{B>0 z=dJC@T3w$_`>R?I>K_m?=TsO*Omnk-r$Yh}2 zjL*6v1lhy?FT8Mn@Uo!JJxWK&$X6s;)Ypo7|LXZ#m-EM`h#RbyP#YwBDx;T>f>QWH zT7R-WgJ53F+D7};yS+@Ibtv{KP&5iS>rrWfvXW&~FQk-AnJ^vQ-eQ8?&nP>lI=={t zbBmAB8#)~Q*=RNA#$ClW#>Oq()5jvt*Zyb@o>T4it%=rI zbVx8WK-lVRi2>_$fFzavg^1{%6i!LsVcTuk=j7-vviM)ae>oI$IVPQ`1_0 ziNb!hTb_>G5a#DUp(-p8qif}Jt={58epjd}(O!HmPP)7Z(!LwmwZG49E3axLs3qOB zY~!D~gaa^#lTk<@-lpV9-jHzpG3wed3Z5;bX}B|`pE*getgkl59K#p#mpQ?|H)GZV zELO3K{ch#MC~iYdxrKz;SE^1kBh9EOcGO&B8^aZHG7^~4(Y6oSUbXdh2+DWzGaZOP z%=b`fKiux*xVU<;L#MT5@_k_|Gb`r@VwLn=R#HYqBUZe}5*>7-t^725z+=^afZuWm zGkSoho^%6iy>7mUqI4!Rg+$5)zEJUam-u3p(=js)snIWdRx>=%R|_M!c*P&!`2rgw zID5Cpi2R)Au}VCdC>I)(Y?5Nr!_W79NPN3{aK#Z5^k6lA*5<>XJ*(sDDd==EIeOge zEUq}}lHOOMyEfsGbyt-<=NGEwGHY{dM{i8D*~o}qW96@LDq%KmISYfDr+p$IJT}1^;;M`O4BuV*2T0zuq0lW@5L)2h zEf6ehHGAl;`x=sS$s=BaKyX_k$9oT!Fg_y~GWF`kU-Fdn_%!D6uS{V>wh+X+vET1z^W{ zs@{u9lstk;5jU_22}?We((9D4!qUw1>+VvGt;Z#d9Z(X1=1}iZw<2=2U6={+>QyA7 z>-9MMKEf%D96T*Jh-ZC9eW$ux@vI*Go~6&eN(IKz3kS|rEBT}J z@D>B?$jJJxp?sSMmdhf zp$lFA=-Esd8tSA=Z{{B4c4;l`*liXA1T_&?bN}jjzEI^-ZZ5y>bFd7uu>om=hZj%_ zK~0ku&xnMAiSVa&@A4RGs<2AxsdKqBNR6v`p8~~kQ3e05{nL2W15ChgEuRiWNhhpQ z^F{=?*=%_feDi>@AEw9tu7IsY9Re{VJJDqf`o+$0rq{z^_H$Ibusjj5eVZ5w-T?x_ zDSib9SCe@eckleo?HZLI@;H-Fn&(^HMKrq$IF%7>vXcmWC&`T+Eo|s8!O+QHGzhEH ziMfa$oiso+GnU4#SKF`G7RXWo?wm#abS76$s63CEOQ?YntTk7!X5!mYNEEaiP?oIA z4KuA-3kk7rLZ78TNBT&U?An~;mgYYYkN>EELbCy--Vp+qttbN z_$DL)Uhx}AjMKJSPnGMEi&&zh1)3VrA5#pR3<#u9uraR*>2|B%*?u8U#+GgM3Ig>I zA|D2hkPHCOQyHQ=YF~&|e31%09DJSxN0OcC0lKgptA3#eR!|=sTKygi)A@_j{{7y< zmkegA7n5@dh5NjDRGjy#kBa4RfHp&+}k3)~)t2waPufHmVVm zt)w-85ieb-%HGpB%}F<>g_w4u!cdZ?Tn$emJ{f0hVpYoH05wG#7l$Mr-v$BrHA zQqo)2(OK563BL<3R?G383Eg4AUGA;ou@#n)2xEmNE;?q`0?9^l`22i@AfdWagBsxE z3XOM!%)*!y3zZs*RL@DJ8%g-|_x6+QLv2V3UP~nM3a<6-JC53a{fQAx<|Yk0Wp z?4)0P_IW8pjOZ&5)-WEJgotjSPUb#(^qr2J2ffK&O_ol4$>GFM(?>|O(b#f3Cy_=F z32*EKIwiGa#eW7$45BihWIu`CUJ7cVZ`B?Q*U>Bn08;JDmbW@DMp`s>!h3#08 zd#is^rp}?g#h=QGksFCq3pa7&?j9AJkl$q7lHucE-ATLtMleiM%^)s~(#%voPr!)B z!9qu{g#YGK%?{E5?lRe!C%+zMDf*=oP!#?Fe{8$tA$E{;+-vg9Qc8E4s*O7~a=7eC z6A?es5>*$$6de)NkJok6x6YKSZbkO$8>=iAO?aJ~by$o}=ae(75}oDR($LvfViny5 z$Twnz8oS>&m*HC~h%GdpM^dy`{!Po5sUue~*$AL%2~=Ulc%m6HZ#rqK=P-A!$CE;4 zFL5a9x)yz2*X|8?0yZX@KBoH0BjfaPi z4i%EUC#N+Qf`0Y+W{W;I;e!W%45Z1iihqx^L4nD`y8lWG3VG6CPi&6h)`|iv@HB1^ z2KSDo8Fx-kJ1UmA=npHOR}f-~S)xsh>9a4Aq~8mNh>Omxr(Rogn!GkE`4!9vae3PW zoFoAW`K3&4tdg;f+L0&H=vgDltAzrv0IS)p~IskkCDTm!!D`ONc*f zxWr!~a;e(B=1oidshin>f2P@4(AN?}!FF~i&#ac5<2G{$aCa?3?jzGe(D)N!7CIS8 zG{oIKMKS@^ok4=`oj`#aSw-`eGrbbW(+7QvYfEmv{RU3#a`1O=8ri#Jc>Uye49<&* z*2w`o16(e&>~)c5#<|_7SAbu{Hw-+uqJvdERsD~aGAkqXh?+50Vvbj-cbD&TmPvMh zQt9Ng=i{{1Xv9-;b0iU8I_OrvbsHWA*V-QQsx!}{xEcEag}wn{s^WqghyNFt?Gq|B z7Q@cGWhkB_OPZl|Msj>)9zqpg?z_8Hj{1RX(lRb zT=*ejW-D(X>uvLUzursok10)d-BUh=J}!{64O={?c8u~3g)NH_@MtKIpfBeCHeSHa zSyM>1C!ctGFq|)TCRe90Y6%n61eyPK1La;QDtrBwySseV!!%|i1WTij1{nLI{jRC~ z{$0aS?#D2s(ZC4Dmt|u|<#nvi2;(J$gafU0FeqGk)7lw#=GgO$;@{RJ!UEd=_=}x> zc9bXEu7v_OMLk6hvrz**Ht<@NgC79eW$)sJdVWd(?BKDtwqS^GTE`+Ukt@4RK63KF z_5!+w5r@m^TwT)fS1U7DYbdlS8j2+TcGmq8n?MM4&W~B?6(mF8r;UF)NX`38TghC{ z{8gL2fguPafFB0$_>)Mb{0yi=bfKlvJH)FYLkXtHTb+Z~W+~!Hpq1^h*e>TVJ7<&SIQ_qh^M|^$ml7*b2Hh8sXAkEkJ9Php-bnQC1qIodb@LmcNT-K zJc>$aW++LRnL=ZUML<*J(UKSHt^m#~`!Y1hZe&gS_3rNFS%9VmM ztoLqDmcJbun25*^{~aRI^3r^1?Ckp>x!2C&z&@$>nmyntso{ER@C9>4FkY=s<-{m#?k1kB ztqNMAXIt#3mmdUv$+s>|>7kbd_Vsm;`&uvB$O_bUPhngbvmIyer!oK=uSxCo%8dCx zWQ^(tbJ|8Po1ME=eQB4skGcG%mnm}ufHriEdg1uNq8&*n<{B^hosiDWu!}k^LVU+c ziQ%a(yLW0TzLXJM;khJ~?{`%|qSA^0Z;y@283gfox>Pz^InCy!A5|QHOQ@)lX3ns1 zHJbsC>-37I_ii+9xiOUIi(Bthm8;HbVAUkc1^?<3TG(X!Mpg3i^k_lASvU+9;hh*7A0Xv{jA#^5bwTPCHo6 z35=NY2TPEsT`3KE_0d2`8)Wi}0VAM< zTa}R&<7Yb2^JB*}+`4eoARF>BHT26pgwNlkoHUooK@7PvoE^G$RCT=Hb@Ls+iPG}p zZa_=UGarRt^JfJIUxH0q4#fp)m8*Jm2{b{G8*Zxb->zCzn`1xen;~tna{Zz6PU>;V z(zZkO_>2y$+JDCP6A0nPHVCh}I^Cw#CXd_|KJaoXkYFH*#J^|%ugT4t@K#AAe?mP? zRrOk9>?JPt|1U9H`H_&XvTJstbn7tZF4jd*jSs3DJQ0hz5X^xvw^ytBRkQbG8b|8x z4iw&5@lVH}00QF+aOa;wv{%A!ys#V!$(3tybA^1wQZ3W_Vw5p~xP!IsP?XyDfG+rh zTfz9@p1I}Z;VAjo%QNqfl{A0>yI=_p%5uYob7iVTo9z7-7ZrXNGPYtf0tc=(Tkor? zY4E-@NuG|3#U0ei@l;aKAELP?@#c0!n_wv<`O&Ae-P@<}h77~3B>>)Vu@xW$s;8A^ zQ@SPAs*Y5gdZC9bpG}C6<)!=@>Hu20#Ft}dcd8cNQ5^e3MDJ!Co0=RTlAKTT%sT<1 z@X);Z^!nK0=!13b7esvrS|M3-UfU_8gRL;YFl^;`jZ8$A&i9<8YIC2hZI&f$b~s&~ z?5SyseOQb@)V}SSWMYHdnWc9DpL9fNIj+zE`^ki?3uT^~3hOFWWaKto2 z>L-1IwVh^Ifuc!^#*;fw?g5ji$mY9aRL;L2+Y^X^ZYJ=fcLJ~467s-R&0Uy(fS+$3 zrGz|i-m0!bugUTR;mcImn%ImY{P%#jJ(27g)-BGb4%*?ELe{J;I-ppgX_x@=VUQ(t zIXxfYspwI)g9X|)$6z%=Fe=KFMO(knItEX?QJ#aPI$vV>fR^7ll#jvikp)=b!*wy7 zK2+cv=kmHz-ez_re8Y z_6iKG60A;W@&h@iQP&2Vt4DgqV24tBXqk2 z+G?O{Fc&8V@Zo0?%yje&JIO<&ll@k1vevBEH41#r1q*IkMjkxn(8k;ef8CnKFUOeG zd7s|{SaxkuX@^1PdBzuo-1``XtBMiP`&StnECQ(SWUb_v(gG=|n<=|27PezPNoO zni*<)M*J6ChH(Ak$k5hYq11z16#Pz4?PmZiZ~9guTgN6?n{-J1Ut;zbZ4jTb-yfZ$ zVF2|))Fp^PVO>Ha>q|YW+w8%X%Ws=5o+UZPeoK|v@c*}#cPJ72=bUe9xGGY$K^=i4 zud+lk^>%H%*fQp$C5oS0o$fGTs3Ow{hQHgY|VcG&!=VTM+VZ z`}cT1MacfcYtqy5w(pDK!Jlr(MR zAl>gns~7u zJHcGy3{8K$fOqN_@c$o{s3JrlmX>Z3lAO6_=!s_@hpHB_^dpQ|3N4=(asFbfpJrh; z*7@!~?U;IV@ARruoQmPerza-uaq)|cXpyP1$LL6aIvC&+IjI{#D$Vb?WtWWD3yH>-k$J^YwA0X^r*Z#lJ*Dh3H5?Y^>u0Sv_5h2 z+9=NhL#7B1@?JOI#YAO9kSd`Kl;?(}wG@`ZrLHM#>x%p}w1bIJs$kyrcceeW1|RWq ziy?vQVSscC?6;A%zWxF)ajm29l%{m4YmsTX;Xj1p&~G!J)^qlsZ-GuuSM$L)mrOH) zA6y9~QO8>Sr}XES@_8%BWzP(&mgTsS{7sXnTjNHD3Go&4gt@vtp>XX94+Kfj8`5PM z)8W5FO$?USKO7K@tjrpTk1x!33o>c{zVzDi6+byK@c^Nk%`!?bSjjqjcXcUr-9=c% zW*ha)=MTH^H}Ja4`>@AWM<9w=vJS%$g^pw=$Bi?G{pu4hI)(Z{a2whHAhvY6V(y`+ zwPb86+IG4U#zBd-{yYQLgnUVBaR{$}m9ISbwrZOH3Jvk_v*^6Uk&VGlN+crf-41O< z<>i#&&aHz_uX`4N{cB2U#t%G0{}ZXa__(;F?Q-Y$Z8yuv1+5~WswVe$^X>9|6W8mK2llG20ToE^7dL=9S~!09SlZL6PEs?=jOS(v&6SA()9( zFfQ-1gPdhutd>vUcf4o+BJ0)ikfEWVg2HpRWw)-YV)&fop>Df@D$N}29jDX7kcQ<1 z*U;XA(0_mlRt_qC39dWRZ$1YZ+TH7ae3dJL1QxK73rOBo-KPZWq}x)GJ?M`1O7y`rDEc5oDED~VqkodsiVQYii*HoC zDxbKGwsyZ6?9NcT<;;R36Q(Kj5~m>zsC)jw0GFum$$T?#dh+T>&4Yp{>R_#?i2RaN zs5#8or8(;owzgljH1A5xc|}WCIw>1HK2Q+v&vY>Fk@uT zJQNbX|k@y zltvmH5a#$Xj0-&pti+=6)6?GbgU18xsrV)#PjiFCAGUno6;2Lz_i@l|BE^792RgM| z%FFUjc!lw^?6U$&BoI6=a6R#QH>C)yXPBX^P5?&r4^YTL1#Z@aWPK3kR%kEH(5pQ& zRHipY^+#N$s9cfPZKXz=K~SQnO+a47_R)^MH^3hs{UXZzHFv8qDa!-X;k+0s3 z+9x=OJW5p+tE5m`0$abrdk1_;K6cV2%W?xZNtJaR5TyUQq(@l4#3f_nUcgmA)QTod zYGw8=(iMNs@F&`AYJSj4ZCEp10ib3_T9XsBVR26Wh+mb zRdz1-X*rY!!+9A4GsdzukQ{sSu0>eFvOB^4Ra(b!S@a*lsNPajRtBo;hU|9t zZ&uZz=Q7)O)<1(86miFEPsGZPB5(d0;Gm;>EUHl#OxK}$9Dys${H7anK1`Gy1O0 zgpJ`6^2i7a?05X^#iGd)l%YqD@N$^Qymq20S7PbERwJmO&3_`GW^Ym5ZVp>YrMCdN z9#!~_F#7KV7Zt>h1ue3l8IbGAO&_Dmxa^C))HQmn!>9^4NFztC!{T&x{WqjOR?&1E zjeyiA5C#h|rqL&JT0AJ$v^*gbB9u$87&@JR&X&i;p_WJ_LV@L(W0y9*YalUWcT}U5-M^{IHz>!(a3<$sp)_g%O-0YxYL^(-VX5IzlLdDic#&@ z9TR&na9d~DJeM(!`FnTK#1Z*~@BnL0(%Y*jU;|2DA8?{nMFNk8{YOnuGJn08O5|86 z?`%4s^ap`m_UKpFL*{; zCTrlbNCK+Jap!a76uXjotAY?-!BhdRy%!Ob8Ngrp(36V$PG2Wtx*WGQojedv61yaS zWctGg5CvX0bFEH5%WSgri3q+0>bJylw1(q{XMAd6-A|_xl5Mv-2D>}Dmd94$Bcxl|ArT%W9=d``3jSU+TsBT$BENclp5LHF zCQ7;Z>*WGd%h=Q7C50mih zu;Q5SL;Yp=2eFjbSw@u4yfb>QI1(3Rx4&;MHRBtjqiR36C;Ly>yRuAKXX~TR&};xz|k%1z-8P~&VL%}-WfULc5<$ATPgC?!V>Pm{{Sm7 zWajASe*k`3+Zx6ARSb5xZ6s$jGe<(NHwCrTU zT&>YdNy~o-L#qbVwbQ{V1eA_h3*HwK4z(NlK;p~_JigSS3vbAqW}ozzR_dj0VVWvk zN%_82uLUn!rVGvtU-uTR!B%P^4wCQE{qT(#ftT`pDoz;{w?ta?GnC_^ov_#ziz4g1 zw3jo3%(~C3vsw8-!rC3pR0Skp8RrXP%~z6}q_OK_0*RQ;Q1pm$O6J_BS2w&uJlCt$ zqLq0$l6Y;=uz=8k0nm}Ik%rZThzf@;UB)$I-t0-!uWF_BpF7`@>E!nSxL(akp{N~A z@~znEgUN;E8#Of}IXQftT}w|4&d9l8feaG85QQ?wmV#RvT^~#$AfldEj6Voip6$jf z#)Q#4N6DN%sqXY|xruEN!;r}3uyDRb`L&1d%xxwtW^+=11)S>|hU|iwSYQ`Px{sD|`OC(onf5?2g29+O5(_|x` ze?KHM5FFJc`rPHAD3axQ3vNn7E|!mQCi^Vpna#t?8>NSj2kkY%7b@A0D@dGunfg}L z_2G{gdMbEhlCk{bzJn)^LOFB2I@%rw0f*A^z}h0QK?*82I*k>)pr`{K>3sKfQfa z`~>WNICnL2^D)Djd;7hJ`c`@y0aw8n9|Nj~=Lie&q?#*%^ai(EIBxwSVqo~VX%LbR z>QC8g(-B>PJ^Xo8!Mt$q$BMb-sezHyJuhF_ac$3e`~GA2 zTVg-r=S}~yD{kUby|P}ceFrJ~^svOKdMm`G>PcJGRzN|Rv5h)U`eVugq;bSxXheA*N0jS z>Q}AaP8WSu7F6Z%Rc)4&o-bXF;LWx7t$OySe%;#7 z5{J6^;%Tiv^M)2Pbs6#ckH^(Ub4t@w(^qSx?D(Zqm#DhlYFr%lxv0B85+pvpvbpBs zyR%AIYf=B(S$;ZpC7NqbKhwTlmtR(MZ|d!<&1=)Qv7)c4szje8++r68xgk<*{V$#B zmmaS(&4~(3uupV5^)a0jxR9~;X5L<|ZqdHnxP`O+F)iVv7C!f=H1gK#AW-P~>(*G8 z!a|Z;IwF1yuM?^H4k_~RPTAgY@ZD+J?>_QQuC_Zyhm>wcUP;`&*YbGO!uCZ? zq>O;TlNx=)`ay#={T72xcvh?G)u-0opE|!$zoT-6(ux5N@4584i7Lw~ZU<%2(Kct& zXD=F7?e(U8es|B_wJt(gdY;Xc_n^6S5_73;f)iwhjTYntb^fw+{WdTX)UX%OzU1=0 zO%mC?f`mFe+b%Z37QVZ*UlTvCwF~f>pY;t1Q+IO+sj7J*;#zBwX2a}yQAtO*_WBH^ z%D>z88zqY4?@jOL8JTYw8#{Wg@sqq;hI}@Ow#m(k-T()0vRQUY=h%P#oZ{qu(S)e* zgo-0+=h_#K|FU$mgBtEchHAa&`|(Rp`5$1HWu5!(6*o`KlV)O4ViN0`Oex9!zv}z@ zCby)2#am@Y$XfBPH$}d@Yj7l%=q_3WW7pIwUG;ZA{-bXr^3rrD;V~&VN@v~t1-W=7 z#V%Gg^dDcKui4HxKhMC)(o&F)0_!|y{#|5%b@F2hS`G@d)=aPI!vs>z{+DDI!vrCJ zQ7US(Q{cwz~} zn&$YkKCN+}MRqVwY}$0*x_b6YX0>7jW&Ef&4Gtf}}0I8S!ptawak&b}u~5xj?G{ zu2$};{8@#Mc{YKfh554zSd-q9;It@>bX1X4s-D3=pEAo0It9CsO$K}xTL(H}XgBr@ z%JW`AGBsNdC%LggxSs#`O=jhUjRMf5A?jW~MjlL{A%~9FxGjtx?`0D(tVv!dBgN&U zZB>6}Hr#wT1L-j}Cg7Um)Up+_nKSMhAO3n_49#=!DiG((Q;5X0p6nN5 zkYx%n_-}XW2keXpKIJG7ysU)pr9fCe3EXUXD^~*PwyZE{A)FV|W>u!@IToiYL96f? z;L&S)y@RqGI=pmmJm#FgDIj}9SYU>5Y4S0$<0uoZH7WD)Zc6_*h{h0ydj~9avUW># zju+xj4r=cIKL~KuS6Qgc^h(E>0wWLas+^q?R1UK!Oi?Dvha$qydz;6dT4?8TjhO*d zOOa#@O3G8cb|Uit%-38pk7I8#vxFEnJ-Ca*T`t9t5`L(^vAn+x=$o==_EGKF$EjXj zYKqG03^^$^W-7O+4xFX&wJryr?(dUI0ag8U72RZ{4K#+*`op$6L#3#`O-JA9+Eta$ z2;K7yOGYYF+`m4)QLn_v6Bc=7Kjx{0B2( zMvocMUlHZ>p01%K?uZ-gC3u!Lb&a^Gu0ou*U-D3+h^Wrc67SXZ2Us}HB z=>Y|5XTpL8^B-MV(R{IeAwA1@U;)5?JXj-%tx(1u!Ma+$n>lK<1fjM zh4dlBl&bcH?}yuA)>uS-^gXSE9I8$zucit%8FA&?X;Y365Q@ zRLpci{yG4)ZDNMPzSJ%ko#`c>bdV~ha}sWR0aQA-+V}E3cZ}_-p&)IJPFij0*$Xb70Ezb%zHX<6LBHUs^Ens+Ci3> zll{vx27?GFVjx5#(;RT5@C+4f6?KY2TvAhosydA~KIQCvMO=f-Hc85U1E4LwF~vLPx4>(D0#CKKq_+jDIZATYz0e z;uibnv@6Ocn-(JP-4@VZG3rhc2{LzpWgns+5DA zy)Z;~KvjpsDcKU_4C-NUBJUyRRb2NJ)RhGEpA996RUFgzBJREeM4r!b8&jN3nA#Gh zM$+49;g?*Z@7HgZDwz-E@0Hs6@d4*Rep*q=QJ2E1ru5n@!fz)TKeu!+2TMUNemEMy zFnIFqK9`8{d8#Gf$5nFQP0z&tuab z*6L2t-?X@DosZ4xDnp+cT{}hEYJ`y)*){>?EF1CbfLA3AuOSBj>R3U4m}gtA*Z%0W zKcjP9?C&HpAtePXe5g5)sbxgOJ7#iWX{}Eus6FhLc>^m~{ThwqkT#iL)_2;A$3~eM zUk6gae}_qEyOGpCp^{dBDyj~C2@$eUEZTQdREn<`fG|c<6nqYa}q>e+L=c=M>&)$#cBF1Y~h%Mr6iKz@kZ{vf{_c3cF< zu=Ko{g`GdtYEN-wdo1SpM`nv_vd4U-IZ*sj1Iu?TQm>R*`(#+nI_ARw!w^VCaq)q| zR7SX)!HFZ#Vg1~Hq;Ku-6z!I0B!mt2NUFD8hs~R8WhD4O-er%p38H$9s!=Zxym{B{ z%X4)HdVO47sW%hU3P_zm!Dt`MEh&PQeK!5fm|yz4vA|S=8YP;CSsF!RnG`DmG9N4E z<~aDI8jVd|5ALLpE9h>4xxfw*e7yimvVO{m{thM$SK$k#DH zRESyiw`{e=Tg33PIaHFK((e_;66R#Y_%3RZ(P8}~JC9DDu=dBAcV0-q>1^0;0gC{H z%?EK-g>v48Wr`cq9MQci*f?KVI;3ge;{Nh5U+y_4ELUxtKaE+H$&jt%K zrE;uXhU=Hm`9J8iy6!94mNT9-H=+t@(;5y?(=S&E6<}q*{lGY-CV;8fT`7!Zxt67V z$IJ{B|MW~%6RWLIb@j~F&5q@LlU7$EKMu1Lv?SJM*nP9pnsPZ45pD9cda@P5(MzUs z_pQTI!r##9Orsr4xQ>tk-Y*Y&N{^B-}0%8k4y9ZLyEqb&*p z<08n>N&UA@P%}O5_#2ssCf&k?M`*eE6>N;*=X05+;=SP?R0nq!TO2O(I zw&RvAICtlfWnb0qCn>?vZ`ZPfqCB+$m|DPzPzbda0cp^`^97rqW|V!;SKaQD3R~9q z^q(p~)efqae*opeXGGmVfMrZ?`aSYfD=1jdov*b)r3Iphm2D+_qb{9 z&>pj0?)T1=G+O7pvhM4|ZUu+{e3-yA!OcDMac0J7%lD3(0NpNm8- zM-*I+=xkIJtBHskw(kjCm;XpP6JIM((zhQIHm$~hf?gU!->f^@rKCpcHn>c?`VX`8 zVv}0+yH4Y4Kph?+_9v&A$~{It{D25=vGO@qq_e22f(*#w0_1~XiZ&rGkuf*;jD&-N^EC!f}dRwo8Lq7{fcTvz5muL*F% zmmXi^qjk-nj=oWNZ^aJ|=+%j^#J~PCwyEapkL5j`yhqoMaqHV->3~+jAT-`Fcf-@= zTBJ*kUao-{YT#OD_`Rs`s+Djl2sIn4bEy(_$%4F(Hkc&E?|P%_|D;eB{&KXge9xG$ zoHhWD$6n5t;Z#rdzvoC9+N=v#a4K=-#q?-D1I_f}F{FY+Hd8lheOsQCvuC({ zl}QHwUXV2ooGwoN_u&+?#3X3M7svGO0+*u8ojHy}{c8iuJkm8-!x(P4+AW3=aurrn z4SmaqWBYz?pL^dQg>E|kBmVetOsxefZza)hfl96`cjgE@I-qsi4D#41DaSx*JiL7d z7BA}>9Gp=ErL&#kquC{o1P|Ic7eCoZ)DNDT)VhXP#B^CC-ImsV_^hjpSs^NLyjP;c z)<;P4o(`hEsOKlM0lo-u`0{3XPuI_0r)#AzCpZEmX+%Y2IO?TZTs*V< z&LeR)8;7^WAsQ-@$_3v2T^UKbQ;v3@E5V?ZN@nA``8Br{#YHGH)}1Hq(9i>y5L}U_ zad+2i2zNY0MOFQ?j9nV-Z0jE9|DSmKW5;?^00sRdJQ6mIEdqpfN?hJKKV3Z|h~Id} z*H?R^K`zALuaAPC9O2CYes|1*-a%a6h_T0FV(9Cvz|6}E)gv^=4gQEM5<#cU$nOoA zTroD{Al0~|lw&#b>=z#kFSP%(S9Ohc|DjQ4m`InQa+|ayrh~@&6*JPmertw4ygk~{tv#rUBL2x z7)QjTzc3$)+0O-`bd*r@QbzpH)p7&4*$;H zeAs68U7y*wj^hbc9<4yvMnB#~IIBBv;uc<7EQ~;Ec)r^T2T*UrBecb+N`nWdVZE!8kjbI=*o!u<=3}8~5}%Yc_J3 zZ`%690#)NVb3m76wE5+kGus@r{DlMv)D%fRnHn-AXXU;TO@JqT+6x25g%dYvXe43j znGhD(lBp520{KIWaFZ^iGPa%gApy%k3kh*XUsX2@DHW(`g2$v7!*OL9YLn^e^&KJ6_-2F`_+S;jmIHRpzoy76V8STYSXB0nU46Efm^ zVdx-M0c;d5MJ3c=wix6gb9)LAf@R#VSy|&GvBpm^GgC=&ZeqN*9oG2$$3l!&aR#&B zcyn^f94xHHm|P#9+INH3&JSQANU2g@hTVmB+65b0n@)JZXQ%JSrrBfFIKiP}7ttk1 zBX*V+c2zV_Dh?>T1ugR!wt}!Na1>xec(kGms|Q!>ZvI5ngpac6ZHk0&-{-I8=!rUA z7e&Zkk^d6bu8GbjTbeZ)*VD*V7LDI|tSng%ufA^j8fU&t8(gtHv4gt3OU&iu>qOPM zBhC8nOQ>tZ7dgP|bH^tgmmhLPGs4XK77Xa08q6hV>j`|#iyiV(wO`vO)y7B?j?hbP zxwKgaNj8VPfI&4SGq|Z~=!pP`(-UcuKvrL$JvA2?;16uM85`N95wS9|IUWO%;EuGa zx26YJw)IQeT{H`7xRln=v03&--ZJhfMwPm>g;cnDvHGv5sDSx{Hu;N1!fwV;CZ>u> zo+r!KtC!6j_wj0S+#BFKKwla_()$>)8h6`n3>p<>k;({4naMVSFO+3I7})SlbS^X< zt(-F*Sid+y_)>h5TMkjkmJC(76d$>S1+HLIsBV|l2R(hhw4&b)mg!l1PnDfVFZlfGi}VIUmCB&Bh?kjm7I9T(|i-4+mixBOekD!pqS8 zH`Q$uneLJV>3k%>zN%^$2lihPAcw~f^mzsV4c@Z%3n*=xnS+}rBe0pa0~FJi1-bV4 zC;rWnS0xLjj)56wJq8Gl!c;|XH~njCsUq^{$RRR2O>1VBo*a6_o3ZaUHWqM4#EnWx zbd`#qXo-PNS7UYcgC0aVS%@PkXy;BTvcb~iN!>m+9GSsxTe9p(JQEdRN=PB}1eB>i zzq}yF5@^2cq^bM)=Zf5+>pIW%x_Z5`O{z4RV{4rPNn4im{>kBW?!71u1nq6=L-&X2dnIwz%db{UR#Q| zlt~R|B>IkTD*dIj0gQumw01dWdFo<*VxY&13k>Ir(KhAe*o!Cx8kAtBl(WE53el`Z;dC*ypu0P^`c~;)O(hh>~FuuQa#I z_g!9&F&PqAqHmqjSOG^c9cUkEFWr0f#L@t1K5op+|<*qz+6e_lcnW2QifOFB3^%6`l_acUfre8CSwy%Px_CAimcte8_pS@LJG1o z?&n~QO!i-J)a_sfEM$iDnjIL6-$3I_vmKFD>m6lFjgCIG(;S^7PF@y^vrJ z3=Fa5nc_Z+g8yb~84l~%31?S9@#*}RV^XYinRpa4w1;BJ%?jZa3?rk?%NYrEteM4c zGoXgda+y*&iU2JIW#6|aWPsT(t6N8`Ox4$`XRRLLj8$lnhoK=(FiQ_ApCrhA8=w&F??mM2Pyl#tAezw5C%>neiT(d!hYSBUD9&g;f*xSQ>5?sL#0>Zy1V*eVg2VTBl8u- zmJK{z<_(#d&xZCrq>2q z;1u^U2Qy}f=Cnojx?&aQFX3*AynhUCB;JW#MuEtf0hy1YEQb%yYDDq|hg`K^7c5%0 zOi}>jbV;$JGDgu7da6RXx+qCHXQf2cZmw5gW*GTyY*@`2?e^Og0 z4_svpkkTrKbzWD-u<|~0>ZC4c^_yG@#2g@m=A1yHw7h->?>w1Efqk#{qR78F=PihL z(ylQI+v)3yP1;E75;$MQ%tLyDOGZj*K>dJKl1_j0F&U%Gtv`e&&@6}Hsu=wRR7=~z))qEgfGPX=eXrb@j}V`*Ob7W zDu$_8wr8*p{{S=P)>f0{|KsQ^+@f0BEOOJ5A{eFJ{7uN-Q@8^Ejz1I32M^r(P8Q)Y?%86;Ut51Cu zw#(|&gBaqBx&9I)nrC%!ec9$yq2t+(lS6!ZFhKI_7m|A9aZIR(Ov=YbwgPS$ZXzJx zRjwjzfq-Q9efu9M3;c4jR>shQ`#rF#Bg0NW5| zoG-4oq0UGo!EitV;FsP{qWl9@_OD7QDtgy%>DZvPc3 zGF87Ow<=RXi~W=Sp=pQ#cv13sPASf)yZA>PG~4QG>4WzgN6;eE<9f7H}gg?xXx zpH*MhVw`kV;G&LPzaEbEe*e$8$~MC^sZN2g|3P1K4eKjvU+#H9L{=EjHzro!RAgny z;s`JON9WRg5`8Ooe>*|-7qZs)zSN1i^~T3U`bZ$2txe9J7iP zf;ErqBD`ma*yAt+#?9iL5!uX}^yT2qz}@)4jqts~`vS!ROAK+M41CSYhoPW#4tqis z<*0n;UOjDIdQ-=(OR(2`~b1EAkc6{B-%L4ay#G(@N;>NCoo(FC0Gb`%VGAsgm{` zMS3x}qwHGTU@xe8;Ob8Jkb8%T~$Z53G<74SGHo-&6LA(4li@*Jv(!?Un$7gd85tZ_W+V$47?ptG zE_dz998-KS$N_T^AfVi^mWE()oVU?*!G%yy!{Vp229d zT3@3*hD>+tB5Wt;wVhD9#PYG>{AyeKFF`)Z*qh|RKeOz@SsZuv5x#c$nihnrV~q6? z|A8U`V>YBDz%OLU&spBTVU`twa2$AEjo+1U_ZwmSbmYCAt(f!G@IR?3y?y{Dutc%} zU=k=>Vk>v7oM5~c#1FDL}JM3I8jfDa*B7Er=wnZbpd z{tf@I*O7WqkUJ`0sR`VDFhb5K@NgP?b#l%?{cheFpX&NRvj54<18!%#f{Ml!#F9Gf ztizudjA%GQ$r~hZ+W!Oj-~)x3k#97Xb4@ zyX()f()I2bCsRCzYn#Bf*#)6XrDe^|f7<1A3ppxIinECQ9c7~%rwo@&vyQGEycK1? zntGHo%djZAMcqvyO>DjKT8Am{osI99L+)8qv^Ee_9!UrRud`5>2jSQcA7&aOj|8&VM{bcT)~m zOdAo^C}+bInk!evk6QScyh6?(R*~nbLV&`hhq`XM#cr2yN`H&#{ct~j7^Y)x-!jGm zBMLZpBRb9jba!8J@=Q-l_$ieCFg+NjcJyGD%c>P2nXs?kTi%HN{VlI-V zMHlu>`zf6*HSLq_+irSULr%@my;{1xp8lGQhIn@d+(rrxd9f3ti1azvxS!RuC#r$J zC!MY{5oUkj3LH%JCB%WwR$F{`I|o~cs7>U`Aq%^&g9C;rex3S^-9zGa#mwZ7T7V&% znT&*4MBt0foi2_;fZlg<+q)3eyl9IjOI>6lO$-+2t)Z^=O623?xH4*=K! z-8{gIwz^{t4KcpOHQQJje4wE_ul$Sfri%9^B>bsAp%kSq3srF6ceatKSYSC#`r)Bq z*}3(tgw4ZIBLkDC1016>cL6GaE@*QAx-o%_zbvV$O+gObbLfpg=v$2qKOC%v6m`mU+7*QW0e`(3UD zw`)N^bK)_~=lUBK_bl#W)G`g#6lxxfK{otK)~a5G=en%M5kQYZndQT@3DwNhShL1@ z-IUiZcE>1UD^$)`>EnXrJp)m1AM@Phv&$-9`#!qdHD_-4@Ni*$RPV0eUNAy~JLCkn z$>CO25yW8d@I)l(Y}jk0)N;n+nYYk&iVIQv$blmRADF#8w?! zG`zvMU0TfJ&{4}o@~*eI#HUPkjE--dM~XFpgRnt5yE+HBa3v`NF(=W44wBt7m%u=# zIR8p0s-Wuy3+@2|DEXT8m#gmAFl94OrV=X*DPMd4&I)9{eDoja-NkNa1t-IVY!b{| z-{%qcB=NlrgK}?wvXb_μ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

3$S&&wY93 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

jZ1@TT(&OEkwAp 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≶E?Wl_6a(}Uwe=JYu&oiZZ=(u?ahUqWe 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%0AqEaU(E`nWXh;q(#U0$ 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ℜ0re2QHLQmOMyj_=@n-~?hH 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

9kIF^VoWKtCHe_QtmYzZ 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�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ⅆc2pUAhpGy+g__S#ijmtui4u)Wg%l=>| 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